JSFiddle - React, Tailwind, and code Playground

Container Example from before, now with WebComponents

by nilloc

HTML

<script src="https://paperclipped.com/js/libraries/parseCSS.js"></script>
<!-- <script src="https://raw.githubusercontent.com/mdevils/node-css-selector-parser/master/lib/css-selector-parser.js" type="text/javascipt"></script> -->

<modkit-container id="editor" row="1" col="1">
  <modkit-container id="toolbar" row="1" col="n">
    <modkit-style>
      default{
        top:0;
        left:0;
        right:0;
        height:60px;
        background-image: linear-gradient(-180deg, #C1C1C1 0%, #AFAFAF 100%);
        box-shadow: 0 1px 3px 0 rgba(0,0,0,0.25);
      }
      .light{
        background-image: linear-gradient(-180deg, #F3F3F3 0%, #E6E6E6 98%);
      }
      .dark{
        background-image: linear-gradient(-180deg, #666666 0%, #4C4C4C 100%);
      }
    </modkit-style>
    toolbar
  </modkit-container>
  <modkit-container id="drawer" row="n" col="1">
    <modkit-style>
      default{
        top:0;
        left:0;
        width:200px;
        bottom:20px; /* could be switched to footer top */
      }
    </modkit-style>
    drawer
  </modkit-container>
  <modkit-container id="handle">
    <modkit-style>
      default{
        top:$('#toolbar').bottom();
        left:$(':prev-sibling()').right();
        right:0;
        bottom:20px;
      }
    </modkit-style>
  </modkit-container>
  <modkit-container id="stage">
    <modkit-style>
      default{
        top:$('#toolbar').bottom();
        left:$('#handle').right();
        right:0;
        bottom:20px;
      }
    </modkit-style>
    stage
    <anchor class="top" contenteditable data-setting="toolbar.bottom">toolbar.bottom</anchor>
    <anchor class="left" contenteditable data-setting="handle.right">handle.right</anchor>
    <anchor class="right" contenteditable data-setting="0">0</anchor>
    <anchor class="bottom" contenteditable data-setting="0">0</anchor>
    <anchor class="width" contenteditable data-setting="auto">auto</anchor>
    <anchor class="height" contenteditable...

SCSS

*{
  box-sizing:border-box;
}
modkit-container{
  display:block;
  position:relative;
  user-select:none;
  overflow:hidden;
}

modkit-style{
  display:none;
}

#editor, #drawer, #handle, #stage{
  position:absolute;
}

#editor{
  background:darkgray;
  top:0;
  left:0;
  bottom:0;
  right:0;
  
  $toolbar-height:60px;
  $drawer-width:200px;
  $handle-width:4px;
  
  #toolbar{
    background:lightgray;
    height:$toolbar-height;
    padding:10px;
    box-shadow:0 2px 3px rgba(0,0,0,0.3);
    z-index:900;
  }
  #drawer{
    background:white;
    top:$toolbar-height;
    left:0;
    width:$drawer-width;
    bottom:0;
  }
  #handle{
    background:#777;
    top:$toolbar-height;
    left:$drawer-width;
    width:$handle-width;
    bottom:0;
    cursor:col-resize;
    z-index:1000;
  }
  #stage{
    background:#eee;
    top:$toolbar-height;
    left:auto;//$drawer-width+$handle-width;
    right:0;
    bottom:0;
  }
  
  
  anchor{
    display:block;
    position:absolute;
    height:20px;
    width:100px;
    background:white;
    border:1px solid darkgray;
    border-radius:4px;
    text-align:center;
    outline: none;
    overflow:hidden;
    
    &.top,  &.bottom, &.height, &.width{left:calc(50% - 50px);}
    &.left, &.right{top:calc(50% - 20px);}
    &.top, &.left, &.right{border-radius:0 0 4px 4px;}
    &.top{top:0;}
    &.bottom{bottom:0;  border-radius:4px 4px 0 0;}
    &.left{   left:-40px; transform:rotate(-90deg); }
    &.right{ right:-40px; transform:rotate(90deg);  }
    &.width{top:calc(50% - 50px);
    }
    &.height{top:calc(50%);
    }
  }
  
  #height-label, #width-label{position:absolute; left:calc(50% - 50px);}
  #height-label{top:calc(50% - 20px);}
  #width-label{top:calc(50% - 70px)}

}

JavaScript

// Add better position methods to $
$.prototype.top = function (margin = false){
return this.offset().top - ((margin === true)? this.css('margin-top'):0);
}
$.prototype.left = function (margin = false){
//console.log("left:", this.offset().left)
return this.offset().left - ((margin === true)? this.css('margin-left'):0);
}
$.prototype.right = function (margin = false){
//console.log('alinging to right edge:', this.outerWidth(margin))
return this.offset().left + this.outerWidth(margin);
}
$.prototype.bottom = function (margin = false){
return this.offset().top + this.outerHeight(margin);
}

$('anchor').on("input", function(){
	console.log($(this).parent(), "changed:", this.textContent.length);

  var $parent = $(this).parent();
  var setting = this.textContent;
  if(this.textContent.length < 1){
  	setting = '0';
  }
  //(this.textContent.length<1)? this.textContent : "0";
  if(setting.indexOf('%') > -1){
    $parent.css(this.className, setting); // make %
    this.dataset.setting = setting;
    // TODO: Could split on . when there is a word first and use a different target for position (width or height depending on anchor)
  }else if(setting == parseFloat(setting)){
  	$parent.css(this.className, setting+"px"); // make abs (px)
    this.dataset.setting = setting;
  }else{
  	// search for id and attach based on edge
    
    //console.log('new $target:', setting)
    
    var edge = this.className;
    if(setting.indexOf('.')>-1){
      var settings = setting.split('.');
      var $target = $('modkit-container#'+settings[0]);
      //if(settings[1] == "top" || settings[1] == "left" || settings[1] == "right"|| settings[1] == "bottom"){
      if($target[settings[1]]){
        var edge = settings[1];
        console.log('found edge:', $target, edge)
      }
    }else{
    	var $target = $('modkit-container#'+setting);
    }
    if($target.length > 0 ){
      //console.log("found:", $target);
      this.dataset.setting = setting;
/* switch(this.className){
       ...