Skip to content

Commit 6e483b4

Browse files
ww-mwclaude
andcommitted
Release v1.1.2
Fix column resize triggering a sort: the trailing click the browser fires on the <th> after a resize mouseup no longer toggles the column sort. onUp sets a suppress-next-click flag consumed by the header click handler, with a setTimeout(0) safety-net so an orphaned flag can't eat a later genuine sort click. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 1c4f6f4 commit 6e483b4

4 files changed

Lines changed: 43 additions & 3 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "data-explorer-vscode",
33
"displayName": "Simulink Data Explorer Extension for Visual Studio Code",
44
"description": "Explore Simulink models, data dictionaries, MAT-files, and projects as interactive tables and relationship trees.",
5-
"version": "1.1.1",
5+
"version": "1.1.2",
66
"publisher": "mathworks",
77
"private": true,
88
"license": "BSD-3-Clause",

src/dex/components/dex-tree-table.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,11 @@ export class DexTreeTable extends LitElement {
580580
private _resizeStartWidth = 0;
581581
private _resizeNextCol: string | null = null;
582582
private _resizeNextStartWidth = 0;
583+
// A resize ends on mouseup, but the browser then fires a `click` on the <th>,
584+
// which would trigger sorting. `_resizingCol` is already cleared by then, so
585+
// this flag carries the "just resized" signal to the click handler to swallow
586+
// that one click.
587+
private _suppressNextHeaderClick = false;
583588

584589
private _dragColId: string | null = null;
585590
private _dragOverColId: string | null = null;
@@ -760,6 +765,15 @@ export class DexTreeTable extends LitElement {
760765
document.removeEventListener('mouseup', onUp);
761766
this._resizingCol = null;
762767
this._resizeNextCol = null;
768+
// Swallow the click the browser fires on the <th> right after this
769+
// mouseup, so ending a resize doesn't also toggle the column sort. The
770+
// trailing click dispatches synchronously before this timeout, so the
771+
// timeout only clears the flag if no click follows (e.g. mouseup landed
772+
// outside the header) — preventing a stuck flag from eating a later sort.
773+
this._suppressNextHeaderClick = true;
774+
setTimeout(() => {
775+
this._suppressNextHeaderClick = false;
776+
}, 0);
763777
};
764778

765779
document.addEventListener('mousemove', onMove);
@@ -944,6 +958,12 @@ export class DexTreeTable extends LitElement {
944958

945959
private _onHeaderClick(col: string, e: MouseEvent): void {
946960
if (this._resizingCol) return;
961+
// A resize just ended: this is the trailing click from that drag, not an
962+
// intent to sort. Consume the flag and bail.
963+
if (this._suppressNextHeaderClick) {
964+
this._suppressNextHeaderClick = false;
965+
return;
966+
}
947967

948968
if (e.shiftKey) {
949969
const existing = this._sortState.findIndex((s) => s.column === col);

test/treeTableSort.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,26 @@ describe('dex-tree-table sorting preserves hierarchy', () => {
6060
expect(visibleOrder(table)).toEqual(['S', 'S/z', 'S/a']);
6161
});
6262

63+
it('does not sort on the trailing click that follows a column resize', () => {
64+
// Ending a resize (mouseup) is followed by a click on the <th>. That click
65+
// must not toggle the sort. The resize's onUp sets _suppressNextHeaderClick;
66+
// _onHeaderClick must consume it and leave the sort state untouched.
67+
const table = new DexTreeTable();
68+
table.rows = [makeRow('S', null, 'Section')];
69+
expect((table as any)._sortState).toEqual([]);
70+
71+
(table as any)._suppressNextHeaderClick = true;
72+
(table as any)._onHeaderClick('Name', { shiftKey: false } as MouseEvent);
73+
74+
// No sort applied, and the flag is consumed (one click only).
75+
expect((table as any)._sortState).toEqual([]);
76+
expect((table as any)._suppressNextHeaderClick).toBe(false);
77+
78+
// The NEXT click (a genuine one) sorts as normal.
79+
(table as any)._onHeaderClick('Name', { shiftKey: false } as MouseEvent);
80+
expect((table as any)._sortState).toEqual([{ column: 'Name', direction: 'asc' }]);
81+
});
82+
6383
it('sorts nested grandchildren within their own subtree only', () => {
6484
const rows: TreeTableRow[] = [
6585
makeRow('B', null, 'Beta'),

0 commit comments

Comments
 (0)