forked from Gitlink/forgeplus-react
180 lines
7.3 KiB
JavaScript
180 lines
7.3 KiB
JavaScript
|
|
/**
|
||
|
|
* Copyright (c) 2013-present, Facebook, Inc.
|
||
|
|
* All rights reserved.
|
||
|
|
*
|
||
|
|
* This source code is licensed under the BSD-style license found in the
|
||
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||
|
|
*
|
||
|
|
* @providesModule DraftEditorContentsExperimental.react
|
||
|
|
* @format
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* This file is a fork of DraftEditorContents.react.js for tree nodes
|
||
|
|
*
|
||
|
|
* This is unstable and not part of the public API and should not be used by
|
||
|
|
* production systems. This file may be update/removed without notice.
|
||
|
|
*/
|
||
|
|
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
var _assign = require('object-assign');
|
||
|
|
|
||
|
|
var _extends = _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; };
|
||
|
|
|
||
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||
|
|
|
||
|
|
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
||
|
|
|
||
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
||
|
|
|
||
|
|
var DraftEditorBlockNode = require('./DraftEditorBlockNode.react');
|
||
|
|
var DraftOffsetKey = require('./DraftOffsetKey');
|
||
|
|
var EditorState = require('./EditorState');
|
||
|
|
var React = require('react');
|
||
|
|
|
||
|
|
var nullthrows = require('fbjs/lib/nullthrows');
|
||
|
|
|
||
|
|
/**
|
||
|
|
* `DraftEditorContents` is the container component for all block components
|
||
|
|
* rendered for a `DraftEditor`. It is optimized to aggressively avoid
|
||
|
|
* re-rendering blocks whenever possible.
|
||
|
|
*
|
||
|
|
* This component is separate from `DraftEditor` because certain props
|
||
|
|
* (for instance, ARIA props) must be allowed to update without affecting
|
||
|
|
* the contents of the editor.
|
||
|
|
*/
|
||
|
|
var DraftEditorContentsExperimental = function (_React$Component) {
|
||
|
|
_inherits(DraftEditorContentsExperimental, _React$Component);
|
||
|
|
|
||
|
|
function DraftEditorContentsExperimental() {
|
||
|
|
_classCallCheck(this, DraftEditorContentsExperimental);
|
||
|
|
|
||
|
|
return _possibleConstructorReturn(this, _React$Component.apply(this, arguments));
|
||
|
|
}
|
||
|
|
|
||
|
|
DraftEditorContentsExperimental.prototype.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
|
||
|
|
var prevEditorState = this.props.editorState;
|
||
|
|
var nextEditorState = nextProps.editorState;
|
||
|
|
|
||
|
|
var prevDirectionMap = prevEditorState.getDirectionMap();
|
||
|
|
var nextDirectionMap = nextEditorState.getDirectionMap();
|
||
|
|
|
||
|
|
// Text direction has changed for one or more blocks. We must re-render.
|
||
|
|
if (prevDirectionMap !== nextDirectionMap) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
var didHaveFocus = prevEditorState.getSelection().getHasFocus();
|
||
|
|
var nowHasFocus = nextEditorState.getSelection().getHasFocus();
|
||
|
|
|
||
|
|
if (didHaveFocus !== nowHasFocus) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
var nextNativeContent = nextEditorState.getNativelyRenderedContent();
|
||
|
|
|
||
|
|
var wasComposing = prevEditorState.isInCompositionMode();
|
||
|
|
var nowComposing = nextEditorState.isInCompositionMode();
|
||
|
|
|
||
|
|
// If the state is unchanged or we're currently rendering a natively
|
||
|
|
// rendered state, there's nothing new to be done.
|
||
|
|
if (prevEditorState === nextEditorState || nextNativeContent !== null && nextEditorState.getCurrentContent() === nextNativeContent || wasComposing && nowComposing) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
var prevContent = prevEditorState.getCurrentContent();
|
||
|
|
var nextContent = nextEditorState.getCurrentContent();
|
||
|
|
var prevDecorator = prevEditorState.getDecorator();
|
||
|
|
var nextDecorator = nextEditorState.getDecorator();
|
||
|
|
return wasComposing !== nowComposing || prevContent !== nextContent || prevDecorator !== nextDecorator || nextEditorState.mustForceSelection();
|
||
|
|
};
|
||
|
|
|
||
|
|
DraftEditorContentsExperimental.prototype.render = function render() {
|
||
|
|
var _props = this.props,
|
||
|
|
blockRenderMap = _props.blockRenderMap,
|
||
|
|
blockRendererFn = _props.blockRendererFn,
|
||
|
|
blockStyleFn = _props.blockStyleFn,
|
||
|
|
customStyleMap = _props.customStyleMap,
|
||
|
|
customStyleFn = _props.customStyleFn,
|
||
|
|
editorState = _props.editorState,
|
||
|
|
editorKey = _props.editorKey,
|
||
|
|
textDirectionality = _props.textDirectionality;
|
||
|
|
|
||
|
|
|
||
|
|
var content = editorState.getCurrentContent();
|
||
|
|
var selection = editorState.getSelection();
|
||
|
|
var forceSelection = editorState.mustForceSelection();
|
||
|
|
var decorator = editorState.getDecorator();
|
||
|
|
var directionMap = nullthrows(editorState.getDirectionMap());
|
||
|
|
|
||
|
|
var blocksAsArray = content.getBlocksAsArray();
|
||
|
|
var rootBlock = blocksAsArray[0];
|
||
|
|
var processedBlocks = [];
|
||
|
|
|
||
|
|
var nodeBlock = rootBlock;
|
||
|
|
|
||
|
|
while (nodeBlock) {
|
||
|
|
var blockKey = nodeBlock.getKey();
|
||
|
|
var blockProps = {
|
||
|
|
blockRenderMap: blockRenderMap,
|
||
|
|
blockRendererFn: blockRendererFn,
|
||
|
|
blockStyleFn: blockStyleFn,
|
||
|
|
contentState: content,
|
||
|
|
customStyleFn: customStyleFn,
|
||
|
|
customStyleMap: customStyleMap,
|
||
|
|
decorator: decorator,
|
||
|
|
editorKey: editorKey,
|
||
|
|
editorState: editorState,
|
||
|
|
forceSelection: forceSelection,
|
||
|
|
selection: selection,
|
||
|
|
block: nodeBlock,
|
||
|
|
direction: textDirectionality ? textDirectionality : directionMap.get(blockKey),
|
||
|
|
tree: editorState.getBlockTree(blockKey)
|
||
|
|
};
|
||
|
|
|
||
|
|
var configForType = blockRenderMap.get(nodeBlock.getType()) || blockRenderMap.get('unstyled');
|
||
|
|
var wrapperTemplate = configForType.wrapper;
|
||
|
|
processedBlocks.push({
|
||
|
|
block: React.createElement(DraftEditorBlockNode, _extends({ key: blockKey }, blockProps)),
|
||
|
|
wrapperTemplate: wrapperTemplate,
|
||
|
|
key: blockKey,
|
||
|
|
offsetKey: DraftOffsetKey.encode(blockKey, 0, 0)
|
||
|
|
});
|
||
|
|
|
||
|
|
var nextBlockKey = nodeBlock.getNextSiblingKey();
|
||
|
|
nodeBlock = nextBlockKey ? content.getBlockForKey(nextBlockKey) : null;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Group contiguous runs of blocks that have the same wrapperTemplate
|
||
|
|
var outputBlocks = [];
|
||
|
|
for (var ii = 0; ii < processedBlocks.length;) {
|
||
|
|
var info = processedBlocks[ii];
|
||
|
|
if (info.wrapperTemplate) {
|
||
|
|
var blocks = [];
|
||
|
|
do {
|
||
|
|
blocks.push(processedBlocks[ii].block);
|
||
|
|
ii++;
|
||
|
|
} while (ii < processedBlocks.length && processedBlocks[ii].wrapperTemplate === info.wrapperTemplate);
|
||
|
|
var wrapperElement = React.cloneElement(info.wrapperTemplate, {
|
||
|
|
key: info.key + '-wrap',
|
||
|
|
'data-offset-key': info.offsetKey
|
||
|
|
}, blocks);
|
||
|
|
outputBlocks.push(wrapperElement);
|
||
|
|
} else {
|
||
|
|
outputBlocks.push(info.block);
|
||
|
|
ii++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return React.createElement(
|
||
|
|
'div',
|
||
|
|
{ 'data-contents': 'true' },
|
||
|
|
outputBlocks
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
return DraftEditorContentsExperimental;
|
||
|
|
}(React.Component);
|
||
|
|
|
||
|
|
module.exports = DraftEditorContentsExperimental;
|