tosijs-ui 1.11.0 → 1.12.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,127 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.12.1
4
+
5
+ ### The Playwright lane no longer fights itself
6
+
7
+ Local workers are pinned to **6** rather than Playwright's default (~half the cores, 9 here).
8
+ Every engine had taken a turn producing a `page.goto` timeout or a `docs.json` load failure —
9
+ roughly one full run in five, always passing in isolation — because 9 browsers were hitting one
10
+ dev server. 1.11.0 fixed the client half (`fetchCorpus` retries); this reduces the contention
11
+ instead of surviving it.
12
+
13
+ Measured, not guessed: 9 workers ran the suite in 82s and 6 in 81s, so the lane is not
14
+ CPU-bound at 9 and a third of the load is free; 4 workers costs 106s and buys nothing further.
15
+ 6/6 clean afterwards. Contributor-facing only — CI already runs at 1 worker.
16
+
17
+ ### `<tosi-schema-form>`: all three perf guards, and they cover different things
18
+
19
+ The keystroke perf guard counts DOM lookups, and provably could not see `syncValues` — which
20
+ runs on add/remove-item, not on keystrokes. A root-scoped per-field scan reintroduced there
21
+ passed the existing test. There is now a sibling test on that path; mutation-testing takes it
22
+ from 1 lookup per add to 41 → 161 as field count grows, while the keystroke test stays green
23
+ under the same mutation.
24
+
25
+ Wall-clock is back alongside them, too. It was removed in 1.11.0 for flaking; with the lane
26
+ quiet the isolated and loaded distributions now overlap (3.20-4.57 vs 2.64-4.14 across all
27
+ three engines, against 4.0 for linear and 16 for quadratic), so a threshold of 8 separates
28
+ them. It earns its place by catching what counting cannot: an O(N) scan per field that uses no
29
+ selector at all fails it at 9.63x while both count guards pass.
30
+
31
+ ### `<tosi-table>`: the header and body can no longer describe different columns (#102)
32
+
33
+ Reported from a host app that changes column visibility when the page size changes. `set
34
+ columns` updates the column list **synchronously** but defers the rebuild to the next frame,
35
+ so between the assignment and that frame anything recomputing widths — a resize drag, a scroll
36
+ handler, or the host's own page-size code — wrote a grid template for the NEW columns over the
37
+ cells the OLD ones had built.
38
+
39
+ Why that reads as _disagreement_ rather than a missing column, which is what made it confusing
40
+ to report: with fewer tracks than cells, CSS Grid auto-places the surplus into **implicit**
41
+ tracks, and implicit tracks size to content. Header text and body text differ, so the two rows
42
+ resolve them to different widths and the columns visibly step apart.
43
+
44
+ `setColumnWidths()` now describes the column set the DOM was actually built from, refreshed by
45
+ `render()` on the frame that installs those cells. A column change is therefore **deferred, not
46
+ dropped** — and because column objects are shared by reference, a resize drag still moves
47
+ widths immediately: it is the shape that is pinned to the DOM, not the widths. All three
48
+ properties have tests, and the fix is mutation-verified (reverting it fails with
49
+ `tracks: 3, headerCells: 4`).
50
+
51
+ The caller arguably should not reassign columns mid-render. It does not matter — a table that
52
+ can show a header and a body describing different columns is our defect whenever the
53
+ assignment lands.
54
+
55
+ ## 1.12.0
56
+
57
+ ### tosijs-ui is Apache-2.0 as of this release (MIT through 1.11.1)
58
+
59
+ **Nothing already published changes licence.** 1.11.1 and everything before it stay MIT under
60
+ the terms they shipped with — a licence grant already made cannot be withdrawn, and this is not
61
+ an attempt to. The change applies from 1.12.0 forward.
62
+
63
+ **Why.** tosijs went Apache-2.0 in its 1.8.0, and `dist/iife.js` inlines tosijs, so this package
64
+ already redistributes Apache-2.0 code and already had to carry its NOTICE. Matching the licence
65
+ of the thing we are built on removes the mismatch rather than papering over it, and it is the
66
+ right direction on its own terms: Apache-2.0 adds an explicit **patent grant** and a
67
+ patent-retaliation clause that MIT simply does not address.
68
+
69
+ **What it means for you, concretely:**
70
+
71
+ - **Using tosijs-ui in an app, or hosting what you build with it — unaffected.** No new
72
+ obligation.
73
+ - **Redistributing it** (vendoring, forking, shipping a bundle that contains it) — §4(d) asks
74
+ you to carry the attribution text from `NOTICE`, and §4(b) to mark files you modified.
75
+ - **GPLv2-only projects can no longer use it.** This is the one real loss and it is worth
76
+ stating plainly rather than burying: Apache-2.0 is incompatible with GPLv2-only. GPLv3+ is
77
+ fine. If you are on GPLv2-only, 1.11.1 remains MIT and remains available.
78
+ - **You gain a patent grant** you did not have under MIT.
79
+
80
+ The root `NOTICE` now carries our own attribution plus tosijs, marked, Feather Icons and
81
+ CodeMirror. It ships in the package (`files`), so a redistributor has it without hunting.
82
+
83
+ ### Upstreams: verified against tosijs 1.8.0 and tjs-lang 0.13.4
84
+
85
+ Both are admitted by our existing peer ranges (`^1.7.8`, `^0.13.1`) — so adopters of 1.11.0 resolve to them today whether or
86
+ not we bump. All six lanes pass against both: unit (1118), Playwright ×2, haltija (60),
87
+ consumer (44 checks), typecheck, format.
88
+
89
+ The peer floors are **unchanged**. Nothing here needs anything new in either release, and the
90
+ floor encodes required fixes rather than a date. `TJS_VERSION` in
91
+ `src/live-example/code-transform.ts` moved to 0.13.4 in lockstep with the dep — it is the CDN
92
+ pin used when an adopter has no tjs-lang peer installed, and the two silently diverging would
93
+ mean testing one transpiler and shipping another. Both CDN assets verified reachable at that
94
+ version.
95
+
96
+ ### Licence: a NOTICE file, because the iife redistributes Apache-2.0 code
97
+
98
+ **tosijs is Apache-2.0 as of 1.8.0** (BSD-3-Clause through 1.7.x). `dist/iife.js` inlines
99
+ tosijs and marked so a page can use the components from a single `<script>` tag, which makes
100
+ this package a redistributor, and Apache-2.0 §4(d) asks redistributors to carry the NOTICE
101
+ text of what they redistribute. There is now a `NOTICE` file at the root, shipped in the
102
+ package, reproducing tosijs's verbatim.
103
+
104
+ **This does not travel with `import 'tosijs-ui'`.** The ESM build bundles neither — tosijs and
105
+ marked are peer dependencies there, resolved from the consumer's own `node_modules`. The
106
+ obligation attaches to the iife and to anything built from it. tosijs-ui itself remains MIT.
107
+
108
+ ### Known: the iife grew
109
+
110
+ `dist/iife.js` is **419.1 KB gzipped, up from 402.3 KB** — +16.8 KB (+4.2%) — entirely from
111
+ tosijs 1.8.0, whose own notes measure +2.9 kB on an app bundle that touches no new API (the
112
+ contract seam, path-segment guard and binding bookkeeping sit on the ordinary path). Ours is
113
+ larger because the iife bundles more of tosijs than a typical app does. Recorded rather than
114
+ absorbed silently: the gate on weight here has always been the printed gzip delta.
115
+
116
+ ### Note for anyone on tosijs 1.7.x
117
+
118
+ tosijs 1.8.0 **deviates from semver and says so** — it removes `data-ref` and `<xin-slot>`
119
+ markup handling, reduces `<xin-blueprint>`/`<xin-loader>` to warning tombstones, and flips
120
+ `on<Event>` member precedence and type-contradicting attribute writes. A consumer on
121
+ `^1.7.9` receives all of it on a routine update. **tosijs-ui uses none of them** — verified by
122
+ grep and by the full lane run, which is why our peer range still spans both. If your own app
123
+ uses any, read tosijs's 1.8.0 notes before updating.
124
+
3
125
  ## 1.11.0
