Column resize modes

by stitot

HTML

<script src="https://cdn.jsdelivr.net/npm/@highcharts/grid-lite/grid-lite.js"></script>
<h1>API naming</h1>
<p>
Only a suggestion, here we go:
</p>
<p>
<em>independent</em>: one column acts alone, independently of others<br>
<em>adjacent</em>: the change is shared only with its adjacent neighbour<br>
<em>distributed</em>: the change is spread/distributed across the grid<br><br>
</p>

<h1>The basics</h1>
<p>
The main point of these 3 basic grids is to highlight that initial rendering is the same for all. No need to talk about "distribution strategy". It is what it is, and only if resizing is important to you you need to care about resizingMode. 
</p>

<div id="container_1"></div>
<div id="container_2"></div>
<div id="container_3"></div>

<h1>Defined widths</h1>
<p>
More complex variants, but the principels are the same as above.
</p>

<div id="container_4"></div>
<div id="container_5"></div>
<div id="container_6"></div>
<div id="container_7"></div>

CSS

@import url("https://cdn.jsdelivr.net/npm/@highcharts/grid-lite/css/grid.css");

.hcg-theme-default {
    --hcg-column-border-width: 1px;
    --hcg-caption-font-size: 15px;
}

#container {
    height: 250px;
    padding: 8px;
}

@media (prefers-color-scheme: dark) {
    #container {
        background-color: #292929;
    }
}

code {
background: #ddd;
display: inline-block;
padding: 2px 5px;
border-radius: 5px;
}

body {
  font-family: sans-serif;
  font-size: 14px;
  line-height: 1.2em;
}

JavaScript

function generateDataTable(numRows, numColumns) {
  const result = { columns: {} }

  for (let col = 1; col <= numColumns; col++) {
    const colName = "C" + col
    result.columns[colName] = []
    for (let row = 1; row <= numRows; row++) {
      result.columns[colName].push(col + "." + row)
    }
  }
  return result
}

class IndependentDistributionStrategy extends Grid.ColumnDistribution.types
  .mixed {
  type = "independent"

  resize(resizer, diff) {
    const column = resizer.draggedColumn
    if (!column) {
      return
    }

    this.columnWidths[column.id] = Math.max(
      (resizer.columnStartWidth || 0) + diff,
      IndependentDistributionStrategy.getMinWidth(column),
    )
    this.columnWidthUnits[column.id] = 0 // Always save in px

    this.viewport.columns.forEach((c) => {
      if (!c.options.width) {
        this.columnWidths[c.id] = c.getWidth()
        this.columnWidthUnits[c.id] = 0
      }
    })
  }
}

class DistributedDistributionStrategy extends Grid.ColumnDistribution.types
  .mixed {
  constructor(viewport) {
    super(viewport)
    this.type = "distributed"
  }

  resize(resizer, diff) {
    const column = resizer.draggedColumn
    if (!column) {
      return
    }

    this.columnWidths[column.id] = Math.max(
      (resizer.columnStartWidth || 0) + diff,
      DistributedDistributionStrategy.getMinWidth(column),
    )
    this.columnWidthUnits[column.id] = 0 // Always save in px
  }
}

Grid.ColumnDistribution.types.independent = IndependentDistributionStrategy
Grid.ColumnDistribution.types.distributed = DistributedDistributionStrategy

Grid.grid("container_1", {
  dataTable: generateDataTable(50, 5),
  caption: {
    text: "<code>resizingMode: 'adjacent'</code> (no config, so default  is used). This is the out-of-the-box sensible default that will cover most usecases for an inline grid primarily ment for data viewing.",
  },
})

Grid.grid("container_2", {
 ...