Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: page spinner is styled incorrectly when scrolling #4163

Merged
merged 3 commits into from
Aug 15, 2024
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
10 changes: 10 additions & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import type { DefaultTheme, HeadConfig } from 'vitepress';

import { resolve } from 'node:path';

import {
GitChangelog,
GitChangelogMarkdownSection,
} from '@nolebase/vitepress-plugin-git-changelog/vite';
import { type PwaOptions, withPwa } from '@vite-pwa/vitepress';
import { defineConfigWithTheme } from 'vitepress';

Expand Down Expand Up @@ -98,6 +102,12 @@ export default withPwa(
json: {
stringify: true,
},
plugins: [
GitChangelog({
repoURL: () => 'https://github.com/vbenjs/vue-vben-admin',
}),
GitChangelogMarkdownSection(),
],
server: {
fs: {
allow: ['../..'],
Expand Down
5 changes: 4 additions & 1 deletion docs/.vitepress/theme/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// https://vitepress.dev/guide/custom-theme
import type { Theme } from 'vitepress';

import { NolebaseGitChangelogPlugin } from '@nolebase/vitepress-plugin-git-changelog/client';
import DefaultTheme from 'vitepress/theme';

import SiteLayout from './components/site-layout.vue';
Expand All @@ -9,11 +10,13 @@ import { initHmPlugin } from './plugins/hm';

import './styles';

import '@nolebase/vitepress-plugin-git-changelog/client/style.css';

export default {
enhanceApp({ app }) {
// ...
app.component('VbenContributors', VbenContributors);

app.use(NolebaseGitChangelogPlugin);
// 百度统计
initHmPlugin();
},
Expand Down
1 change: 1 addition & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"medium-zoom": "^1.1.0"
},
"devDependencies": {
"@nolebase/vitepress-plugin-git-changelog": "^2.4.0",
"@vite-pwa/vitepress": "^0.5.0",
"vitepress": "^1.3.2",
"vue": "^3.4.37"
Expand Down
6 changes: 3 additions & 3 deletions docs/src/guide/in-depth/theme.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ css 变量内的颜色,必须使用 `hsl` 格式,如 `0 0% 100%`,不需要

你只需要在你的项目中覆盖你想要修改的 CSS 变量即可。例如,要更改默认卡片背景色,你可以在你的 CSS 文件中添加以下内容进行覆盖:

### 默认主题下
### 默认主题下

```css
:root {
Expand Down Expand Up @@ -1222,7 +1222,7 @@ export const overridesPreferences = defineOverridesPreferences({

侧边栏颜色通过`--sidebar`变量来配置

### 默认主题下
### 默认主题下

```css
:root {
Expand All @@ -1244,7 +1244,7 @@ export const overridesPreferences = defineOverridesPreferences({

侧边栏颜色通过`--header`变量来配置

### 默认主题下
### 默认主题下

```css
:root {
Expand Down
2 changes: 1 addition & 1 deletion internal/vite-config/src/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { viteImportMapPlugin } from './importmap';
import { viteInjectAppLoadingPlugin } from './inject-app-loading';
import { viteMetadataPlugin } from './inject-metadata';
import { viteLicensePlugin } from './license';
import { viteNitroMockPlugin } from './nitor-mock';
import { viteNitroMockPlugin } from './nitro-mock';
import { vitePrintPlugin } from './print';

/**
Expand Down
1 change: 1 addition & 0 deletions packages/@core/base/shared/src/constants/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* @en_US Layout content height
*/
export const CSS_VARIABLE_LAYOUT_CONTENT_HEIGHT = `--vben-content-height`;
export const CSS_VARIABLE_LAYOUT_CONTENT_WIDTH = `--vben-content-width`;

/**
* @zh_CN 默认命名空间
Expand Down
219 changes: 103 additions & 116 deletions packages/@core/base/shared/src/utils/dom.test.ts
Original file line number Diff line number Diff line change
@@ -1,140 +1,127 @@
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';

import { getElementVisibleHeight } from './dom'; // 假设函数位于 utils.ts 中

describe('getElementVisibleHeight', () => {
// Mocking the getBoundingClientRect method
const mockGetBoundingClientRect = vi.fn();
const originalGetBoundingClientRect = Element.prototype.getBoundingClientRect;

beforeAll(() => {
// Mock getBoundingClientRect method
Element.prototype.getBoundingClientRect = mockGetBoundingClientRect;
});

afterAll(() => {
// Restore original getBoundingClientRect method
Element.prototype.getBoundingClientRect = originalGetBoundingClientRect;
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { getElementVisibleRect } from './dom'; // 假设函数位于 utils.ts 中

describe('getElementVisibleRect', () => {
// 设置浏览器视口尺寸的 mock
beforeEach(() => {
vi.spyOn(document.documentElement, 'clientHeight', 'get').mockReturnValue(
800,
);
vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(800);
vi.spyOn(document.documentElement, 'clientWidth', 'get').mockReturnValue(
1000,
);
vi.spyOn(window, 'innerWidth', 'get').mockReturnValue(1000);
});

it('should return 0 if the element is null or undefined', () => {
expect(getElementVisibleHeight(null)).toBe(0);
expect(getElementVisibleHeight()).toBe(0);
});

it('should return the visible height of the element', () => {
// Mock the getBoundingClientRect return value
mockGetBoundingClientRect.mockReturnValue({
bottom: 500,
height: 400,
it('should return default rect if element is undefined', () => {
expect(getElementVisibleRect()).toEqual({
bottom: 0,
height: 0,
left: 0,
right: 0,
toJSON: () => ({}),
top: 100,
top: 0,
width: 0,
x: 0,
y: 0,
});

const mockElement = document.createElement('div');
document.body.append(mockElement);

// Mocking window.innerHeight and document.documentElement.clientHeight
const originalInnerHeight = window.innerHeight;
const originalClientHeight = document.documentElement.clientHeight;

Object.defineProperty(window, 'innerHeight', {
value: 600,
writable: true,
});

Object.defineProperty(document.documentElement, 'clientHeight', {
value: 600,
writable: true,
});

expect(getElementVisibleHeight(mockElement)).toBe(400);

// Restore original values
Object.defineProperty(window, 'innerHeight', {
value: originalInnerHeight,
writable: true,
});

Object.defineProperty(document.documentElement, 'clientHeight', {
value: originalClientHeight,
writable: true,
});

mockElement.remove();
});

it('should return the visible height when element is partially out of viewport', () => {
// Mock the getBoundingClientRect return value
mockGetBoundingClientRect.mockReturnValue({
bottom: 300,
height: 400,
it('should return default rect if element is null', () => {
expect(getElementVisibleRect(null)).toEqual({
bottom: 0,
height: 0,
left: 0,
right: 0,
toJSON: () => ({}),
top: -100,
top: 0,
width: 0,
x: 0,
y: 0,
});

const mockElement = document.createElement('div');
document.body.append(mockElement);

// Mocking window.innerHeight and document.documentElement.clientHeight
const originalInnerHeight = window.innerHeight;
const originalClientHeight = document.documentElement.clientHeight;

Object.defineProperty(window, 'innerHeight', {
value: 600,
writable: true,
});
});

Object.defineProperty(document.documentElement, 'clientHeight', {
value: 600,
writable: true,
it('should return correct visible rect when element is fully visible', () => {
const element = {
getBoundingClientRect: () => ({
bottom: 400,
height: 300,
left: 200,
right: 600,
top: 100,
width: 400,
}),
} as HTMLElement;

expect(getElementVisibleRect(element)).toEqual({
bottom: 400,
height: 300,
left: 200,
right: 600,
top: 100,
width: 400,
});
});

expect(getElementVisibleHeight(mockElement)).toBe(300);

// Restore original values
Object.defineProperty(window, 'innerHeight', {
value: originalInnerHeight,
writable: true,
it('should return correct visible rect when element is partially off-screen at the top', () => {
const element = {
getBoundingClientRect: () => ({
bottom: 200,
height: 250,
left: 100,
right: 500,
top: -50,
width: 400,
}),
} as HTMLElement;

expect(getElementVisibleRect(element)).toEqual({
bottom: 200,
height: 200,
left: 100,
right: 500,
top: 0,
width: 400,
});
});

Object.defineProperty(document.documentElement, 'clientHeight', {
value: originalClientHeight,
writable: true,
it('should return correct visible rect when element is partially off-screen at the right', () => {
const element = {
getBoundingClientRect: () => ({
bottom: 400,
height: 300,
left: 800,
right: 1200,
top: 100,
width: 400,
}),
} as HTMLElement;

expect(getElementVisibleRect(element)).toEqual({
bottom: 400,
height: 300,
left: 800,
right: 1000,
top: 100,
width: 200,
});

mockElement.remove();
});

it('should return 0 if the element is completely out of viewport', () => {
// Mock the getBoundingClientRect return value
mockGetBoundingClientRect.mockReturnValue({
bottom: -100,
height: 400,
left: 0,
right: 0,
toJSON: () => ({}),
top: -500,
it('should return all zeros when element is completely off-screen', () => {
const element = {
getBoundingClientRect: () => ({
bottom: 1200,
height: 300,
left: 1100,
right: 1400,
top: 900,
width: 300,
}),
} as HTMLElement;

expect(getElementVisibleRect(element)).toEqual({
bottom: 800,
height: 0,
left: 1100,
right: 1000,
top: 900,
width: 0,
x: 0,
y: 0,
});

const mockElement = document.createElement('div');
document.body.append(mockElement);

expect(getElementVisibleHeight(mockElement)).toBe(0);

mockElement.remove();
});
});
43 changes: 36 additions & 7 deletions packages/@core/base/shared/src/utils/dom.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
export interface VisibleDomRect {
bottom: number;
height: number;
left: number;
right: number;
top: number;
width: number;
}

/**
* 获取元素可见高度
* 获取元素可见信息
* @param element
*/
function getElementVisibleHeight(
export function getElementVisibleRect(
element?: HTMLElement | null | undefined,
): number {
): VisibleDomRect {
if (!element) {
return 0;
return {
bottom: 0,
height: 0,
left: 0,
right: 0,
top: 0,
width: 0,
};
}
const rect = element.getBoundingClientRect();
const viewHeight = Math.max(
Expand All @@ -17,7 +33,20 @@ function getElementVisibleHeight(
const top = Math.max(rect.top, 0);
const bottom = Math.min(rect.bottom, viewHeight);

return Math.max(0, bottom - top);
}
const viewWidth = Math.max(
document.documentElement.clientWidth,
window.innerWidth,
);

const left = Math.max(rect.left, 0);
const right = Math.min(rect.right, viewWidth);

export { getElementVisibleHeight };
return {
bottom,
height: Math.max(0, bottom - top),
left,
right,
top,
width: Math.max(0, right - left),
};
}
Loading
Loading