UNPKG

@lobehub/editor

Version:

A powerful and extensible rich text editor built on Meta's Lexical framework, providing a modern editing experience with React integration.

140 lines 6.81 kB
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } import { mergeRegister } from '@lexical/utils'; import { Block } from '@lobehub/ui'; import { cx, useThemeMode } from 'antd-style'; import { $getSelection, COMMAND_PRIORITY_LOW, SELECTION_CHANGE_COMMAND, getDOMSelection } from 'lexical'; import { useCallback, useRef } from 'react'; import { useLexicalComposerContext, useLexicalEditor } from "../../../editor-kernel/react"; import { ILinkService } from "../../link"; import { createDebugLogger } from "../../../utils/debug"; import { HIDE_TOOLBAR_COMMAND, registerToolbarCommand } from "../command"; import { getDOMRangeRect } from "../utils/getDOMRangeRect"; import { setFloatingElemPosition } from "../utils/setFloatingElemPosition"; import { styles } from "./style"; import { jsx as _jsx } from "react/jsx-runtime"; export var ReactToolbarPlugin = function ReactToolbarPlugin(_ref) { var className = _ref.className, children = _ref.children; var popupCharStylesEditorRef = useRef(null); var anchorElemRef = useRef(null); var _useLexicalComposerCo = useLexicalComposerContext(), _useLexicalComposerCo2 = _slicedToArray(_useLexicalComposerCo, 1), kernelEditor = _useLexicalComposerCo2[0]; var _useThemeMode = useThemeMode(), isDarkMode = _useThemeMode.isDarkMode; var isMouseDownRef = useRef(false); var logger = createDebugLogger('plugin', 'toolbar'); var $updateTextFormatFloatingToolbar = useCallback(function (editor) { if (!anchorElemRef.current) { return; } var selection = $getSelection(); var popupCharStylesEditorElem = popupCharStylesEditorRef.current; var nativeSelection = getDOMSelection(editor._window); if (popupCharStylesEditorElem === null) { return; } var rootElement = editor.getRootElement(); if (selection !== null && nativeSelection !== null && !nativeSelection.isCollapsed && rootElement !== null && rootElement.contains(nativeSelection.anchorNode)) { var rangeRect = getDOMRangeRect(nativeSelection, rootElement); logger.debug('🔍 rangeRect', rangeRect); setFloatingElemPosition(rangeRect, popupCharStylesEditorElem, anchorElemRef.current, false); } else { popupCharStylesEditorElem.style.opacity = '0'; popupCharStylesEditorElem.style.transform = 'translate(-10000px, -10000px)'; } }, [anchorElemRef]); var $hideFloatingToolbar = useCallback(function () { if (!anchorElemRef.current) { return; } var popupCharStylesEditorElem = popupCharStylesEditorRef.current; if (popupCharStylesEditorElem === null) { return; } popupCharStylesEditorElem.style.opacity = '0'; popupCharStylesEditorElem.style.transform = 'translate(-10000px, -10000px)'; }, [anchorElemRef]); var handleMouseDownFactory = useCallback(function (updateToolbar) { return function (e) { if (e.button === 0) { // 0 is left mouse button isMouseDownRef.current = true; // Update toolbar when mouse is released updateToolbar(); } }; }, []); var handleMouseUpFactory = useCallback(function (updateToolbar) { return function (e) { if (e.button === 0) { // 0 is left mouse button isMouseDownRef.current = false; // Update toolbar when mouse is released updateToolbar(); } }; }, []); useLexicalEditor(function () { var service = kernelEditor.requireService(ILinkService); if (service) { service.setLinkToolbar(false); return function () { service.setLinkToolbar(true); }; } }, []); useLexicalEditor(function (editor) { var handleMouseDown = handleMouseDownFactory(function () { editor.dispatchCommand(HIDE_TOOLBAR_COMMAND, undefined); }); var handleMouseUp = handleMouseUpFactory(function () { editor.update(function () { $updateTextFormatFloatingToolbar(editor); }); }); var rootElement = editor.getRootElement(); if (rootElement) { rootElement.addEventListener('mousedown', handleMouseDown); document.addEventListener('mouseup', handleMouseUp); } return mergeRegister(registerToolbarCommand(editor, { onHide: $hideFloatingToolbar }), editor.registerUpdateListener(function (_ref2) { var editorState = _ref2.editorState; // Only update when mouse is not pressed if (!isMouseDownRef.current) { editorState.read(function () { $updateTextFormatFloatingToolbar(editor); }); } }), editor.registerCommand(SELECTION_CHANGE_COMMAND, function () { // Only update when mouse is not pressed if (!isMouseDownRef.current) { $updateTextFormatFloatingToolbar(editor); } return false; }, COMMAND_PRIORITY_LOW), function () { if (rootElement) { rootElement.removeEventListener('mousedown', handleMouseDown); document.removeEventListener('mouseup', handleMouseUp); } }); }); return /*#__PURE__*/_jsx("div", { className: styles.anchor, ref: anchorElemRef, children: /*#__PURE__*/_jsx(Block, { className: cx(isDarkMode ? styles.toolbarDark : styles.toolbarLight, className), padding: 4, ref: popupCharStylesEditorRef, variant: 'outlined', children: children }) }); };