4
126
 
5
127
  **Schema-driven editing.** Three new pieces that compose: `<tosi-schema-form>` renders a form
package/LICENSE CHANGED
@@ -1,21 +1,202 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Tonio Loewald
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright 2023-2026 Tonio Loewald
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
package/NOTICE ADDED
@@ -0,0 +1,79 @@
1
+ tosijs-ui
2
+ Copyright 2023-2026 Tonio Loewald
3
+
4
+ This product includes software developed by Tonio Loewald.
5
+
6
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
7
+ use this file except in compliance with the License. You may obtain a copy
8
+ of the License at
9
+
10
+ http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+ Unless required by applicable law or agreed to in writing, software
13
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ License for the specific language governing permissions and limitations
16
+ under the License.
17
+
18
+ tosijs-ui was licensed under the MIT License through version 1.11.1, and is
19
+ Apache-2.0 from 1.12.0 onward. Nothing already released changes licence:
20
+ 1.11.1 and everything before it remain MIT under the terms they shipped with.
21
+
22
+ ==========================================================================
23
+ THIRD-PARTY NOTICES
24
+ ==========================================================================
25
+
26
+ `dist/iife.js` inlines its dependencies so a page can use the components from
27
+ a single <script> tag. The ESM build does NOT — tosijs and marked are peer
28
+ dependencies there, resolved from the consumer's own node_modules — so the
29
+ attribution below travels with the iife and with anything built from it.
30
+
31
+ --------------------------------------------------------------------------
32
+ tosijs — https://github.com/tonioloewald/tosijs
33
+ Apache-2.0 as of 1.8.0 (BSD-3-Clause through 1.7.x).
34
+ Reproduced from the tosijs package's own NOTICE:
35
+ --------------------------------------------------------------------------
36
+
37
+ tosijs
38
+ Copyright 2022-2026 Tonio Loewald
39
+
40
+ This product includes software developed by Tonio Loewald.
41
+
42
+ Portions of the published bundles (dist/module.js, dist/main.js,
43
+ dist/index.js, dist/module.debug.js and dist/module.safe.js) are generated
44
+ from tosijs-floorplan (https://github.com/tonioloewald/tosijs-floorplan),
45
+ Copyright 2026 Tonio Loewald, licensed under the Apache License, Version 2.0
46
+ — vendored at build time so tosijs ships with zero runtime dependencies.
47
+
48
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not
49
+ use this file except in compliance with the License. You may obtain a copy
50
+ of the License at
51
+
52
+ http://www.apache.org/licenses/LICENSE-2.0
53
+
54
+ Unless required by applicable law or agreed to in writing, software
55
+ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
56
+ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
57
+ License for the specific language governing permissions and limitations
58
+ under the License.
59
+
60
+ --------------------------------------------------------------------------
61
+ marked — https://github.com/markedjs/marked
62
+ MIT. Ships no NOTICE; its copyright and permission notice travel in the
63
+ bundle's own header.
64
+ --------------------------------------------------------------------------
65
+
66
+ --------------------------------------------------------------------------
67
+ Feather Icons — https://github.com/feathericons/feather
68
+ Copyright (c) 2013-2023 Cole Bemis. MIT.
69
+ Some icons in `icons/` and the generated `src/icon-data.ts` derive from
70
+ Feather. The full permission notice is reproduced in `src/icons.ts` and on
71
+ the icons documentation page.
72
+ --------------------------------------------------------------------------
73
+
74
+ --------------------------------------------------------------------------
75
+ CodeMirror — https://codemirror.net/
76
+ Copyright (c) by Marijn Haverbeke and others. MIT.
77
+ The @codemirror/* and @lezer/* packages are runtime dependencies, bundled
78
+ into `dist/iife.js` and into the lazy `dist/code-editor-cm.js` chunk.
79
+ --------------------------------------------------------------------------
@@ -202,6 +202,7 @@ export declare class TosiTable extends WebComponent {
202
202
  private rowData;
203
203
  private _array;
204
204
  private _columns;
205
+ private _renderedCols;
205
206
  private _filter;
206
207
  private _sort?;
207
208
  private _rowGroupId;
@@ -1311,6 +1311,11 @@ export class TosiTable extends WebComponent {
1311
1311
  };
1312
1312
  _array = [];
1313
1313
  _columns = null;
1314
+ /*
1315
+ The columns the CURRENT DOM was built from — see `setColumnWidths`. Not `_columns`: that one
1316
+ changes the instant a caller assigns it, which is exactly the window this exists to cover.
1317
+ */
1318
+ _renderedCols = [];
1314
1319
  _filter = passThru;
1315
1320
  _sort;
1316
1321
  _rowGroupId = null;
@@ -2611,7 +2616,30 @@ export class TosiTable extends WebComponent {
2611
2616
  this.addEventListener('keydown', this.handleKeyNav);
2612
2617
  }
2613
2618
  setColumnWidths() {
2614
- const cols = this.visibleColumns;
2619
+ /*
2620
+ The widths describe the columns the DOM ACTUALLY HAS, not the ones it is about to get.
2621
+
2622
+ `set columns` updates `_columns` synchronously but defers the rebuild to `queueRender()`,
2623
+ so between the assignment and the frame, `visibleColumns` already answers for a column set
2624
+ no cell in the document belongs to. Anything that recomputes widths in that window — a
2625
+ resize drag, a scroll handler, a host reacting to a page-size change — used to write a
2626
+ template for the NEW columns over the OLD cells.
2627
+
2628
+ That reads as the header disagreeing with the body (#102), and the reason it looks like
2629
+ disagreement rather than simple breakage is worth knowing: with fewer tracks than cells,
2630
+ CSS Grid auto-places the surplus into IMPLICIT tracks, which size to content. Header text
2631
+ and body text differ, so the two rows resolve those tracks to different widths and the
2632
+ columns visibly step apart.
2633
+
2634
+ `_renderedCols` is the set the last render built the cells from; `render()` refreshes it
2635
+ immediately before calling here, so a legitimate column change still takes effect on the
2636
+ very frame that installs its cells. Column objects are shared by reference, so a resize
2637
+ drag that mutates `column.width` is still reflected — it is the SHAPE that is pinned to
2638
+ the DOM, not the widths.
2639
+ */
2640
+ const cols = this._renderedCols.length
2641
+ ? this._renderedCols
2642
+ : this.visibleColumns;
2615
2643
  const total = cols.reduce((w, c) => w + c.width, 0);
2616
2644
  /*
2617
2645
  `fullWidthHeader` lets ONE column absorb whatever width is left over, so a table narrower
@@ -2886,6 +2914,8 @@ export class TosiTable extends WebComponent {
2886
2914
  if (cols.length === 0)
2887
2915
  return;
2888
2916
  const stickyInfo = this.computeStickyInfo(cols);
2917
+ // Before setColumnWidths, so the widths describe the cells this render is about to build.
2918
+ this._renderedCols = cols;
2889
2919
  this.style.setProperty('--tosi-table-row-height', this.rowHeight > 0 ? `${this.rowHeight}px` : 'auto');
2890
2920
  this.setColumnWidths();
2891
2921
  // Build the regions. Header + optional pinned tbodies are siblings