UNPKG

@onesy/ui-react

Version:
1,030 lines 72.2 kB
"use strict";
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importDefault(require("react"));
const utils_1 = require("@onesy/utils");
const style_react_1 = require("@onesy/style-react");
const IconMaterialFormatAlignLeftW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatAlignLeftW100"));
const IconMaterialFormatAlignCenterW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatAlignCenterW100"));
const IconMaterialFormatAlignRightW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatAlignRightW100"));
const IconMaterialFormatAlignJustifyW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatAlignJustifyW100"));
const IconMaterialFormatColorTextW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatColorTextW100"));
const IconMaterialFormatColorFillW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatColorFillW100"));
const IconMaterialFormatListNumberedW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatListNumberedW100"));
const IconMaterialFormatListBulletedW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatListBulletedW100"));
const IconMaterialSuperscriptW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialSuperscriptW100"));
const IconMaterialSubscriptW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialSubscriptW100"));
const IconMaterialFormatItalicW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatItalicW100"));
const IconMaterialFormatUnderlinedW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatUnderlinedW100"));
const IconMaterialStrikethroughSW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialStrikethroughSW100"));
const IconMaterialFormatBoldW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatBoldW100"));
const IconMaterialAddLinkW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialAddLinkW100"));
const IconMaterialLinkOffW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialLinkOffW100"));
const IconMaterialFormatClearW100_1 = __importDefault(require("@onesy/icons-material-rounded-react/IconMaterialFormatClearW100"));
const ColorTextField_1 = __importDefault(require("../ColorTextField"));
const TextField_1 = __importDefault(require("../TextField/TextField"));
const Line_1 = __importDefault(require("../Line"));
const List_1 = __importDefault(require("../List"));
const ListItem_1 = __importDefault(require("../ListItem"));
const Avatar_1 = __importDefault(require("../Avatar"));
const Type_1 = __importDefault(require("../Type"));
const Surface_1 = __importDefault(require("../Surface"));
const Button_1 = __importDefault(require("../Button"));
const Append_1 = __importDefault(require("../Append"));
const Fade_1 = __importDefault(require("../Fade"));
const Tooltip_1 = __importDefault(require("../Tooltip"));
const ToggleButton_1 = __importDefault(require("../ToggleButton"));
const ClickListener_1 = __importDefault(require("../ClickListener"));
const ToggleButtons_1 = __importDefault(require("../ToggleButtons"));
const Menu_1 = __importDefault(require("../Menu"));
const Divider_1 = __importDefault(require("../Divider"));
const utils_2 = require("../utils");
const useStyle = (0, style_react_1.style)(theme => ({
    root: {
        minHeight: '20px',
        width: '100%',
        '& .onesy-TextField-input': Object.assign({ wordBreak: 'break-word', color: theme.methods.palette.color.value('primary', 10) }, theme.typography.values.b2),
        '& ul, & ol': {
            listStylePosition: 'inside'
        }
    },
    root_type: {
        minHeight: '20px',
        width: '100%',
        cursor: 'text',
        '& .onesy-TextField-input': Object.assign({ wordBreak: 'break-word', color: theme.methods.palette.color.value('primary', 10) }, theme.typography.values.b2),
        '& ul, & ol': {
            listStylePosition: 'inside'
        }
    },
    menu: {
        width: '100vw',
        maxWidth: '240px',
        borderRadius: theme.methods.shape.radius.value(2.5),
        boxShadow: '0px 4px 32px 0px rgba(0, 0, 0, 0.04)',
        background: theme.palette.light ? theme.palette.color.neutral[99] : theme.palette.color.neutral[20]
    },
    list: {
        maxHeight: '240px',
        overflow: 'hidden auto'
    },
    textMiniMenuWrapper: {
        paddingBlock: theme.methods.space.value(1, 'px')
    },
    textMiniMenu: {
        padding: theme.methods.space.value(1.5, 'px'),
        borderRadius: theme.methods.shape.radius.value(140, 'px'),
        boxShadow: theme.shadows.values.default[2],
        maxWidth: 'calc(100vw - 24px)',
        rowGap: '4px'
    },
    textMiniMenuAdditionalMenu: {
        minWidth: 'clamp(140px, 90%, 250px)',
        zIndex: '1514',
        boxShadow: theme.shadows.values.default[2]
    },
    inputWrapper: {
        padding: theme.methods.space.value(1, 'px'),
        borderRadius: theme.methods.shape.radius.value(1, 'px'),
        boxShadow: theme.shadows.values.default[2]
    },
    singleLine: {
        whiteSpace: 'nowrap',
        overflow: 'hidden'
    },
    input: {
        '&.onesy-TextField-root': {
            flex: '1 1 auto !important'
        }
    },
    palette: {
        padding: theme.methods.space.value(1.5, 'px'),
        borderRadius: theme.methods.shape.radius.value(1, 'px'),
        boxShadow: theme.shadows.values.default[2]
    },
    paletteItem: {
        position: 'relative',
        width: '17px',
        height: '17px',
        cursor: 'pointer',
        borderRadius: theme.methods.shape.radius.value(40, 'px'),
        boxShadow: theme.shadows.values.default[1],
        transition: theme.methods.transitions.make('box-shadow'),
        '&:hover': {
            boxShadow: theme.shadows.values.default[2],
        }
    },
    textFieldColor: {
        '&.onesy-ColorTextField-root': {
            flex: '1 1 auto'
        }
    },
    helperText: {
        display: 'inline-flex',
        color: theme.palette.text.default.secondary,
        userSelect: 'none'
    },
    error_color: {
        color: [theme.palette.light ? theme.palette.color.error[40] : theme.palette.color.error[80], '!important']
    },
    error_hover_color: {
        color: [theme.palette.light ? theme.palette.color.error[20] : theme.palette.color.error[90], '!important']
    }
}), { name: 'onesy-SmartTextField' });
const SmartTextField = react_1.default.forwardRef((props_, ref) => {
    var _a;
    const theme = (0, style_react_1.useOnesyTheme)();
    const l = theme.l;
    const props = react_1.default.useMemo(() => { var _a, _b, _c, _d, _e, _f, _g, _h; return (Object.assign(Object.assign(Object.assign({}, (_d = (_c = (_b = (_a = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _a === void 0 ? void 0 : _a.elements) === null || _b === void 0 ? void 0 : _b.all) === null || _c === void 0 ? void 0 : _c.props) === null || _d === void 0 ? void 0 : _d.default), (_h = (_g = (_f = (_e = theme === null || theme === void 0 ? void 0 : theme.ui) === null || _e === void 0 ? void 0 : _e.elements) === null || _f === void 0 ? void 0 : _f.onesySmartTextField) === null || _g === void 0 ? void 0 : _g.props) === null || _h === void 0 ? void 0 : _h.default), props_)); }, [props_]);
    const Line = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Line) || Line_1.default; }, [theme]);
    const TextField = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.TextField) || TextField_1.default; }, [theme]);
    const List = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.List) || List_1.default; }, [theme]);
    const ListItem = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.ListItem) || ListItem_1.default; }, [theme]);
    const Avatar = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Avatar) || Avatar_1.default; }, [theme]);
    const Type = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Type) || Type_1.default; }, [theme]);
    const Surface = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Surface) || Surface_1.default; }, [theme]);
    const Button = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Button) || Button_1.default; }, [theme]);
    const Append = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Append) || Append_1.default; }, [theme]);
    const Fade = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Fade) || Fade_1.default; }, [theme]);
    const Tooltip = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Tooltip) || Tooltip_1.default; }, [theme]);
    const ToggleButton = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.ToggleButton) || ToggleButton_1.default; }, [theme]);
    const ClickListener = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.ClickListener) || ClickListener_1.default; }, [theme]);
    const ToggleButtons = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.ToggleButtons) || ToggleButtons_1.default; }, [theme]);
    const Menu = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Menu) || Menu_1.default; }, [theme]);
    const Divider = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.Divider) || Divider_1.default; }, [theme]);
    const ColorTextField = react_1.default.useMemo(() => { var _a; return ((_a = theme === null || theme === void 0 ? void 0 : theme.elements) === null || _a === void 0 ? void 0 : _a.ColorTextField) || ColorTextField_1.default; }, [theme]);
    const { tonal = true, color = 'default', version = 'text', size = 'regular', valueDefault, value: value_, inputProps, onChange, error: error_, name, placeholder, edit, mention, multiline, onChangeMention, optionsMention: optionsMention_, error, helperText, mentionLabel, onKeyDown: onKeyDown_, pasteText = true, readOnly, additional, miniMenuExtended, HelperTextProps, ColorTextFieldProps, className } = props, other = __rest(props, ["tonal", "color", "version", "size", "valueDefault", "value", "inputProps", "onChange", "error", "name", "placeholder", "edit", "mention", "multiline", "onChangeMention", "optionsMention", "error", "helperText", "mentionLabel", "onKeyDown", "pasteText", "readOnly", "additional", "miniMenuExtended", "HelperTextProps", "ColorTextFieldProps", "className"]);
    const { classes } = useStyle();
    const [value, setValue] = react_1.default.useState(valueDefault || '');
    const [openMenu, setOpenMenu] = react_1.default.useState(false);
    const [offset, setOffset] = react_1.default.useState([0, 8]);
    const [selectionMenu, setSelectionMenu] = react_1.default.useState();
    const [optionsMention, setOptionsMention] = react_1.default.useState([]);
    const [textSelection, setTextSelection] = react_1.default.useState();
    const [textSelected, setTextSelected] = react_1.default.useState([]);
    const [open, setOpen] = react_1.default.useState({});
    const [inputValues, setInputValues] = react_1.default.useState({});
    const refs = {
        root: react_1.default.useRef(null),
        input: react_1.default.useRef(null),
        searchElement: react_1.default.useRef(null),
        error: react_1.default.useRef(null),
        search: react_1.default.useRef(null),
        open: react_1.default.useRef(null),
        openMenu: react_1.default.useRef(null),
        selectionMenu: react_1.default.useRef(null),
        caret: react_1.default.useRef(null),
        value: react_1.default.useRef(null),
        version: react_1.default.useRef(version),
        optionsMention: react_1.default.useRef(optionsMention),
        validateMeta: react_1.default.useRef({}),
        range: react_1.default.useRef(null),
        inputValues: react_1.default.useRef(null),
        miniMenu: react_1.default.useRef(null),
        miniMenuElements: {
            color: react_1.default.useRef(null),
            colorPalette: react_1.default.useRef(null),
            background: react_1.default.useRef(null),
            backgroundPalette: react_1.default.useRef(null),
            linkAdd: react_1.default.useRef(null),
            linkAddInput: react_1.default.useRef(null),
            linkRemove: react_1.default.useRef(null)
        },
        elements: {
            color: react_1.default.useRef(null),
            background: react_1.default.useRef(null),
            linkAdd: react_1.default.useRef(null),
            linkRemove: react_1.default.useRef(null),
            quote: react_1.default.useRef(null),
            image: react_1.default.useRef(null),
            video: react_1.default.useRef(null),
            videoYoutube: react_1.default.useRef(null),
            table: react_1.default.useRef(null),
            drawing: react_1.default.useRef(null),
            drawingSvg: react_1.default.useRef(null),
            drawingSize: react_1.default.useRef(null),
            drawingSelect: react_1.default.useRef(null),
            drawingPalette: react_1.default.useRef(null),
            code: react_1.default.useRef(null)
        },
        textSelected: react_1.default.useRef(null),
        textSelection: react_1.default.useRef(null),
        rootDocument: react_1.default.useRef(null),
        rootWindow: react_1.default.useRef(null),
        edit: react_1.default.useRef(edit),
        multiline: react_1.default.useRef(multiline),
        readOnly: react_1.default.useRef(readOnly),
        onChange: react_1.default.useRef(onChange),
        props: react_1.default.useRef(props)
    };
    refs.value.current = value;
    refs.version.current = version;
    refs.open.current = open;
    refs.openMenu.current = openMenu;
    refs.selectionMenu.current = selectionMenu;
    refs.optionsMention.current = optionsMention;
    refs.inputValues.current = inputValues;
    refs.textSelected.current = textSelected;
    refs.textSelection.current = textSelection;
    refs.edit.current = edit;
    refs.multiline.current = multiline;
    refs.readOnly.current = readOnly;
    refs.onChange.current = onChange;
    refs.props.current = props;
    const rootDocument = (0, utils_1.isEnvironment)('browser') && (((_a = refs.root.current) === null || _a === void 0 ? void 0 : _a.ownerDocument) || window.document);
    const rootWindow = rootDocument && (rootDocument.defaultView || window);
    refs.rootDocument.current = rootDocument;
    refs.rootWindow.current = rootWindow;
    const init = react_1.default.useCallback(() => {
        if (version === 'text') {
            const valueNew = valueDefault || value || '';
            if (refs.root.current) {
                refs.root.current.innerHTML = valueNew;
            }
        }
    }, [version, value, valueDefault]);
    react_1.default.useEffect(() => {
        // init
        init();
    }, []);
    react_1.default.useEffect(() => {
        setOptionsMention([...(optionsMention_ || [])]);
    }, [(0, utils_1.hash)(optionsMention_)]);
    react_1.default.useEffect(() => {
        const valuePrevious = (refs.root.current.innerHTML || '').replaceAll('&nbsp;', ' ');
        const valueNew = (0, utils_1.textToInnerHTML)(value_);
        if (value_ !== undefined && valuePrevious !== valueNew)
            validate(!value_ ? '' : (0, utils_2.sanitize)(value_));
    }, [value_]);
    // Save selection to revive, use it on execComand
    react_1.default.useEffect(() => {
        var _a, _b;
        const selection_ = refs.rootWindow.current.getSelection();
        if (selection_ &&
            selection_.anchorNode &&
            !((_b = (_a = selection_.anchorNode) === null || _a === void 0 ? void 0 : _a.className) === null || _b === void 0 ? void 0 : _b.includes('TextField')))
            refs.range.current = selection_.getRangeAt(0);
    }, [open]);
    const updateInputValues = (property, itemValue) => {
        setInputValues((values) => (Object.assign(Object.assign({}, values), { [property]: itemValue })));
    };
    const updateOpen = (property, itemValue) => {
        setOpen((values) => (Object.assign(Object.assign({}, values), { [property]: itemValue })));
    };
    const validateElement = react_1.default.useCallback((element) => {
        if (element === null || element === void 0 ? void 0 : element.children) {
            Array.from(element === null || element === void 0 ? void 0 : element.children).forEach((child) => {
                // Any tag
                if (child.dataset.onesyVersion === 'mention-user') {
                    // Replace the child if label & textContent don't match
                    if (child.dataset.onesyLabel !== child.innerHTML) {
                        element.replaceChild(window.document.createTextNode(child.textContent), child);
                        refs.validateMeta.current.restore = true;
                    }
                }
                if (child === null || child === void 0 ? void 0 : child.children)
                    validateElement(child);
            });
        }
    }, []);
    const validate = react_1.default.useCallback((valueNew = undefined) => {
        // Save caret position
        refs.caret.current = utils_2.caret.save(refs.root.current);
        // Update the root innerHTML
        if (valueNew !== undefined)
            refs.root.current.innerHTML = valueNew;
        refs.validateMeta.current.restore = false;
        // Find all span onesy-mention children
        // if they aren't valid, replace them with text node of their textContent
        validateElement(refs.root.current);
        if (refs.validateMeta.current.restore)
            utils_2.caret.restore(refs.root.current, refs.caret.current);
        return refs.root.current.innerHTML;
    }, []);
    const getAtSearchData = react_1.default.useCallback(() => {
        var _a, _b, _c, _d, _e;
        if (refs.root.current) {
            const windowSelection = window.document.getSelection();
            if (!(windowSelection && windowSelection.rangeCount > 0))
                return;
            const range = windowSelection === null || windowSelection === void 0 ? void 0 : windowSelection.getRangeAt(0);
            if (!range)
                return;
            // Only allow for text not in span user mention element
            if (((_c = (_b = (_a = windowSelection.anchorNode) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.dataset) === null || _c === void 0 ? void 0 : _c.onesyVersion) === 'mention-user')
                return '';
            // Text
            if (!['text', '#text'].includes((_d = range === null || range === void 0 ? void 0 : range.commonAncestorContainer) === null || _d === void 0 ? void 0 : _d.nodeName))
                return '';
            const text = ((_e = windowSelection.anchorNode) === null || _e === void 0 ? void 0 : _e.textContent) || '';
            const start = text.slice(0, range.endOffset).split('').reverse().join('');
            let result = [];
            for (const valueText of start) {
                // All characters other than space, numbers
                if (!!valueText.match(/[^<>\\/\n\r\t]/))
                    result.unshift(valueText);
                else
                    break;
                if (['@'].includes(valueText))
                    break;
            }
            result = result.includes('@') ? result.join('') : '';
            // Allow 1 space only
            if (result && result.match(/\s{2}/g))
                return '';
            return result;
        }
    }, []);
    refs.search.current = getAtSearchData();
    const onInput = react_1.default.useCallback((event) => {
        if (refs.root.current) {
            let valueInput = refs.root.current.innerHTML || '';
            if (refs.root.current.textContent === '') {
                valueInput = '';
                refs.root.current.innerHTML = '';
            }
            if (!refs.multiline.current) {
                const previous = valueInput;
                valueInput = valueInput.replace(/\r?\n|\r/gm, '');
                if (previous !== valueInput)
                    refs.root.current.innerHTML = valueInput;
            }
            valueInput = (0, utils_1.innerHTMLToText)(valueInput);
            setValue(valueInput);
            if ((0, utils_1.is)('function', refs.onChange.current))
                refs.onChange.current(valueInput, event);
        }
    }, []);
    react_1.default.useEffect(() => {
        if (mention && refs.search.current !== undefined)
            onChangeMention === null || onChangeMention === void 0 ? void 0 : onChangeMention(refs.search.current, '@');
    }, [mention, refs.search.current]);
    react_1.default.useEffect(() => {
        const method = () => {
            if (window.document.activeElement === refs.input.current)
                onInput();
        };
        window.document.addEventListener('selectionchange', method);
        onChangeMention === null || onChangeMention === void 0 ? void 0 : onChangeMention(refs.search.current, '@');
        return () => {
            window.document.removeEventListener('selectionchange', method);
        };
    }, []);
    const updateSelection = react_1.default.useCallback(() => {
        const windowSelection = window.document.getSelection();
        if (!(windowSelection && windowSelection.rangeCount > 0))
            return;
        const range = windowSelection === null || windowSelection === void 0 ? void 0 : windowSelection.getRangeAt(0);
        if (range)
            setSelectionMenu(range === null || range === void 0 ? void 0 : range.getBoundingClientRect());
    }, []);
    const onOpenSearch = react_1.default.useCallback(async () => {
        if (!refs.openMenu.current && !!refs.optionsMention.current.length) {
            // open
            setOpenMenu(true);
            // selection
            updateSelection();
        }
    }, []);
    const onCloseSearch = react_1.default.useCallback(() => {
        if (refs.openMenu.current) {
            setOpenMenu(false);
            setSelectionMenu(null);
        }
    }, []);
    const updateOffset = react_1.default.useCallback(() => {
        var _a;
        setOffset([-(((_a = refs.searchElement.current) === null || _a === void 0 ? void 0 : _a.clientWidth) || 0), 8]);
    }, []);
    const onFocus = react_1.default.useCallback(() => {
        // setFocus(true);
    }, []);
    const onBlur = react_1.default.useCallback(() => {
        // setFocus(false);
    }, []);
    const onKeyDown = react_1.default.useCallback((event) => {
        var _a;
        const windowSelection = window.getSelection();
        if (windowSelection) {
            // if (event.key === 'Enter') {
            //   event.preventDefault();
            //   const anchor = windowSelection.anchorNode as HTMLElement;
            //   const element = anchor.parentElement;
            //   const multiple = anchor.tagName === 'P' && anchor.children.length === 1 && anchor.children[0].tagName === 'BR';
            //   window.document.execCommand('insertHTML', false, `<p><br /></p>`.repeat(multiple ? 2 : 1));
            //   const range = new Range();
            //   const rangeStartElement = ((multiple ? anchor : element) as any)?.nextElementSibling;
            //   if (rangeStartElement) range.setStart(rangeStartElement, 0);
            //   windowSelection.removeAllRanges();
            //   windowSelection.addRange(range);
            // }
            if (event.key === 'ArrowRight') {
                // If in user mention span
                // move out of it with adding new empty space root node after the user mention span
                // only if caret is at the end of the span, & span is last child of it's parent
                if (!(windowSelection && windowSelection.rangeCount > 0))
                    return;
                const range = windowSelection.getRangeAt(0);
                const caretElement = windowSelection.anchorNode.parentElement;
                const caretElementParent = caretElement.parentElement;
                const caretElementParentChildNodes = Array.from(caretElementParent.childNodes);
                if (((_a = caretElement === null || caretElement === void 0 ? void 0 : caretElement.dataset) === null || _a === void 0 ? void 0 : _a.onesyVersion) === 'mention-user' &&
                    range.endOffset === windowSelection.anchorNode.textContent.length &&
                    caretElementParentChildNodes[caretElementParentChildNodes.length - 1] === caretElement) {
                    caretElementParent.insertBefore(window.document.createTextNode('\u00A0'), caretElement.nextElementSibling);
                }
            }
        }
        if (!refs.multiline.current) {
            if (event.key === 'Enter') {
                event.preventDefault();
            }
        }
        if (!refs.edit.current &&
            ((event.metaKey && (utils_2.keyboardStyleCommands.includes(event.key))) ||
                (event.ctrlKey && (utils_2.keyboardStyleCommands.includes(event.key))))) {
            event.preventDefault();
        }
        if ((0, utils_1.is)('function', onKeyDown_))
            onKeyDown_(event);
    }, [onKeyDown_]);
    const onPaste = react_1.default.useCallback((event) => {
        // event.preventDefault();
        // const text = event.clipboardData?.getData('text/plain');
        // window.document.execCommand('insertText', false, text);
    }, []);
    const onPasteText = react_1.default.useCallback((event) => {
        var _a;
        event.preventDefault();
        const text = (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.getData('text/plain');
        window.document.execCommand('insertText', false, text);
    }, []);
    const onDrop = react_1.default.useCallback((event) => {
        event.preventDefault();
    }, []);
    const addTag = react_1.default.useCallback((item, versionMention = 'user') => {
        // Save caret position
        refs.caret.current = utils_2.caret.save(refs.root.current);
        const itemName = item.name;
        const classesElement = ['onesy-mention'];
        // Query text node that equals selection anchorNode
        // and replace its textContent's search value with new span
        const windowSelection = window.document.getSelection();
        if (!(windowSelection && windowSelection.rangeCount > 0))
            return;
        const range = windowSelection === null || windowSelection === void 0 ? void 0 : windowSelection.getRangeAt(0);
        if (!range)
            return;
        const textNode = windowSelection.anchorNode;
        const textContent = textNode.textContent;
        // Bug fix
        // only be able to insert data within the input
        // if by accident selection went outside the input
        // basically do nothing with it
        if (refs.root.current.contains(textNode.parentElement)) {
            const end = range.endOffset;
            const start = end - refs.search.current.length;
            const pre = textContent.slice(0, start);
            const post = textContent.slice(end);
            // Insert before anchorNode pre, item mention, and post
            if (pre)
                textNode.parentElement.insertBefore(window.document.createTextNode(pre), windowSelection.anchorNode);
            const span = window.document.createElement('span');
            span.className = classesElement.join(' ');
            span.dataset.onesyLabel = `@${itemName}`;
            span.dataset.onesyVersion = `mention-${versionMention}`;
            span.dataset.onesyObject = `${versionMention}`;
            span.dataset.onesyId = item.id;
            span.innerHTML = `@${itemName}`;
            textNode.parentElement.insertBefore(span, windowSelection.anchorNode);
            // 1 space only following the item mention
            textNode.parentElement.insertBefore(window.document.createTextNode('\u00A0'), windowSelection.anchorNode);
            if (post)
                textNode.parentElement.insertBefore(window.document.createTextNode(post), windowSelection.anchorNode);
            // Remove the text node
            textNode.remove();
            // Invoke onChange method with new value
            const valueInput = (0, utils_1.innerHTMLToText)(refs.root.current.innerHTML);
            if ((0, utils_1.is)('function', refs.onChange.current))
                refs.onChange.current(valueInput, { target: refs.root.current });
            // Update the caret position to be outside the span mention
            // for amount of added characters + 1 space
            const added = `@${itemName}`.length - refs.search.current.length + 1;
            refs.caret.current.start = refs.caret.current.end += added;
            utils_2.caret.restore(refs.root.current, refs.caret.current);
        }
        // Close the search
        onCloseSearch();
    }, [onChange]);
    // If users response & not open, open
    // else if no users response & opened, close the search
    react_1.default.useEffect(() => {
        if (mention) {
            if (refs.openMenu.current && !optionsMention.length)
                onCloseSearch();
            else if (!refs.openMenu.current && refs.search.current && !!optionsMention.length)
                onOpenSearch();
        }
    }, [mention, optionsMention]);
    react_1.default.useEffect(() => {
        if (mention) {
            // Validate
            validate();
            // Update
            // open, selection & offset
            setTimeout(() => {
                refs.search.current ? onOpenSearch() : onCloseSearch();
                if (refs.openMenu.current)
                    updateSelection();
                updateOffset();
            });
        }
    }, [mention, value]);
    react_1.default.useEffect(() => {
        // setError(error_);
    }, [error_]);
    const label = react_1.default.useCallback(() => ((0, utils_1.is)('function', mentionLabel) ? mentionLabel(optionsMention, { addTag }) :
        (0, jsx_runtime_1.jsx)(Line, Object.assign({ className: classes.menu }, { children: (0, jsx_runtime_1.jsx)(List, Object.assign({ size: 'small', className: classes.list }, { children: optionsMention === null || optionsMention === void 0 ? void 0 : optionsMention.map((item, index) => {
                    var _a;
                    return ((0, jsx_runtime_1.jsx)(ListItem, { start: ((0, jsx_runtime_1.jsx)(Avatar, Object.assign({ color: (0, utils_1.stringToColor)(item.name), size: 'small' }, { children: (_a = item.name) === null || _a === void 0 ? void 0 : _a.slice(0, 1) }))), primary: ((0, jsx_runtime_1.jsx)(Type, Object.assign({ version: 'l3' }, { children: item.name }))), onClick: () => addTag(item), button: true }, index));
                }) })) }))), [optionsMention]);
    const paste = async () => {
        const valueClipboard = await navigator.clipboard.read();
        if (valueClipboard) {
            let values = '';
            for (const item of Array.from(valueClipboard)) {
                const valueItem = await item.getType('text/html');
                values += await valueItem.text();
            }
            rootDocument.execCommand('insertHTML', undefined, values);
        }
    };
    const query = (command) => {
        return (0, utils_1.parse)(refs.rootDocument.current.queryCommandValue(command));
    };
    const textQueryUpdate = () => {
        const selected = [];
        const updateOptionValues = [
            { name: 'italic', command: 'italic' },
            { name: 'underline', command: 'underline' },
            { name: 'bold', command: 'bold' },
            { name: 'strike-line', command: 'strikeThrough' }
        ];
        updateOptionValues.forEach(item => {
            if (query(item.command))
                selected.push(item.name);
        });
        setTextSelected(selected);
    };
    const onMouseUp = react_1.default.useCallback(() => {
        if (!refs.edit.current)
            return;
        const selection_ = refs.rootWindow.current.getSelection();
        if (!selection_)
            return;
        if (!selection_.anchorNode || !refs.root.current.contains(selection_.anchorNode))
            return setTextSelection(null);
        setTimeout(() => {
            var _a;
            const rect = selection_.getRangeAt(0).getBoundingClientRect();
            setTextSelection(Math.round(rect.width) ? { selection: rect, element: (_a = selection_.anchorNode) === null || _a === void 0 ? void 0 : _a.parentElement } : null);
            textQueryUpdate();
        }, 140);
    }, []);
    const onMouseDown = react_1.default.useCallback(() => {
        if (!refs.edit.current)
            return;
        textQueryUpdate();
    }, []);
    const onKeyUp = react_1.default.useCallback(() => {
        if (!refs.edit.current)
            return;
        textQueryUpdate();
    }, []);
    const textMethod = react_1.default.useCallback((command) => (argument) => {
        var _a;
        switch (command) {
            // updates
            case 'italic':
                refs.rootDocument.current.execCommand('italic');
                if (query('italic'))
                    setTextSelected(values => [...values, 'italic']);
                else
                    setTextSelected(values => values.filter(item => item !== 'italic'));
                break;
            case 'underline':
                refs.rootDocument.current.execCommand('underline');
                if (query('underline'))
                    setTextSelected(values => [...values, 'underline']);
                else
                    setTextSelected(values => values.filter(item => item !== 'underline'));
                break;
            case 'bold':
                refs.rootDocument.current.execCommand('bold');
                if (query('bold'))
                    setTextSelected(values => [...values, 'bold']);
                else
                    setTextSelected(values => values.filter(item => item !== 'bold'));
                break;
            case 'strike-line':
                refs.rootDocument.current.execCommand('strikeThrough');
                if (query('strikeThrough'))
                    setTextSelected(values => [...values, 'strike-line']);
                else
                    setTextSelected(values => values.filter(item => item !== 'strike-line'));
                break;
            case 'align-left':
                refs.rootDocument.current.execCommand('justifyLeft');
                if (query('justifyLeft'))
                    setTextSelected(values => [...values.filter(item => !item.includes('align')), 'align-left']);
                else
                    setTextSelected(values => values.filter(item => item !== 'align-left'));
                break;
            case 'align-center':
                refs.rootDocument.current.execCommand('justifyCenter');
                if (query('justifyCenter'))
                    setTextSelected(values => [...values.filter(item => !item.includes('align')), 'align-center']);
                else
                    setTextSelected(values => values.filter(item => item !== 'align-center'));
                break;
            case 'align-right':
                refs.rootDocument.current.execCommand('justifyRight');
                if (query('justifyRight'))
                    setTextSelected(values => [...values.filter(item => !item.includes('align')), 'align-right']);
                else
                    setTextSelected(values => values.filter(item => item !== 'align-right'));
                break;
            case 'align-justify':
                refs.rootDocument.current.execCommand('justifyFull');
                if (query('justifyFull'))
                    setTextSelected(values => [...values.filter(item => !item.includes('align')), 'align-justify']);
                else
                    setTextSelected(values => values.filter(item => item !== 'align-justify'));
                break;
            case 'superscript':
                refs.rootDocument.current.execCommand('superscript');
                if (query('superscript'))
                    setTextSelected(values => [...values, 'superscript']);
                else
                    setTextSelected(values => values.filter(item => item !== 'superscript'));
                break;
            case 'subscript':
                refs.rootDocument.current.execCommand('subscript');
                if (query('subscript'))
                    setTextSelected(values => [...values, 'subscript']);
                else
                    setTextSelected(values => values.filter(item => item !== 'subscript'));
                break;
            case 'indent':
                refs.rootDocument.current.execCommand('indent');
                break;
            case 'outdent':
                refs.rootDocument.current.execCommand('outdent');
                break;
            case 'font-version':
                refs.rootDocument.current.execCommand('formatBlock', undefined, argument);
                break;
            case 'font-family':
                refs.rootDocument.current.execCommand('styleWithCSS', true);
                refs.rootDocument.current.execCommand('fontName', undefined, argument);
                refs.rootDocument.current.execCommand('styleWithCSS', false);
                break;
            case 'font-size':
                refs.rootDocument.current.execCommand('styleWithCSS', true);
                refs.rootDocument.current.execCommand('fontSize', undefined, argument);
                refs.rootDocument.current.execCommand('styleWithCSS', false);
                break;
            case 'font-color':
                refs.rootDocument.current.execCommand('styleWithCSS', true);
                refs.rootDocument.current.execCommand('foreColor', undefined, argument);
                refs.rootDocument.current.execCommand('styleWithCSS', false);
                break;
            case 'font-background':
                refs.rootDocument.current.execCommand('styleWithCSS', true);
                refs.rootDocument.current.execCommand('backColor', undefined, argument);
                refs.rootDocument.current.execCommand('styleWithCSS', false);
                break;
            case 'list-ordered':
                refs.rootDocument.current.execCommand('insertOrderedList');
                if (query('insertOrderedList'))
                    setTextSelected(values => [...values.filter(item => !item.includes('list')), 'list-ordered']);
                else
                    setTextSelected(values => values.filter(item => item !== 'list-ordered'));
                break;
            case 'list-unordered':
                refs.rootDocument.current.execCommand('insertUnorderedList');
                if (query('insertUnorderedList'))
                    setTextSelected(values => [...values.filter(item => !item.includes('list')), 'list-unordered']);
                else
                    setTextSelected(values => values.filter(item => item !== 'list-unordered'));
                break;
            case 'horizontal-rule':
                refs.rootDocument.current.execCommand('insertHorizontalRule');
                break;
            case 'link-add':
                refs.rootDocument.current.execCommand('createLink', undefined, argument);
                break;
            case 'link-remove':
                refs.rootDocument.current.execCommand('unlink');
                break;
            case 'image':
                refs.rootDocument.current.execCommand('insertImage', undefined, argument);
                break;
            case 'html':
                refs.rootDocument.current.execCommand('insertHTML', undefined, argument);
                break;
            // actions
            case 'copy':
                refs.rootDocument.current.execCommand('copy');
                break;
            case 'cut':
                refs.rootDocument.current.execCommand('cut');
                break;
            case 'paste':
                if (refs.rootDocument.current.queryCommandSupported('paste'))
                    refs.rootDocument.current.execCommand('paste');
                else
                    paste();
                break;
            case 'delete':
                refs.rootDocument.current.execCommand('delete');
                break;
            case 'clear':
                refs.rootDocument.current.execCommand('removeFormat');
                break;
            case 'select-all':
                refs.rootDocument.current.execCommand('selectAll');
                break;
            case 'undo':
                refs.rootDocument.current.execCommand('undo');
                break;
            case 'redo':
                refs.rootDocument.current.execCommand('redo');
                break;
            default:
                break;
        }
        const element = (_a = refs.textSelection.current) === null || _a === void 0 ? void 0 : _a.element;
        if (element) {
            let valueElement = element.innerHTML || '';
            if (element.textContent === '') {
                valueElement = '';
                element.innerHTML = '';
            }
            if (valueElement)
                valueElement = (0, utils_1.innerHTMLToText)(valueElement);
        }
        textQueryUpdate();
    }, []);
    const PaletteItem = react_1.default.useCallback((propsItem) => {
        const { color: color_ } = propsItem, other_ = __rest(propsItem, ["color"]);
        return ((0, jsx_runtime_1.jsx)("span", Object.assign({ className: (0, style_react_1.classNames)([
                (0, utils_2.staticClassName)('RichTextEditor', theme) && [
                    'onesy-RichTextEditor-palette-item'
                ],
                classes.paletteItem
            ]), style: {
                background: color_
            } }, other_)));
    }, []);
    const Palette = react_1.default.useCallback(react_1.default.forwardRef((propsPalette, ref_) => {
        const { version: version_, onUpdate: onUpdate_, onClose } = propsPalette, other_ = __rest(propsPalette, ["version", "onUpdate", "onClose"]);
        const onUpdateColor = itemColor => {
            if (refs.range.current) {
                const selection_ = refs.rootWindow.current.getSelection();
                selection_.removeAllRanges();
                selection_.addRange(refs.range.current);
            }
            onUpdate_(itemColor);
            onClose();
        };
        return ((0, jsx_runtime_1.jsxs)(Line, Object.assign({ ref: ref_, gap: 1, direction: 'column', tonal: tonal, color: refs.props.current.color !== undefined ? refs.props.current.color : 'themed', Component: Surface, className: (0, style_react_1.classNames)([
                (0, utils_2.staticClassName)('RichTextEditor', theme) && [
                    'onesy-RichTextEditor-palette'
                ],
                classes.palette
            ]) }, other_, { children: [(0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 0.5, style: {
                        maxHeight: 136,
                        padding: '10px 10px 0',
                        overflow: 'hidden auto'
                    } }, { children: [(0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 0.5, direction: 'row', style: {
                                width: '100%'
                            } }, { children: [(0, jsx_runtime_1.jsx)(PaletteItem, { color: '#000000', onClick: () => {
                                        onUpdateColor('#000000');
                                    } }), (0, jsx_runtime_1.jsx)(PaletteItem, { color: '#ffffff', onClick: () => {
                                        onUpdateColor('#ffffff');
                                    } })] })), Object.keys(style_react_1.colors).filter(item => !['black', 'white'].includes(item)).map((item, index) => ((0, jsx_runtime_1.jsx)(Line, Object.assign({ gap: 0.5, direction: 'row', style: {
                                width: '100%'
                            } }, { children: Object.keys(style_react_1.colors[item]).map((item_, index_) => ((0, jsx_runtime_1.jsx)(PaletteItem, { color: style_react_1.colors[item][item_], onClick: () => {
                                    onUpdateColor(style_react_1.colors[item][item_]);
                                } }, index_))) }), index)))] })), (0, jsx_runtime_1.jsx)(Divider, {}), (0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 0.5, direction: 'row', align: 'center', fullWidth: true, style: {
                        padding: '0px 10px 10px'
                    } }, { children: [(0, jsx_runtime_1.jsx)(ColorTextField, Object.assign({ tonal: tonal, color: color, name: l('Custom color'), version: 'outlined', size: 'small', value: refs.inputValues.current[version_], onChange: valueNew => updateInputValues(version_, valueNew) }, ColorTextFieldProps, { className: (0, style_react_1.classNames)([
                                (0, utils_2.staticClassName)('RichTextEditor', theme) && [
                                    'onesy-RichTextEditor-text-field-color'
                                ],
                                ColorTextFieldProps === null || ColorTextFieldProps === void 0 ? void 0 : ColorTextFieldProps.className,
                                classes.textFieldColor
                            ]) })), (0, jsx_runtime_1.jsx)(Button, Object.assign({ tonal: tonal, color: 'inherit', version: 'text', size: 'small', onClick: () => {
                                if (refs.range.current) {
                                    const selection_ = refs.rootWindow.current.getSelection();
                                    selection_.removeAllRanges();
                                    selection_.addRange(refs.range.current);
                                }
                                onUpdate_(refs.inputValues.current[version_]);
                                onClose();
                            } }, { children: "Apply" }))] }))] })));
    }), []);
    const AppendProps = {
        padding: [14, 14]
    };
    const IconProps = {
        size: 'small'
    };
    const TooltipProps = {
        position: 'bottom',
        interactive: false
    };
    const ToggleButtonsProps = {
        tonal: false,
        color: 'default',
        version: 'text',
        border: false
    };
    const ToggleButtonProps = {
        size: 'small'
    };
    const Input = react_1.default.useCallback(react_1.default.forwardRef((propsInput, ref_) => {
        const { label: labelInput, labelButton, value: value__, onChange: onChange__, onClick, placeholder: placeholderInputProps, InputComponent = TextField, InputProps } = propsInput, other_ = __rest(propsInput, ["label", "labelButton", "value", "onChange", "onClick", "placeholder", "InputComponent", "InputProps"]);
        return ((0, jsx_runtime_1.jsx)(Line, Object.assign({ ref: ref_, gap: 1, direction: 'column', color: 'themed', Component: Surface }, other_, { className: (0, style_react_1.classNames)([
                other_ === null || other_ === void 0 ? void 0 : other_.className,
                classes.inputWrapper
            ]) }, { children: (0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 0.5, direction: 'row', align: 'center', style: {
                    width: '100%'
                } }, { children: [(0, jsx_runtime_1.jsx)(InputComponent, Object.assign({ name: labelInput, version: 'outlined', size: 'small', valueDefault: value__, onChange: onChange__, placeholder: placeholderInputProps, flex: true }, InputProps, { style: {
                            width: 'unset',
                            flex: '1 1 auto'
                        } })), (0, jsx_runtime_1.jsx)(Button, Object.assign({ color: 'inherit', version: 'text', size: 'small', onClick: onClick }, { children: labelButton }))] })) })));
    }), []);
    const WrapperAppend = react_1.default.useCallback((propsWrapper) => {
        const { open: open_, element, anchorElement, onClose, children: childrenWrapperAppend } = propsWrapper, other_ = __rest(propsWrapper, ["open", "element", "anchorElement", "onClose", "children"]);
        return ((0, jsx_runtime_1.jsx)(Append, Object.assign({ open: open_, element: ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: (0, style_react_1.classNames)([
                    (0, utils_2.staticClassName)('SmartTextField', theme) && [
                        'onesy-SmartTextField-mini-menu-additional'
                    ],
                    classes.textMiniMenuAdditionalMenu
                ]) }, { children: (0, jsx_runtime_1.jsx)(Fade, Object.assign({ in: open_, add: true }, { children: react_1.default.cloneElement(element) })) }))), anchorElement: anchorElement, portal: true, alignment: 'center', position: 'bottom' }, AppendProps, { children: react_1.default.cloneElement(childrenWrapperAppend, Object.assign(Object.assign({}, other_), childrenWrapperAppend.props)) })));
    }, []);
    const WrapperToggleButton = react_1.default.useCallback(react_1.default.forwardRef((propsWrapperToggleButton, ref_) => {
        const { open: open_, name: nameWrapperToogleButton, children: childrenWrapperToggleButton } = propsWrapperToggleButton, other_ = __rest(propsWrapperToggleButton, ["open", "name", "children"]);
        return ((0, jsx_runtime_1.jsx)(Tooltip, Object.assign({ open: open_ !== undefined ? open_ : undefined, name: nameWrapperToogleButton }, TooltipProps, { children: react_1.default.cloneElement(childrenWrapperToggleButton, Object.assign(Object.assign({}, other_), childrenWrapperToggleButton.props)) })));
    }), []);
    const updateElements = {
        'italic': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Italic') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('italic'), onClick: textMethod('italic') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatItalicW100_1.default, Object.assign({}, IconProps)) })) }))),
        'underline': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Underline') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('underline'), onClick: textMethod('underline') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatUnderlinedW100_1.default, Object.assign({}, IconProps)) })) }))),
        'bold': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Bold'), onClick: textMethod('bold') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('bold') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatBoldW100_1.default, Object.assign({}, IconProps)) })) }))),
        'superscript': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Superscript'), onClick: textMethod('superscript') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('superscript') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialSuperscriptW100_1.default, Object.assign({}, IconProps)) })) }))),
        'subscript': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Subscript'), onClick: textMethod('subscript') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('subscript') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialSubscriptW100_1.default, Object.assign({}, IconProps)) })) }))),
        'strike-line': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Strike Line'), onClick: textMethod('strike-line') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('strike-line') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialStrikethroughSW100_1.default, Object.assign({}, IconProps)) })) }))),
        'link-add': ((0, jsx_runtime_1.jsx)(WrapperAppend, Object.assign({ open: refs.open.current.linkMiniMenu, anchorElement: refs.miniMenuElements.linkAdd, element: ((0, jsx_runtime_1.jsx)(ClickListener, Object.assign({ onClickOutside: () => updateOpen('linkMiniMenu', false), include: [refs.miniMenuElements.linkAdd] }, { children: (0, jsx_runtime_1.jsx)(Input, { ref: refs.miniMenuElements.linkAddInput, name: l('Link'), labelButton: l('Add'), value: refs.inputValues.current.link, onChange: (valueNew) => updateInputValues('link', valueNew), placeholder: l('URL'), onClick: () => {
                        if (refs.range.current) {
                            const selection_ = refs.rootWindow.current.getSelection();
                            if (!selection_)
                                return;
                            selection_.removeAllRanges();
                            selection_.addRange(refs.range.current);
                        }
                        textMethod('link-add')(refs.inputValues.current.link);
                        updateOpen('linkMiniMenu', false);
                        updateInputValues('link', '');
                    }, className: classes.input }) }))) }, { children: (0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Insert Link'), open: refs.open.current.linkMiniMenu ? false : undefined }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({ ref: refs.miniMenuElements.linkAdd }, ToggleButtonProps, { selected: refs.open.current.linkMiniMenu, onClick: () => updateOpen('linkMiniMenu', !refs.open.current.linkMiniMenu) }, { children: (0, jsx_runtime_1.jsx)(IconMaterialAddLinkW100_1.default, Object.assign({}, IconProps)) })) })) }))),
        'link-remove': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Remove Link') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { onClick: textMethod('link-remove') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialLinkOffW100_1.default, Object.assign({}, IconProps)) })) }))),
        'font-color': ((0, jsx_runtime_1.jsx)(WrapperAppend, Object.assign({ open: refs.open.current.color, anchorElement: refs.elements.color.current, element: ((0, jsx_runtime_1.jsx)(ClickListener, Object.assign({ onClickOutside: () => updateOpen('color', false), include: [refs.elements.color.current] }, { children: (0, jsx_runtime_1.jsx)(Palette, { version: 'font-color', onClose: () => updateOpen('color', false), onUpdate: () => {
                        if (refs.range.current) {
                            const selection_ = refs.rootWindow.current.getSelection();
                            selection_.removeAllRanges();
                            selection_.addRange(refs.range.current);
                        }
                        textMethod('font-color');
                    } }) }))) }, { children: (0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Text Color'), open: refs.open.current.color ? false : undefined }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({ ref: refs.elements.color }, ToggleButtonProps, { selected: refs.open.current.color, onClick: () => updateOpen('color', !refs.open.current.color) }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatColorTextW100_1.default, Object.assign({}, IconProps)) })) })) }))),
        'font-color-mini-menu': ((0, jsx_runtime_1.jsx)(WrapperAppend, Object.assign({ open: refs.open.current.colorMiniMenu, anchorElement: refs.miniMenuElements.color, element: ((0, jsx_runtime_1.jsx)(ClickListener, Object.assign({ onClickOutside: () => updateOpen('colorMiniMenu', false), include: [refs.miniMenuElements.color] }, { children: (0, jsx_runtime_1.jsx)(Palette, { ref: refs.miniMenuElements.colorPalette, version: 'font-color', onClose: () => updateOpen('colorMiniMenu', false), onUpdate: textMethod('font-color') }) }))) }, { children: (0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Text Color'), open: refs.open.current.colorMiniMenu ? false : undefined }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({ ref: refs.miniMenuElements.color }, ToggleButtonProps, { selected: refs.open.current.colorMiniMenu, onClick: () => updateOpen('colorMiniMenu', !refs.open.current.colorMiniMenu) }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatColorTextW100_1.default, Object.assign({}, IconProps)) })) })) }))),
        'font-background': ((0, jsx_runtime_1.jsx)(WrapperAppend, Object.assign({ open: refs.open.current.background, anchorElement: refs.elements.background.current, element: ((0, jsx_runtime_1.jsx)(ClickListener, Object.assign({ onClickOutside: () => updateOpen('background', false), include: [refs.elements.background.current] }, { children: (0, jsx_runtime_1.jsx)(Palette, { version: 'font-background', onClose: () => updateOpen('background', false), onUpdate: textMethod('font-background') }) }))) }, { children: (0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Background Color'), open: refs.open.current.background ? false : undefined }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({ ref: refs.elements.background }, ToggleButtonProps, { selected: refs.open.current.background, onClick: () => updateOpen('background', !refs.open.current.background) }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatColorFillW100_1.default, Object.assign({}, IconProps)) })) })) }))),
        'font-background-mini-menu': ((0, jsx_runtime_1.jsx)(WrapperAppend, Object.assign({ open: refs.open.current.backgroundMiniMenu, anchorElement: refs.miniMenuElements.background, element: ((0, jsx_runtime_1.jsx)(ClickListener, Object.assign({ onClickOutside: () => updateOpen('backgroundMiniMenu', false), include: [refs.miniMenuElements.background] }, { children: (0, jsx_runtime_1.jsx)(Palette, { ref: refs.miniMenuElements.backgroundPalette, version: 'font-background', onClose: () => updateOpen('backgroundMiniMenu', false), onUpdate: textMethod('font-background') }) }))) }, { children: (0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Text Color'), open: refs.open.current.backgroundMiniMenu ? false : undefined }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({ ref: refs.miniMenuElements.background }, ToggleButtonProps, { selected: refs.open.current.backgroundMiniMenu, onClick: () => updateOpen('backgroundMiniMenu', !refs.open.current.backgroundMiniMenu) }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatColorFillW100_1.default, Object.assign({}, IconProps)) })) })) }))),
        'align-left': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Align Left') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('align-left'), onClick: textMethod('align-left') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatAlignLeftW100_1.default, Object.assign({}, IconProps)) })) }))),
        'align-center': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Align Center') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('align-center'), onClick: textMethod('align-center') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatAlignCenterW100_1.default, Object.assign({}, IconProps)) })) }))),
        'align-right': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Align Right') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('align-right'), onClick: textMethod('align-right') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatAlignRightW100_1.default, Object.assign({}, IconProps)) })) }))),
        'align-justify': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Align Justify') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('align-justify'), onClick: textMethod('align-justify') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatAlignJustifyW100_1.default, Object.assign({}, IconProps)) })) }))),
        'list-ordered': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('List Ordered') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('list-ordered'), onClick: textMethod('list-ordered') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatListNumberedW100_1.default, Object.assign({}, IconProps)) })) }))),
        'list-unordered': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('List Unordered') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { selected: refs.textSelected.current.includes('list-unordered'), onClick: textMethod('list-unordered') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatListBulletedW100_1.default, Object.assign({}, IconProps)) })) })))
    };
    const actionElements = {
        'clear': ((0, jsx_runtime_1.jsx)(WrapperToggleButton, Object.assign({ name: l('Clear') }, { children: (0, jsx_runtime_1.jsx)(ToggleButton, Object.assign({}, ToggleButtonProps, { onClick: textMethod('clear') }, { children: (0, jsx_runtime_1.jsx)(IconMaterialFormatClearW100_1.default, Object.assign({}, IconProps)) })) })))
    };
    const miniMenu = react_1.default.useMemo(() => {
        return ((0, jsx_runtime_1.jsx)(Append, Object.assign({ open: !!textSelection, element: (body) => {
                const { ref: ref_, values, style: styleAppend } = body;
                return ((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: item => {
                        if (ref_) {
                            if ((0, utils_1.is)('function', ref_))
                                ref_(item);
                            else
                                ref_.current = item;
                            refs.miniMenu.current = item;
                        }
                    }, style: Object.assign(Object.assign(Object.assign({}, (((values === null || values === void 0 ? void 0 : values.x) === 0 && (values === null || values === void 0 ? void 0 : values.y) === 0) ? {
                        visibility: 'hidden'
                    } : undefined)), styleAppend), { zIndex: 1500 }), className: (0, style_react_1.classNames)([
                        (0, utils_2.staticClassName)('SmartTextField', theme) && [
                            'onesy-SmartTextField-mini-menu-wrapper'
                        ],
                        classes.textMiniMenuWrapper
                    ]) }, { children: (0, jsx_runtime_1.jsx)(Fade, Object.assign({ in: !!textSelection, add: true }, { children: (0, jsx_runtime_1.jsx)(ClickListener, Object.assign({ onClickOutside: () => {
                                setTextSelection(null);
                            }, include: [refs.miniMenu, refs.miniMenu.current, refs.miniMenuElements.colorPalette, refs.miniMenuElements.colorPalette.current, refs.miniMenuElements.backgroundPalette, refs.miniMenuElements.backgroundPalette.current, refs.miniMenuElements.linkAddInput, refs.miniMenuElements.linkAddInput.current] }, { children: (0, jsx_runtime_1.jsxs)(Line, Object.assign({ gap: 2, direction: 'row', align: 'center', justify: 'flex-start', wrap: 'wrap', role: 'toolbar', color: 'themed', "aria-label": l('Mini menu'), Component: Surface, className: (0, style_react_1.classNames)([
                                    classes.textMiniMenu
                                ]) }, { children: [(0, jsx_runtime_1.jsxs)(ToggleButtons, Object.assign({}, ToggleButtonsProps, { children: [updateElements['italic'], updateElements['underline'], updateElements['bold'], updateElements['strike-line']] })), miniMenuExtended && ((0, jsx_runtime_1.jsxs)(ToggleButtons, Object.assign({}, ToggleButtonsProps, { children: [updateElements['align-left'], updateElements['align-center'], updateElements['align-right'], updateElements['align-justify']] }))), miniMenuExtended && ((0, jsx_runtime_1.jsxs)(ToggleButtons, Object.assign({}, ToggleButtonsProps, { children: [updateElements['font-color-mini-menu'], updateElements['font-background-mini-menu']] }))), miniMenuExtended && ((0, jsx_runtime_1.jsxs)(ToggleButtons, Object.assign({}, ToggleButtonsProps, { children: [updateElements['list-ordered'], updateElements['list-unordered']] }))), (0, jsx_runtime_1.jsxs)(ToggleButtons, Object.assign({}, ToggleButtonsProps, { children: [updateElements['superscript'], updateElements['subscript']] })), (0, jsx_runtime_1.jsxs)(ToggleButtons, Object.assign({}, ToggleButtonsProps, { children: [updateElements['link-add'], updateElements['link-remove']] })), (0, jsx_runtime_1.jsx)(ToggleButtons, Object.assign({}, ToggleButtonsProps, { children: actionElements['clear'] }))] })) })) })) })));
            }, parent: refs.root.current, anchor: textSelection === null || textSelection === void 0 ? void 0 : textSelection.selection, portal: true, alignment: 'center', position: 'bottom', clearOnClose: true }, AppendProps)));
    }, [open, textSelection, textSelected]);
    const menu = react_1.default.useMemo(() => {
        return ((0, jsx_runtime_1.jsx)(Menu, { open: openMenu, position: 'top', alignment: 'start', offset: offset, anchor: selectionMenu, onClose: onCloseSearch, label: label(), interactive: true }));
    }, [openMenu, optionsMention, selectionMenu, label]);
    let main = ((0, jsx_runtime_1.jsx)(TextField, Object.assign({ ref: (item) => {
            if (ref) {
                if ((0, utils_1.is)('function', ref))
                    ref(item);
                else
                    ref.current = item;
            }
            refs.root.current = item;
        }, color: color, tonal: tonal, version: 'text', size: size, minRows: 12, multiline: true, enabled: true, fullWidth: true, onInput: onInput, onKeyDown: onKeyDown, onKeyUp: onKeyUp, onFocus: onFocus, onBlur: onBlur, readOnly: readOnly, inputProps: Object.assign(Object.assign({ version: 'b2', contentEditable: true, spellCheck: false, onPaste: pasteText ? onPasteText : onPaste, onDrop,
            onMouseUp,
            onMouseDown, 'data-placeholder': placeholder !== undefined ? placeholder : name }, inputProps), { ref: (item) => {
                refs.input.current = item;
                if (inputProps === null || inputProps === void 0 ? void 0 : inputProps.ref) {
                    if ((0, utils_1.is)('function', inputProps.ref))
                        inputProps.ref(item);
                    else
                        inputProps.ref.current = item;
                }
            } }), InputComponent: Type, className: (0, style_react_1.classNames)([
            (0, utils_2.staticClassName)('SmartTextField', theme) && [
                'onesy-SmartTextField-root',
                `onesy-SmartTextField-version-${version}`,
                `onesy-SmartTextField-size-${size}`
            ],
            className,
            classes.root
        ]) }, additional, other)));
    if (version === 'text')
        main = ((0, jsx_runtime_1.jsx)(Type, Object.assign({ ref: (item) => {
                if (ref) {
                    if ((0, utils_1.is)('function', ref))
                        ref(item);
                    else
                        ref.current = item;
                }
                if (inputProps === null || inputProps === void 0 ? void 0 : inputProps.ref) {
                    if ((0, utils_1.is)('function', inputProps.ref))
                        inputProps.ref(item);
                    else
                        inputProps.ref.current = item;
                }
                refs.root.current = item;
                refs.input.current = item;
            }, color: color, tonal: tonal, onInput: onInput, onKeyDown: onKeyDown, onKeyUp: onKeyUp, onFocus: onFocus, onBlur: onBlur, onPaste: pasteText ? onPasteText : onPaste, onDrop: onDrop, onMouseUp: onMouseUp, onMouseDown: onMouseDown, spellCheck: false, "data-placeholder": placeholder !== undefined ? placeholder : name }, inputProps, { contentEditable: !readOnly, className: (0, style_react_1.classNames)([
                (0, utils_2.staticClassName)('SmartTextField', theme) && [
                    'onesy-SmartTextField-root',
                    `onesy-SmartTextField-version-${version}`,
                    `onesy-SmartTextField-size-${size}`
                ],
                className,
                classes.root_type,
                !multiline && classes.singleLine
            ]) }, additional, other)));
    return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [main, version === 'text' && (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: helperText && (0, utils_1.is)('string', helperText) ? ((0, jsx_runtime_1.jsx)(Type, Object.assign({ version: size === 'large' ? 'b1' : size === 'regular' ? 'b2' : 'b3' }, HelperTextProps, { className: (0, style_react_1.classNames)([
                        (0, utils_2.staticClassName)('SmartTextField', theme) && [
                            'onesy-SmartTextField-helper-text',
                            error && 'onesy-SmartTextField-error'
                        ],
                        HelperTextProps === null || HelperTextProps === void 0 ? void 0 : HelperTextProps.className,
                        classes.helperText,
                        error && classes.error_color
                    ]) }, { children: (0, utils_1.textToInnerHTML)(helperText) }))) : helperText }), miniMenu, menu] });
});
SmartTextField.displayName = 'onesy-SmartTextField';
exports.default = SmartTextField;