/* * This file is part of ORY Editor. * * ORY Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ORY Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with ORY Editor. If not, see . * * @license LGPL-3.0 * @copyright 2016-2018 Aeneas Rekkas * @author Aeneas Rekkas * */ import * as React from 'react'; import { connect } from 'react-redux'; import { bindActionCreators, Dispatch } from 'redux'; import { createStructuredSelector } from 'reselect'; import { updateCellContent, UpdateCellContentAction } from '../../../actions/cell'; import { isEditMode, isLayoutMode, isPreviewMode, isInsertMode, isResizeMode } from '../../../selector/display'; import { ComponetizedCell } from '../../../types/editable'; import { ContentPluginProps } from '../../../service/plugin/classes'; // TODO clean me up #157 class Content extends React.PureComponent { private ref: HTMLDivElement; UNSAFE_componentWillReceiveProps(nextProps: ComponetizedCell) { const { node: { focused: was }, } = this.props; const { node: { focused: is, focusSource }, } = nextProps; const { editable, id, node: { content: { plugin: { handleFocus = () => null, handleBlur = () => null, name = 'N/A', version = 'N/A', } = {}, state = {}, } = {}, focused, }, } = nextProps; // FIXME this is really shitty because it will break when the state changes before the blur comes through, see #157 // tslint:disable-next-line:no-any const pass: ContentPluginProps = { editable, id, state, focused: this.props.isEditMode && focused, readOnly: !isEditMode, onChange: this.props.updateCellContent, name, version, isEditMode: nextProps.isEditMode, isResizeMode: nextProps.isResizeMode, isPreviewMode: nextProps.isPreviewMode, isInsertMode: nextProps.isInsertMode, isLayoutMode: nextProps.isLayoutMode, }; // Basically we check if the focus state changed and if yes, we execute the callback handler from the plugin, that // can set some side effects. if (!was && is) { // We need this because otherwise we lose hotkey focus on elements like spoilers. // This could probably be solved in an easier way by listening to window.document? handleFocus(pass, focusSource, this.ref); } else if (was && !is) { handleBlur(pass); } } onRef = (ref: HTMLDivElement) => { this.ref = ref; } render() { const { editable, id, node: { content: { plugin: { Component = () => null, name = 'N/A', version = 'N/A', } = {}, state = {}, } = {}, focused, }, } = this.props; const { focusCell, blurCell } = this.props; let focusProps; if (!this.props.isPreviewMode) { focusProps = { onMouseDown: () => { if (!focused) { focusCell({ source: 'onMouseDown' }); } return true; }, }; } return (
); } } const mapStateToProps = createStructuredSelector({ isEditMode, isLayoutMode, isPreviewMode, isInsertMode, isResizeMode, }); const mapDispatchToProps = ( dispatch: Dispatch, { id }: ComponetizedCell ) => bindActionCreators( { updateCellContent: updateCellContent(id), }, // tslint:disable-next-line:no-any dispatch as any ); export default connect( mapStateToProps, mapDispatchToProps )(Content);