@toclocoinc/lattice-grid 1.45.0 → 1.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +1 -1
  2. package/docs/API.html +7 -0
  3. package/docs/api-detail.html +71 -1
  4. package/lattice-grid.d.ts +62 -1
  5. package/lattice-grid.esm.min.js +60 -6
  6. package/lattice-grid.min.cjs +60 -6
  7. package/lattice-grid.min.css +1 -1
  8. package/lattice-grid.min.js +60 -6
  9. package/modules/ai.esm.min.js +4 -4
  10. package/modules/ai.min.cjs +4 -4
  11. package/modules/ai.min.js +4 -4
  12. package/modules/angular.esm.min.js +2 -2
  13. package/modules/angular.min.cjs +2 -2
  14. package/modules/angular.min.js +2 -2
  15. package/modules/chart-alluvial.esm.min.js +1 -1
  16. package/modules/chart-arc.esm.min.js +1 -1
  17. package/modules/chart-bubblemap.esm.min.js +1 -1
  18. package/modules/chart-bump.esm.min.js +1 -1
  19. package/modules/chart-calendar.esm.min.js +1 -1
  20. package/modules/chart-decomposition.esm.min.js +1 -1
  21. package/modules/chart-diverging.esm.min.js +1 -1
  22. package/modules/chart-dumbbell.esm.min.js +1 -1
  23. package/modules/chart-fan.esm.min.js +1 -1
  24. package/modules/chart-hexbin.esm.min.js +1 -1
  25. package/modules/chart-hexmap.esm.min.js +1 -1
  26. package/modules/chart-icicle.esm.min.js +1 -1
  27. package/modules/chart-parallel.esm.min.js +1 -1
  28. package/modules/chart-ridgeline.esm.min.js +1 -1
  29. package/modules/chart-roc.esm.min.js +1 -1
  30. package/modules/chart-slope.esm.min.js +1 -1
  31. package/modules/chart-splom.esm.min.js +1 -1
  32. package/modules/chart-waffle.esm.min.js +1 -1
  33. package/modules/charts.esm.min.js +4 -4
  34. package/modules/charts.min.cjs +4 -4
  35. package/modules/charts.min.js +4 -4
  36. package/modules/data-router.esm.min.js +4 -4
  37. package/modules/data-router.min.cjs +4 -4
  38. package/modules/data-router.min.js +4 -4
  39. package/modules/devtools.esm.min.js +2 -2
  40. package/modules/devtools.min.cjs +2 -2
  41. package/modules/devtools.min.js +2 -2
  42. package/modules/dhtmlx-compat.esm.min.js +4 -4
  43. package/modules/dhtmlx-compat.min.cjs +4 -4
  44. package/modules/dhtmlx-compat.min.js +4 -4
  45. package/modules/gantt.esm.min.js +4 -4
  46. package/modules/gantt.min.cjs +4 -4
  47. package/modules/gantt.min.js +4 -4
  48. package/modules/htmx.esm.min.js +60 -6
  49. package/modules/htmx.min.cjs +60 -6
  50. package/modules/htmx.min.js +60 -6
  51. package/modules/kanban.esm.min.js +4 -4
  52. package/modules/kanban.min.cjs +4 -4
  53. package/modules/kanban.min.js +4 -4
  54. package/modules/kpi.esm.min.js +4 -4
  55. package/modules/kpi.min.cjs +4 -4
  56. package/modules/kpi.min.js +4 -4
  57. package/modules/mock-socket.esm.min.js +2 -2
  58. package/modules/mock-socket.min.cjs +2 -2
  59. package/modules/mock-socket.min.js +2 -2
  60. package/modules/react.esm.min.js +2 -2
  61. package/modules/react.min.cjs +2 -2
  62. package/modules/react.min.js +2 -2
  63. package/modules/svelte.esm.min.js +2 -2
  64. package/modules/svelte.min.cjs +2 -2
  65. package/modules/svelte.min.js +2 -2
  66. package/modules/vue.esm.min.js +2 -2
  67. package/modules/vue.min.cjs +2 -2
  68. package/modules/vue.min.js +2 -2
  69. package/modules/webcomponent.esm.min.js +60 -6
  70. package/modules/webcomponent.min.cjs +60 -6
  71. package/modules/webcomponent.min.js +60 -6
  72. package/package.json +1 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  dependencies, no build step required. Optional adapters for React, Vue, Svelte
