import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
import { $getSelection, $isElementNode, $isRangeSelection, $isTextNode, COMMAND_PRIORITY_CRITICAL, INSERT_PARAGRAPH_COMMAND, } from 'lexical';
import { $isListItemNode } from '@lexical/list';
import { $getSelectionStyleValueForProperty, $patchStyleText, getCSSFromStyleObject, getStyleObjectFromCSS, } from '@lexical/selection';
import { useEffect } from 'react';
/**
 * Extracts font size from a CSS style string.
 * @param style CSS style text to parse.
 * @returns Font size value, or an empty string when absent.
 */
function getFontSizeFromStyle(style) {
    var _a;
    return ((_a = getStyleObjectFromCSS(style)) === null || _a === void 0 ? void 0 : _a['font-size']) || '';
}
/**
 * Gets the font size that should be preserved for a collapsed selection.
 * @returns Font size value, or an empty string when no font size is available.
 */
function getCollapsedSelectionFontSize() {
    const selection = $getSelection();
    if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
        return '';
    }
    const selectionFontSize = $getSelectionStyleValueForProperty(selection, 'font-size', '');
    if (selectionFontSize) {
        return selectionFontSize;
    }
    const anchor = selection.anchor;
    const anchorNode = anchor.getNode();
    if ($isTextNode(anchorNode)) {
        return getFontSizeFromStyle(anchorNode.getStyle());
    }
    if ($isElementNode(anchorNode)) {
        const previousNode = anchor.offset > 0 ? anchorNode.getChildAtIndex(anchor.offset - 1) : null;
        const nextNode = anchorNode.getChildAtIndex(anchor.offset);
        if ($isTextNode(previousNode)) {
            return getFontSizeFromStyle(previousNode.getStyle());
        }
        if ($isTextNode(nextNode)) {
            return getFontSizeFromStyle(nextNode.getStyle());
        }
    }
    return '';
}
/**
 * Checks whether the current selection is inside an empty list item.
 * @returns True when the collapsed selection is in an empty list item.
 */
function isSelectionInEmptyListItem() {
    const selection = $getSelection();
    if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
        return false;
    }
    const anchorNode = selection.anchor.getNode();
    if ($isListItemNode(anchorNode) && anchorNode.getChildrenSize() === 0) {
        return true;
    }
    if (!$isTextNode(anchorNode)) {
        return false;
    }
    const parent = anchorNode.getParent();
    return ($isListItemNode(parent) &&
        parent.getChildren().every((node) => $isTextNode(node) && node.getTextContent().trim() === ''));
}
/**
 * Syncs the inserted block and collapsed selection to a font size after Lexical handles list exit.
 * @param editor Active Lexical editor.
 * @param fontSize Font size that should drive the next caret height.
 */
function syncListExitFontSize(editor, fontSize) {
    const applyFontSize = () => {
        editor.update(() => {
            const selection = $getSelection();
            if (!$isRangeSelection(selection) || !selection.isCollapsed()) {
                return;
            }
            const anchorNode = selection.anchor.getNode();
            const targetNode = $isElementNode(anchorNode)
                ? anchorNode
                : $isTextNode(anchorNode)
                    ? anchorNode.getTopLevelElement()
                    : null;
            if (!$isElementNode(targetNode)) {
                return;
            }
            const targetNodeKey = targetNode.getKey();
            const blockStyles = getStyleObjectFromCSS(targetNode.getStyle());
            const fontSizeStyle = getCSSFromStyleObject({ 'font-size': fontSize });
            targetNode.setStyle(getCSSFromStyleObject({
                ...blockStyles,
                'font-size': fontSize,
            }));
            targetNode.setTextStyle(fontSizeStyle);
            $patchStyleText(selection, {
                'font-size': fontSize,
            });
            const applyFontSizeToElement = () => {
                const targetElement = editor.getElementByKey(targetNodeKey);
                targetElement === null || targetElement === void 0 ? void 0 : targetElement.style.setProperty('font-size', fontSize);
            };
            if (typeof queueMicrotask === 'function') {
                queueMicrotask(applyFontSizeToElement);
            }
            requestAnimationFrame(applyFontSizeToElement);
        });
    };
    if (typeof queueMicrotask === 'function') {
        queueMicrotask(applyFontSize);
    }
    else {
        setTimeout(applyFontSize);
    }
}
/**
 * Preserves font size when inserting a paragraph with Enter.
 * @returns Null because the plugin renders no UI.
 */
export default function PreserveFontSizeOnEnterPlugin() {
    const [editor] = useLexicalComposerContext();
    useEffect(() => {
        return editor.registerCommand(INSERT_PARAGRAPH_COMMAND, () => {
            const selection = $getSelection();
            const fontSize = getCollapsedSelectionFontSize();
            if (!$isRangeSelection(selection) || !selection.isCollapsed() || !fontSize) {
                return false;
            }
            if (isSelectionInEmptyListItem()) {
                syncListExitFontSize(editor, fontSize);
                return false;
            }
            const insertedBlock = selection.insertParagraph();
            if ($isElementNode(insertedBlock)) {
                const insertedBlockKey = insertedBlock.getKey();
                const blockStyles = getStyleObjectFromCSS(insertedBlock.getStyle());
                const fontSizeStyle = getCSSFromStyleObject({ 'font-size': fontSize });
                insertedBlock.setStyle(getCSSFromStyleObject({
                    ...blockStyles,
                    'font-size': fontSize,
                }));
                insertedBlock.setTextStyle(fontSizeStyle);
                insertedBlock.selectStart();
                const applyFontSizeToInsertedElement = () => {
                    const insertedElement = editor.getElementByKey(insertedBlockKey);
                    insertedElement === null || insertedElement === void 0 ? void 0 : insertedElement.style.setProperty('font-size', fontSize);
                };
                if (typeof queueMicrotask === 'function') {
                    queueMicrotask(applyFontSizeToInsertedElement);
                }
                requestAnimationFrame(applyFontSizeToInsertedElement);
            }
            const nextSelection = $getSelection();
            if ($isRangeSelection(nextSelection) && nextSelection.isCollapsed()) {
                $patchStyleText(nextSelection, {
                    'font-size': fontSize,
                });
            }
            return true;
        }, COMMAND_PRIORITY_CRITICAL);
    }, [editor]);
    return null;
}
//# sourceMappingURL=index.js.map