function processTypeUserAttrs(typeUserAttr, values) {
    const advField = []
    const attrTypeMap = {
      array: selectUserAttrs,
      string: inputUserAttrs,
      number: numberAttribute,
      boolean: (attr, attrData) => {
        let isChecked = false
        if (attr.type === 'checkbox') {
          isChecked = Boolean(attrData.hasOwnProperty('value') ? attrData.value : false)
        } else if (values.hasOwnProperty(attr)) {
          isChecked = values[attr]
        } else if (attrData.hasOwnProperty('value') || attrData.hasOwnProperty('checked')) {
          isChecked = attrData.value || attrData.checked || false
        }
        return boolAttribute(attr, { ...attrData, [attr]: isChecked }, { first: i18n[attr] })
      },
      options: fieldOptions,
    }

    for (const attribute in typeUserAttr) {
      if (typeUserAttr.hasOwnProperty(attribute)) {
        const attrValType = userAttrType(typeUserAttr[attribute])
        if (attrValType !== 'undefined') {
          const orig = mi18n.get(attribute)
          const tUA = Object.assign({}, typeUserAttr[attribute]) //Ensure we work on a copy of the attributes
          let origValue = tUA.value
          if (attrValType === 'boolean') {
            tUA[attribute] ??= tUA.value
          } else if (attrValType === 'number') {
            tUA[attribute] ??= firstNumberOrUndefined(values[attribute], origValue)
          } else {
            origValue ??= ''
            tUA[attribute] ??= values[attribute] || origValue
          }
          tUA.value = tUA[attribute]

          if (tUA.label) {
            i18n[attribute] = Array.isArray(tUA.label) ? mi18n.get(...tUA.label) || tUA.label[0] : tUA.label
          }

          if (attrTypeMap[attrValType]) {
            advField.push(attrTypeMap[attrValType](attribute, tUA))
          }

          i18n[attribute] = orig
        } else if (attrValType === 'undefined' && hasSubType(values, attribute)) {
          advField.push(processTypeUserAttrs(typeUserAttr[attribute], values))
        } else {
          const def = {}
          def[attribute] = typeUserAttr[attribute]
          opts.notify.warning('Warning: unable to process typeUserAttr definition : ' + JSON.stringify(def))
        }
      }
    }

    return advField.join('')
  }
Processes typeUserAttrs
@param  {Object} typeUserAttr option
@param  {Object} values       field attributes
@return {string}              markup for custom user attributes