Skip to content
Open
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
14 changes: 13 additions & 1 deletion src/hooks/useAlign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ export default function useAlign(
const originOverflowX = popupElement.style.overflowX;
const originOverflowY = popupElement.style.overflowY;


// Placement
const placementInfo: AlignType = {
...builtinPlacements[placement],
Expand Down Expand Up @@ -666,6 +665,19 @@ export default function useAlign(
nextOffsetY += targetRect.y - visibleRegionArea.bottom + numShiftY;
}
}

// 目标仍在平移范围内时,避免方向偏移量将弹层再次推到视口外。
if (
targetRect.y + targetHeight >= visibleRegionArea.top + numShiftY &&
targetRect.y <= visibleRegionArea.bottom - numShiftY
) {
const minOffsetY = visibleRegionArea.top - popupRect.y;
const maxOffsetY = Math.max(
minOffsetY,
visibleRegionArea.bottom - popupHeight - popupRect.y,
);
nextOffsetY = Math.min(Math.max(nextOffsetY, minOffsetY), maxOffsetY);
}
}

// ============================ Arrow ============================
Expand Down
57 changes: 56 additions & 1 deletion tests/flipShift.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,10 @@ const builtinPlacements = {

describe('Trigger.Flip+Shift', () => {
let spanRect = { x: 0, y: 0, left: 0, top: 0, width: 0, height: 0 };
let popupHeight = 300;

beforeEach(() => {
popupHeight = 300;
spanRect = {
x: 0,
y: 100,
Expand Down Expand Up @@ -118,7 +120,7 @@ describe('Trigger.Flip+Shift', () => {
left: 0,
top: 0,
width: 100,
height: 300,
height: popupHeight,
};
},
});
Expand Down Expand Up @@ -170,6 +172,59 @@ describe('Trigger.Flip+Shift', () => {
});
});

it.each([
{ placement: 'top', offset: -4, targetY: 100, top: '100px' },
{ placement: 'bottom', offset: 4, targetY: 100, top: '100px' },
{ placement: 'top', offset: -4, targetY: 200, top: '0px' },
{ placement: 'bottom', offset: 4, targetY: 200, top: '0px' },
])(
'$placement 在目标位于 $targetY 时,平移不应被偏移量推回视口外',
async ({ placement, offset, targetY, top }) => {
spanRect.y = targetY;
spanRect.top = targetY;

render(
<Trigger
popupVisible
popupPlacement={placement}
builtinPlacements={builtinPlacements}
popupAlign={{ offset: [0, offset] }}
popup={<strong>日期面板</strong>}
>
<span className="target" />
</Trigger>,
);

await act(async () => {
await Promise.resolve();
});

expect(document.querySelector('.rc-trigger-popup')).toHaveStyle({ top });
},
);

it('面板高于视口时优先保留顶部内容', async () => {
popupHeight = 500;
render(
<Trigger
popupVisible
popupPlacement="top"
builtinPlacements={builtinPlacements}
popup={<strong>日期面板</strong>}
>
<span className="target" />
</Trigger>,
);

await act(async () => {
await Promise.resolve();
});

expect(document.querySelector('.rc-trigger-popup')).toHaveStyle({
top: '0px',
});
});

it('top with visibleFirst region', async () => {
spanRect.x = -1000;
document.documentElement.scrollLeft = 500;
Expand Down