UNPKG

@lyra/form-builder

Version:
429 lines (351 loc) 12.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _linkIcon = require('part:@lyra/base/link-icon'); var _linkIcon2 = _interopRequireDefault(_linkIcon); var _fold = require('part:@lyra/components/edititem/fold'); var _fold2 = _interopRequireDefault(_fold); var _popover = require('part:@lyra/components/dialogs/popover'); var _popover2 = _interopRequireDefault(_popover); var _fullscreen = require('part:@lyra/components/dialogs/fullscreen'); var _fullscreen2 = _interopRequireDefault(_fullscreen); var _default = require('part:@lyra/components/dialogs/default'); var _default2 = _interopRequireDefault(_default); var _content = require('part:@lyra/components/dialogs/content'); var _content2 = _interopRequireDefault(_content); var _status = require('part:@lyra/components/validation/status'); var _status2 = _interopRequireDefault(_status); var _sortable = require('part:@lyra/components/lists/sortable'); var _router = require('part:@lyra/base/router'); var _barsIcon = require('part:@lyra/base/bars-icon'); var _barsIcon2 = _interopRequireDefault(_barsIcon); var _FormBuilderInput = require('../../FormBuilderInput'); var _PatchEvent = require('../../PatchEvent'); var _PatchEvent2 = _interopRequireDefault(_PatchEvent); var _Preview = require('../../Preview'); var _Preview2 = _interopRequireDefault(_Preview); var _resolveTypeName = require('../../utils/resolveTypeName'); var _pathUtils = require('../../utils/pathUtils'); var PathUtils = _interopRequireWildcard(_pathUtils); var _ConfirmButton = require('./ConfirmButton'); var _ConfirmButton2 = _interopRequireDefault(_ConfirmButton); var _ItemValue = require('./styles/ItemValue.css'); var _ItemValue2 = _interopRequireDefault(_ItemValue); 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 }; } /* eslint-disable complexity */ /*:: import type {Node} from 'react'*/ /*:: import type {Path} from '../../typedefs/path'*/ /*:: import type {Type, Marker} from '../../typedefs'*/ /*:: import type {ArrayType, ItemValue} from './typedefs'*/ const DragHandle = (0, _sortable.createDragHandle)(() => _react2.default.createElement( 'span', { className: _ItemValue2.default.dragHandle }, _react2.default.createElement(_barsIcon2.default, null) )); const CLOSE_ACTION = { name: 'close', title: 'Close' }; const CANCEL_ACTION = { name: 'close', title: 'Cancel' }; const DELETE_ACTION = { name: 'delete', kind: 'simple', title: 'Delete', color: 'danger', secondary: true }; /*:: type Props = { type: ArrayType, value: ItemValue, level: number, markers: Array<Marker>, layout?: 'media' | 'default', onRemove: ItemValue => void, onChange: (PatchEvent, ItemValue) => void, onFocus: Path => void, onBlur: void => void, readOnly: ?boolean, focusPath: Path }*/ function pathSegmentFrom(value) { return { _key: value._key }; } function hasFocusInPath(path, value) { return path.length === 1 && PathUtils.isSegmentEqual(path[0], pathSegmentFrom(value)); } const IGNORE_KEYS = ['_key', '_type', '_weak']; function isEmpty(value) { return Object.keys(value).every(key => IGNORE_KEYS.includes(key)); } class RenderItemValue extends _react2.default.Component /*:: <Props>*/ { constructor(...args) { var _temp; return _temp = super(...args), this.handleEditStart = event => { this.setFocus([PathUtils.FOCUS_TERMINATOR]); }, this.handleFocus = () => { this.setFocus(); }, this.handleEditStop = () => { if (isEmpty(this.props.value)) { this.handleRemove(); } else { this.setFocus(); } }, this.handleKeyPress = (event /*: SyntheticKeyboardEvent<*>*/) => { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); this.setFocus([PathUtils.FOCUS_TERMINATOR]); } }, this.handleRemove = () => { var _props = this.props; const onRemove = _props.onRemove, value = _props.value; onRemove(value); }, this.handleChange = (event /*: PatchEvent*/) => { var _props2 = this.props; const onChange = _props2.onChange, value = _props2.value; onChange(event, value); }, this.setFocusArea = (el /*: ?FocusArea*/) => { this._focusArea = el; }, this.handleDialogAction = action => { if (action.name === 'close') { this.handleEditStop(); } if (action.name === 'delete') { // Needs a proper confirm dialog later // eslint-disable-next-line no-alert if (window.confirm('Do you really want to delete?')) { this.handleRemove(); } } }, _temp; } componentDidMount() { var _props3 = this.props; const focusPath = _props3.focusPath, value = _props3.value; if (hasFocusInPath(focusPath, value)) { this.focus(); } } componentDidUpdate(prevProps) { const hadFocus = hasFocusInPath(prevProps.focusPath, prevProps.value); const hasFocus = hasFocusInPath(this.props.focusPath, this.props.value); if (!hadFocus && hasFocus) { this.focus(); } } getMemberType() /*: ?Type*/ { var _props4 = this.props; const value = _props4.value, type = _props4.type; const itemTypeName = (0, _resolveTypeName.resolveTypeName)(value); return type.of.find(memberType => memberType.name === itemTypeName); } setFocus(path /*: Path*/ = []) { var _props5 = this.props; const value = _props5.value, onFocus = _props5.onFocus; onFocus([{ _key: value._key }, ...path]); } focus() { if (this._focusArea) { this._focusArea.focus(); } } renderEditItemForm(item /*: ItemValue*/) /*: Node*/ { var _props6 = this.props; const type = _props6.type, markers = _props6.markers, focusPath = _props6.focusPath, onFocus = _props6.onFocus, onBlur = _props6.onBlur, readOnly = _props6.readOnly; const options = type.options || {}; const memberType = this.getMemberType() || {}; const childMarkers = markers.filter(marker => marker.path.length > 1); const content = _react2.default.createElement(_FormBuilderInput.FormBuilderInput, { type: memberType, level: 0, value: isEmpty(item) ? undefined : item, onChange: this.handleChange, onFocus: onFocus, onBlur: onBlur, focusPath: focusPath, readOnly: readOnly || memberType.readOnly, markers: childMarkers, path: [{ _key: item._key }] }); // test focus issues by uncommenting the next line // return content if (options.editModal === 'fullscreen') { return _react2.default.createElement( _fullscreen2.default, { title: memberType.title, onClose: this.handleEditStop, isOpen: true }, content ); } if (options.editModal === 'fold') { return _react2.default.createElement( 'div', { className: _ItemValue2.default.popupAnchorRelative }, _react2.default.createElement( _fold2.default, { title: `Edit ${memberType.title}`, onClose: this.handleEditStop }, content ) ); } const dialogSize = 'medium'; const isItemEmpty = isEmpty(item); const actions = [isItemEmpty ? CANCEL_ACTION : CLOSE_ACTION, !isItemEmpty && !readOnly && DELETE_ACTION].filter(Boolean); if (options.editModal === 'popover') { return _react2.default.createElement( 'div', { className: _ItemValue2.default.popupAnchor }, _react2.default.createElement( _popover2.default, { title: `Edit ${memberType.title}`, onClose: this.handleEditStop, onEscape: this.handleEditStop, onClickOutside: this.handleEditStop, actions: actions, onAction: this.handleDialogAction }, _react2.default.createElement( _content2.default, { size: dialogSize }, content ) ) ); } return _react2.default.createElement( _default2.default, { onClose: this.handleEditStop, key: item._key, title: `Edit ${memberType.title}`, actions: actions, onAction: this.handleDialogAction, showCloseButton: false }, _react2.default.createElement( 'div', { className: _ItemValue2.default.defaultDialogContent }, _react2.default.createElement( _content2.default, { size: dialogSize }, content ) ) ); } renderItem() { var _props7 = this.props; const value = _props7.value, markers = _props7.markers, type = _props7.type, readOnly = _props7.readOnly; const options = type.options || {}; const isGrid = options.layout === 'grid'; const isSortable = !readOnly && !type.readOnly && options.sortable !== false; const previewLayout = isGrid ? 'media' : 'default'; const validation = markers.filter(marker => marker.type === 'validation'); const errors = validation.filter(marker => marker.level === 'error'); const scopedValidation = validation.map(marker => { if (marker.path.length <= 1) { return marker; } const level = marker.level === 'error' ? 'errors' : 'warnings'; return Object.assign({}, marker, { item: marker.item.cloneWithMessage(`Contains ${level}`) }); }); return _react2.default.createElement( 'div', { className: errors.length > 0 ? _ItemValue2.default.innerWithError : _ItemValue2.default.inner }, !isGrid && isSortable && _react2.default.createElement(DragHandle, null), _react2.default.createElement( 'div', { tabIndex: 0, onClick: this.handleEditStart, onKeyPress: this.handleKeyPress, className: _ItemValue2.default.previewWrapper }, _react2.default.createElement( 'div', { tabIndex: -1, ref: this.setFocusArea, className: _ItemValue2.default.previewWrapperHelper, onFocus: this.handleFocus }, _react2.default.createElement(_Preview2.default, { layout: previewLayout, value: value, type: this.getMemberType() }) ) ), _react2.default.createElement( 'div', { className: isGrid ? _ItemValue2.default.functionsInGrid : _ItemValue2.default.functions }, _react2.default.createElement( 'div', { className: _ItemValue2.default.validationStatus }, _react2.default.createElement(_status2.default, { markers: scopedValidation }) ), value._ref && _react2.default.createElement( _router.IntentLink, { className: _ItemValue2.default.linkToReference, intent: 'edit', params: { id: value._ref } }, _react2.default.createElement(_linkIcon2.default, null) ), !readOnly && _react2.default.createElement(_ConfirmButton2.default, { title: 'Remove this item', onConfirm: this.handleRemove }) ) ); } render() { var _props8 = this.props; const value = _props8.value, focusPath = _props8.focusPath, type = _props8.type; const options = type.options || {}; const isGrid = options.layout === 'grid'; const isExpanded = PathUtils.isExpanded(value, focusPath); return _react2.default.createElement( 'div', { className: isGrid ? _ItemValue2.default.gridItem : _ItemValue2.default.listItem }, this.renderItem(), isExpanded && this.renderEditItemForm(value) ); } } exports.default = RenderItemValue; RenderItemValue.defaultProps = { level: 0, markers: [] };