Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -451,11 +451,13 @@ tr:hover .selectedCell {
background: var(--card);
}

.activeHeaderCell.frozenHeaderCell {
background: color-mix(in srgb, var(--agent-blue-500) 8%, var(--card));
}

.evenRow .stickyActionCell,
.evenRow .frozenCell {
background:
linear-gradient(var(--subtle-bg), var(--subtle-bg)),
var(--card);
background: linear-gradient(var(--subtle-bg), var(--subtle-bg)), var(--card);
}

tr:hover .stickyActionCell,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { EnhancedMarkdownTable } from './EnhancedMarkdownTable';
).IS_REACT_ACT_ENVIRONMENT = true;

const mounted: Array<{ root: Root; container: HTMLElement }> = [];
const originalDocumentHidden = Object.getOwnPropertyDescriptor(
document,
'hidden',
);
const originalElementFromPoint = document.elementFromPoint;
const COLUMN_DRAG_MIME = 'application/x-qwen-web-shell-table-column';

Expand All @@ -21,6 +25,11 @@ afterEach(() => {
vi.restoreAllMocks();
vi.useRealTimers();
document.getSelection()?.removeAllRanges();
if (originalDocumentHidden) {
Object.defineProperty(document, 'hidden', originalDocumentHidden);
} else {
Reflect.deleteProperty(document, 'hidden');
}
if (originalElementFromPoint) {
Object.defineProperty(document, 'elementFromPoint', {
configurable: true,
Expand Down Expand Up @@ -866,6 +875,31 @@ describe('EnhancedMarkdownTable', () => {
);
});

it('flushes pending resize width when the window blurs', () => {
const container = renderTable();
const resize = button(container, 'Resize Team');

act(() => {
resize.dispatchEvent(
new MouseEvent('mousedown', {
bubbles: true,
button: 0,
clientX: 100,
}),
);
});
act(() => {
window.dispatchEvent(
new MouseEvent('mousemove', { bubbles: true, clientX: 200 }),
);
window.dispatchEvent(new Event('blur'));
});

expect(button(container, 'Sort by Team').closest('th')?.style.width).toBe(
'260px',
);
});

it('stops resizing a column when page visibility changes', () => {
const container = renderTable();
const resize = button(container, 'Resize Team');
Expand All @@ -879,6 +913,10 @@ describe('EnhancedMarkdownTable', () => {
}),
);
});
Object.defineProperty(document, 'hidden', {
configurable: true,
value: true,
});
act(() => {
document.dispatchEvent(new Event('visibilitychange'));
});
Expand All @@ -893,6 +931,38 @@ describe('EnhancedMarkdownTable', () => {
);
});

it('keeps resizing when page visibility changes while visible', () => {
const container = renderTable();
const resize = button(container, 'Resize Team');

act(() => {
resize.dispatchEvent(
new MouseEvent('mousedown', {
bubbles: true,
button: 0,
clientX: 100,
}),
);
});
Object.defineProperty(document, 'hidden', {
configurable: true,
value: false,
});
act(() => {
document.dispatchEvent(new Event('visibilitychange'));
});
act(() => {
window.dispatchEvent(
new MouseEvent('mousemove', { bubbles: true, clientX: 220 }),
);
window.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
});

expect(button(container, 'Sort by Team').closest('th')?.style.width).toBe(
'280px',
);
});

it('resizes a column with keyboard arrows', () => {
const container = renderTable();
const resize = button(container, 'Resize Team');
Expand Down Expand Up @@ -924,6 +994,25 @@ describe('EnhancedMarkdownTable', () => {
);
});

it('ignores keyboard resize arrows with modifiers', () => {
const container = renderTable();
const resize = button(container, 'Resize Team');

act(() => {
resize.dispatchEvent(
new KeyboardEvent('keydown', {
bubbles: true,
ctrlKey: true,
key: 'ArrowRight',
}),
);
});

expect(button(container, 'Sort by Team').closest('th')?.style.width).toBe(
'160px',
);
});

it('shows column move handles only for the active column', () => {
const container = renderWideTable();
const teamHandle = button(container, 'Move Team');
Expand All @@ -945,6 +1034,66 @@ describe('EnhancedMarkdownTable', () => {
).toContain('activeHeaderCell');
});

it('clears the active column move handle on outside click, cell selection, and Escape', () => {
const container = renderWideTable();
const teamHandle = button(container, 'Move Team');

click(button(container, 'Sort by Team'));
act(() => {
document.body.dispatchEvent(
new MouseEvent('mousedown', { bubbles: true }),
);
});
expect(teamHandle.className).not.toContain('reorderHandleVisible');
expect(teamHandle.tabIndex).toBe(-1);

click(button(container, 'Sort by Team, ascending'));
act(() => {
dataCell(container, 0, 0).dispatchEvent(
new MouseEvent('mousedown', { bubbles: true, button: 0 }),
);
});
expect(teamHandle.className).not.toContain('reorderHandleVisible');
expect(teamHandle.tabIndex).toBe(-1);

click(button(container, 'Sort by Team, descending'));
act(() => {
document.dispatchEvent(
new KeyboardEvent('keydown', { bubbles: true, key: 'Escape' }),
);
});
expect(teamHandle.className).not.toContain('reorderHandleVisible');
expect(teamHandle.tabIndex).toBe(-1);
});

it('keeps the active column when Escape closes an open filter menu first', () => {
const container = renderWideTable();
const teamHandle = button(container, 'Move Team');

click(button(container, 'Sort by Team'));
click(button(container, 'Filter Team'));
expect(container.textContent).toContain('Custom filter');

act(() => {
document.dispatchEvent(
new KeyboardEvent('keydown', { bubbles: true, key: 'Escape' }),
);
});

expect(container.textContent).not.toContain('Custom filter');
expect(teamHandle.className).toContain('reorderHandleVisible');
expect(teamHandle.tabIndex).toBe(0);

act(() => {
document.dispatchEvent(
new KeyboardEvent('keydown', { bubbles: true, key: 'Escape' }),
);
});

expect(teamHandle.className).not.toContain('reorderHandleVisible');
expect(teamHandle.tabIndex).toBe(-1);
});

it('reorders columns and quick copies in the visible order', () => {
const writeText = mockClipboard();
const container = renderWideTable();
Expand Down Expand Up @@ -978,7 +1127,10 @@ describe('EnhancedMarkdownTable', () => {
const source = renderWideTable();
const target = renderWideTable();

dragColumnElements(button(source, 'Move Score'), button(target, 'Move Team'));
dragColumnElements(
button(source, 'Move Score'),
button(target, 'Move Team'),
);

expect(rowTexts(source)).toEqual(['Alpha|US|10', 'Beta|EMEA|2']);
expect(rowTexts(target)).toEqual(['Alpha|US|10', 'Beta|EMEA|2']);
Expand Down Expand Up @@ -1033,6 +1185,14 @@ describe('EnhancedMarkdownTable', () => {
).toContain('frozenHeaderCell');
expect(dataCell(container, 0, 0).className).toContain('frozenCell');

click(button(container, 'Sort by Team'));
expect(
button(container, 'Sort by Team, ascending').closest('th')?.className,
).toContain('activeHeaderCell');
expect(
button(container, 'Sort by Team, ascending').closest('th')?.className,
).toContain('frozenHeaderCell');

dragColumn(container, 'Move Score', 'Move Team');
expect(
button(container, 'Sort by Score').closest('th')?.className,
Expand Down
Loading
Loading