5
5
  and Web Components ship alongside it.
6
6
 
7
- Version 1.45.0 · [latticegrid.dev](https://www.latticegrid.dev) · TOCLOCO Inc
7
+ Version 1.46.1 · [latticegrid.dev](https://www.latticegrid.dev) · TOCLOCO Inc
8
8
 
9
9
  ---
10
10
 
package/docs/API.html CHANGED
@@ -872,6 +872,8 @@ autoInit(document); <span class="cmt">// builds every [data-lattice-grid] under
872
872
  <tr><td class="name">gridLines</td><td class="type">boolean | 'both' | 'horizontal' | 'vertical' | 'none'</td><td class="dflt">'horizontal'</td><td class="desc">Which rules are drawn between cells. Horizontal is what the grid has always drawn; vertical rules are additive. <code>'rows'</code> and <code>'columns'</code> are accepted aliases. Only the rules between data are affected, the header underline and pinned seams are structure.</td></tr>
873
873
  <tr><td class="name">cornerRadius</td><td class="type">boolean | number | string</td><td class="dflt">, </td><td class="desc">Round the grid's outer corners. <code>true</code> adopts the theme's radius, a number is pixels, a string is used as written.</td></tr>
874
874
  <tr><td class="name">stripedRows</td><td class="type">boolean</td><td class="dflt">false</td><td class="desc">Shade alternate data rows (zebra striping). Strictly opt-in, so an existing grid is unchanged on upgrade. Parity follows each row's logical index, so a stripe survives a scroll; group headings, footers and the grand total are never striped; selection and hover still win. Uses the theme's <code>--lattice-surface-alt</code>, so dark, high-contrast and terminal come for free.</td></tr>
875
+ <tr><td class="name">verticalAlign</td><td class="type">'top' | 'middle' | 'bottom'</td><td class="dflt">, </td><td class="desc">Vertical alignment of cell content within a row, as a default for every column &mdash; the vertical counterpart to the per-column <code>align</code>. A column's own <code>verticalAlign</code> (or <code>cell.verticalAlign</code>) overrides it. Omitted, the grid keeps its historical placement (centred in a fixed-height row, top in an <code>autoHeight</code> row), so an existing grid is unchanged on upgrade. Setting a value aligns every column uniformly, including auto-height rows, unless a column opts out. See <a href="api-detail.html#vertical-align">Vertical alignment</a>.</td></tr>
876
+ <tr><td class="name">scrollbars</td><td class="type">'auto' | 'always' | { x, y }</td><td class="dflt">'auto'</td><td class="desc">Keep the scroll viewport's scrollbars visible. <code>'auto'</code> is the platform's native behaviour, where overlay scrollbars fade when idle; <code>'always'</code> keeps both axes shown whether or not the pointer is over the grid. The object form <code>{ x, y }</code> pins each axis on its own, so <code>{ y: 'always' }</code> keeps the vertical bar while the horizontal one stays native. Omitted, the grid is unchanged on upgrade. See <a href="api-detail.html#scrollbars">Always-visible scrollbars</a>.</td></tr>
875
877
  <tr><td class="name">columnTagFilter</td><td class="type">boolean | { multiple, label }</td><td class="dflt">, </td><td class="desc">A bar above the headings for showing only the columns carrying a chosen tag. Draws nothing unless some column has <code>tags</code>. See <a href="api-detail.html#column-tags">Column tags</a>.</td></tr>
876
878
  <tr><td class="name">rowTemplate</td><td class="type">string | { template, cardsPerRow, maxCardWidth, gap, className, role, itemRole }</td><td class="dflt">, </td><td class="desc">Draw each row with a template instead of dividing it into columns, a card list, a feed, a search-result list. Compiles once; binds with <code>{{data.field}}</code>. <code>cardsPerRow</code> or <code>maxCardWidth</code> puts several on a line. The pipeline underneath is unchanged. See <a href="api-detail.html#cards">Cards, lists and feeds</a>.</td></tr>
877
879
  <tr><td class="name">gallery</td><td class="type">boolean | { template, tileWidth, tileHeight, cardsPerRow, gap, className, role, itemRole }</td><td class="dflt">, </td><td class="desc">Present rows as a gallery of tiles, laid out by the same 2-D virtualisation the grid runs. <code>true</code> generates a tile per row from the columns; <code>tileWidth</code> sizes them and the count across follows the container, or <code>cardsPerRow</code> fixes it. Presentation only &mdash; sort, filter, group and export are unchanged. See <a href="api-detail.html#cards">Cards, lists and feeds</a>.</td></tr>
@@ -6979,6 +6981,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
6979
6981
  <tr><td class="name">layout</td><td class="type">ColumnLayoutSpec | number</td><td class="desc">Width, pinning and flex. A bare number is the width in pixels. <small>(optional)</small></td></tr>
6980
6982
  <tr><td class="name">header</td><td class="type">ColumnHeaderSpec | string</td><td class="desc">The header cell: its text, tooltip, menu and any header chart. <small>(optional)</small></td></tr>
6981
6983
  <tr><td class="name">headerControls</td><td class="type">'hover' | 'always' | 'hidden'</td><td class="desc">When this column's header controls — its sort arrow, filter funnel and menu button — are shown, overriding the grid-level `headerControls` default for this column alone (BACKLOG-0000982). `'hover'` reveals them on hover or focus, `'always'` keeps them visible, `'hidden'` draws none of them and leaves them out of the tab order. Omitted, the column follows the grid default, which is itself `'hover'`. <small>(optional)</small></td></tr>
6984
+ <tr><td class="name">verticalAlign</td><td class="type">VAlign</td><td class="desc">Vertical alignment of this column's cell content within the row (BACKLOG-0000989). Overrides the grid-level `verticalAlign` for this column alone; `top`, `middle` or `bottom`. Also accepted as `cell.verticalAlign`, the way `align` is. Omitted, the column follows the grid default. <small>(optional)</small></td></tr>
6982
6985
  <tr><td class="name">export</td><td class="type">ColumnExportSpec</td><td class="desc">How the column leaves the grid, where that differs from how it is shown. <small>(optional)</small></td></tr>
6983
6986
  <tr><td class="name">allowGroup</td><td class="type">boolean</td><td class="desc">Whether the user may group by this column from the interface. <small>(optional)</small></td></tr>
6984
6987
  <tr><td class="name">allowPivot</td><td class="type">boolean</td><td class="desc">Whether the user may pivot on it. <small>(optional)</small></td></tr>
@@ -7003,6 +7006,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
7003
7006
  <tr><td class="name">style</td><td class="type">CellStyle | ((p: CellParams) =&gt; CellStyle)</td><td class="desc"><small>(optional)</small></td></tr>
7004
7007
  <tr><td class="name">tooltip</td><td class="type">string | ((p: CellParams) =&gt; string)</td><td class="desc"><small>(optional)</small></td></tr>
7005
7008
  <tr><td class="name">align</td><td class="type">Align</td><td class="desc"><small>(optional)</small></td></tr>
7009
+ <tr><td class="name">verticalAlign</td><td class="type">VAlign</td><td class="desc">Vertical alignment of this column's cell content, overriding the grid-level `verticalAlign` for this column alone (BACKLOG-0000989). Accepted at the top level of the column too, as `align` is. <small>(optional)</small></td></tr>
7006
7010
  <tr><td class="name">wrap</td><td class="type">boolean</td><td class="desc"><small>(optional)</small></td></tr>
7007
7011
  <tr><td class="name">autoHeight</td><td class="type">boolean</td><td class="desc"><small>(optional)</small></td></tr>
7008
7012
  <tr><td class="name">flash</td><td class="type">boolean</td><td class="desc"><small>(optional)</small></td></tr>
@@ -8222,6 +8226,8 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
8222
8226
  <tr><td class="name">gridLines</td><td class="type">boolean | 'both' | 'horizontal' | 'vertical' | 'none' | 'rows' | 'columns'</td><td class="desc">Which rules are drawn between cells. `'both'` by default. The two axes are separate decisions: horizontal rules help the eye track along a row, vertical ones stop adjacent values running together. `false` or `'none'` draws neither. Only the rules *between data* are affected, the header's underline, the pinned seams and the totals separator are structure, not grid lines. <small>(optional)</small></td></tr>
8223
8227
  <tr><td class="name">cornerRadius</td><td class="type">boolean | number | string</td><td class="desc">Round the grid's outer corners. Square by default. `true` adopts the theme's own radius; a number is pixels; a string is used as written, so a host can pass its own token or a relative unit. <small>(optional)</small></td></tr>
8224
8228
  <tr><td class="name">stripedRows</td><td class="type">boolean</td><td class="desc">Shade alternate data rows (zebra striping). Off by default, and strictly opt-in: an existing grid must look exactly the same on upgrade. When `true`, every other data row takes the theme's `--lattice-surface-alt` background, which every palette already defines, so dark, high-contrast and terminal stripe correctly without extra work. Parity follows the row's *logical* index, not its position in the DOM, so a row keeps its stripe across a scroll even though the rows are recycled. Structural rows — group headings, group footers and the grand total — are never striped, and both selection and hover still win over the stripe. <small>(optional)</small></td></tr>
8229
+ <tr><td class="name">verticalAlign</td><td class="type">VAlign</td><td class="desc">Vertical alignment of cell content within a row, as a default for every column (BACKLOG-0000989). `top`, `middle` or `bottom`; a column's own `verticalAlign` overrides it for that column. The horizontal counterpart is the per-column `align`. Omitted, the grid keeps its historical placement — content centred in a fixed-height row and top-aligned in an `autoHeight` row — so an existing grid is unchanged on upgrade. Setting a value aligns every column uniformly, including `autoHeight` rows, unless a column opts out. <small>(optional)</small></td></tr>
8230
+ <tr><td class="name">scrollbars</td><td class="type">ScrollbarMode | { x?: ScrollbarMode; y?: ScrollbarMode }</td><td class="desc">Keep the scroll viewport's scrollbars visible (BACKLOG-0000990). `'auto'` (the default) is the platform's native behaviour, where overlay scrollbars fade when idle. `'always'` keeps both axes shown whether or not the pointer is over the grid. The object form controls each axis on its own — `{ y: 'always' }` pins the vertical bar while the horizontal one stays native. Omitted, the grid is unchanged on upgrade. <small>(optional)</small></td></tr>
8225
8231
  <tr><td class="name">columnTagFilter</td><td class="type">boolean | { multiple?: boolean; label?: string }</td><td class="desc">Show a bar above the column headings for filtering columns by tag. Off by default, and it draws nothing unless some column carries a `tags` entry. `multiple: true` lets more than one tag be chosen at once. Only tagged columns are ever hidden, so an untagged account or total column stays visible whatever is selected. <small>(optional)</small></td></tr>
8226
8232
  <tr><td class="name">anomalySummary</td><td class="type">boolean | { column?: string; label?: string }</td><td class="desc">Show a small chip in the grid chrome that reads how many rows an anomaly shadow column has flagged, and filters the grid to exactly those when it is clicked (BACKLOG-0000799). Off by default, and it draws nothing unless a column declares a `shadow: { kind: 'anomalyFlag' }`. The count and the filter both read that one shadow column, so the number on the chip is the number of rows the click reveals. `column` names the base column to summarise when more than one anomaly-flag shadow is present; `label` overrides the chip's wording. <small>(optional)</small></td></tr>
8227
8233
  <tr><td class="name">typeOptions</td><td class="type">Record&lt;string, {</td><td class="desc">Per-column options a data type reads. `ratio` and `percentRate` use `{ weight }` to name the column their average is weighted by. A unit type reads `{ significantFigures }` to render to a fixed precision rather than a fixed number of decimals. <small>(optional)</small></td></tr>
@@ -9331,6 +9337,7 @@ return `next ${p.mean.toFixed(1)}; r2 ${f.r2.toFixed(1)}; band ${p.upper - p.low
9331
9337
  <tr><td class="name">dataType</td><td class="type">DataType</td><td class="desc"></td></tr>
9332
9338
  <tr><td class="name">nullable</td><td class="type">boolean</td><td class="desc"></td></tr>
9333
9339
  <tr><td class="name">align</td><td class="type">Align</td><td class="desc"></td></tr>
9340
+ <tr><td class="name">verticalAlign</td><td class="type">VAlign</td><td class="desc">The resolved vertical alignment (BACKLOG-0000989), or `undefined` when neither the column nor the grid set one — in which case the cell keeps the grid's historical vertical placement (centred, or top for `autoHeight`). <small>(optional)</small></td></tr>
9334
9341
  <tr><td class="name">value</td><td class="type">Required&lt;Pick&lt;ColumnValueSpec, 'pure'&gt;&gt; &amp; ColumnValueSpec</td><td class="desc"></td></tr>
9335
9342
  <tr><td class="name">cell</td><td class="type">ColumnCellSpec</td><td class="desc"></td></tr>
9336
9343
  <tr><td class="name">edit</td><td class="type">ColumnEditSpec</td><td class="desc"></td></tr>
@@ -437,7 +437,7 @@
437
437
  <div class="shell">
438
438
  <aside class="rail">
439
439
  <p class="rail__brand">Lattice Grid</p>
440
- <p class="rail__sub">Developer guide · v1.45.0</p>
440
+ <p class="rail__sub">Developer guide · v1.46.1</p>
441
441
  <nav>
442
442
  <div class="rail__group">
443
443
  <span class="rail__label">Start here</span>
@@ -3512,6 +3512,76 @@ grid.edit.deleteRows();</code></pre>
3512
3512
  both selection and hover still win over it.
3513
3513
  </p>
3514
3514
 
3515
+ <h2 id="vertical-align">Vertical alignment</h2>
3516
+ <p class="lead-in">
3517
+ <code>verticalAlign</code> is the vertical counterpart to the per-column <code>align</code>:
3518
+ where <code>align</code> places cell content across the column (<code>start</code>,
3519
+ <code>center</code>, <code>end</code>), <code>verticalAlign</code> places it down the row &mdash;
3520
+ <code>'top'</code>, <code>'middle'</code> or <code>'bottom'</code>. It is a grid-level default
3521
+ with a per-column override: set it on the grid to align every column, and a column's own
3522
+ <code>verticalAlign</code> (or <code>cell.verticalAlign</code>) wins for that column alone.
3523
+ <code>center</code> and <code>centre</code> are accepted as synonyms for <code>middle</code>,
3524
+ the same leniency <code>align</code> gives the horizontal names.
3525
+ </p>
3526
+ <p class="lead-in">
3527
+ Omitted, the grid keeps the placement it has always had &mdash; content centred in a
3528
+ fixed-height row and top-aligned in an <code>autoHeight</code> row &mdash; so a grid that never
3529
+ mentions it is unchanged on upgrade. Where it earns its keep is a tall or <code>autoHeight</code>
3530
+ grid: a wrapped-text column can sit at the top while its single-line neighbours are
3531
+ <code>middle</code>, rather than every value floating in the middle of a tall row. The value
3532
+ beats the auto-height rule, so a column asked to sit <code>middle</code> does so even when the
3533
+ row is stretched to fit a wrapped sibling (BACKLOG-0000989).
3534
+ </p>
3535
+
3536
+ <div class="example">
3537
+ <p class="example__label">A grid default, with one column overriding it</p>
3538
+ <pre data-run="js" data-expect="middle, bottom" data-covers="config:verticalAlign"><code><span class="kw">const</span> { createHeadlessGrid } = <span class="kw">await</span> import('../packages/core/src/index.js');
3539
+
3540
+ <span class="kw">const</span> grid = createHeadlessGrid({
3541
+ verticalAlign: <span class="str">'middle'</span>, <span class="cmt">// the default for every column</span>
3542
+ columns: [
3543
+ { field: <span class="str">'name'</span> }, <span class="cmt">// follows the default: middle</span>
3544
+ { field: <span class="str">'note'</span>, verticalAlign: <span class="str">'bottom'</span> }, <span class="cmt">// this column overrides it</span>
3545
+ ],
3546
+ rows: [{ name: <span class="str">'a'</span>, note: <span class="str">'b'</span> }],
3547
+ rowKey: <span class="str">'name'</span>,
3548
+ });
3549
+
3550
+ <span class="cmt">// The resolved value the renderer reads for each column.</span>
3551
+ <span class="kw">const</span> a = grid.columns.get(<span class="str">'name'</span>).verticalAlign;
3552
+ <span class="kw">const</span> b = grid.columns.get(<span class="str">'note'</span>).verticalAlign;
3553
+ grid.destroy();
3554
+ <span class="kw">return</span> `${a}, ${b}`;</code></pre>
3555
+ </div>
3556
+
3557
+ <h2 id="scrollbars">Always-visible scrollbars</h2>
3558
+ <p class="lead-in">
3559
+ Native scrollbars are overlay bars on most platforms now: they fade away when the pointer is
3560
+ idle, which reads as a cleaner surface but hides the affordance &mdash; a touchpad user has no
3561
+ standing sign that a grid scrolls at all. <code>scrollbars: 'always'</code> keeps them shown
3562
+ whether or not the pointer is over the grid; <code>'auto'</code> (the default) leaves the
3563
+ platform's own behaviour alone, so an existing grid is unchanged on upgrade.
3564
+ </p>
3565
+ <p class="lead-in">
3566
+ The two axes are separate decisions, so the object form controls each on its own:
3567
+ <code>{ y: 'always' }</code> pins the vertical bar while the horizontal one stays native, and
3568
+ <code>{ x: 'always', y: 'always' }</code> is the same as the bare <code>'always'</code>. Under
3569
+ the hood the pinned axis switches to <code>overflow: scroll</code> so its track is present even
3570
+ when the content fits, and the scrollbar is styled as a classic, always-drawn bar rather than a
3571
+ fading overlay (BACKLOG-0000990). The same viewport also suppresses the overscroll rubber-band
3572
+ bounce, so a synchronised grid does not spring at its scroll boundary (BACKLOG-0000991).
3573
+ </p>
3574
+
3575
+ <div class="example">
3576
+ <p class="example__label">Pinning both axes, and one axis at a time</p>
3577
+ <pre data-run="js" data-expect="always: always/always; y-only: auto/always" data-covers="config:scrollbars"><code><span class="cmt">// The renderer resolves `scrollbars` to a per-axis mode it stamps on the root.</span>
3578
+ <span class="kw">const</span> { resolveScrollbars } = <span class="kw">await</span> import('../packages/dom/src/renderer/renderer.js');
3579
+
3580
+ <span class="kw">const</span> both = resolveScrollbars(<span class="str">'always'</span>); <span class="cmt">// pins both axes</span>
3581
+ <span class="kw">const</span> onlyY = resolveScrollbars({ y: <span class="str">'always'</span> }); <span class="cmt">// pins the vertical bar only</span>
3582
+ <span class="kw">return</span> `always: ${both.x}/${both.y}; y-only: ${onlyY.x}/${onlyY.y}`;</code></pre>
3583
+ </div>
3584
+
3515
3585
  <h2 id="cards">Cards, lists and feeds</h2>
3516
3586
  <p class="lead-in">
3517
3587
  <code>rowTemplate</code> draws each row with a layout of your own instead of dividing it into
package/lattice-grid.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Lattice Grid 1.45.0, type declarations
2
+ * Lattice Grid 1.46.1, type declarations
3
3
  * Copyright (c) 2026 TOCLOCO Inc. All rights reserved.
4
4
  * https://latticegrid.dev
5
5
  */
@@ -62,6 +62,24 @@ export type TypeName =
62
62
  * `center`.
63
63
  */
64
64
  export type Align = 'start' | 'center' | 'end' | 'left' | 'right' | 'centre';
65
+ /**
66
+ * Vertical alignment of a cell's content within its row (BACKLOG-0000989).
67
+ *
68
+ * The vertical counterpart to {@link Align}. `top` sits the content at the top
69
+ * of the row, `middle` centres it and `bottom` drops it to the bottom. It is
70
+ * most visible on tall or `autoHeight` rows, where a wrapped-text column can be
71
+ * `top` while its single-line neighbours are `middle`.
72
+ */
73
+ export type VAlign = 'top' | 'middle' | 'bottom';
74
+ /**
75
+ * When the grid's scroll viewport keeps its scrollbars visible
76
+ * (BACKLOG-0000990).
77
+ *
78
+ * `auto` is the platform's native behaviour — overlay scrollbars fade away when
79
+ * idle. `always` keeps the bar shown whether or not the pointer is over the
80
+ * grid, so the affordance never disappears on a touchpad or an overlay OS.
81
+ */
82
+ export type ScrollbarMode = 'auto' | 'always';
65
83
  /**
66
84
  * A named preset, or a raw scale where 1 is `standard`. Row heights are
67
85
  * 23.8 / 28 / 42 / 56px for the four presets; a number scales 28px.
@@ -507,6 +525,12 @@ export interface ColumnCellSpec {
507
525
  style?: CellStyle | ((p: CellParams) => CellStyle);
508
526
  tooltip?: string | ((p: CellParams) => string);
509
527
  align?: Align;
528
+ /**
529
+ * Vertical alignment of this column's cell content, overriding the grid-level
530
+ * `verticalAlign` for this column alone (BACKLOG-0000989). Accepted at the
531
+ * top level of the column too, as `align` is.
532
+ */
533
+ verticalAlign?: VAlign;
510
534
  wrap?: boolean;
511
535
  autoHeight?: boolean;
512
536
  flash?: boolean;
@@ -832,6 +856,13 @@ export interface Column {
832
856
  * default, which is itself `'hover'`.
833
857
  */
834
858
  headerControls?: 'hover' | 'always' | 'hidden';
859
+ /**
860
+ * Vertical alignment of this column's cell content within the row
861
+ * (BACKLOG-0000989). Overrides the grid-level `verticalAlign` for this column
862
+ * alone; `top`, `middle` or `bottom`. Also accepted as `cell.verticalAlign`,
863
+ * the way `align` is. Omitted, the column follows the grid default.
864
+ */
865
+ verticalAlign?: VAlign;
835
866
  /** How the column leaves the grid, where that differs from how it is shown. */
836
867
  export?: ColumnExportSpec;
837
868
  /** Whether the user may group by this column from the interface. */
@@ -866,6 +897,12 @@ export interface ResolvedColumn {
866
897
  dataType: DataType;
867
898
  nullable: boolean;
868
899
  align: Align;
900
+ /**
901
+ * The resolved vertical alignment (BACKLOG-0000989), or `undefined` when
902
+ * neither the column nor the grid set one — in which case the cell keeps the
903
+ * grid's historical vertical placement (centred, or top for `autoHeight`).
904
+ */
905
+ verticalAlign?: VAlign;
869
906
  value: Required<Pick<ColumnValueSpec, 'pure'>> & ColumnValueSpec;
870
907
  cell: ColumnCellSpec;
871
908
  edit: ColumnEditSpec;
@@ -1475,6 +1512,30 @@ export interface GridConfig {
1475
1512
  */
1476
1513
  stripedRows?: boolean;
1477
1514
 
1515
+ /**
1516
+ * Vertical alignment of cell content within a row, as a default for every
1517
+ * column (BACKLOG-0000989). `top`, `middle` or `bottom`; a column's own
1518
+ * `verticalAlign` overrides it for that column.
1519
+ *
1520
+ * The horizontal counterpart is the per-column `align`. Omitted, the grid
1521
+ * keeps its historical placement — content centred in a fixed-height row and
1522
+ * top-aligned in an `autoHeight` row — so an existing grid is unchanged on
1523
+ * upgrade. Setting a value aligns every column uniformly, including
1524
+ * `autoHeight` rows, unless a column opts out.
1525
+ */
1526
+ verticalAlign?: VAlign;
1527
+
1528
+ /**
1529
+ * Keep the scroll viewport's scrollbars visible (BACKLOG-0000990).
1530
+ *
1531
+ * `'auto'` (the default) is the platform's native behaviour, where overlay
1532
+ * scrollbars fade when idle. `'always'` keeps both axes shown whether or not
1533
+ * the pointer is over the grid. The object form controls each axis on its
1534
+ * own — `{ y: 'always' }` pins the vertical bar while the horizontal one
1535
+ * stays native. Omitted, the grid is unchanged on upgrade.
1536
+ */
1537
+ scrollbars?: ScrollbarMode | { x?: ScrollbarMode; y?: ScrollbarMode };
1538
+
1478
1539
  /**
1479
1540
  * Show a bar above the column headings for filtering columns by tag.
1480
1541
  *