Vue - Nested Draggable with Properties Dialog V4

Vue ideas to drive PE Properties dialog and draggable blocks and Block Treeview. You select more than one block and edit properties together. Selection order matters atm. Also uses a single component to wrapper all blocks with a single template with one set of code.

by Ben Clayton

HTML

<script src="https://unpkg.com/vue"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.16.0/vuedraggable.min.js"></script>
<div id="preview">
  <div class="collection with-header">
      <draggable :list="blocks"
                  :group="options"
             class="dragArea"
                  :move="beforeMove"
                  @end="onEnd">
         <component  v-for="(block,idx) in blocks" :is="block.componentId" :block="block" :key="idx"></component>
      </draggable>
   </div>
</div>
<hr>
<div id="propdialog">
  
    Properties: ({{blkname}}) {{blocks.length}} selected <br>
  
  <vue-propedit v-for="(option,idx) in options" :option="option" :blocks="blocks" :trigger="trigger" :block="block" :key="idx"></vue-propedit>

</div>
<div id="treedialog">
  
    Blocks: <br>
  
  <vue-treenode v-for="(block,idx) in blocks" :block="block" :key="idx"></vue-treenode>

</div>

CSS

.textbox-edit {
  display: block;
}

.textbox-edit label {
  display: inline-block;
  margin-right: 10px;
  width: 40px;
  text-transform: capitalize;
}
.textbox-edit input {
  width: 30%;
  font-size: 10px;
  height: 20px;
}

.select-edit select {
  display: inline-block;
  font-size: 10px;
  line-height: 12px;
  width: 40px;
  height: 20px;
  padding: 1px;
}

.color-edit {
  font-size: 10px;
}

.color-edit fieldset {
  border-width: 1px;
}

.color-edit label {
  width: 230px;
}

.color-edit fieldset legend {
  font-size: 10px;
}

#propdialog {
  display: inline-block;
  transition: all 1s ease;
  width: 50%;
  border: 1px solid gray;
  padding: 10px;
  margin: 10px;
  vertical-align: top;
}

.propedit {
  margin-bottom: 0px;
  display: inline-block;
}

.propedit .color-edit {
  width: 90%;
}

.color-edit input[type=range] {
  width: 20%;
}

#preview {
  margin-top: 30px;
  position: relative;
}

/* ------------------------------------- */
.block {
  overflow: hidden;
  position:relative;
  overflow: visible;
  margin: 10px;
}

.block.selected::before {
  display:block;
  content:'';
  position: absolute;
  top: 0;
  right: 0;
  width: 100%;
  height: 100%;
  font-size: 24px;
  border: 2px solid blue;
 }
  
  
.vue-box-block {
  padding: 5px;
}

.vue-wrapper-block {
  padding: 5px;
  position: relative;
}

.vue-wrapper-block > div {
  xxxposition: absolute;
}


.vue-circle-block {
  border: 1px solid gray;
  border-radius: 50%;
  padding-top: 19px;
  padding-left: 10px;
}

.vue-box-block.selected::before {
  border-color: blue;
}

.vue-wrapper-block.selected::before {
  border-color: blue;
}

.vue-circle-block.selected::before {
  border-color: red;
}

/* ------------------------- */
#treedialog {
  display: inline-block;
  transition: all 1s ease;
  width: 35%;
  border: 1px solid gray;
  padding: 5px;
  margin: 10px;
  vertical-align: top;
}

.treenode {
  margin-left: 20px;
  cursor: pointer;
  font-size: 10px;
}

.treenode::before {
  content: '';
  display:...

JavaScript

// Code copyright Holograph   2020


var global = {

  options1: {
    name: 'block',
    pull: true,
    put: true
  },
  options2: {
    name: 'block',
    pull: true,
    put: true
  }
}

// Some globals which should be now in a store  (Vuex)
//xblocks = [];
blockptr = [];



// Property Dialog Configs
// Here you can predefine menu controls her once
// Otherwise you would have to have this config repeated on each class where you wanted
// to allow edit of the same functional property

// 'width' does not need to be defined as the property dialog cleverly defaults a lot from
//  the name making config on the fly of the following
//  width: {
//    control: "textbox-edit",
//    propertyName: "width",
//    label: "width"   // CSS capitalises this to 'Width'
//  }
//
// 
var menuitems = {
  importance: {
    control: "select-edit",
    propertyName: "importance",
    label: "Importance",
    options: "h1:h1,h2:h2,h3:h3,h4:h4,h5:h5,h6:h6"
  },
  positioning: {
    control: "select-edit",
    propertyName: "positioning",
    label: "Positioning",
    options: "absolute:Absolute,relative:Relative"
  }
}


// Property Dialog Control components
// vue-propedit - is a base component for all controls
// vue-textbox-edit - textbox edit control
// vue-select-edit - dropdown edit control
// vue-color-edit - color edit control

// ==============================================================================
// Vue components


Vue.component('vue-treedialog', {
  props: ["blocks"],
  template: `
  	<div id="treedialog">
      	Blocks: <br>
    		<vue-treenode v-for="(block,idx) in blocks" :block="block" :key="idx"></vue-treenode>
		</div>  
      `,
});

Vue.component('vue-treenode', {
  props: ["block"],
  data: function() {
    return {
      "blocks": this.block.blocks
    }
  },
  template: `
  	<div class="treenode" :class="{selected: block.selected}"  @click.stop="block.select($event)"> 
      	{{block.name}} {{block.idx}}<br>
        <vue-treenode...