Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

DraftEditorBlock.react.js 8.6 KiB

3 anni fa
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @format
  8. *
  9. * @emails oncall+draft_js
  10. */
  11. 'use strict';
  12. var _assign = require("object-assign");
  13. function _extends() { _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; }; return _extends.apply(this, arguments); }
  14. function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
  15. function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
  16. function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  17. var DraftEditorLeaf = require("./DraftEditorLeaf.react");
  18. var DraftOffsetKey = require("./DraftOffsetKey");
  19. var React = require("react");
  20. var Scroll = require("fbjs/lib/Scroll");
  21. var Style = require("fbjs/lib/Style");
  22. var UnicodeBidi = require("fbjs/lib/UnicodeBidi");
  23. var UnicodeBidiDirection = require("fbjs/lib/UnicodeBidiDirection");
  24. var cx = require("fbjs/lib/cx");
  25. var getElementPosition = require("fbjs/lib/getElementPosition");
  26. var getScrollPosition = require("fbjs/lib/getScrollPosition");
  27. var getViewportDimensions = require("fbjs/lib/getViewportDimensions");
  28. var invariant = require("fbjs/lib/invariant");
  29. var isHTMLElement = require("./isHTMLElement");
  30. var nullthrows = require("fbjs/lib/nullthrows");
  31. var SCROLL_BUFFER = 10;
  32. /**
  33. * Return whether a block overlaps with either edge of the `SelectionState`.
  34. */
  35. var isBlockOnSelectionEdge = function isBlockOnSelectionEdge(selection, key) {
  36. return selection.getAnchorKey() === key || selection.getFocusKey() === key;
  37. };
  38. /**
  39. * The default block renderer for a `DraftEditor` component.
  40. *
  41. * A `DraftEditorBlock` is able to render a given `ContentBlock` to its
  42. * appropriate decorator and inline style components.
  43. */
  44. var DraftEditorBlock =
  45. /*#__PURE__*/
  46. function (_React$Component) {
  47. _inheritsLoose(DraftEditorBlock, _React$Component);
  48. function DraftEditorBlock() {
  49. var _this;
  50. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  51. args[_key] = arguments[_key];
  52. }
  53. _this = _React$Component.call.apply(_React$Component, [this].concat(args)) || this;
  54. _defineProperty(_assertThisInitialized(_this), "_node", void 0);
  55. return _this;
  56. }
  57. var _proto = DraftEditorBlock.prototype;
  58. _proto.shouldComponentUpdate = function shouldComponentUpdate(nextProps) {
  59. return this.props.block !== nextProps.block || this.props.tree !== nextProps.tree || this.props.direction !== nextProps.direction || isBlockOnSelectionEdge(nextProps.selection, nextProps.block.getKey()) && nextProps.forceSelection;
  60. }
  61. /**
  62. * When a block is mounted and overlaps the selection state, we need to make
  63. * sure that the cursor is visible to match native behavior. This may not
  64. * be the case if the user has pressed `RETURN` or pasted some content, since
  65. * programmatically creating these new blocks and setting the DOM selection
  66. * will miss out on the browser natively scrolling to that position.
  67. *
  68. * To replicate native behavior, if the block overlaps the selection state
  69. * on mount, force the scroll position. Check the scroll state of the scroll
  70. * parent, and adjust it to align the entire block to the bottom of the
  71. * scroll parent.
  72. */
  73. ;
  74. _proto.componentDidMount = function componentDidMount() {
  75. if (this.props.preventScroll) {
  76. return;
  77. }
  78. var selection = this.props.selection;
  79. var endKey = selection.getEndKey();
  80. if (!selection.getHasFocus() || endKey !== this.props.block.getKey()) {
  81. return;
  82. }
  83. var blockNode = this._node;
  84. if (blockNode == null) {
  85. return;
  86. }
  87. var scrollParent = Style.getScrollParent(blockNode);
  88. var scrollPosition = getScrollPosition(scrollParent);
  89. var scrollDelta;
  90. if (scrollParent === window) {
  91. var nodePosition = getElementPosition(blockNode);
  92. var nodeBottom = nodePosition.y + nodePosition.height;
  93. var viewportHeight = getViewportDimensions().height;
  94. scrollDelta = nodeBottom - viewportHeight;
  95. if (scrollDelta > 0) {
  96. window.scrollTo(scrollPosition.x, scrollPosition.y + scrollDelta + SCROLL_BUFFER);
  97. }
  98. } else {
  99. !isHTMLElement(blockNode) ? process.env.NODE_ENV !== "production" ? invariant(false, 'blockNode is not an HTMLElement') : invariant(false) : void 0;
  100. var blockBottom = blockNode.offsetHeight + blockNode.offsetTop;
  101. var pOffset = scrollParent.offsetTop + scrollParent.offsetHeight;
  102. var scrollBottom = pOffset + scrollPosition.y;
  103. scrollDelta = blockBottom - scrollBottom;
  104. if (scrollDelta > 0) {
  105. Scroll.setTop(scrollParent, Scroll.getTop(scrollParent) + scrollDelta + SCROLL_BUFFER);
  106. }
  107. }
  108. };
  109. _proto._renderChildren = function _renderChildren() {
  110. var _this2 = this;
  111. var block = this.props.block;
  112. var blockKey = block.getKey();
  113. var text = block.getText();
  114. var lastLeafSet = this.props.tree.size - 1;
  115. var hasSelection = isBlockOnSelectionEdge(this.props.selection, blockKey);
  116. return this.props.tree.map(function (leafSet, ii) {
  117. var leavesForLeafSet = leafSet.get('leaves'); // T44088704
  118. if (leavesForLeafSet.size === 0) {
  119. return null;
  120. }
  121. var lastLeaf = leavesForLeafSet.size - 1;
  122. var leaves = leavesForLeafSet.map(function (leaf, jj) {
  123. var offsetKey = DraftOffsetKey.encode(blockKey, ii, jj);
  124. var start = leaf.get('start');
  125. var end = leaf.get('end');
  126. return React.createElement(DraftEditorLeaf, {
  127. key: offsetKey,
  128. offsetKey: offsetKey,
  129. block: block,
  130. start: start,
  131. selection: hasSelection ? _this2.props.selection : null,
  132. forceSelection: _this2.props.forceSelection,
  133. text: text.slice(start, end),
  134. styleSet: block.getInlineStyleAt(start),
  135. customStyleMap: _this2.props.customStyleMap,
  136. customStyleFn: _this2.props.customStyleFn,
  137. isLast: ii === lastLeafSet && jj === lastLeaf
  138. });
  139. }).toArray();
  140. var decoratorKey = leafSet.get('decoratorKey');
  141. if (decoratorKey == null) {
  142. return leaves;
  143. }
  144. if (!_this2.props.decorator) {
  145. return leaves;
  146. }
  147. var decorator = nullthrows(_this2.props.decorator);
  148. var DecoratorComponent = decorator.getComponentForKey(decoratorKey);
  149. if (!DecoratorComponent) {
  150. return leaves;
  151. }
  152. var decoratorProps = decorator.getPropsForKey(decoratorKey);
  153. var decoratorOffsetKey = DraftOffsetKey.encode(blockKey, ii, 0);
  154. var start = leavesForLeafSet.first().get('start');
  155. var end = leavesForLeafSet.last().get('end');
  156. var decoratedText = text.slice(start, end);
  157. var entityKey = block.getEntityAt(leafSet.get('start')); // Resetting dir to the same value on a child node makes Chrome/Firefox
  158. // confused on cursor movement. See http://jsfiddle.net/d157kLck/3/
  159. var dir = UnicodeBidiDirection.getHTMLDirIfDifferent(UnicodeBidi.getDirection(decoratedText), _this2.props.direction);
  160. var commonProps = {
  161. contentState: _this2.props.contentState,
  162. decoratedText: decoratedText,
  163. dir: dir,
  164. start: start,
  165. end: end,
  166. blockKey: blockKey,
  167. entityKey: entityKey,
  168. offsetKey: decoratorOffsetKey
  169. };
  170. return React.createElement(DecoratorComponent, _extends({}, decoratorProps, commonProps, {
  171. key: decoratorOffsetKey
  172. }), leaves);
  173. }).toArray();
  174. };
  175. _proto.render = function render() {
  176. var _this3 = this;
  177. var _this$props = this.props,
  178. direction = _this$props.direction,
  179. offsetKey = _this$props.offsetKey;
  180. var className = cx({
  181. 'public/DraftStyleDefault/block': true,
  182. 'public/DraftStyleDefault/ltr': direction === 'LTR',
  183. 'public/DraftStyleDefault/rtl': direction === 'RTL'
  184. });
  185. return React.createElement("div", {
  186. "data-offset-key": offsetKey,
  187. className: className,
  188. ref: function ref(_ref) {
  189. return _this3._node = _ref;
  190. }
  191. }, this._renderChildren());
  192. };
  193. return DraftEditorBlock;
  194. }(React.Component);
  195. module.exports = DraftEditorBlock;