JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<div id="main-input" contenteditable="true">

  <span style="font-size: 24px">Hello <span style="color: rgb(255, 0, 0)"> red world!</span> and black text</span><br>
  <span style="color: rgb(0, 255, 0)"><b>Green text</b></span>

  <br></div>

JavaScript

/**
 * Get current selection Range
 * @returns {*}
 */
function getSelectionRange() {
    var sel;
    if (window.getSelection) {
        sel = window.getSelection();
        if (sel.rangeCount) {
            return sel.getRangeAt(0);
        }
    } else if (document.selection) {
        return document.createRange();
    }

    return null;
}

(function ($) {
    var $mainInput = $('#main-input');

    var draggedText;
    var dragStartContainer;
    var dragEndContainer;
    var dragStartOffset;
    var dragEndOffset;

    $mainInput.on('dragstart', function(e) {
        var dragRange = getSelectionRange();
        dragStartContainer = dragRange.startContainer;
        dragEndContainer   = dragRange.endContainer;
        dragStartOffset    = dragRange.startOffset;
        dragEndOffset      = dragRange.endOffset;
        draggedText        = e.originalEvent.dataTransfer.getData("text");
    });

    $mainInput.on('drop', function(e) {
        // Get caret at mouse cursor position
        var range     = createCollapsedRangeFromPoint(e.clientX, e.clientY);
        var container = range.startContainer;

        if(container === 'undefined' || !container) { // for IE browser
            var rangeCopy=range.duplicate(); //Create a copy
            var rangeObj=range.duplicate();
            rangeCopy.collapse(true); //Go to beginning of the selection
            rangeCopy.moveEnd('character',1); //Select only the first character
            var parentElement=rangeCopy.parentElement();
            rangeObj.moveToElementText(parentElement); //Select all text of parentElement
            rangeObj.setEndPoint('EndToEnd',rangeCopy); //Set end point to the first character of the 'real' selection
            var text=rangeObj.text; //Now we get all text from parentElement's first character upto the real selection's first character

            //Iterate through all the child text nodes and check for matches
            //As we go through each text node keep removing the...