"use strict";
var __webpack_require__ = {};
(()=>{
    __webpack_require__.n = function(module) {
        var getter = module && module.__esModule ? function() {
            return module['default'];
        } : function() {
            return module;
        };
        __webpack_require__.d(getter, {
            a: getter
        });
        return getter;
    };
})();
(()=>{
    __webpack_require__.d = function(exports1, definition) {
        for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
            enumerable: true,
            get: definition[key]
        });
    };
})();
(()=>{
    __webpack_require__.o = function(obj, prop) {
        return Object.prototype.hasOwnProperty.call(obj, prop);
    };
})();
(()=>{
    __webpack_require__.r = function(exports1) {
        if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
            value: 'Module'
        });
        Object.defineProperty(exports1, '__esModule', {
            value: true
        });
    };
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
    TextArea: ()=>TextArea
});
const jsx_runtime_namespaceObject = require("react/jsx-runtime");
const external_react_namespaceObject = require("react");
const schema_namespaceObject = require("@tachybase/schema");
const client_namespaceObject = require("@tachybase/utils/client");
const external_antd_namespaceObject = require("antd");
const external_classnames_namespaceObject = require("classnames");
var external_classnames_default = /*#__PURE__*/ __webpack_require__.n(external_classnames_namespaceObject);
const external_lodash_namespaceObject = require("lodash");
const external_sanitize_html_namespaceObject = require("sanitize-html");
var external_sanitize_html_default = /*#__PURE__*/ __webpack_require__.n(external_sanitize_html_namespaceObject);
const external_index_js_namespaceObject = require("../../index.js");
const external_style_js_namespaceObject = require("./style.js");
const external_VariableSelect_js_namespaceObject = require("./VariableSelect.js");
const VARIABLE_RE = /{{\s*([^{}]+)\s*}}/g;
function pasteHTML(container, html) {
    let { selectPastedContent = false, range: indexes } = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {};
    var _window_getSelection, _window;
    const sel = null === (_window_getSelection = (_window = window).getSelection) || void 0 === _window_getSelection ? void 0 : _window_getSelection.call(_window);
    const range = null == sel ? void 0 : sel.getRangeAt(0);
    if (!range) return;
    if (indexes) {
        const children = Array.from(container.childNodes);
        if (-1 === indexes[0]) {
            if (indexes[1]) range.setStartAfter(children[indexes[1] - 1]);
            else range.setStart(container, 0);
        } else range.setStart(children[indexes[0]], indexes[1]);
        if (-1 === indexes[2]) {
            if (indexes[3]) range.setEndAfter(children[indexes[3] - 1]);
            else range.setEnd(container, 0);
        } else range.setEnd(children[indexes[2]], indexes[3]);
    }
    const el = document.createElement('div');
    el.innerHTML = html;
    const frag = document.createDocumentFragment();
    let lastNode;
    while(el.firstChild)lastNode = frag.appendChild(el.firstChild);
    const { firstChild } = frag;
    range.deleteContents();
    range.insertNode(frag);
    if (lastNode) {
        const next = new Range();
        next.setStartAfter(lastNode);
        if (selectPastedContent) {
            if (firstChild) next.setStartBefore(firstChild);
        } else next.collapse(true);
        sel.removeAllRanges();
        sel.addRange(next);
    }
}
function getValue(el) {
    const values = [];
    for (const node of el.childNodes)if ('SPAN' === node.nodeName && node['dataset']['variable']) values.push("{{".concat(node['dataset']['variable'], "}}"));
    else values.push(node.textContent);
    return values.join('');
}
function renderHTML(exp, keyLabelMap) {
    return exp.replace(VARIABLE_RE, (_, i)=>{
        const key = i.trim();
        var _createVariableTagHTML;
        return null !== (_createVariableTagHTML = createVariableTagHTML(key, keyLabelMap)) && void 0 !== _createVariableTagHTML ? _createVariableTagHTML : '';
    });
}
function createOptionsValueLabelMap(options) {
    const map = new Map();
    for (const option of options){
        map.set(option.value, [
            option.label
        ]);
        if (option.children) for (const [value, labels] of createOptionsValueLabelMap(option.children))map.set("".concat(option.value, ".").concat(value), [
            option.label,
            ...labels
        ]);
    }
    return map;
}
function createVariableTagHTML(variable, keyLabelMap) {
    const labels = keyLabelMap.get(variable);
    return '<span class="ant-tag ant-tag-blue" contentEditable="false" data-variable="'.concat(variable, '">').concat(labels ? labels.join(' / ') : '...', "</span>");
}
function getSingleEndRange(nodes, index, offset) {
    if (-1 === index) {
        var _nodes_realIndex;
        let realIndex = offset;
        let collapseFlag = false;
        if (realIndex && '#text' === nodes[realIndex - 1].nodeName && (null === (_nodes_realIndex = nodes[realIndex]) || void 0 === _nodes_realIndex ? void 0 : _nodes_realIndex.nodeName) === '#text') collapseFlag = true;
        let textOffset = 0;
        for(let i = offset - 1; i >= 0; i--){
            var _nodes_;
            if (collapseFlag) {
                if ('#text' === nodes[i].nodeName) textOffset += nodes[i].textContent.length;
                else collapseFlag = false;
            }
            if ('#text' === nodes[i].nodeName && (null === (_nodes_ = nodes[i + 1]) || void 0 === _nodes_ ? void 0 : _nodes_.nodeName) === '#text') realIndex -= 1;
        }
        return textOffset ? [
            realIndex,
            textOffset
        ] : [
            -1,
            realIndex
        ];
    }
    {
        let realIndex = 0;
        let textOffset = 0;
        for(let i = 0; i < index + 1; i++)if ('#text' === nodes[i].nodeName) {
            if (i !== index && nodes[i + 1] && '#text' !== nodes[i + 1].nodeName) realIndex += 1;
            textOffset += i === index ? offset : nodes[i].textContent.length;
        } else {
            realIndex += 1;
            textOffset = 0;
        }
        return [
            realIndex,
            textOffset
        ];
    }
}
function getCurrentRange(element) {
    var _window_getSelection, _window;
    const sel = null === (_window_getSelection = (_window = window).getSelection) || void 0 === _window_getSelection ? void 0 : _window_getSelection.call(_window);
    const range = null == sel ? void 0 : sel.getRangeAt(0);
    if (!range) return [
        -1,
        0,
        -1,
        0
    ];
    const nodes = Array.from(element.childNodes);
    if (!nodes.length) return [
        -1,
        0,
        -1,
        0
    ];
    const startElementIndex = range.startContainer === element ? -1 : nodes.indexOf(range.startContainer);
    const endElementIndex = range.endContainer === element ? -1 : nodes.indexOf(range.endContainer);
    const result = [
        ...getSingleEndRange(nodes, startElementIndex, range.startOffset),
        ...getSingleEndRange(nodes, endElementIndex, range.endOffset)
    ];
    return result;
}
function TextArea(props) {
    const { value = '', scope, onChange, multiline = true, changeOnSelect } = props;
    const { styles } = (0, external_style_js_namespaceObject.useStyles)({
        multiline
    });
    const inputRef = (0, external_react_namespaceObject.useRef)(null);
    const [options, setOptions] = (0, external_react_namespaceObject.useState)([]);
    const form = (0, schema_namespaceObject.useForm)();
    const keyLabelMap = (0, external_react_namespaceObject.useMemo)(()=>createOptionsValueLabelMap(options), [
        options
    ]);
    const [ime, setIME] = (0, external_react_namespaceObject.useState)(false);
    const [changed, setChanged] = (0, external_react_namespaceObject.useState)(false);
    const [html, setHtml] = (0, external_react_namespaceObject.useState)(()=>renderHTML(null != value ? value : '', keyLabelMap));
    const [range, setRange] = (0, external_react_namespaceObject.useState)([
        -1,
        0,
        -1,
        0
    ]);
    (0, external_react_namespaceObject.useEffect)(()=>{
        preloadOptions(scope, value).then((preloaded)=>{
            setOptions(preloaded);
        }).catch((err)=>console.error);
    }, [
        scope,
        value
    ]);
    (0, external_react_namespaceObject.useEffect)(()=>{
        setHtml(renderHTML(null != value ? value : '', keyLabelMap));
        if (!changed) setRange([
            -1,
            0,
            -1,
            0
        ]);
    }, [
        value,
        keyLabelMap
    ]);
    (0, external_react_namespaceObject.useEffect)(()=>{
        const { current } = inputRef;
        if (!current) return;
        const nextRange = new Range();
        if (changed) {
            var _window_getSelection, _window;
            if ('-1,0,-1,0' === range.join()) return;
            const sel = null === (_window_getSelection = (_window = window).getSelection) || void 0 === _window_getSelection ? void 0 : _window_getSelection.call(_window);
            if (sel) try {
                const children = Array.from(current.childNodes);
                if (children.length) {
                    if (-1 === range[0]) {
                        if (range[1]) nextRange.setStartAfter(children[range[1] - 1]);
                    } else nextRange.setStart(children[range[0]], range[1]);
                    if (-1 === range[2]) {
                        if (range[3]) nextRange.setEndAfter(children[range[3] - 1]);
                    } else nextRange.setEnd(children[range[2]], range[3]);
                }
                nextRange.collapse(true);
                sel.removeAllRanges();
                sel.addRange(nextRange);
            } catch (ex) {}
        } else {
            const { lastChild } = current;
            if (lastChild) {
                nextRange.setStartAfter(lastChild);
                nextRange.setEndAfter(lastChild);
                const nodes = Array.from(current.childNodes);
                const startElementIndex = nextRange.startContainer === current ? -1 : nodes.indexOf(lastChild);
                const endElementIndex = nextRange.startContainer === current ? -1 : nodes.indexOf(lastChild);
                setRange([
                    startElementIndex,
                    nextRange.startOffset,
                    endElementIndex,
                    nextRange.endOffset
                ]);
            }
        }
    }, [
        html
    ]);
    const onInsert = (0, external_react_namespaceObject.useCallback)(function(paths) {
        const variable = paths.filter((key)=>Boolean(key.trim()));
        const { current } = inputRef;
        if (!current || !variable) return;
        current.focus();
        const content = createVariableTagHTML(variable.join('.'), keyLabelMap);
        pasteHTML(current, content, {
            range
        });
        setChanged(true);
        setRange(getCurrentRange(current));
        onChange(getValue(current));
    }, [
        keyLabelMap,
        onChange,
        range
    ]);
    const onInput = (0, external_react_namespaceObject.useCallback)(function(param) {
        let { currentTarget } = param;
        if (ime) return;
        setChanged(true);
        setRange(getCurrentRange(currentTarget));
        onChange(getValue(currentTarget));
    }, [
        ime,
        onChange
    ]);
    const onBlur = (0, external_react_namespaceObject.useCallback)(function(param) {
        let { currentTarget } = param;
        setRange(getCurrentRange(currentTarget));
    }, []);
    const onKeyDown = (0, external_react_namespaceObject.useCallback)(function(ev) {
        if ('Enter' === ev.key) ev.preventDefault();
    }, []);
    const onCompositionStart = (0, external_react_namespaceObject.useCallback)(function() {
        setIME(true);
    }, []);
    const onCompositionEnd = (0, external_react_namespaceObject.useCallback)((param)=>{
        let { currentTarget } = param;
        setIME(false);
        setChanged(true);
        setRange(getCurrentRange(currentTarget));
        onChange(getValue(currentTarget));
    }, [
        onChange
    ]);
    const onPaste = (0, external_react_namespaceObject.useCallback)(function(ev) {
        ev.preventDefault();
        const input = ev.clipboardData.getData('text/html') || ev.clipboardData.getData('text');
        const sanitizedHTML = external_sanitize_html_default()(input, {
            allowedTags: [
                'span'
            ],
            allowedAttributes: {
                span: [
                    'data-variable',
                    'contenteditable'
                ]
            },
            allowedClasses: {
                span: [
                    'ant-tag',
                    'ant-tag-*'
                ]
            },
            transformTags: {
                span (tagName, attribs) {
                    return attribs['data-variable'] ? {
                        tagName: tagName,
                        attribs
                    } : {};
                }
            }
        }).replace(/\n/g, ' ');
        setChanged(true);
        pasteHTML(ev.currentTarget, sanitizedHTML);
        setRange(getCurrentRange(ev.currentTarget));
        onChange(getValue(ev.currentTarget));
    }, [
        onChange
    ]);
    const disabled = props.disabled || form.disabled;
    return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(external_antd_namespaceObject.Space.Compact, {
        className: external_classnames_default()(styles.fixInput, styles.outerContainer, styles.container),
        children: [
            /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("div", {
                role: "button",
                "aria-label": "textbox",
                onInput: onInput,
                onBlur: onBlur,
                onKeyDown: onKeyDown,
                onPaste: onPaste,
                onCompositionStart: onCompositionStart,
                onCompositionEnd: onCompositionEnd,
                className: external_classnames_default()('ant-input', {
                    'ant-input-disabled': disabled
                }, styles.button),
                ref: inputRef,
                contentEditable: !disabled,
                dangerouslySetInnerHTML: {
                    __html: html
                }
            }),
            disabled ? null : /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_VariableSelect_js_namespaceObject.VariableSelect, {
                className: "",
                options: options,
                setOptions: setOptions,
                onInsert: onInsert,
                changeOnSelect: changeOnSelect
            })
        ]
    });
}
async function preloadOptions(scope, value) {
    const options = (0, external_lodash_namespaceObject.cloneDeep)(null != scope ? scope : []);
    VARIABLE_RE.lastIndex = 0;
    for(let matcher; matcher = VARIABLE_RE.exec(null != value ? value : '');){
        const keys = matcher[1].split('.');
        let prevOption = null;
        for(let i = 0; i < keys.length; i++){
            const key = keys[i];
            try {
                if (0 === i) prevOption = options.find((item)=>item.value === key);
                else {
                    var _prevOption_children;
                    if (prevOption.loadChildren && !(null === (_prevOption_children = prevOption.children) || void 0 === _prevOption_children ? void 0 : _prevOption_children.length)) await prevOption.loadChildren(prevOption);
                    prevOption = prevOption.children.find((item)=>item.value === key);
                }
            } catch (err) {
                (0, client_namespaceObject.error)(err);
            }
        }
    }
    return options;
}
TextArea.ReadPretty = function(props) {
    const { value } = props;
    const scope = 'function' == typeof props.scope ? props.scope() : props.scope;
    const [options, setOptions] = (0, external_react_namespaceObject.useState)([]);
    const keyLabelMap = (0, external_react_namespaceObject.useMemo)(()=>createOptionsValueLabelMap(options), [
        options
    ]);
    const { styles } = (0, external_style_js_namespaceObject.useStyles)();
    (0, external_react_namespaceObject.useEffect)(()=>{
        preloadOptions(scope, value).then((preloaded)=>{
            setOptions(preloaded);
        }).catch(client_namespaceObject.error);
    }, [
        scope,
        value
    ]);
    const html = renderHTML(null != value ? value : '', keyLabelMap);
    const content = /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("span", {
        dangerouslySetInnerHTML: {
            __html: html
        },
        className: styles.pretty
    });
    return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_index_js_namespaceObject.EllipsisWithTooltip, {
        ellipsis: true,
        popoverContent: content,
        children: content
    });
};
var __webpack_export_target__ = exports;
for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__] = __webpack_exports__[__webpack_i__];
if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, '__esModule', {
    value: true
});
