|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- /**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
- * @emails oncall+draft_js
- *
- * 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';
-
- import type { BlockNodeRecord } from "./BlockNodeRecord";
- import type { DraftBlockRenderMap } from "./DraftBlockRenderMap";
- import type { DraftInlineStyle } from "./DraftInlineStyle";
- import type EditorState from "./EditorState";
- import type { BidiDirection } from "fbjs/lib/UnicodeBidiDirection";
-
- const DraftEditorBlockNode = require("./DraftEditorBlockNode.react");
-
- const DraftOffsetKey = require("./DraftOffsetKey");
-
- const React = require("react");
-
- const nullthrows = require("fbjs/lib/nullthrows");
-
- type Props = {
- blockRenderMap: DraftBlockRenderMap,
- blockRendererFn: (block: BlockNodeRecord) => ?Object,
- blockStyleFn?: (block: BlockNodeRecord) => string,
- customStyleFn?: (style: DraftInlineStyle, block: BlockNodeRecord) => ?Object,
- customStyleMap?: Object,
- editorKey?: string,
- editorState: EditorState,
- textDirectionality?: BidiDirection,
- ...
- };
- /**
- * `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.
- */
-
- class DraftEditorContentsExperimental extends React.Component<Props> {
- shouldComponentUpdate(nextProps: Props): boolean {
- const prevEditorState = this.props.editorState;
- const nextEditorState = nextProps.editorState;
- const prevDirectionMap = prevEditorState.getDirectionMap();
- const nextDirectionMap = nextEditorState.getDirectionMap(); // Text direction has changed for one or more blocks. We must re-render.
-
- if (prevDirectionMap !== nextDirectionMap) {
- return true;
- }
-
- const didHaveFocus = prevEditorState.getSelection().getHasFocus();
- const nowHasFocus = nextEditorState.getSelection().getHasFocus();
-
- if (didHaveFocus !== nowHasFocus) {
- return true;
- }
-
- const nextNativeContent = nextEditorState.getNativelyRenderedContent();
- const wasComposing = prevEditorState.isInCompositionMode();
- const 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;
- }
-
- const prevContent = prevEditorState.getCurrentContent();
- const nextContent = nextEditorState.getCurrentContent();
- const prevDecorator = prevEditorState.getDecorator();
- const nextDecorator = nextEditorState.getDecorator();
- return wasComposing !== nowComposing || prevContent !== nextContent || prevDecorator !== nextDecorator || nextEditorState.mustForceSelection();
- }
-
- render(): React.Node {
- const {
- blockRenderMap,
- blockRendererFn,
- blockStyleFn,
- customStyleMap,
- customStyleFn,
- editorState,
- editorKey,
- textDirectionality
- } = this.props;
- const content = editorState.getCurrentContent();
- const selection = editorState.getSelection();
- const forceSelection = editorState.mustForceSelection();
- const decorator = editorState.getDecorator();
- const directionMap = nullthrows(editorState.getDirectionMap());
- const blocksAsArray = content.getBlocksAsArray();
- const rootBlock = blocksAsArray[0];
- const processedBlocks = [];
- let nodeBlock = rootBlock;
-
- while (nodeBlock) {
- const blockKey = nodeBlock.getKey();
- const blockProps = {
- blockRenderMap,
- blockRendererFn,
- blockStyleFn,
- contentState: content,
- customStyleFn,
- customStyleMap,
- decorator,
- editorKey,
- editorState,
- forceSelection,
- selection,
- block: nodeBlock,
- direction: textDirectionality ? textDirectionality : directionMap.get(blockKey),
- tree: editorState.getBlockTree(blockKey)
- };
- const configForType = blockRenderMap.get(nodeBlock.getType()) || blockRenderMap.get('unstyled');
- const wrapperTemplate = configForType.wrapper;
- processedBlocks.push({
- /* $FlowFixMe(>=0.112.0 site=www,mobile) This comment suppresses an
- * error found when Flow v0.112 was deployed. To see the error delete
- * this comment and run Flow. */
- block: <DraftEditorBlockNode key={blockKey} {...blockProps} />,
- wrapperTemplate,
- key: blockKey,
- offsetKey: DraftOffsetKey.encode(blockKey, 0, 0)
- });
- const nextBlockKey = nodeBlock.getNextSiblingKey();
- nodeBlock = nextBlockKey ? content.getBlockForKey(nextBlockKey) : null;
- } // Group contiguous runs of blocks that have the same wrapperTemplate
-
-
- const outputBlocks = [];
-
- for (let ii = 0; ii < processedBlocks.length;) {
- const info: any = processedBlocks[ii];
-
- if (info.wrapperTemplate) {
- const blocks = [];
-
- do {
- blocks.push(processedBlocks[ii].block);
- ii++;
- } while (ii < processedBlocks.length && processedBlocks[ii].wrapperTemplate === info.wrapperTemplate);
-
- const 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 <div data-contents="true">{outputBlocks}</div>;
- }
-
- }
-
- module.exports = DraftEditorContentsExperimental;
|