"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = __importStar(require("react"));
const react_dom_1 = require("react-dom");
const focusElement_1 = __importDefault(require("../lib/helpers/focusElement"));
const getCursorOffset_1 = __importDefault(require("../lib/helpers/caret/getCursorOffset"));
const isElementFocused_1 = __importDefault(require("../lib/helpers/isElementFocused"));
const isElementEditable_1 = __importDefault(require("../lib/helpers/isElementEditable"));
const ContentEditable = (props) => {
    const { children, disabled, className, style, innerRef, onChange, onBeforeChange, onKeyDown } = props;
    const caretPosition = (0, react_1.useRef)(null);
    const missedCharacters = (0, react_1.useRef)('');
    const [childrenPortals, setChildrenPortals] = react_1.default.useState([]);
    const caretUpdater = () => {
        if (!innerRef.current)
            return;
        innerRef.current.style.caretColor = 'auto';
        if (caretPosition.current === null)
            return;
        (0, focusElement_1.default)(innerRef.current, caretPosition.current);
        caretPosition.current = null;
    };
    (0, react_1.useEffect)(() => {
        const caretFixer = () => {
            if (!innerRef.current)
                return;
            if (!(0, isElementFocused_1.default)(innerRef.current))
                return;
            const caretOffset = (0, getCursorOffset_1.default)(innerRef.current);
            if (caretOffset <= innerRef.current.innerText.length)
                return;
            caretPosition.current = caretOffset;
            (0, focusElement_1.default)(innerRef.current, caretOffset);
        };
        document.addEventListener('selectionchange', caretFixer);
        document.addEventListener('selectionchange', caretUpdater);
        return () => {
            document.removeEventListener('selectionchange', caretFixer);
            document.removeEventListener('selectionchange', caretUpdater);
        };
    }, [innerRef.current]);
    (0, react_1.useEffect)(() => {
        if (!innerRef.current)
            return;
        if ((0, isElementFocused_1.default)(innerRef.current)) {
            caretPosition.current = (0, getCursorOffset_1.default)(innerRef.current);
            innerRef.current.style.caretColor = 'transparent';
        }
        innerRef.current.innerHTML = '';
        const arrayChildren = Array.isArray(children) ? children : [children];
        const childrenPortals = arrayChildren
            .map((child, index) => {
            if (!innerRef.current)
                return;
            const childWrapperElement = document.createElement('span');
            innerRef.current.appendChild(childWrapperElement);
            const parsedChild = typeof child === 'string' ? (<span key={index}>
            {child}
          </span>) : child;
            return (0, react_dom_1.createPortal)(parsedChild, childWrapperElement);
        });
        setChildrenPortals(childrenPortals);
        setTimeout(() => {
            caretUpdater();
        });
    }, [children, innerRef.current]);
    return (<span ref={innerRef} onClick={(e) => {
            var _a, _b, _c, _d, _e;
            if (!((_a = document.getSelection()) === null || _a === void 0 ? void 0 : _a.getRangeAt(0).collapsed))
                return;
            const targetedElement = e.target;
            const secondLastElement = (_b = innerRef.current) === null || _b === void 0 ? void 0 : _b.childNodes[((_c = innerRef.current) === null || _c === void 0 ? void 0 : _c.childNodes.length) - 2];
            const isSecondLastElementEditable = (0, isElementEditable_1.default)(secondLastElement);
            if (targetedElement === innerRef.current) {
                const offset = isSecondLastElementEditable ? 1 : 0;
                (0, focusElement_1.default)(innerRef.current, (((_d = innerRef.current.textContent) === null || _d === void 0 ? void 0 : _d.length) || offset) - offset);
            }
            const isTargetedElementEditable = targetedElement.isContentEditable;
            const isTargetedElementLast = secondLastElement === null || secondLastElement === void 0 ? void 0 : secondLastElement.contains(targetedElement);
            if (!isTargetedElementLast
                || isTargetedElementEditable
                || !innerRef.current)
                return;
            const targetedBoundingBox = targetedElement.getBoundingClientRect();
            const isNearEndOfElement = (targetedBoundingBox.x + targetedBoundingBox.width) <= e.clientX + 3;
            if (!isNearEndOfElement)
                return;
            (0, focusElement_1.default)(innerRef.current, ((_e = innerRef.current.textContent) === null || _e === void 0 ? void 0 : _e.length) || 0);
        }} contentEditable={!disabled} suppressContentEditableWarning onBeforeInput={(event) => {
            if (onBeforeChange)
                onBeforeChange(event);
            if (!caretPosition.current)
                return;
            console.error('Cursor fatally out of sync, preventing input event');
            missedCharacters.current += event.data || '';
            event.preventDefault();
            event.stopPropagation();
        }} onKeyDown={onKeyDown} onInput={(event) => {
            var _a;
            if (!innerRef.current)
                return;
            caretPosition.current = (0, getCursorOffset_1.default)(innerRef.current);
            ;
            innerRef.current.style.caretColor = 'transparent';
            if (missedCharacters.current && innerRef.current.textContent) {
                console.error('Characters out of sync, attempting to recover');
                const currentInlineBlock = (_a = document.getSelection()) === null || _a === void 0 ? void 0 : _a.anchorNode;
                if (!(currentInlineBlock === null || currentInlineBlock === void 0 ? void 0 : currentInlineBlock.textContent))
                    return;
                const before = currentInlineBlock.textContent.slice(0, caretPosition.current - 1);
                const after = currentInlineBlock.textContent.slice(caretPosition.current - 1);
                currentInlineBlock.textContent = before + missedCharacters.current + after;
                caretPosition.current += missedCharacters.current.length;
                missedCharacters.current = '';
            }
            onChange(event);
        }} className={className} style={style}>
      {childrenPortals}
    </span>);
};
exports.default = ContentEditable;
//# sourceMappingURL=ContentEditable.jsx.map