"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = ToolbarPlugin;
const tslib_1 = require("tslib");
const link_1 = require("@lexical/link");
const list_1 = require("@lexical/list");
const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
const rich_text_1 = require("@lexical/rich-text");
const selection_1 = require("@lexical/selection");
const utils_1 = require("@lexical/utils");
const lexical_1 = require("lexical");
const react_1 = require("react");
const React = tslib_1.__importStar(require("react"));
const getSelectedNode_1 = require("../../utils/getSelectedNode");
const url_1 = require("../../utils/url");
const heading_1 = tslib_1.__importStar(require("./components/heading"));
const font_size_1 = tslib_1.__importDefault(require("./components/font-size"));
const bold_text_1 = tslib_1.__importDefault(require("./components/bold-text"));
const italic_text_1 = tslib_1.__importDefault(require("./components/italic-text"));
const underline_text_1 = tslib_1.__importDefault(require("./components/underline-text"));
const text_color_1 = tslib_1.__importDefault(require("./components/text-color"));
const text_align_1 = tslib_1.__importDefault(require("./components/text-align"));
const bullet_1 = tslib_1.__importDefault(require("./components/bullet"));
const number_bullet_1 = tslib_1.__importDefault(require("./components/number-bullet"));
const upload_pdf_1 = tslib_1.__importDefault(require("./components/upload-pdf"));
const upload_image_1 = tslib_1.__importDefault(require("./components/upload-image"));
const link_2 = tslib_1.__importDefault(require("./components/link"));
const ImageNode_1 = require("../../nodes/ImageNode");
const InlineImageNode_1 = require("../../nodes/InlineImageNode");
const blockTypeToBlockName = {
    bullet: 'Bulleted List',
    check: 'Check List',
    code: 'Code Block',
    h1: 'Heading 1',
    h2: 'Heading 2',
    h3: 'Heading 3',
    h4: 'Heading 4',
    h5: 'Heading 5',
    h6: 'Heading 6',
    number: 'Numbered List',
    paragraph: 'Normal',
    quote: 'Quote',
};
/**
 * Checks whether a block type is a heading type.
 * @param value Block type to test.
 * @returns True when the value is a heading block type.
 */
function isHeadingBlockType(value) {
    return value in heading_1.DEFAULT_HEADING_FONT_SIZES;
}
/**
 * Gets the fallback block type represented by a list item font size.
 * @param fontSize Font size from the selected list item.
 * @returns Matching heading type, or paragraph when there is no match.
 */
function getBlockTypeFromFontSize(fontSize) {
    var _a;
    const headingType = (_a = Object.entries(heading_1.DEFAULT_HEADING_FONT_SIZES).find(([, size]) => size === fontSize)) === null || _a === void 0 ? void 0 : _a[0];
    return headingType !== undefined ? headingType : 'paragraph';
}
/**
 * Reads font size from a serialized style string.
 * @param style Serialized CSS style string.
 * @returns Font size value when present.
 */
