diff --git a/package.json b/package.json index e37e4f14a7..4476ab7746 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,7 @@ "react-copy-to-clipboard": "^5.1.0", "react-error-boundary": "^4.0.10", "react-intl": "^6.4.4", + "react-loading-skeleton": "^3.1.1", "react-simple-code-editor": "^0.13.1", "rehype-autolink-headings": "^6.1.1", "rehype-remove-comments": "^5.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2464a9fd6e..d538229908 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - importers: .: @@ -146,6 +142,9 @@ importers: react-intl: specifier: ^6.4.4 version: 6.4.4(react@18.2.0)(typescript@5.0.4) + react-loading-skeleton: + specifier: ^3.1.1 + version: 3.1.1(react@18.2.0) react-simple-code-editor: specifier: ^0.13.1 version: 0.13.1(react-dom@18.2.0)(react@18.2.0) @@ -12245,6 +12244,14 @@ packages: resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} dev: true + /react-loading-skeleton@3.1.1(react@18.2.0): + resolution: {integrity: sha512-gQeNzzKXlevvquRDOhN5kas5VE7toTKrpmE9BpUdf0iip9c5ae0LcVbulh5ebO2CFl4RrYsyLuDtYGyrh1h1iA==} + peerDependencies: + react: '>=16.8.0' + dependencies: + react: 18.2.0 + dev: false + /react-merge-refs@1.1.0: resolution: {integrity: sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==} dev: false @@ -15029,3 +15036,7 @@ packages: /zwitch@2.0.2: resolution: {integrity: sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA==} dev: false + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false diff --git a/src/client/pages/Loading.ts b/src/client/pages/Loading.ts new file mode 100644 index 0000000000..610b3cef0a --- /dev/null +++ b/src/client/pages/Loading.ts @@ -0,0 +1,2 @@ +// allow customize loading via theme slots or ./dumi/loading.tsx +export { default } from 'dumi/theme/slots/Loading'; diff --git a/src/client/theme-default/slots/Loading/index.less b/src/client/theme-default/slots/Loading/index.less new file mode 100644 index 0000000000..4685a2093f --- /dev/null +++ b/src/client/theme-default/slots/Loading/index.less @@ -0,0 +1,20 @@ +@import (reference) '../../styles/variables.less'; + +@skeleton-cls: react-loading-skeleton; + +.@{prefix}-loading-skeleton { + .@{skeleton-cls} { + margin-block-end: 0.38em; + + &.first-line { + width: calc(100% - 2em); + margin-inline-start: 2em; + } + + // ======== dark mode ======== + @{dark-selector} & { + --highlight-color: fade(@c-text-dark, @dark-light-amount); + --base-color: @c-text; + } + } +} diff --git a/src/client/theme-default/slots/Loading/index.tsx b/src/client/theme-default/slots/Loading/index.tsx new file mode 100644 index 0000000000..9e6042c220 --- /dev/null +++ b/src/client/theme-default/slots/Loading/index.tsx @@ -0,0 +1,14 @@ +import React from 'react'; +import Skeleton from 'react-loading-skeleton'; +import 'react-loading-skeleton/dist/skeleton.css'; +import './index.less'; + +const Loading: React.FC = () => ( +
+ + + +
+); + +export default Loading; diff --git a/src/features/theme/index.ts b/src/features/theme/index.ts index ea0243c619..d2572765d9 100644 --- a/src/features/theme/index.ts +++ b/src/features/theme/index.ts @@ -17,6 +17,9 @@ import { safeExcludeInMFSU } from '../derivative'; import loadTheme, { IThemeLoadResult } from './loader'; const DEFAULT_THEME_PATH = path.join(__dirname, '../../../theme-default'); +const DEFAULT_LOADING_PATH = winPath( + path.resolve(__dirname, '../../client/pages/Loading'), +); /** * get pkg theme name @@ -273,7 +276,7 @@ export default (api: IApi) => { // execute before umi tmpFiles plugin stage: -Infinity, fn() { - const { globalLoading } = api.appData; + const { globalLoading = DEFAULT_LOADING_PATH } = api.appData; const enableNProgress = !!api.config.themeConfig.nprogress; // replace original loading component data @@ -291,12 +294,8 @@ export default (api: IApi) => { )}'; import './nprogress.css';` : '' - }${ - globalLoading - ? ` -import UserLoading from '${globalLoading}';` - : '' } +import UserLoading from '${globalLoading}'; import React, { useLayoutEffect, type FC } from 'react'; import { useSiteData } from 'dumi'; @@ -321,7 +320,7 @@ const DumiLoading: FC = () => { } }, []); - return ${globalLoading ? '' : 'null'}; + return } export default DumiLoading;