JSFiddle - React, Tailwind, and code Playground

HTML

<h2>Openly configurable:</h2>
<div id="no1"></div>
<div style="min-height: 40px;"></div>
JSON:
<div id="no1JSON"></div>

<h2>Closed configuration:</h2>
<div id="no2"></div>
<div style="min-height: 40px;"></div>
JSON:
<div id="no2JSON"></div>

CSS

.container .spacer, .container .sub_element, .container .numeric_content, .container .string_content  {
    padding-left: 12px;  
    position: relative;   
}
.container .spacer::before, .container .spacer::after,
.container .sub_element::before, .container .sub_element::after, 
.container .numeric_content::before, .container .numeric_content::after, 
.container .string_content::before, .container .string_content::after{
    content: '';
    position: absolute;
    left: 0;
}
.container .sub_element::before, .container .numeric_content::before, .container .string_content::before{
    border-top: 1px solid #999;
    top: 12px;
    width: 12px;
    height: 0;    
}
.container .spacer::after, .container .sub_element::after, .container .numeric_content::after, .container .string_content::after{
    border-left: 1px solid #999;
    height: 100%;
    width: 0px;
    top: -12px; 
}
.spacer::after, .sub_element::after, .numeric_content::after, .string_content::after{
    top: 12px;
}
.sub_element:last-child::after {
    height: 24px;
}
.needed {
    border-color: red;
    border-width: 2;
}
.duplicate {
    border-color: green;
    border-width: 2;
}
input {
    border-width: 0;
    background-color: transparent;
    padding-left: 5px;
    height: 24px;
}
input:disabled {
    padding-left: 10px;
}
.spacer {
    height: 5px;
}
.additional {
    background-color: white;
}
select {
    height: 22px;
    padding:3px;
    margin: 0;
    -webkit-border-radius:4px;
    -moz-border-radius:4px;
    border-radius:4px;
    -webkit-box-shadow: 0 3px 0 #ccc, 0 -1px #bbb inset;
    -moz-box-shadow: 0 3px 0 #ccc, 0 -1px #bbb inset;
    box-shadow: 0 3px 0 #ccc, 0 -1px #bbb inset;
    background: #eee;
    color:#444;
    border:none;
    outline:none;
    display: inline-block;
    -webkit-appearance:none;
    -moz-appearance:none;
    appearance:none;
    cursor:pointer;
}

JavaScript

(function (document, $) {
    context = function(container, config) {
        var class_names, drop_labels, include_spacers, refreshHandler, modifiable_form
        
        // set configuration variables to config dictionary/object
        function resetConfig(config) {
            if (!config) {
                config = {}
            }
            class_names = config['class_names']
            if (class_names == undefined) {
                class_names = {string_content:"string_content",
                               numeric_content:"numeric_content",
                               array_content:"array_content",
                               object_content:"object_content",
                               sub_element:"sub_element",
                               content:"content",
                               container:"container",
                               spacer:"spacer",
                               additional:"additional",
                               needed:"needed",
                               duplicate:"duplicate",
                               name_box:"name_box"}
            }
            drop_labels = config['drop_labels']
            if (drop_labels == undefined) {
                drop_labels = {None:"",
                               String:"String",
                               Number:"Number",
                               Array:"Array",
                               Object:"Object"}
            }
            include_spacers = config['include_spacers']
            refreshHandler = config['refreshHandler']
            modifiable_form = config['modifiable_form']
            if (modifiable_form == undefined) {
                modifiable_form = true
            }
        }
        //call it
        resetConfig(config)
        
        // manually set the refresh handler hook
        function setRefreshHandler(handler) {
            refreshHandler = handler
        }
        // Given the 'content' DOM object of a presumed string...