function getFontSizeFromStyle(style) {
    return (0, selection_1.getStyleObjectFromCSS)(style)['font-size'];
}
function DisabledToolbarGroup({ children, disabled, }) {
    return (React.createElement("div", { className: disabled ? 'relative cursor-not-allowed opacity-40' : undefined },
        children,
        disabled && React.createElement("div", { className: 'absolute inset-0 z-10 cursor-not-allowed' })));
}
function ToolbarPlugin({ apiCdnUpload, disabled, }) {
    const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
    const [activeEditor, setActiveEditor] = (0, react_1.useState)(editor);
    const [blockType, setBlockType] = (0, react_1.useState)('paragraph');
    const [listBlockType, setListBlockType] = (0, react_1.useState)(null);
    const [fontSize, setFontSize] = (0, react_1.useState)('14px');
    const [fontColor, setFontColor] = (0, react_1.useState)('#000');
    const [elementFormat, setElementFormat] = (0, react_1.useState)('left');
    const [isImageSelected, setIsImageSelected] = (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 $updateToolbar = (0, react_1.useCallback)(() => {
        var _a;
        const selection = (0, lexical_1.$getSelection)();
        if ((0, lexical_1.$isNodeSelection)(selection)) {
            const node = selection.getNodes()[0];
            if ((0, ImageNode_1.$isImageNode)(node) || (0, InlineImageNode_1.$isInlineImageNode)(node)) {
                setIsImageSelected(true);
                setElementFormat((node.getPosition() || 'center'));
            }
            else {
                setIsImageSelected(false);
            }
            return;
        }
        if ((0, lexical_1.$isRangeSelection)(selection)) {
            setIsImageSelected(false);
            const anchorNode = selection.anchor.getNode();
            let element = anchorNode.getKey() === 'root'
                ? anchorNode
                : (0, utils_1.$findMatchingParent)(anchorNode, (e) => {
                    const parent = e.getParent();
                    return parent !== null && (0, lexical_1.$isRootOrShadowRoot)(parent);
                });
            if (element === null) {
                element = anchorNode.getTopLevelElementOrThrow();
            }
            const elementKey = element.getKey();
            const elementDOM = activeEditor.getElementByKey(elementKey);
            // Update text format
            setIsBold(selection.hasFormat('bold'));
            setIsItalic(selection.hasFormat('italic'));
            setIsUnderline(selection.hasFormat('underline'));
            // Update links
            const node = (0, getSelectedNode_1.getSelectedNode)(selection);
            const parent = node.getParent();
            if ((0, link_1.$isLinkNode)(parent) || (0, link_1.$isLinkNode)(node)) {
                setIsLink(true);
            }
            else {
                setIsLink(false);
            }
            const defaultFontSize = (0, rich_text_1.$isHeadingNode)(element) ? heading_1.DEFAULT_HEADING_FONT_SIZES[element.getTag()] : '14px';
            let selectionFontSize = (0, selection_1.$getSelectionStyleValueForProperty)(selection, 'font-size', defaultFontSize);
            if (elementDOM !== null) {
                const parentList = (0, utils_1.$getNearestNodeOfType)(anchorNode, list_1.ListNode);
                if (parentList !== null || (0, list_1.$isListNode)(element)) {
                    const listItemNode = (0, list_1.$isListItemNode)(anchorNode)
                        ? anchorNode
                        : (0, utils_1.$findMatchingParent)(anchorNode, (node) => (0, list_1.$isListItemNode)(node));
                    const selectedListItems = (0, heading_1.getSelectedListItems)(selection);
                    const firstSelectedListItem = (_a = selectedListItems.values().next().value) !== null && _a !== void 0 ? _a : listItemNode;
                    const listItemFontSize = (0, list_1.$isListItemNode)(firstSelectedListItem)
                        ? getFontSizeFromStyle(firstSelectedListItem.getTextStyle())
                        : undefined;
                    const listItemBlockType = (0, list_1.$isListItemNode)(firstSelectedListItem)
                        ? (0, heading_1.getListItemBlockType)(firstSelectedListItem)
                        : null;
                    // @ts-ignore
                    const type = parentList ? parentList.getListType() : element.getListType();
                    if (listItemFontSize !== undefined && !selection.isCollapsed()) {
                        selectionFontSize = listItemFontSize;
                    }
                    setListBlockType(type);
                    setBlockType(listItemBlockType !== null && listItemBlockType !== void 0 ? listItemBlockType : getBlockTypeFromFontSize(selectionFontSize));
                }
                else {
                    setListBlockType(null);
                    const type = (0, rich_text_1.$isHeadingNode)(element) ? element.getTag() : element.getType();
                    if (type in blockTypeToBlockName) {
                        setBlockType(type);
                    }
                }
            }
            // Handle buttons
            setFontSize(selectionFontSize);
            setFontColor((0, selection_1.$getSelectionStyleValueForProperty)(selection, 'color', '#000'));
            let matchingParent;
            if ((0, link_1.$isLinkNode)(parent)) {
                // If node is a link, we need to fetch the parent paragraph node to set format
                matchingParent = (0, utils_1.$findMatchingParent)(node, (parentNode) => (0, lexical_1.$isElementNode)(parentNode) && !parentNode.isInline());
            }
            // If matchingParent is a valid node, pass it's format type
            setElementFormat((0, lexical_1.$isElementNode)(matchingParent)
                ? matchingParent.getFormatType()
                : (0, lexical_1.$isElementNode)(node)
                    ? node.getFormatType()
                    : (parent === null || parent === void 0 ? void 0 : parent.getFormatType()) || 'left');
        }
    }, [activeEditor]);
    (0, react_1.useEffect)(() => activeEditor.registerCommand(lexical_1.SELECTION_CHANGE_COMMAND, (_payload, newEditor) => {
        $updateToolbar();
        setActiveEditor(newEditor);
        return false;
    }, lexical_1.COMMAND_PRIORITY_CRITICAL), [activeEditor, $updateToolbar]);
    (0, react_1.useEffect)(() => (0, utils_1.mergeRegister)(activeEditor.registerUpdateListener(({ editorState }) => {
        editorState.read(() => {
            $updateToolbar();
        });
    })), [$updateToolbar, activeEditor]);
    (0, react_1.useEffect)(() => activeEditor.registerCommand(lexical_1.KEY_MODIFIER_COMMAND, (payload) => {
        const event = payload;
        const { code, ctrlKey, metaKey } = event;
        if (code === 'KeyK' && (ctrlKey || metaKey)) {
            event.preventDefault();
            return activeEditor.dispatchCommand(link_1.TOGGLE_LINK_COMMAND, (0, url_1.sanitizeUrl)('https://'));
        }
        return false;
    }, lexical_1.COMMAND_PRIORITY_NORMAL), [activeEditor, isLink]);
    (0, react_1.useEffect)(() => {
        if (!window.pdfjsLib) {
            const script = document.createElement('script');
            script.src = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js';
            document.body.appendChild(script);
        }
    }, []);
    (0, react_1.useEffect)(() => {
        if (activeEditor) {
            activeEditor.setEditable(!disabled);
        }
    }, [activeEditor, disabled]);
    const parsedFontSize = parseInt(fontSize, 10);
    const activeListHeadingTag = listBlockType !== null && isHeadingBlockType(blockType) ? blockType : null;
    return (React.createElement("div", { className: 'flex relative flex-wrap gap-1 p-2 bg-gray-100 border-b border-gray-300' },
        disabled && React.createElement("div", { className: 'cursor-not-allowed z-20 absolute inset-0 bg-gray-200 opacity-20' }),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected }, blockType in blockTypeToBlockName && activeEditor === editor && (React.createElement(heading_1.default, { value: blockType, editor: activeEditor }))),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(font_size_1.default, { editor: activeEditor, fontSize: Number.isNaN(parsedFontSize) ? null : parsedFontSize, listHeadingTag: activeListHeadingTag })),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(bold_text_1.default, { isActive: isBold, editor: activeEditor })),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(italic_text_1.default, { isActive: isItalic, editor: activeEditor })),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(underline_text_1.default, { isActive: isUnderline, editor: activeEditor })),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(text_color_1.default, { editor: activeEditor, color: fontColor })),
        React.createElement(text_align_1.default, { value: elementFormat, editor: activeEditor, isImageSelected: isImageSelected }),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(bullet_1.default, { isActive: listBlockType === 'bullet', editor: activeEditor })),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(number_bullet_1.default, { isActive: listBlockType === 'number', editor: activeEditor })),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(upload_pdf_1.default, { editor: activeEditor, apiCdnUpload: apiCdnUpload })),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(upload_image_1.default, { editor: activeEditor, apiCdnUpload: apiCdnUpload })),
        React.createElement(DisabledToolbarGroup, { disabled: isImageSelected },
            React.createElement(link_2.default, { editor: activeEditor }))));
}
//# sourceMappingURL=index.js.map