fix: correct piano-roll header seek when horizontally scrolled
This commit is contained in:
@@ -28,10 +28,12 @@ function renderHeader({
|
|||||||
hasPianoKeys = true,
|
hasPianoKeys = true,
|
||||||
scrollLeft = 0,
|
scrollLeft = 0,
|
||||||
paddingLeft = hasPianoKeys ? '60px' : '0px',
|
paddingLeft = hasPianoKeys ? '60px' : '0px',
|
||||||
|
scrollContainerLeft = 100,
|
||||||
}: {
|
}: {
|
||||||
hasPianoKeys?: boolean;
|
hasPianoKeys?: boolean;
|
||||||
scrollLeft?: number;
|
scrollLeft?: number;
|
||||||
paddingLeft?: string;
|
paddingLeft?: string;
|
||||||
|
scrollContainerLeft?: number;
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const view = render(
|
const view = render(
|
||||||
<div className="piano-roll-note-scroll">
|
<div className="piano-roll-note-scroll">
|
||||||
@@ -48,18 +50,33 @@ function renderHeader({
|
|||||||
writable: true,
|
writable: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Object.defineProperty(scrollContainer, 'getBoundingClientRect', {
|
||||||
|
configurable: true,
|
||||||
|
value: () => ({
|
||||||
|
left: scrollContainerLeft,
|
||||||
|
top: 0,
|
||||||
|
right: scrollContainerLeft + 500,
|
||||||
|
bottom: 20,
|
||||||
|
width: 500,
|
||||||
|
height: 20,
|
||||||
|
x: scrollContainerLeft,
|
||||||
|
y: 0,
|
||||||
|
toJSON: () => ({}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
header.style.paddingLeft = paddingLeft;
|
header.style.paddingLeft = paddingLeft;
|
||||||
|
|
||||||
Object.defineProperty(header, 'getBoundingClientRect', {
|
Object.defineProperty(header, 'getBoundingClientRect', {
|
||||||
configurable: true,
|
configurable: true,
|
||||||
value: () => ({
|
value: () => ({
|
||||||
left: 100,
|
left: scrollContainerLeft - scrollLeft,
|
||||||
top: 0,
|
top: 0,
|
||||||
right: 600,
|
right: scrollContainerLeft - scrollLeft + 500,
|
||||||
bottom: 20,
|
bottom: 20,
|
||||||
width: 500,
|
width: 500,
|
||||||
height: 20,
|
height: 20,
|
||||||
x: 100,
|
x: scrollContainerLeft - scrollLeft,
|
||||||
y: 0,
|
y: 0,
|
||||||
toJSON: () => ({}),
|
toJSON: () => ({}),
|
||||||
}),
|
}),
|
||||||
@@ -88,7 +105,7 @@ describe('PianoGridHeader', () => {
|
|||||||
expect(requestMainContentScroll).toHaveBeenCalledWith(3);
|
expect(requestMainContentScroll).toHaveBeenCalledWith(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('includes the note scroll offset when seeking after horizontal scroll', () => {
|
it('seeks to the same beat after horizontal scroll when the header rect already shifts with content', () => {
|
||||||
const { header } = renderHeader({ scrollLeft: 160 });
|
const { header } = renderHeader({ scrollLeft: 160 });
|
||||||
|
|
||||||
fireEvent.click(header, { clientX: 280 });
|
fireEvent.click(header, { clientX: 280 });
|
||||||
@@ -118,4 +135,13 @@ describe('PianoGridHeader', () => {
|
|||||||
expect(setPlayheadPosition).toHaveBeenCalledWith(5);
|
expect(setPlayheadPosition).toHaveBeenCalledWith(5);
|
||||||
expect(requestMainContentScroll).not.toHaveBeenCalled();
|
expect(requestMainContentScroll).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('ignores clicks inside the visible piano-key gutter before it fully scrolls out of view', () => {
|
||||||
|
const { header } = renderHeader({ scrollLeft: 20 });
|
||||||
|
|
||||||
|
fireEvent.click(header, { clientX: 110 });
|
||||||
|
|
||||||
|
expect(setPlayheadPosition).not.toHaveBeenCalled();
|
||||||
|
expect(requestMainContentScroll).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ const PianoGridHeader: React.FC<PianoGridHeaderProps> = ({
|
|||||||
if (!headerElementRef.current) return null;
|
if (!headerElementRef.current) return null;
|
||||||
|
|
||||||
const headerElement = headerElementRef.current;
|
const headerElement = headerElementRef.current;
|
||||||
const rect = headerElement.getBoundingClientRect();
|
|
||||||
const relativeX = clientX - rect.left;
|
|
||||||
const scrollContainer = headerElement.closest('.piano-roll-note-scroll') as HTMLElement | null;
|
const scrollContainer = headerElement.closest('.piano-roll-note-scroll') as HTMLElement | null;
|
||||||
|
const referenceRect = scrollContainer?.getBoundingClientRect() ?? headerElement.getBoundingClientRect();
|
||||||
|
const relativeX = clientX - referenceRect.left;
|
||||||
const scrollLeft = scrollContainer?.scrollLeft ?? 0;
|
const scrollLeft = scrollContainer?.scrollLeft ?? 0;
|
||||||
const leftGutter = parseFloat(getComputedStyle(headerElement).paddingLeft) || 0;
|
const leftGutter = parseFloat(getComputedStyle(headerElement).paddingLeft) || 0;
|
||||||
const adjustedX = relativeX + scrollLeft - leftGutter;
|
const adjustedX = relativeX + scrollLeft - leftGutter;
|
||||||
|
|||||||
Reference in New Issue
Block a user