UNPKG

@draft-js-plugins/inline-toolbar

Version:
190 lines (179 loc) 7.43 kB
import React, { useState, useRef, useEffect, Fragment } from 'react'; import { createStore } from '@draft-js-plugins/utils'; import { getVisibleSelectionRect } from 'draft-js'; import { ItalicButton, BoldButton, UnderlineButton, CodeButton } from '@draft-js-plugins/buttons'; function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); } var Toolbar = function Toolbar(_ref) { var defaultStore = _ref.store, children = _ref.children, defaultIsVisible = _ref.isVisible, defaultPosition = _ref.position, defaultOverrideContent = _ref.overrideContent, defaultTheme = _ref.theme; var _useState = useState({ store: defaultStore, isVisible: defaultIsVisible, position: defaultPosition, theme: defaultTheme, overrideContent: defaultOverrideContent }), toolbarPropsState = _useState[0], setToolbarPropsState = _useState[1]; var toolbar = useRef(null); var onOverrideContent = function onOverrideContent(newOverrideContent) { setToolbarPropsState(function (prev) { return _extends({}, prev, { overrideContent: newOverrideContent }); }); }; var onSelectionChanged = function onSelectionChanged() { // need to wait a tick for window.getSelection() to be accurate // when focusing editor with already present selection setTimeout(function () { var _toolbar$current; if (!toolbar) return; // The editor root should be two levels above the node from // `getEditorRef`. In case this changes in the future, we // attempt to find the node dynamically by traversing upwards. var editorRef = toolbarPropsState.store.getItem('getEditorRef')(); if (!editorRef) return; // This keeps backwards compatibility with React 15 var editorRoot = editorRef.refs && editorRef.refs.editor ? editorRef.refs.editor : editorRef.editor; while (editorRoot.className.indexOf('DraftEditor-root') === -1) { editorRoot = editorRoot.parentNode; } var editorRootRect = editorRoot.getBoundingClientRect(); var parentWindow = editorRoot.ownerDocument && editorRoot.ownerDocument.defaultView; var selectionRect = getVisibleSelectionRect(parentWindow || window); if (!selectionRect) return; // The toolbar shouldn't be positioned directly on top of the selected text, // but rather with a small offset so the caret doesn't overlap with the text. var extraTopOffset = -5; // Account for scrollTop of all ancestors var scrollOffset = 0; var ancestorNode = editorRoot.parentNode; while (ancestorNode !== null && ancestorNode.nodeName !== 'HTML') { var _ancestorNode$scrollT; scrollOffset += (_ancestorNode$scrollT = ancestorNode.scrollTop) != null ? _ancestorNode$scrollT : 0; ancestorNode = ancestorNode.parentNode; } var newPosition = { top: editorRoot.offsetTop - scrollOffset - (((_toolbar$current = toolbar.current) == null ? void 0 : _toolbar$current.offsetHeight) || 0) + (selectionRect.top - editorRootRect.top) + extraTopOffset, left: editorRoot.offsetLeft + (selectionRect.left - editorRootRect.left) + selectionRect.width / 2 }; setToolbarPropsState(function (prevState) { return _extends({}, prevState, { position: newPosition }); }); }); }; var getStyle = function getStyle() { var overrideContent = toolbarPropsState.overrideContent, position = toolbarPropsState.position, store = toolbarPropsState.store; var selection = store.getItem('getEditorState')().getSelection(); // overrideContent could for example contain a text input, hence we always show overrideContent // TODO: Test readonly mode and possibly set isVisible to false if the editor is readonly var visible = !selection.isCollapsed() && selection.getHasFocus() || overrideContent; var style = _extends({}, position); if (visible) { style.visibility = 'visible'; style.transform = 'translate(-50%) scale(1)'; style.transition = 'transform 0.15s cubic-bezier(.3,1.2,.2,1)'; } else { style.transform = 'translate(-50%) scale(0)'; style.visibility = 'hidden'; } return style; }; var childrenProps = { theme: toolbarPropsState.theme.buttonStyles, getEditorState: toolbarPropsState.store.getItem('getEditorState'), setEditorState: toolbarPropsState.store.getItem('setEditorState'), onOverrideContent: onOverrideContent }; useEffect(function () { toolbarPropsState.store.subscribeToItem('selection', onSelectionChanged); }, []); useEffect(function () { return function () { toolbarPropsState.store.unsubscribeFromItem('selection', onSelectionChanged); }; }, []); var OverrideContent = toolbarPropsState.overrideContent; return /*#__PURE__*/React.createElement("div", { className: toolbarPropsState.theme.toolbarStyles.toolbar, style: getStyle(), ref: toolbar }, OverrideContent ? /*#__PURE__*/React.createElement(OverrideContent, childrenProps) : /*#__PURE__*/React.createElement(React.Fragment, null, children ? children(childrenProps) : /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(ItalicButton, childrenProps), /*#__PURE__*/React.createElement(BoldButton, childrenProps), /*#__PURE__*/React.createElement(UnderlineButton, childrenProps), /*#__PURE__*/React.createElement(CodeButton, childrenProps)))); }; var Toolbar$1 = Toolbar; var separator = "s1o2cezu"; function Seperator(_ref) { var _ref$className = _ref.className, className = _ref$className === void 0 ? separator : _ref$className; return /*#__PURE__*/React.createElement("div", { className: className }); } var buttonStyles = { buttonWrapper: "bpsgbes", button: "b181v2oy", active: "a9immln" }; var toolbarStyles = { toolbar: "tukdd6b" }; var defaultTheme = { buttonStyles: buttonStyles, toolbarStyles: toolbarStyles }; var index = (function (config) { if (config === void 0) { config = {}; } var store = createStore({ isVisible: false }); var _config = config, _config$theme = _config.theme, theme = _config$theme === void 0 ? defaultTheme : _config$theme; var InlineToolbar = function InlineToolbar(props) { return /*#__PURE__*/React.createElement(Toolbar$1, _extends({}, props, { store: store, theme: theme })); }; return { initialize: function initialize(_ref) { var getEditorState = _ref.getEditorState, setEditorState = _ref.setEditorState, getEditorRef = _ref.getEditorRef; store.updateItem('getEditorState', getEditorState); store.updateItem('setEditorState', setEditorState); store.updateItem('getEditorRef', getEditorRef); }, // Re-Render the text-toolbar on selection change onChange: function onChange(editorState) { store.updateItem('selection', editorState.getSelection()); return editorState; }, InlineToolbar: InlineToolbar }; }); export { Seperator as Separator, index as default };