UNPKG

megadraft

Version:

Rich Text editor built on top of draft.js

165 lines (135 loc) 5.39 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.editorStateToJSON = editorStateToJSON; exports.editorStateFromRaw = editorStateFromRaw; exports.getSelectedBlockElement = getSelectedBlockElement; exports.getSelectionCoords = getSelectionCoords; exports.createTypeStrategy = createTypeStrategy; exports.delayCall = delayCall; var _draftJs = require("draft-js"); var _defaultDecorator = _interopRequireDefault(require("./decorators/defaultDecorator")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } /* * Copyright (c) 2016, Globo.com (https://github.com/globocom) * Copyright (c) 2016, Andrew Coelho <info@andrewcoelho.com> * * License: MIT */ function editorStateToJSON(editorState) { var humanReadable = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (editorState) { var content = editorState.getCurrentContent(); return JSON.stringify((0, _draftJs.convertToRaw)(content), null, humanReadable ? 2 : 0); } } function editorStateFromRaw(rawContent) { var decorator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _defaultDecorator["default"]; if (rawContent) { var content = (0, _draftJs.convertFromRaw)(rawContent); return _draftJs.EditorState.createWithContent(content, decorator); } return _draftJs.EditorState.createEmpty(decorator); } function getSelectedBlockElement(range) { var node = range.startContainer; do { try { var nodeIsDataBlock = node.getAttribute ? node.getAttribute("data-block") : null; if (nodeIsDataBlock) { return node; } node = node.parentNode; } catch (error) { return null; } } while (node !== null); return null; } function getSelectionCoords(editor, toolbar) { var editorBounds = editor.getBoundingClientRect(); var win = editor.ownerDocument.defaultView || window; var rangeBounds = (0, _draftJs.getVisibleSelectionRect)(win); if (!rangeBounds || !toolbar) { return null; } var toolbarHeight = toolbar.offsetHeight; var toolbarWidth = toolbar.offsetWidth; var minOffsetLeft = 5; var minOffsetRight = 5; var minOffsetTop = 5; var rangeWidth = rangeBounds.right - rangeBounds.left; var arrowStyle = {}; var offsetLeft = rangeBounds.left - editorBounds.left + rangeWidth / 2 - toolbarWidth / 2; arrowStyle.left = "50%"; //When the left distance of the selection is less than the width of the toolbar. if (rangeBounds.left + rangeWidth / 2 - toolbarWidth / 2 < minOffsetLeft) { offsetLeft = minOffsetLeft - editorBounds.left; arrowStyle.left = (rangeBounds.left + rangeBounds.right) / 2 - minOffsetLeft; } //When the right distance of the selection is less than the width of the toolbar. if (rangeBounds.left + rangeWidth / 2 + toolbarWidth / 2 + minOffsetLeft + minOffsetRight > win.innerWidth - minOffsetRight) { offsetLeft = win.visualViewport.width - (toolbarWidth + minOffsetRight + editorBounds.left); arrowStyle.left = rangeBounds.left - editorBounds.left + rangeWidth / 2 - offsetLeft; } var offsetTop = rangeBounds.top - editorBounds.top - 14; arrowStyle.top = "97%"; if (offsetTop - minOffsetTop - toolbarHeight + editorBounds.top < 0) { //Always make sure that, if the range bounds does not fully exists, we keep the current coordinates if (rangeBounds.bottom && !Number.isNaN(rangeBounds.bottom)) { offsetTop = rangeBounds.bottom - editorBounds.top + toolbarHeight + 14; arrowStyle.top = "-14px"; arrowStyle.transform = "rotate(180deg)"; } } //When the selection is on extreme left if ((rangeBounds.left + rangeWidth) / 2 < 10) { offsetLeft = 0; arrowStyle.left = (rangeBounds.left + rangeWidth) / 2; } return { offsetLeft: offsetLeft, offsetTop: offsetTop, arrowStyle: arrowStyle }; } function createTypeStrategy(type) { return function (contentBlock, callback, contentState) { contentBlock.findEntityRanges(function (character) { var entityKey = character.getEntity(); return entityKey !== null && contentState.getEntity(entityKey).getType() === type; }, callback); }; } /** * Returns a wrapper for the given function which cannot be called * more often than the given interval. Every time the wrapper is called * a timeout gets reset to the interval's number of ms before calling the fn. * * Keep attention to bind the correct context to the provided funtion using bind() or '::'! * * @export * @param {function} fn The function to execute after the given interval. * @param {number} [interval=100] The interval to wait for before calling the wrapped function. * @example * ``` * const delayedLog = delayCall(::console.log, 200); * delayedLog('hans'); * delayedLog('heiri'); * // logs 'heiri' after 200ms, 'hans' won't be logged at all. * ``` * @returns {void} */ function delayCall(fn) { var interval = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; var timeout; return function () { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } if (timeout) { window.clearTimeout(timeout); } timeout = window.setTimeout(function () { return fn.apply(window, args); }, interval); }; }