JSFiddle - React, Tailwind, and code Playground

HTML

<table class="table table-bordered"><thead></thead>
<tbody><tr><td></td></tr></tbody>
</table>

JavaScript

var setFieldIndex = function (columns) {
    var i, j, k,
        totalCol = 0,
        flag = [];
    
    for (i = 0; i < columns[0].length; i++) {
        totalCol += columns[0][i].colspan || 1;
    }
    
    for (i = 0; i < columns.length; i++) {
        flag[i] = [];
        for (j = 0; j < totalCol; j++) {
            flag[i][j] = false;
        }
    }
    
    for (i = 0; i < columns.length; i++) {
        for (j = 0; j < columns[i].length; j++) {
            var r = columns[i][j],
                rowspan = r.rowspan || 1,
                colspan = r.colspan || 1,
                index = $.inArray(false, flag[i]);
            
            if (colspan === 1) {
                r.fieldIndex = index;
                // when field is undefined, use index instead
                if (typeof r.field === 'undefined') {
                    r.field = index;
                }
            }
            
            for (k = 0; k < rowspan; k++) {
                flag[i + k][index] = true;
            }
            for (k = 0; k < colspan; k++) {
                flag[i][index + k] = true;
            }
        }
    }
}

$(function () {
    var data = [
    [
        {colspan: 4, title: 'Group1'},
        {rowspan: 3, title: 'ID'},
    ],  
    [
        {rowspan: 2, title: 'Name1'},
        {colspan: 3, title: 'Group2'},
    ],  
    [
        {title: 'Name2'},
        {title: 'Name3'},
        {title: 'Name4'},
    ]];

    setFieldIndex(data);
        console.log(data);

    var html = [];
    for (i = 0; i < data.length; i++) {
        html.push('<tr>');
        for (j = 0; j < data[i].length; j++) {
            var r = data[i][j];
    html.push('<th rowspan="' + r.rowspan + '" colspan="' + r.colspan + '">' + r.title + (typeof r.fieldIndex !== 'undefined' ? ': ' + r.fieldIndex : '') + '</th>');
        }
        html.push('</tr>');
    }
    $('thead').html(html.join(''));
});