From edd3dea7a388016a9118e4716742249e8bcd151d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 30 Mar 2025 17:29:29 +0800 Subject: [PATCH 1/8] chore(deps): update dependency nwsapi to v2.2.20 (#53343) * chore(deps): update dependency nwsapi to v2.2.20 * test: update test case --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: lijianan <574980606@qq.com> --- components/_util/responsiveObserver.ts | 1 - components/_util/toList.ts | 1 - components/theme/__tests__/token.test.tsx | 31 ++++++++++------------- package.json | 6 ++--- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/components/_util/responsiveObserver.ts b/components/_util/responsiveObserver.ts index fe4559f1fc..db19410b53 100644 --- a/components/_util/responsiveObserver.ts +++ b/components/_util/responsiveObserver.ts @@ -72,7 +72,6 @@ export const matchScreen = (screens: ScreenMap, screenSizes?: ScreenSizeMap) => } }; - interface ResponsiveObserverType { responsiveMap: BreakpointMap; dispatch: (map: ScreenMap) => boolean; diff --git a/components/_util/toList.ts b/components/_util/toList.ts index ae29f448c7..a3b359088a 100644 --- a/components/_util/toList.ts +++ b/components/_util/toList.ts @@ -1,5 +1,4 @@ export default function toList(candidate: T | T[], skipEmpty = false): T[] { if (skipEmpty && (candidate === undefined || candidate === null)) return []; - return Array.isArray(candidate) ? candidate : [candidate]; } diff --git a/components/theme/__tests__/token.test.tsx b/components/theme/__tests__/token.test.tsx index 45c0949ecf..b47bb0a95b 100644 --- a/components/theme/__tests__/token.test.tsx +++ b/components/theme/__tests__/token.test.tsx @@ -313,28 +313,25 @@ describe('Theme', () => { }); it('component token should support algorithm', () => { - const Demo = ({ algorithm }: { algorithm?: boolean | typeof theme.darkAlgorithm }) => ( - - - - ); + const Demo: React.FC<{ algorithm?: boolean | typeof theme.darkAlgorithm }> = (props) => { + const { algorithm } = props; + return ( + + + + ); + }; const { container, rerender } = render(); - expect(container.querySelector('input')).toHaveStyle({ 'border-color': '#4096ff' }); + + const inputElement = container.querySelector('input'); + + expect(inputElement).toHaveStyle({ 'border-color': '#d9d9d9' }); rerender(); - expect(container.querySelector('input')).toHaveStyle({ 'border-color': '#20c77c' }); + expect(inputElement).toHaveStyle({ 'border-color': '#d9d9d9' }); rerender(); - expect(container.querySelector('input')).toHaveStyle({ 'border-color': '#1fb572' }); + expect(inputElement).toHaveStyle({ 'border-color': '#ffffff' }); }); }); diff --git a/package.json b/package.json index 9871abe767..9b9b8af0a9 100644 --- a/package.json +++ b/package.json @@ -354,13 +354,13 @@ }, "pnpm":{ "overrides": { - "nwsapi":"2.2.19" + "nwsapi":"2.2.20" } }, "overrides": { - "nwsapi": "2.2.19" + "nwsapi": "2.2.20" }, "resolutions": { - "nwsapi": "2.2.19" + "nwsapi": "2.2.20" } } From ad99af8116d241299fa4811bcbf37d74aaf6acf5 Mon Sep 17 00:00:00 2001 From: lijianan <574980606@qq.com> Date: Sun, 30 Mar 2025 23:00:22 +0800 Subject: [PATCH 2/8] test: add test case for toList candidate branch (#53344) Signed-off-by: lijianan <574980606@qq.com> --- components/_util/__tests__/util.test.tsx | 9 +++++++++ components/_util/toList.ts | 10 +++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/components/_util/__tests__/util.test.tsx b/components/_util/__tests__/util.test.tsx index 067c9aa518..ec3693f627 100644 --- a/components/_util/__tests__/util.test.tsx +++ b/components/_util/__tests__/util.test.tsx @@ -1,6 +1,7 @@ import { waitFakeTimer } from '../../../tests/utils'; import { isStyleSupport } from '../styleChecker'; import throttleByAnimationFrame from '../throttleByAnimationFrame'; +import toList from '../toList'; describe('Test utils function', () => { describe('throttle', () => { @@ -56,4 +57,12 @@ describe('Test utils function', () => { spy.mockRestore(); }); }); + describe('toList', () => { + it('toList should work', () => { + expect(toList(123)).toEqual([123]); + expect(toList([123])).toEqual([123]); + expect(toList(null, true)).toEqual([]); + expect(toList(undefined, true)).toEqual([]); + }); + }); }); diff --git a/components/_util/toList.ts b/components/_util/toList.ts index a3b359088a..ebb536cd9b 100644 --- a/components/_util/toList.ts +++ b/components/_util/toList.ts @@ -1,4 +1,8 @@ -export default function toList(candidate: T | T[], skipEmpty = false): T[] { - if (skipEmpty && (candidate === undefined || candidate === null)) return []; +const toList = (candidate: T | T[], skipEmpty = false): T[] => { + if (skipEmpty && (candidate === undefined || candidate === null)) { + return []; + } return Array.isArray(candidate) ? candidate : [candidate]; -} +}; + +export default toList; From c74ee1cd420fc198050f0fbf977e3e6c4d83ded0 Mon Sep 17 00:00:00 2001 From: lijianan <574980606@qq.com> Date: Mon, 31 Mar 2025 09:54:16 +0800 Subject: [PATCH 3/8] docs: update renderItem prop type (#53346) --- components/list/index.en-US.md | 2 +- components/list/index.zh-CN.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/list/index.en-US.md b/components/list/index.en-US.md index 23fc1da35a..a01b0cc35d 100644 --- a/components/list/index.en-US.md +++ b/components/list/index.en-US.md @@ -44,7 +44,7 @@ Common props ref:[Common props](/docs/react/common-props) | loadMore | Shows a load more content | ReactNode | - | | | locale | The i18n text including empty text | object | {emptyText: `No Data`} | | | pagination | Pagination [config](/components/pagination/), hide it by setting it to false | boolean \| object | false | | -| renderItem | Customize list item when using `dataSource` | (item) => ReactNode | - | | +| renderItem | Customize list item when using `dataSource` | (item: T, index: number) => ReactNode | - | | | rowKey | Item's unique value, could be an Item's key which holds a unique value of type `React.Key` or function that receives Item and returns a `React.Key` | `keyof` T \| (item: T) => `React.Key` | `"key"` | | | size | Size of list | `default` \| `large` \| `small` | `default` | | | split | Toggles rendering of the split under the list item | boolean | true | | diff --git a/components/list/index.zh-CN.md b/components/list/index.zh-CN.md index 8a0ec408b3..4a83d5fb0c 100644 --- a/components/list/index.zh-CN.md +++ b/components/list/index.zh-CN.md @@ -47,7 +47,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*tBzwQ7raKX8AAA | loadMore | 加载更多 | ReactNode | - | | | locale | 默认文案设置,目前包括空数据文案 | object | {emptyText: `暂无数据`} | | | pagination | 对应的 `pagination` 配置,设置 false 不显示 | boolean \| object | false | | -| renderItem | 当使用 dataSource 时,可以用 `renderItem` 自定义渲染列表项 | (item) => ReactNode | - | | +| renderItem | 当使用 dataSource 时,可以用 `renderItem` 自定义渲染列表项 | (item: T, index: number) => ReactNode | - | | | rowKey | 当 `renderItem` 自定义渲染列表项有效时,自定义每一行的 `key` 的获取方式 | `keyof` T \| (item: T) => `React.Key` | `"key"` | | | size | list 的尺寸 | `default` \| `large` \| `small` | `default` | | | split | 是否展示分割线 | boolean | true | | From f8983c68940f4e2d0cb73e269bd920f5734f764f Mon Sep 17 00:00:00 2001 From: lijianan <574980606@qq.com> Date: Mon, 31 Mar 2025 11:03:49 +0800 Subject: [PATCH 4/8] site: update React.useContext to React.use (#53341) * chore: update use to react19 * fix: fix * fix: fix * fix: fix * fix: fix * fix: fix * fix: fix --------- Signed-off-by: lijianan <574980606@qq.com> --- .dumi/components/SemanticPreview.tsx | 1 + .dumi/hooks/useDark.tsx | 4 - .../index/components/BannerRecommends.tsx | 6 +- .../pages/index/components/ComponentsList.tsx | 106 ++++++------ .../index/components/DesignFramework.tsx | 23 ++- .dumi/pages/index/components/Group.tsx | 3 +- .../index/components/PreviewBanner/index.tsx | 159 +++++++++--------- .dumi/pages/index/components/SiteContext.ts | 4 +- .dumi/pages/index/components/Theme/index.tsx | 13 +- .dumi/pages/index/index.tsx | 6 +- .dumi/pages/theme-editor/index.tsx | 3 +- .dumi/theme/SiteThemeProvider.tsx | 6 +- .../builtins/ComponentOverview/index.tsx | 4 +- .dumi/theme/builtins/DemoWrapper/index.tsx | 8 +- .../builtins/Previewer/CodePreviewer.tsx | 8 +- .dumi/theme/common/CodePreview.tsx | 5 +- .dumi/theme/common/PrevAndNext.tsx | 5 +- .dumi/theme/common/ThemeSwitch/index.tsx | 8 +- .dumi/theme/layouts/DocLayout/index.tsx | 4 +- .dumi/theme/layouts/GlobalLayout.tsx | 8 +- .dumi/theme/layouts/ResourceLayout/index.tsx | 134 +++++++-------- .dumi/theme/slots/Content/Contributors.tsx | 4 +- .dumi/theme/slots/Content/index.tsx | 12 +- .dumi/theme/slots/Footer/index.tsx | 95 +++++------ .dumi/theme/slots/Header/index.tsx | 15 +- .dumi/theme/slots/Sidebar/index.tsx | 4 +- components/watermark/index.tsx | 4 +- components/watermark/useClips.ts | 44 ++--- components/watermark/useSingletonCache.ts | 2 +- docs/blog/config-provider-style.en-US.md | 12 +- docs/blog/config-provider-style.zh-CN.md | 12 +- package.json | 10 +- 32 files changed, 353 insertions(+), 379 deletions(-) diff --git a/.dumi/components/SemanticPreview.tsx b/.dumi/components/SemanticPreview.tsx index ecdfa5442e..55ea4727bf 100644 --- a/.dumi/components/SemanticPreview.tsx +++ b/.dumi/components/SemanticPreview.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-hooks-extra/no-direct-set-state-in-use-effect */ import React from 'react'; import { Col, ConfigProvider, Flex, Row, Tag, theme, Typography } from 'antd'; import { createStyles, css } from 'antd-style'; diff --git a/.dumi/hooks/useDark.tsx b/.dumi/hooks/useDark.tsx index 6b31dee12c..b604d87776 100644 --- a/.dumi/hooks/useDark.tsx +++ b/.dumi/hooks/useDark.tsx @@ -1,7 +1,3 @@ import React from 'react'; export const DarkContext = React.createContext(false); - -export default function useDark() { - return React.useContext(DarkContext); -} diff --git a/.dumi/pages/index/components/BannerRecommends.tsx b/.dumi/pages/index/components/BannerRecommends.tsx index 2859c9b43b..a2ced6ba38 100644 --- a/.dumi/pages/index/components/BannerRecommends.tsx +++ b/.dumi/pages/index/components/BannerRecommends.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { Badge, Carousel, Flex, Skeleton, Typography } from 'antd'; import { createStyles } from 'antd-style'; import classNames from 'classnames'; @@ -110,7 +110,7 @@ const RecommendItem: React.FC = ({ extra, index, icons, clas }; export const BannerRecommendsFallback: React.FC = () => { - const { isMobile } = useContext(SiteContext); + const { isMobile } = React.use(SiteContext); const { styles } = useStyle(); const list = Array.from({ length: 3 }); @@ -137,7 +137,7 @@ export const BannerRecommendsFallback: React.FC = () => { const BannerRecommends: React.FC = () => { const { styles } = useStyle(); const [, lang] = useLocale(); - const { isMobile } = React.useContext(SiteContext); + const { isMobile } = React.use(SiteContext); const data = useSiteData(); const extras = data?.extras?.[lang]; const icons = data?.icons || []; diff --git a/.dumi/pages/index/components/ComponentsList.tsx b/.dumi/pages/index/components/ComponentsList.tsx index 739355b890..28211493de 100644 --- a/.dumi/pages/index/components/ComponentsList.tsx +++ b/.dumi/pages/index/components/ComponentsList.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { CustomerServiceOutlined, QuestionCircleOutlined, SyncOutlined } from '@ant-design/icons'; import { Alert, @@ -16,9 +16,9 @@ import { createStyles, css } from 'antd-style'; import classNames from 'classnames'; import dayjs from 'dayjs'; -import useDark from '../../../hooks/useDark'; import useLocale from '../../../hooks/useLocale'; import SiteContext from '../../../theme/slots/SiteContext'; +import { DarkContext } from './../../../hooks/useDark'; import { getCarouselStyle } from './util'; const { _InternalPanelDoNotUseOrYouWillBeFired: ModalDoNotUseOrYouWillBeFired } = Modal; @@ -61,66 +61,62 @@ const locales = { }, }; -const useStyle = () => { - const isRootDark = useDark(); +const useStyle = createStyles(({ token }) => { + const { carousel } = getCarouselStyle(); + const isDark = React.use(DarkContext); + return { + card: css` + border-radius: ${token.borderRadius}px; + border: 1px solid ${isDark ? token.colorBorder : 'transparent'}; + background-color: ${isDark ? token.colorBgContainer : '#f5f8ff'}; + padding: ${token.paddingXL}px; + flex: none; + overflow: hidden; + position: relative; + display: flex; + flex-direction: column; + align-items: stretch; - return createStyles(({ token }) => { - const { carousel } = getCarouselStyle(); - - return { - card: css` - border-radius: ${token.borderRadius}px; - border: 1px solid ${isRootDark ? token.colorBorder : 'transparent'}; - background: ${isRootDark ? token.colorBgContainer : '#f5f8ff'}; - padding: ${token.paddingXL}px; + > * { flex: none; - overflow: hidden; - position: relative; - display: flex; - flex-direction: column; - align-items: stretch; - - > * { - flex: none; - } - `, - cardCircle: css` - position: absolute; - width: 120px; - height: 120px; - background: #1677ff; - border-radius: 50%; - filter: blur(40px); - opacity: 0.1; - `, - mobileCard: css` - height: 395px; - `, - nodeWrap: css` - margin-top: ${token.paddingLG}px; - flex: auto; - display: flex; - align-items: center; - justify-content: center; - `, - carousel, - componentsList: css` - width: 100%; - overflow: hidden; - `, - mobileComponentsList: css` - margin: 0 ${token.margin}px; - `, - }; - })(); -}; + } + `, + cardCircle: css` + position: absolute; + width: 120px; + height: 120px; + background: #1677ff; + border-radius: 50%; + filter: blur(40px); + opacity: 0.1; + `, + mobileCard: css` + height: 395px; + `, + nodeWrap: css` + margin-top: ${token.paddingLG}px; + flex: auto; + display: flex; + align-items: center; + justify-content: center; + `, + carousel, + componentsList: css` + width: 100%; + overflow: hidden; + `, + mobileComponentsList: css` + margin: 0 ${token.margin}px; + `, + }; +}); const ComponentItem: React.FC = ({ title, node, type, index }) => { const tagColor = type === 'new' ? 'processing' : 'warning'; const [locale] = useLocale(locales); const tagText = type === 'new' ? locale.new : locale.update; const { styles } = useStyle(); - const { isMobile } = useContext(SiteContext); + const { isMobile } = React.use(SiteContext); return (
{/* Decorator */} @@ -151,7 +147,7 @@ interface ComponentItemProps { const ComponentsList: React.FC = () => { const { styles } = useStyle(); const [locale] = useLocale(locales); - const { isMobile } = useContext(SiteContext); + const { isMobile } = React.use(SiteContext); const COMPONENTS = React.useMemo[]>( () => [ { diff --git a/.dumi/pages/index/components/DesignFramework.tsx b/.dumi/pages/index/components/DesignFramework.tsx index e2816d9118..8b6852c995 100644 --- a/.dumi/pages/index/components/DesignFramework.tsx +++ b/.dumi/pages/index/components/DesignFramework.tsx @@ -1,13 +1,13 @@ -import React, { useContext } from 'react'; +import React from 'react'; import { Col, Row, Typography } from 'antd'; import { createStyles, useTheme } from 'antd-style'; import { useLocation } from 'dumi'; -import useDark from '../../../hooks/useDark'; import useLocale from '../../../hooks/useLocale'; import Link from '../../../theme/common/Link'; import SiteContext from '../../../theme/slots/SiteContext'; import * as utils from '../../../theme/utils'; +import { DarkContext } from './../../../hooks/useDark'; const SECONDARY_LIST = [ { @@ -63,14 +63,13 @@ const locales = { }, }; -const useStyle = () => { - const isRootDark = useDark(); - - return createStyles(({ token, css }) => ({ +const useStyle = createStyles(({ token, css }) => { + const isDark = React.use(DarkContext); + return { card: css` padding: ${token.paddingSM}px; border-radius: ${token.borderRadius * 2}px; - background: ${isRootDark ? 'rgba(0, 0, 0, 0.45)' : token.colorBgElevated}; + background: ${isDark ? 'rgba(0, 0, 0, 0.45)' : token.colorBgElevated}; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), 0 1px 6px -1px rgba(0, 0, 0, 0.02), @@ -87,15 +86,15 @@ const useStyle = () => { display: block; border-radius: ${token.borderRadius * 2}px; padding: ${token.paddingMD}px ${token.paddingLG}px; - background: ${isRootDark ? 'rgba(0, 0, 0, 0.25)' : 'rgba(0, 0, 0, 0.02)'}; - border: 1px solid ${isRootDark ? 'rgba(255, 255, 255, 0.45)' : 'rgba(0, 0, 0, 0.06)'}; + background: ${isDark ? 'rgba(0, 0, 0, 0.25)' : 'rgba(0, 0, 0, 0.02)'}; + border: 1px solid ${isDark ? 'rgba(255, 255, 255, 0.45)' : 'rgba(0, 0, 0, 0.06)'}; img { height: 48px; } `, - }))(); -}; + }; +}); const DesignFramework: React.FC = () => { const [locale] = useLocale(locales); @@ -103,7 +102,7 @@ const DesignFramework: React.FC = () => { const { styles } = useStyle(); const { pathname, search } = useLocation(); const isZhCN = utils.isZhCN(pathname); - const { isMobile } = useContext(SiteContext); + const { isMobile } = React.use(SiteContext); const colSpan = isMobile ? 24 : 8; const MAINLY_LIST = [ diff --git a/.dumi/pages/index/components/Group.tsx b/.dumi/pages/index/components/Group.tsx index 437fdcaada..fcc5e45e9f 100644 --- a/.dumi/pages/index/components/Group.tsx +++ b/.dumi/pages/index/components/Group.tsx @@ -1,5 +1,4 @@ import * as React from 'react'; -import { useContext } from 'react'; import { Typography } from 'antd'; import { createStyles, useTheme } from 'antd-style'; import classNames from 'classnames'; @@ -40,7 +39,7 @@ const Group: React.FC> = (props) => { const { id, title, titleColor, description, children, decoration, background, collapse } = props; const token = useTheme(); const { styles } = useStyle(); - const { isMobile } = useContext(SiteContext); + const { isMobile } = React.use(SiteContext); const childNode = ( <>
diff --git a/.dumi/pages/index/components/PreviewBanner/index.tsx b/.dumi/pages/index/components/PreviewBanner/index.tsx index 0e222dda99..c04687e4de 100644 --- a/.dumi/pages/index/components/PreviewBanner/index.tsx +++ b/.dumi/pages/index/components/PreviewBanner/index.tsx @@ -26,101 +26,98 @@ const locales = { }, }; -const useStyle = () => { +const useStyle = createStyles(({ token, css, cx }) => { + const textShadow = `0 0 4px ${token.colorBgContainer}`; const { isMobile, theme } = use(SiteContext); const isDark = theme.includes('dark'); - return createStyles(({ token, css, cx }) => { - const textShadow = `0 0 4px ${token.colorBgContainer}`; + const mask = cx(css` + position: absolute; + inset: 0; + backdrop-filter: blur(2px); + opacity: 1; + background-color: ${isDark ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.2)'}; + transition: all 1s ease; + pointer-events: none; + `); - const mask = cx(css` - position: absolute; - inset: 0; - backdrop-filter: blur(2px); - opacity: 1; - background-color: ${isDark ? 'rgba(0, 0, 0, 0.2)' : 'rgba(255, 255, 255, 0.2)'}; - transition: all 1s ease; - pointer-events: none; - `); + const block = cx(css` + position: absolute; + inset-inline-end: -60px; + top: -24px; + transition: all 1s cubic-bezier(0.03, 0.98, 0.52, 0.99); + `); - const block = cx(css` - position: absolute; - inset-inline-end: -60px; - top: -24px; - transition: all 1s cubic-bezier(.03,.98,.52,.99); - `); + return { + holder: css` + height: 640px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; + overflow: hidden; + perspective: 800px; + /* fix safari bug by removing blur style */ + transform: translateZ(1000px); + row-gap: ${token.marginXL}px; - return { - holder: css` - height: 640px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: relative; - overflow: hidden; - perspective: 800px; - /* fix safari bug by removing blur style */ - transform: translateZ(1000px); - row-gap: ${token.marginXL}px; - - &:hover { + &:hover { .${mask} { opacity: 0; } .${block} { - transform: scale(0.96); + transform: scale(0.96); } - } - `, + } + `, - mask, + mask, - typography: css` - text-align: center; - position: relative; - z-index: 1; - padding-inline: ${token.paddingXL}px; - text-shadow: ${Array.from({ length: 5 }, () => textShadow).join(', ')}; - h1 { - font-family: AliPuHui, ${token.fontFamily} !important; - font-weight: 900 !important; - font-size: ${token.fontSizeHeading2 * 2}px !important; - line-height: ${token.lineHeightHeading2} !important; - } + typography: css` + text-align: center; + position: relative; + z-index: 1; + padding-inline: ${token.paddingXL}px; + text-shadow: ${Array.from({ length: 5 }, () => textShadow).join(', ')}; + h1 { + font-family: AliPuHui, ${token.fontFamily} !important; + font-weight: 900 !important; + font-size: ${token.fontSizeHeading2 * 2}px !important; + line-height: ${token.lineHeightHeading2} !important; + } - p { - font-size: ${token.fontSizeLG}px !important; - font-weight: normal !important; - margin-bottom: 0; - } - `, - block, - child: css` - position: relative; - width: 100%; - max-width: 1200px; - margin: 0 auto; - z-index: 1; - `, - btnWrap: css` - margin-bottom: ${token.marginXL}px; - `, - bgImg: css` - position: absolute; - width: 240px; - `, - bgImgTop: css` - top: 0; - inset-inline-start: ${isMobile ? '-120px' : 0}; - `, - bgImgBottom: css` - bottom: 120px; - inset-inline-end: ${isMobile ? 0 : '40%'}; - `, - }; - })(); -}; + p { + font-size: ${token.fontSizeLG}px !important; + font-weight: normal !important; + margin-bottom: 0; + } + `, + block, + child: css` + position: relative; + width: 100%; + max-width: 1200px; + margin: 0 auto; + z-index: 1; + `, + btnWrap: css` + margin-bottom: ${token.marginXL}px; + `, + bgImg: css` + position: absolute; + width: 240px; + `, + bgImgTop: css` + top: 0; + inset-inline-start: ${isMobile ? '-120px' : 0}; + `, + bgImgBottom: css` + bottom: 120px; + inset-inline-end: ${isMobile ? 0 : '40%'}; + `, + }; +}); const PreviewBanner: React.FC> = (props) => { const { children } = props; diff --git a/.dumi/pages/index/components/SiteContext.ts b/.dumi/pages/index/components/SiteContext.ts index 9767a89b50..a2cfed721f 100644 --- a/.dumi/pages/index/components/SiteContext.ts +++ b/.dumi/pages/index/components/SiteContext.ts @@ -4,8 +4,6 @@ export interface SiteContextProps { isMobile: boolean; } -const SiteContext = React.createContext({ - isMobile: false, -}); +const SiteContext = React.createContext({ isMobile: false }); export default SiteContext; diff --git a/.dumi/pages/index/components/Theme/index.tsx b/.dumi/pages/index/components/Theme/index.tsx index 2a60ebada0..ea5970ba7f 100644 --- a/.dumi/pages/index/components/Theme/index.tsx +++ b/.dumi/pages/index/components/Theme/index.tsx @@ -1,12 +1,13 @@ +/* eslint-disable react-hooks-extra/no-direct-set-state-in-use-effect */ import * as React from 'react'; import { defaultAlgorithm, defaultTheme } from '@ant-design/compatible'; +import { FastColor } from '@ant-design/fast-color'; import { BellOutlined, FolderOutlined, HomeOutlined, QuestionCircleOutlined, } from '@ant-design/icons'; -import { FastColor } from '@ant-design/fast-color'; import type { ColorPickerProps, GetProp, MenuProps, ThemeConfig } from 'antd'; import { Breadcrumb, @@ -25,13 +26,13 @@ import { generateColor } from 'antd/es/color-picker/util'; import classNames from 'classnames'; import { useLocation } from 'dumi'; -import useDark from '../../../../hooks/useDark'; import useLocale from '../../../../hooks/useLocale'; import LinkButton from '../../../../theme/common/LinkButton'; import SiteContext from '../../../../theme/slots/SiteContext'; import { getLocalizedPathname } from '../../../../theme/utils'; import Group from '../Group'; import { getCarouselStyle } from '../util'; +import { DarkContext } from './../../../../hooks/useDark'; import BackgroundImage from './BackgroundImage'; import ColorPicker from './ColorPicker'; import { DEFAULT_COLOR, getAvatarURL, getClosetColor, PINK_COLOR } from './colorUtil'; @@ -360,7 +361,7 @@ const Theme: React.FC = () => { const { compact, themeType, colorPrimary, ...themeToken } = themeData; const isLight = themeType !== 'dark'; const [form] = Form.useForm(); - const { isMobile } = React.useContext(SiteContext); + const { isMobile } = React.use(SiteContext); const colorPrimaryValue = React.useMemo( () => (typeof colorPrimary === 'string' ? colorPrimary : colorPrimary.toHexString()), [colorPrimary], @@ -393,11 +394,11 @@ const Theme: React.FC = () => { form.setFieldsValue(mergedData); }, [themeType]); - const isRootDark = useDark(); + const isDark = React.use(DarkContext); React.useEffect(() => { - onThemeChange({}, { ...themeData, themeType: isRootDark ? 'dark' : 'default' }); - }, [isRootDark]); + onThemeChange({}, { ...themeData, themeType: isDark ? 'dark' : 'default' }); + }, [isDark]); // ================================ Tokens ================================ const closestColor = getClosetColor(colorPrimaryValue); diff --git a/.dumi/pages/index/index.tsx b/.dumi/pages/index/index.tsx index 9e5a23705e..e14fc66a43 100644 --- a/.dumi/pages/index/index.tsx +++ b/.dumi/pages/index/index.tsx @@ -2,8 +2,8 @@ import React, { Suspense } from 'react'; import { ConfigProvider, theme } from 'antd'; import { createStyles, css } from 'antd-style'; -import useDark from '../../hooks/useDark'; import useLocale from '../../hooks/useLocale'; +import { DarkContext } from './../../hooks/useDark'; import BannerRecommends from './components/BannerRecommends'; import Group from './components/Group'; import PreviewBanner from './components/PreviewBanner'; @@ -41,7 +41,7 @@ const Homepage: React.FC = () => { const { styles } = useStyle(); const { token } = theme.useToken(); - const isRootDark = useDark(); + const isDark = React.use(DarkContext); return (
@@ -78,7 +78,7 @@ const Homepage: React.FC = () => { > = ({ children, theme, ...rest }) => { - const { getPrefixCls, iconPrefixCls } = useContext(ConfigProvider.ConfigContext); + const { getPrefixCls, iconPrefixCls } = React.use(ConfigProvider.ConfigContext); const rootPrefixCls = getPrefixCls(); const { token } = antdTheme.useToken(); - const { bannerVisible } = useContext(SiteContext); + const { bannerVisible } = React.use(SiteContext); React.useEffect(() => { // 需要注意与 components/config-provider/demo/holderRender.tsx 配置冲突 ConfigProvider.config({ theme: theme as ThemeConfig }); diff --git a/.dumi/theme/builtins/ComponentOverview/index.tsx b/.dumi/theme/builtins/ComponentOverview/index.tsx index ad02ce28e5..ebcce7c1eb 100644 --- a/.dumi/theme/builtins/ComponentOverview/index.tsx +++ b/.dumi/theme/builtins/ComponentOverview/index.tsx @@ -1,4 +1,4 @@ -import React, { memo, useContext, useMemo, useRef, useState } from 'react'; +import React, { memo, useMemo, useRef, useState } from 'react'; import type { CSSProperties } from 'react'; import { SearchOutlined } from '@ant-design/icons'; import { Affix, Card, Col, Divider, Flex, Input, Row, Tag, Typography } from 'antd'; @@ -83,7 +83,7 @@ const { Title } = Typography; const Overview: React.FC = () => { const { styles } = useStyle(); - const { theme } = useContext(SiteContext); + const { theme } = React.use(SiteContext); const data = useSidebarData(); const [searchBarAffixed, setSearchBarAffixed] = useState(false); diff --git a/.dumi/theme/builtins/DemoWrapper/index.tsx b/.dumi/theme/builtins/DemoWrapper/index.tsx index 18ca44f5b5..98deca8d7e 100644 --- a/.dumi/theme/builtins/DemoWrapper/index.tsx +++ b/.dumi/theme/builtins/DemoWrapper/index.tsx @@ -1,8 +1,8 @@ -import React, { Suspense, useContext } from 'react'; +import React, { Suspense } from 'react'; import { BugOutlined, CodeOutlined, ExperimentOutlined } from '@ant-design/icons'; -import { ConfigProvider, Tooltip, Button } from 'antd'; -import { DumiDemoGrid, FormattedMessage, DumiDemo } from 'dumi'; import { css, Global } from '@emotion/react'; +import { Button, ConfigProvider, Tooltip } from 'antd'; +import { DumiDemo, DumiDemoGrid, FormattedMessage } from 'dumi'; import useLayoutState from '../../../hooks/useLayoutState'; import useLocale from '../../../hooks/useLocale'; @@ -21,7 +21,7 @@ const locales = { }; const DemoWrapper: typeof DumiDemoGrid = ({ items }) => { - const { showDebug, setShowDebug } = useContext(DemoContext); + const { showDebug, setShowDebug } = React.use(DemoContext); const [locale] = useLocale(locales); const [expandAll, setExpandAll] = useLayoutState(false); diff --git a/.dumi/theme/builtins/Previewer/CodePreviewer.tsx b/.dumi/theme/builtins/Previewer/CodePreviewer.tsx index 3188f26899..da1114687f 100644 --- a/.dumi/theme/builtins/Previewer/CodePreviewer.tsx +++ b/.dumi/theme/builtins/Previewer/CodePreviewer.tsx @@ -1,4 +1,5 @@ -import React, { useContext, useEffect, useRef, useState } from 'react'; +/* eslint-disable react-hooks-extra/no-direct-set-state-in-use-effect */ +import React, { useEffect, useRef, useState } from 'react'; import { LinkOutlined, ThunderboltOutlined, UpOutlined } from '@ant-design/icons'; import type { Project } from '@stackblitz/sdk'; import stackblitzSdk from '@stackblitz/sdk'; @@ -17,7 +18,6 @@ import CodePenIcon from '../../icons/CodePenIcon'; import CodeSandboxIcon from '../../icons/CodeSandboxIcon'; import ExternalLinkIcon from '../../icons/ExternalLinkIcon'; import DemoContext from '../../slots/DemoContext'; -import type { SiteContextProps } from '../../slots/SiteContext'; import SiteContext from '../../slots/SiteContext'; import CodeBlockButton from './CodeBlockButton'; import type { AntdPreviewerProps } from './Previewer'; @@ -86,7 +86,7 @@ const CodePreviewer: React.FC = (props) => { clientOnly, pkgDependencyList, } = props; - const { codeType } = useContext(DemoContext); + const { codeType } = React.use(DemoContext); const { pkg } = useSiteData(); const location = useLocation(); @@ -110,7 +110,7 @@ const CodePreviewer: React.FC = (props) => { const codeSandboxIconRef = useRef(null); const codepenIconRef = useRef(null); const [codeExpand, setCodeExpand] = useState(false); - const { theme } = useContext(SiteContext); + const { theme } = React.use(SiteContext); const { hash, pathname, search } = location; const docsOnlineUrl = `https://ant.design${pathname}${search}#${asset.id}`; diff --git a/.dumi/theme/common/CodePreview.tsx b/.dumi/theme/common/CodePreview.tsx index 0cbf131e4c..3f7347120b 100644 --- a/.dumi/theme/common/CodePreview.tsx +++ b/.dumi/theme/common/CodePreview.tsx @@ -1,5 +1,6 @@ +/* eslint-disable react-hooks-extra/no-direct-set-state-in-use-effect */ import type { ComponentProps } from 'react'; -import React, { useContext, useEffect, useMemo } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { Button, Tabs, Typography } from 'antd'; import { createStyles } from 'antd-style'; import toReactElement from 'jsonml-to-react-element'; @@ -108,7 +109,7 @@ const CodePreview: React.FC = ({ initialCodes.style = ''; } const [highlightedCodes, setHighlightedCodes] = React.useState(initialCodes); - const { codeType, setCodeType } = useContext(DemoContext); + const { codeType, setCodeType } = React.use(DemoContext); const sourceCodes = { // omit trailing line break tsx: sourceCode?.trim(), diff --git a/.dumi/theme/common/PrevAndNext.tsx b/.dumi/theme/common/PrevAndNext.tsx index 2a4464ad0c..a75e8f425a 100644 --- a/.dumi/theme/common/PrevAndNext.tsx +++ b/.dumi/theme/common/PrevAndNext.tsx @@ -1,5 +1,5 @@ import type { ReactElement } from 'react'; -import React, { useContext, useMemo } from 'react'; +import React, { useMemo } from 'react'; import { LeftOutlined, RightOutlined } from '@ant-design/icons'; import type { GetProp, MenuProps } from 'antd'; import { createStyles } from 'antd-style'; @@ -7,7 +7,6 @@ import classNames from 'classnames'; import useMenu from '../../hooks/useMenu'; import SiteContext from '../slots/SiteContext'; -import type { SiteContextProps } from '../slots/SiteContext'; type MenuItemType = Extract[number], { type?: 'item' }>; @@ -115,7 +114,7 @@ const PrevAndNext: React.FC<{ rtl?: boolean }> = ({ rtl }) => { const [menuItems, selectedKey] = useMenu({ before, after }); - const { isMobile } = useContext(SiteContext); + const { isMobile } = React.use(SiteContext); const [prev, next] = useMemo(() => { const flatMenu = flattenMenu(menuItems); diff --git a/.dumi/theme/common/ThemeSwitch/index.tsx b/.dumi/theme/common/ThemeSwitch/index.tsx index 3dc2d31f50..aeaa10f3cf 100644 --- a/.dumi/theme/common/ThemeSwitch/index.tsx +++ b/.dumi/theme/common/ThemeSwitch/index.tsx @@ -1,17 +1,19 @@ import React, { use } from 'react'; -import { BgColorsOutlined, SmileOutlined, SunOutlined, LinkOutlined } from '@ant-design/icons'; -import { Dropdown, Button, Badge } from 'antd'; +import { BgColorsOutlined, LinkOutlined, SmileOutlined, SunOutlined } from '@ant-design/icons'; +import { Badge, Button, Dropdown } from 'antd'; import type { MenuProps } from 'antd'; import { CompactTheme, DarkTheme } from 'antd-token-previewer/es/icons'; import { FormattedMessage, useLocation } from 'dumi'; + +import useThemeAnimation from '../../../hooks/useThemeAnimation'; import type { SiteContextProps } from '../../slots/SiteContext'; import SiteContext from '../../slots/SiteContext'; -import useThemeAnimation from '../../../hooks/useThemeAnimation'; import { getLocalizedPathname, isZhCN } from '../../utils'; import Link from '../Link'; import ThemeIcon from './ThemeIcon'; export type ThemeName = 'light' | 'dark' | 'compact' | 'motion-off' | 'happy-work'; + export interface ThemeSwitchProps { value?: ThemeName[]; } diff --git a/.dumi/theme/layouts/DocLayout/index.tsx b/.dumi/theme/layouts/DocLayout/index.tsx index 3e53440ee4..6ae53f24cc 100644 --- a/.dumi/theme/layouts/DocLayout/index.tsx +++ b/.dumi/theme/layouts/DocLayout/index.tsx @@ -3,7 +3,7 @@ import dayjs from 'dayjs'; import 'dayjs/locale/zh-cn'; -import React, { useContext, useEffect, useLayoutEffect, useRef } from 'react'; +import React, { useEffect, useLayoutEffect, useRef } from 'react'; import ConfigProvider from 'antd/es/config-provider'; import zhCN from 'antd/es/locale/zh_CN'; import { Helmet, useOutlet, useSiteData } from 'dumi'; @@ -38,7 +38,7 @@ const DocLayout: React.FC = () => { const { pathname, search, hash } = location; const [locale, lang] = useLocale(locales); const timerRef = useRef>(null!); - const { direction } = useContext(SiteContext); + const { direction } = React.use(SiteContext); const { loading } = useSiteData(); useLayoutEffect(() => { diff --git a/.dumi/theme/layouts/GlobalLayout.tsx b/.dumi/theme/layouts/GlobalLayout.tsx index 641b4310fe..d1da1e9640 100644 --- a/.dumi/theme/layouts/GlobalLayout.tsx +++ b/.dumi/theme/layouts/GlobalLayout.tsx @@ -204,20 +204,20 @@ const GlobalLayout: React.FC = () => { )); return ( - + - + {outlet} - + - + ); }; diff --git a/.dumi/theme/layouts/ResourceLayout/index.tsx b/.dumi/theme/layouts/ResourceLayout/index.tsx index 93d0fd20b2..7df6f86e45 100644 --- a/.dumi/theme/layouts/ResourceLayout/index.tsx +++ b/.dumi/theme/layouts/ResourceLayout/index.tsx @@ -4,10 +4,10 @@ import { ConfigProvider, Layout, Typography } from 'antd'; import { createStyles } from 'antd-style'; import { FormattedMessage, useRouteMeta } from 'dumi'; -import useDark from '../../../hooks/useDark'; import CommonHelmet from '../../common/CommonHelmet'; import EditButton from '../../common/EditButton'; import Footer from '../../slots/Footer'; +import { DarkContext } from './../../../hooks/useDark'; import AffixTabs from './AffixTabs'; export type ResourceLayoutProps = PropsWithChildren>; @@ -16,85 +16,77 @@ const resourcePadding = 40; const articleMaxWidth = 1208; const resourcePaddingXS = 24; -const useStyle = () => { - const isRootDark = useDark(); - - return createStyles((config) => { - const { token, css } = config; - const { antCls } = token; - - return { - resourcePage: css` - footer { - margin-top: 176px; - - .rc-footer-container { - max-width: ${articleMaxWidth}px; - margin: 0 auto; - padding-inline-end: 0; - padding-inline-start: 0; - } - } - `, - resourceContent: css` - padding: 0 ${resourcePadding}px; - max-width: ${articleMaxWidth}px; - margin: 0 auto; - box-sizing: content-box; - min-height: 100vh; - - @media only screen and (max-width: 767.99px) { - & { - article { - padding: 0 ${resourcePaddingXS}px; - } - ${antCls}-col { - padding-top: ${token.padding}px !important; - padding-bottom: ${token.padding}px !important; - } - } - } - `, - banner: css` - padding: 0 ${resourcePadding}px; - overflow: hidden; - ${ - isRootDark - ? `` - : `background: url('https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*y_r7RogIG1wAAAAAAAAAAABkARQnAQ');` - } - background-size: cover; - - h1 { - box-sizing: content-box; +const useStyle = createStyles(({ token, css }) => { + const isDark = React.use(DarkContext); + return { + resourcePage: css` + footer { + margin-top: 176px; + .rc-footer-container { max-width: ${articleMaxWidth}px; - margin: 56px auto 16px; + margin: 0 auto; + padding-inline-end: 0; + padding-inline-start: 0; } + } + `, + resourceContent: css` + padding: 0 ${resourcePadding}px; + max-width: ${articleMaxWidth}px; + margin: 0 auto; + box-sizing: content-box; + min-height: 100vh; - section { - max-width: ${articleMaxWidth}px; - margin: 0 auto 56px; - font-weight: 200; - font-size: ${token.fontSizeLG}px; - line-height: 24px; - } - - @media only screen and (max-width: 767.99px) { - & { - margin: 0 -${resourcePaddingXS}px; + @media only screen and (max-width: 767.99px) { + & { + article { padding: 0 ${resourcePaddingXS}px; } + ${token.antCls}-col { + padding-top: ${token.padding}px !important; + padding-bottom: ${token.padding}px !important; + } } - `, - }; - })(); -}; + } + `, + banner: css` + padding: 0 ${resourcePadding}px; + overflow: hidden; + ${ + isDark + ? `` + : `background: url('https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*y_r7RogIG1wAAAAAAAAAAABkARQnAQ');` + } + background-size: cover; + + h1 { + box-sizing: content-box; + max-width: ${articleMaxWidth}px; + margin: 56px auto 16px; + } + + section { + max-width: ${articleMaxWidth}px; + margin: 0 auto 56px; + font-weight: 200; + font-size: ${token.fontSizeLG}px; + line-height: 24px; + } + + @media only screen and (max-width: 767.99px) { + & { + margin: 0 -${resourcePaddingXS}px; + padding: 0 ${resourcePaddingXS}px; + } + } + `, + }; +}); const ResourceLayout: React.FC = ({ children }) => { const { styles } = useStyle(); const meta = useRouteMeta(); - const isRootDark = useDark(); - + const isDark = React.use(DarkContext); const node = ( @@ -116,7 +108,7 @@ const ResourceLayout: React.FC = ({ children }) => { ); - if (!isRootDark) { + if (!isDark) { return {node}; } diff --git a/.dumi/theme/slots/Content/Contributors.tsx b/.dumi/theme/slots/Content/Contributors.tsx index 95747a47dd..ac2ce33266 100644 --- a/.dumi/theme/slots/Content/Contributors.tsx +++ b/.dumi/theme/slots/Content/Contributors.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React from 'react'; import ContributorsList from '@qixian.cs/github-contributors-list'; import { createStyles } from 'antd-style'; import classNames from 'classnames'; @@ -40,7 +40,7 @@ interface ContributorsProps { const Contributors: React.FC = ({ filename }) => { const { formatMessage } = useIntl(); const { styles } = useStyle(); - const { isMobile } = useContext(SiteContext); + const { isMobile } = React.use(SiteContext); if (!filename) { return null; diff --git a/.dumi/theme/slots/Content/index.tsx b/.dumi/theme/slots/Content/index.tsx index f9a55859f0..a7eebbddb5 100644 --- a/.dumi/theme/slots/Content/index.tsx +++ b/.dumi/theme/slots/Content/index.tsx @@ -1,5 +1,5 @@ -import React, { useContext, useLayoutEffect, useMemo, useState } from 'react'; -import { Col, Flex, Space, Typography, Skeleton } from 'antd'; +import React, { useLayoutEffect, useMemo, useState } from 'react'; +import { Col, Flex, Skeleton, Space, Typography } from 'antd'; import classNames from 'classnames'; import { FormattedMessage, useRouteMeta } from 'dumi'; @@ -9,8 +9,8 @@ import ComponentMeta from '../../builtins/ComponentMeta'; import type { DemoContextProps } from '../DemoContext'; import DemoContext from '../DemoContext'; import SiteContext from '../SiteContext'; -import InViewSuspense from './InViewSuspense'; import { useStyle } from './DocAnchor'; +import InViewSuspense from './InViewSuspense'; const Contributors = React.lazy(() => import('./Contributors')); const ColumnCard = React.lazy(() => import('./ColumnCard')); @@ -28,7 +28,7 @@ const AvatarPlaceholder: React.FC<{ num?: number }> = ({ num = 6 }) => const Content: React.FC = ({ children }) => { const meta = useRouteMeta(); const { pathname, hash } = useLocation(); - const { direction } = useContext(SiteContext); + const { direction } = React.use(SiteContext); const { styles } = useStyle(); const [showDebug, setShowDebug] = useLayoutState(false); @@ -52,7 +52,7 @@ const Content: React.FC = ({ children }) => { const isRTL = direction === 'rtl'; return ( - + @@ -110,7 +110,7 @@ const Content: React.FC = ({ children }) => {