"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = FloatingTextFormatToolbarPlugin;
const tslib_1 = require("tslib");
const link_1 = require("@lexical/link");
const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
const utils_1 = require("@lexical/utils");
const lexical_1 = require("lexical");
const react_1 = require("react");
const React = tslib_1.__importStar(require("react"));
const react_dom_1 = require("react-dom");
const getDOMRangeRect_1 = require("../../utils/getDOMRangeRect");
const getSelectedNode_1 = require("../../utils/getSelectedNode");
const setFloatingElemPosition_1 = require("../../utils/setFloatingElemPosition");
function TextFormatFloatingToolbar({ anchorElem, editor, isBold, isCode, isItalic, isLink, isStrikethrough, isSubscript, isSuperscript, isUnderline, }) {
    const popupCharStylesEditorRef = (0, react_1.useRef)(null);
    const insertLink = (0, react_1.useCallback)(() => {
        if (!isLink) {
            editor.dispatchCommand(link_1.TOGGLE_LINK_COMMAND, 'https://');
        }
        else {
            editor.dispatchCommand(link_1.TOGGLE_LINK_COMMAND, null);
        }
    }, [editor, isLink]);
    const insertComment = () => {
        console.log('insert comment');
    };
    function mouseMoveListener(e) {
        if ((popupCharStylesEditorRef === null || popupCharStylesEditorRef === void 0 ? void 0 : popupCharStylesEditorRef.current) && (e.buttons === 1 || e.buttons === 3)) {
            if (popupCharStylesEditorRef.current.style.pointerEvents !== 'none') {
                const x = e.clientX;
                const y = e.clientY;
                const elementUnderMouse = document.elementFromPoint(x, y);
                if (!popupCharStylesEditorRef.current.contains(elementUnderMouse)) {
                    // Mouse is not over the target element => not a normal click, but probably a drag
                    popupCharStylesEditorRef.current.style.pointerEvents = 'none';
                }
            }
        }
    }
    function mouseUpListener() {
        if (popupCharStylesEditorRef === null || popupCharStylesEditorRef === void 0 ? void 0 : popupCharStylesEditorRef.current) {
            if (popupCharStylesEditorRef.current.style.pointerEvents !== 'auto') {
                popupCharStylesEditorRef.current.style.pointerEvents = 'auto';
            }
        }
    }
    (0, react_1.useEffect)(() => {
        if (popupCharStylesEditorRef === null || popupCharStylesEditorRef === void 0 ? void 0 : popupCharStylesEditorRef.current) {
            document.addEventListener('mousemove', mouseMoveListener);
            document.addEventListener('mouseup', mouseUpListener);
            return () => {
                document.removeEventListener('mousemove', mouseMoveListener);
                document.removeEventListener('mouseup', mouseUpListener);
            };
        }
        return () => {
            console.log('clean up');
        };
    }, [popupCharStylesEditorRef]);
    const updateTextFormatFloatingToolbar = (0, react_1.useCallback)(() => {
        const selection = (0, lexical_1.$getSelection)();
        const popupCharStylesEditorElem = popupCharStylesEditorRef.current;
        const nativeSelection = window.getSelection();
        if (popupCharStylesEditorElem === null) {
            return;
        }
        const rootElement = editor.getRootElement();
        if (selection !== null &&
            nativeSelection !== null &&
            !nativeSelection.isCollapsed &&
            rootElement !== null &&
            rootElement.contains(nativeSelection.anchorNode)) {
            const rangeRect = (0, getDOMRangeRect_1.getDOMRangeRect)(nativeSelection, rootElement);
            (0, setFloatingElemPosition_1.setFloatingElemPosition)(rangeRect, popupCharStylesEditorElem, anchorElem, isLink);
        }
    }, [editor, anchorElem, isLink]);
    (0, react_1.useEffect)(() => {
        const scrollerElem = anchorElem.parentElement;
        const update = () => {
            editor.getEditorState().read(() => {
                updateTextFormatFloatingToolbar();
            });
        };
        window.addEventListener('resize', update);
        if (scrollerElem) {
            scrollerElem.addEventListener('scroll', update);
        }
        return () => {
            window.removeEventListener('resize', update);
            if (scrollerElem) {
                scrollerElem.removeEventListener('scroll', update);
            }
        };
    }, [editor, updateTextFormatFloatingToolbar, anchorElem]);
    (0, react_1.useEffect)(() => {
        editor.getEditorState().read(() => {
            updateTextFormatFloatingToolbar();
        });
        return (0, utils_1.mergeRegister)(editor.registerUpdateListener(({ editorState }) => {
            editorState.read(() => {
                updateTextFormatFloatingToolbar();
            });
        }), editor.registerCommand(lexical_1.SELECTION_CHANGE_COMMAND, () => {
            updateTextFormatFloatingToolbar();
            return false;
        }, lexical_1.COMMAND_PRIORITY_LOW));
    }, [editor, updateTextFormatFloatingToolbar]);
    return (React.createElement("div", { ref: popupCharStylesEditorRef, className: 'floating-text-format-popup' },
        editor.isEditable() && (React.createElement(React.Fragment, null,
            React.createElement("button", { "aria-label": 'Format text as bold', className: 'popup-item spaced ' + (isBold ? 'active' : ''), onClick: () => {
                    editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'bold');
                }, type: 'button' },
                React.createElement("i", { className: 'format bold' })),
            React.createElement("button", { "aria-label": 'Format text as italics', className: 'popup-item spaced ' + (isItalic ? 'active' : ''), onClick: () => {
                    editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'italic');
                }, type: 'button' },
                React.createElement("i", { className: 'format italic' })),
            React.createElement("button", { "aria-label": 'Format text to underlined', className: 'popup-item spaced ' + (isUnderline ? 'active' : ''), onClick: () => {
                    editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'underline');
                }, type: 'button' },
                React.createElement("i", { className: 'format underline' })),
            React.createElement("button", { "aria-label": 'Format text with a strikethrough', className: 'popup-item spaced ' + (isStrikethrough ? 'active' : ''), onClick: () => {
                    editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'strikethrough');
                }, type: 'button' },
                React.createElement("i", { className: 'format strikethrough' })),
            React.createElement("button", { "aria-label": 'Format Subscript', className: 'popup-item spaced ' + (isSubscript ? 'active' : ''), onClick: () => {
                    editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'subscript');
                }, title: 'Subscript', type: 'button' },
                React.createElement("i", { className: 'format subscript' })),
            React.createElement("button", { "aria-label": 'Format Superscript', className: 'popup-item spaced ' + (isSuperscript ? 'active' : ''), onClick: () => {
                    editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'superscript');
                }, title: 'Superscript', type: 'button' },
                React.createElement("i", { className: 'format superscript' })),
            React.createElement("button", { "aria-label": 'Insert code block', className: 'popup-item spaced ' + (isCode ? 'active' : ''), onClick: () => {
                    editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'code');
                }, type: 'button' },
                React.createElement("i", { className: 'format code' })),
            React.createElement("button", { "aria-label": 'Insert link', className: 'popup-item spaced ' + (isLink ? 'active' : ''), onClick: insertLink, type: 'button' },
                React.createElement("i", { className: 'format link' })))),
        React.createElement("button", { "aria-label": 'Insert comment', className: 'popup-item spaced insert-comment', onClick: insertComment, type: 'button' },
            React.createElement("i", { className: 'format add-comment' }))));
}
function useFloatingTextFormatToolbar(editor, anchorElem) {
    const [isText, setIsText] = (0, react_1.useState)(false);
    const [isLink, setIsLink] = (0, react_1.useState)(false);
    const [isBold, setIsBold] = (0, react_1.useState)(false);
    const [isItalic, setIsItalic] = (0, react_1.useState)(false);
    const [isUnderline, setIsUnderline] = (0, react_1.useState)(false);
    const [isStrikethrough, setIsStrikethrough] = (0, react_1.useState)(false);
    const [isSubscript, setIsSubscript] = (0, react_1.useState)(false);
    const [isSuperscript, setIsSuperscript] = (0, react_1.useState)(false);
    const [isCode, setIsCode] = (0, react_1.useState)(false);
    const updatePopup = (0, react_1.useCallback)(() => {
        editor.getEditorState().read(() => {
            // Should not to pop up the floating toolbar when using IME input
            if (editor.isComposing()) {
                return;
            }
            const selection = (0, lexical_1.$getSelection)();
            const nativeSelection = window.getSelection();
            const rootElement = editor.getRootElement();
            if (nativeSelection !== null &&
                (!(0, lexical_1.$isRangeSelection)(selection) || rootElement === null || !rootElement.contains(nativeSelection.anchorNode))) {
                setIsText(false);
                return;
            }
            if (!(0, lexical_1.$isRangeSelection)(selection)) {
                return;
            }
            const node = (0, getSelectedNode_1.getSelectedNode)(selection);
            // Update text format
            setIsBold(selection.hasFormat('bold'));
            setIsItalic(selection.hasFormat('italic'));
            setIsUnderline(selection.hasFormat('underline'));
            setIsStrikethrough(selection.hasFormat('strikethrough'));
            setIsSubscript(selection.hasFormat('subscript'));
            setIsSuperscript(selection.hasFormat('superscript'));
            setIsCode(selection.hasFormat('code'));
            // Update links
            const parent = node.getParent();
            if ((0, link_1.$isLinkNode)(parent) || (0, link_1.$isLinkNode)(node)) {
                setIsLink(true);
            }
            else {
                setIsLink(false);
            }
            if (selection.getTextContent() !== '') {
                setIsText((0, lexical_1.$isTextNode)(node) || (0, lexical_1.$isParagraphNode)(node));
            }
            else {
                setIsText(false);
            }
            const rawTextContent = selection.getTextContent().replace(/\n/g, '');
            if (!selection.isCollapsed() && rawTextContent === '') {
                setIsText(false);
                return;
            }
        });
    }, [editor]);
    (0, react_1.useEffect)(() => {
        document.addEventListener('selectionchange', updatePopup);
        return () => {
            document.removeEventListener('selectionchange', updatePopup);
        };
    }, [updatePopup]);
    (0, react_1.useEffect)(() => (0, utils_1.mergeRegister)(editor.registerUpdateListener(() => {
        updatePopup();
    }), editor.registerRootListener(() => {
        if (editor.getRootElement() === null) {
            setIsText(false);
        }
    })), [editor, updatePopup]);
    if (!isText) {
        return null;
    }
    return (0, react_dom_1.createPortal)(React.createElement(TextFormatFloatingToolbar, { anchorElem: anchorElem, editor: editor, isBold: isBold, isCode: isCode, isItalic: isItalic, isLink: isLink, isStrikethrough: isStrikethrough, isSubscript: isSubscript, isSuperscript: isSuperscript, isUnderline: isUnderline }), anchorElem);
}
function FloatingTextFormatToolbarPlugin({ anchorElem = document.body, }) {
    const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
    return useFloatingTextFormatToolbar(editor, anchorElem);
}
//# sourceMappingURL=index.js.map