Skip to content

Commit

Permalink
fix(Cell): patch client height of html (see draggable mode) (#6456)
Browse files Browse the repository at this point in the history
  • Loading branch information
inomdzhon authored Jan 26, 2024
1 parent a80760b commit 9918a9d
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
27 changes: 23 additions & 4 deletions packages/vkui/src/lib/dom.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const getChildElOfParentWithTransformedStyle = (
return { parentEl, parentElRect, childEl, childElRect };
};

describe('getTransformedParentCoords', () => {
describe(getTransformedParentCoords, () => {
const transformDefault = TRANSFORM_DEFAULT_VALUES.map((v) => ({ transform: v }));
const willChangeDefault = WILL_CHANGE_DEFAULT_VALUES.map((v) => ({ willChange: v }));

Expand Down Expand Up @@ -68,13 +68,16 @@ describe('getTransformedParentCoords', () => {
});
});

describe('getScrollRect', () => {
describe(getScrollRect, () => {
test.each([
{ scrollTop: 0, viewportHeight: 100 },
{ scrollTop: 10, viewportHeight: 100 },
{ scrollTop: 0, viewportHeight: 768 },
{ scrollTop: 10, viewportHeight: 768 },
])('[window] should return correct y edges for %j', ({ scrollTop, viewportHeight }) => {
jest
.spyOn(document.documentElement, 'clientHeight', 'get')
.mockImplementation(() => viewportHeight);
const rect = new DOMRect(0, scrollTop > 0 ? -1 * scrollTop : scrollTop, 1280, viewportHeight);
window.scrollY = document.documentElement.scrollTop = scrollTop;
document.documentElement.getBoundingClientRect = jest.fn(() => rect);
Expand All @@ -99,7 +102,7 @@ describe('getScrollRect', () => {
});
});

describe('getScrollHeight', () => {
describe(getScrollHeight, () => {
const getScrollHeightMock = () => 1000;
const scrollEl = document.createElement('div');
beforeEach(() => {
Expand All @@ -116,7 +119,7 @@ describe('getScrollHeight', () => {
});
});

describe('getBoundingClientRect', () => {
describe(getBoundingClientRect, () => {
it('should return rect without offset', () => {
const { childEl, childElRect } = getChildElOfParentWithTransformedStyle();
expect(getBoundingClientRect(childEl)).toEqual(childElRect);
Expand Down Expand Up @@ -144,6 +147,22 @@ describe('getBoundingClientRect', () => {
}),
);
});

it('should apply `clientHeight` to `height` of `getBoundingClientRect()` if element is HTML', () => {
const HTML_CLIENT_HEIGHT = 768;
const HTML_SCROLL_HEIGHT = 2000;

jest
.spyOn(document.documentElement, 'clientHeight', 'get')
.mockImplementation(() => HTML_CLIENT_HEIGHT);

// Симулируем, что на странице не указан `html, body { height: 100% }` (или `height: 100vh`).
document.documentElement.getBoundingClientRect = jest.fn(
() => new DOMRect(0, 0, 1280, HTML_SCROLL_HEIGHT),
);

expect(getBoundingClientRect(document.documentElement).height).toBe(HTML_CLIENT_HEIGHT);
});
});

describe(getDocumentBody, () => {
Expand Down
15 changes: 15 additions & 0 deletions packages/vkui/src/lib/dom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ export const isBody = (
return node !== null && node !== undefined && 'tagName' in node && node.tagName === 'BODY';
};

export const isDocumentElement = (
node: Element | Window | VisualViewport | undefined | null,
): node is HTMLHtmlElement => {
return node !== null && node !== undefined && 'tagName' in node && node.tagName === 'HTML';
};

export function withDOM<Props>(
Component: React.ComponentType<Props & DOMProps>,
): React.ComponentType<Props> {
Expand Down Expand Up @@ -98,6 +104,15 @@ export const getBoundingClientRect = (node: Element | Window, isFixedStrategy =
const element = isWindow(node) ? node.document.documentElement : node;
const clientRect = element.getBoundingClientRect();

if (isDocumentElement(element)) {
/**
* Если на странице не используется `html, body { height: 100% }` (или `height: 100vh`), то
* `height`, полученный из `document.documentElement.getBoundingClientRect()`, будет возвращать
* `scrollHeight`, а не `clientHeight`. Поэтому перебиваем `height` на `clientHeight`.
*/
clientRect.height = element.clientHeight;
}

let offsetX = 0;
let offsetY = 0;
if (isFixedStrategy) {
Expand Down

0 comments on commit 9918a9d

Please sign in to comment.