JSFiddle - React, Tailwind, and code Playground

by levchenko_d

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/quill/1.1.10/quill.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/quill/1.1.10/quill.snow.min.css">
<script src="https://beat.today/javascripts/functions.js"></script>
<link rel="stylesheet" href="//cdn.quilljs.com/1.2.0/quill.bubble.css">
<div class="editor-wrapper">
  <textarea name="task-description" style="display: none;"></textarea>
  <form method="POST" action="/project/app/files/add" enctype="multipart/form-data" class="upload-form"><input type="file" name="files" multiple="multiple"></form>
  <div class="toolbar ql-toolbar ql-snow">
    <span class="ql-formats">
      <button type="button" class="ql-bold"></button>
      <button type="button" class="ql-italic">i</button>
      <button type="button" class="ql-blockquote">"</button>
    </span>
    
    <span class="ql-formats">
      <button type="button" class="ql-link">πŸ”—</button>
      <button type="button" class="ql-code-block">&lt;\&gt;</button>
      <button type="button" class="ql-list" value="bullet">πŸ—’</button>
    </span>
    
    <span class="ql-formats">
      <button type="button" class="ql-file">πŸ“Ž</button>
<!--       <button type="button" class="ql-image">🏞</button> -->
      <button type="button" class="ql-image-url" >πŸ“·</button>
      <button type="button" class="ql-video">πŸŽ₯</button>
    </span>
  </div>
  <div class="editor ql-container ql-snow">
  <p><strong>This is Hello World Example</strong></p>

   <p> <a href="https://jsfiddle.net/levchenko_d/cnq51sxa/">Heey</a></p>
   <p> www.google.com</p>
  </div>
</div>

CSS

/* QL EDITOR */


.ql-toolbar.ql-snow,
.ql-container.ql-snow{
  border: none;
}

.ql-toolbar.ql-snow{
  display: inline-block;
  box-shadow: 0 1px 3px rgba(0,0,0,0.15);
  border-radius: 7px;
      padding: 3px;
    margin-left: 13px;
  background: #fff;
}

.ql-toolbar .ql-file:after{
  content: '';
}

.ql-snow .ql-tooltip {
    background-color: rgba(0, 0, 0, 0.73);
    border: none;
    box-shadow: none;
    color: #fff;
    padding: 5px;
    white-space: nowrap;
    border-radius: 7px;
    left: 10% !important;
    right: 10%;
}

.ql-tooltip::before{
  content: '' !important;
  margin: 0;
}

.ql-snow .ql-tooltip .ql-action{

}

.ql-snow .ql-tooltip input[type=text] {
    display: none;
    border: none;
    font-size: 13px;
    height: 26px;
    margin: 0;
    padding: 3px 0;
    width: calc(100% - 100px);
    box-sizing: border-box;
    background: transparent;
    color: #fff;
}

.ql-snow .ql-tooltip input[type=text]:focus{
  outline: none;
}

.ql-snow .ql-tooltip a.ql-preview{
    max-width: calc(100% - 150px);
    text-decoration: underline;
    color: #fff;
}

.ql-tooltip-image.error{
  background: red;
  animation: shake 0.5s;
}

.ql-snow .ql-tooltip .ql-action, .ql-snow .ql-tooltip .ql-remove {
    color: #fff;
    float: right;
    border: none;
    max-width: 50px;
    right: 20px;
}

.ql-snow .ql-tooltip a.ql-action::after{
  border: none;
}

@keyframes shake {
  10%, 90% {
    transform: translate3d(-1px, 10px, 0);
  }
  
  20%, 80% {
    transform: translate3d(2px, 10px, 0);
  }

  30%, 50%, 70% {
    transform: translate3d(-4px, 10px, 0);
  }

  40%, 60% {
    transform: translate3d(4px, 10px, 0);
  }
}

.editor-wrapper{
 
}

.editor-wrapper .upload-form{
  display: none;
}

.editor-wrapper .editor{
  min-height: 200px;
  padding: 15px;
}

.ql-editor{
  padding: 0;
}

.editor p, .editor ol, .editor ul, .editor pre, .editor blockquote, .editor h1, .editor h2, .editor h3, .editor h4, .editor h5, .editor h6 {
    margin: 0;
    padding: 0;
   ...

JavaScript

App.q = function(selector){
  return selector ? document.querySelector(selector) : {};
};


function removeClass(classNames){
  var _t = this,
      currentClass = _t.className;

  classNames.split(' ').loop(function(className){
    var reg = new RegExp('([^-_]|^)'+className+'([^-_]|$)', 'gm');

    _t.className = currentClass.replace(reg, ' ').replace(/\s+/g, " ");
    _t.className = _t.className.replace(/\s+/g, " ").trim();
  });

  return _t;
};

Element.prototype.removeClass = removeClass;
function parseIntSafe(n){ return parseInt(n)||0; };

App.create = function(tag, options){
  var Elem = document.createElement(tag);

  for(attr in options){
    Elem.setAttribute(attr, options[attr]);
  }

  return Elem;
};

function isFn(fn){
  if(fn && typeof(fn) === 'function'){
    return fn
  } else {
    return function(){
      return false
    };
  }
};

function getScrollTop(obj){
  if(obj === document.body){
    return document.documentElement.scrollTop || document.body.scrollTop;
  } else {
    return obj.scrollTop;
  }
};

App.getScrollTop = function(obj){
  if(obj === document.body){
    return document.documentElement.scrollTop || document.body.scrollTop;
  } else {
    return obj.scrollTop;
  }
};

/* Progress usage example:

<span class="progress-icon-wrapper">
  <span class="text text-queue">
    <!-- Progress queue will be placed here via innerText -->
  </span>
  <span class="icon-wrapper">
    <!-- Progress icon will be placed here via appendChild -->
  </span>
  <span class="text loading-text">
    <!-- Progress percentage (45%) will be placed here via innerText -->
  </span>
</span>



var uploadProgress = new App.Progress({
  wrapper : '.wrapper-selector',
  progress : 49, //49%

  //circular options
  radius: 14, //default 14
  strokeWidth:, 4 //default 4
});

uploadProgress.update(50);
uploadProgress.update(75);
// ...
// And so on
*/

var Progress = function(options){
  var t = this,
      o = options;

  t.wrapperSelector = o.wrapper;
  t.wrapper...