constructor(templates, preview = false, disableHTMLLabels = false, controlConfig = {}) {
    this.preview = preview ?? false
    this.disableHTMLLabels = disableHTMLLabels ?? false
    this.controlConfig = controlConfig ?? {}

    // supported templates for outputting a field
    // preferred layout template can be indicated by specifying a 'layout' in the return object of control::build
    this.templates = {
      label: null, // can be overridden with a function(labelDOMElements, data) to generate the label element - returns a DOM element
      help: null, // can be overridden with a function(helpText, data) to generate the help element - returns a DOM element
      default: (field, label, help, data) => {
        // append help into the label
        if (help) {
          label.appendChild(help)
        }

        return this.markup('div', [label, field], {
          className: processClassName(data, field),
        })
      },
      noLabel: (field, label, help, data) => {
        return this.markup('div', field, {
          className: processClassName(data, field),
        })
      },
      hidden: field => {
        // no wrapper any any visible elements
        return field
      },
    }

    // merge in any custom templates
    if (templates) {
      this.templates = jQuery.extend(this.templates, templates)
    }
    this.configure()
  }
Prepare the templates for layout
@param {Object} templates object containing custom or overwrite templates
@param {Boolean} [preview=false] - are we rendering a preview for the formBuilder stage
@param {Boolean} [disableHTMLLabels=false] - do we render labels as HTML or plain text
@param {Array} [controlConfig={}] - ability for controls to have their own configuration / options of the format control identifier (type, or type.subtype): {options}