diff --git a/docs/demos/customization-value-type.tsx b/docs/demos/customization-value-type.tsx index 49622751aea3..94119d3bb682 100644 --- a/docs/demos/customization-value-type.tsx +++ b/docs/demos/customization-value-type.tsx @@ -1,14 +1,9 @@ import type { ProFormColumnsType } from '@ant-design/pro-components'; -import { - BetaSchemaForm, - ProCard, - ProDescriptions, - ProProvider, - ProTable, -} from '@ant-design/pro-components'; +import { ProConfigProvider } from '@ant-design/pro-components'; +import { BetaSchemaForm, ProCard, ProDescriptions, ProTable } from '@ant-design/pro-components'; import type { InputRef } from 'antd'; import { Input, Space, Tag } from 'antd'; -import React, { useContext, useRef, useState } from 'react'; +import React, { useRef, useState } from 'react'; const valueEnum = { 0: 'close', @@ -149,33 +144,29 @@ const initialValue = { }; export default () => { - const values = useContext(ProProvider); return ( - {text}, - renderFormItem: (text, props) => ( - - ), - }, - tags: { - render: (text) => { - return ( - <> - {[text].flat(1).map((item) => ( - {item.label} - ))} - - ); - }, - renderFormItem: (text, props) => , + {text}, + renderFormItem: (text, props) => ( + + ), + }, + tags: { + render: (text) => { + return ( + <> + {[text].flat(1).map((item) => ( + {item.label} + ))} + + ); }, + renderFormItem: (text, props) => , }, }} + hashed={false} > { > - + ); }; diff --git a/packages/field/src/index.tsx b/packages/field/src/index.tsx index 283a94790bc4..b01232a8e35a 100644 --- a/packages/field/src/index.tsx +++ b/packages/field/src/index.tsx @@ -1,4 +1,4 @@ -import ConfigContext from '@ant-design/pro-provider'; +import ProConfigContext from '@ant-design/pro-provider'; import type { BaseProFieldFC, ProFieldFCRenderProps, @@ -466,7 +466,7 @@ const ProFieldComponent: React.ForwardRefRenderFunction { text, valueType = 'text', mode = 'read', onChange, renderFormItem, value, readonly, ...rest }, ref: any, ) => { - const context = useContext(ConfigContext); + const context = useContext(ProConfigContext); const fieldProps = (value !== undefined || onChange || rest?.fieldProps) && { value, diff --git a/packages/layout/src/ProLayout.tsx b/packages/layout/src/ProLayout.tsx index f3fa6b3ee1f7..b7be5d5db8ad 100644 --- a/packages/layout/src/ProLayout.tsx +++ b/packages/layout/src/ProLayout.tsx @@ -1,7 +1,7 @@ -import { darkAlgorithm, defaultAlgorithm, ProTokenType } from '@ant-design/pro-provider'; +import type { ProTokenType } from '@ant-design/pro-provider'; import { ProProvider } from '@ant-design/pro-provider'; import { ProConfigProvider } from '@ant-design/pro-provider'; -import { isBrowser, merge, useDocumentTitle, useMountMergeState } from '@ant-design/pro-utils'; +import { isBrowser, useDocumentTitle, useMountMergeState } from '@ant-design/pro-utils'; import { getMatchMenu } from '@umijs/route-utils'; import type { BreadcrumbProps as AntdBreadcrumbProps } from 'antd'; import { ConfigProvider, Layout } from 'antd'; @@ -717,33 +717,16 @@ BaseProLayout.defaultProps = { const ProLayout: React.FC = (props) => { const { colorPrimary } = props; - const tokenContext = useContext(ProProvider); return ( - + diff --git a/packages/layout/src/demos/base.tsx b/packages/layout/src/demos/base.tsx index b8e593fcbfa6..26d2c5d1f828 100644 --- a/packages/layout/src/demos/base.tsx +++ b/packages/layout/src/demos/base.tsx @@ -10,7 +10,7 @@ import { import ProCard from '@ant-design/pro-card'; import type { ProSettings } from '@ant-design/pro-layout'; import { PageContainer, ProLayout, SettingDrawer } from '@ant-design/pro-layout'; -import { ProProvider } from '@ant-design/pro-provider'; +import { ProConfigProvider } from '@ant-design/pro-provider'; import { css } from '@emotion/css'; import { Button, Divider, Popover, Input, theme } from 'antd'; import React, { useState } from 'react'; @@ -261,11 +261,7 @@ export default () => { height: '100vh', }} > - + { disableUrlParams={false} /> - + ); }; diff --git a/packages/layout/src/index.tsx b/packages/layout/src/index.tsx index 2252f1d68c7e..a21b47f0a7a7 100644 --- a/packages/layout/src/index.tsx +++ b/packages/layout/src/index.tsx @@ -33,7 +33,8 @@ import type { SettingDrawerProps, SettingDrawerState } from './components/Settin import { SettingDrawer } from './components/SettingDrawer'; import type { TopNavHeaderProps } from './components/TopNavHeader'; import { TopNavHeader } from './components/TopNavHeader'; -import { WaterMark, WaterMarkProps } from './components/WaterMark'; +import type { WaterMarkProps } from './components/WaterMark'; +import { WaterMark } from './components/WaterMark'; import type { RouteContextType } from './context/RouteContext'; import { RouteContext } from './context/RouteContext'; import { getPageTitle } from './getPageTitle'; diff --git a/packages/provider/src/index.tsx b/packages/provider/src/index.tsx index 664da4ae393f..539744fe70b5 100644 --- a/packages/provider/src/index.tsx +++ b/packages/provider/src/index.tsx @@ -31,6 +31,7 @@ import zhTW from './locale/zh_TW'; import type { DeepPartial, ProTokenType } from './typing/layoutToken'; import { getLayoutDesignToken } from './typing/layoutToken'; import type { ProAliasToken } from './useStyle'; +import { darkAlgorithm, defaultAlgorithm } from './useStyle'; import { useToken } from './useStyle'; import { emptyTheme, defaultToken } from './useStyle/token'; import { merge } from './utils/merge'; @@ -261,7 +262,7 @@ export type ConfigContextPropsType = { }; /* Creating a context object with the default values. */ -const ConfigContext = React.createContext({ +const ProConfigContext = React.createContext({ intl: { ...zhCNIntl, locale: 'default', @@ -272,7 +273,7 @@ const ConfigContext = React.createContext({ token: defaultToken as ProAliasToken, }); -export const { Consumer: ConfigConsumer } = ConfigContext; +export const { Consumer: ConfigConsumer } = ProConfigContext; /** * 根据 antd 的 key 来找到的 locale 插件的 key @@ -292,8 +293,8 @@ const findIntlKeyByAntdLocaleKey = (localeKey: T) /** * 组件解除挂载后清空一下 cache - * - * @returns + * @date 2022-11-28 + * @returns null */ const CacheClean = () => { const { cache } = useSWRConfig(); @@ -309,29 +310,18 @@ const CacheClean = () => { return null; }; -/** - * 如果没有配置 locale,这里组件会根据 antd 的 key 来自动选择 - * - * @param param0 - */ -export const ProConfigProvider: React.FC<{ +const ConfigProVoidContainer: React.FC<{ children: React.ReactNode; autoClearCache?: boolean; + valueTypeMap?: Record; token?: DeepPartial; - needDeps?: boolean; + hashed?: boolean; }> = (props) => { - const { children, autoClearCache = false, token: propsToken, needDeps = false } = props; - const { locale, getPrefixCls } = useContext(AntdConfigProvider.ConfigContext); + const { children, valueTypeMap, autoClearCache = false, token: propsToken } = props; + const { locale, getPrefixCls, ...restConfig } = useContext(AntdConfigProvider.ConfigContext); const tokenContext = useToken?.(); - // 如果 locale 不存在自动注入的 AntdConfigProvider - const ANTDProvider = locale === undefined ? AntdConfigProvider : React.Fragment; - const proProvide = useContext(ConfigContext); - - const isNullProvide = - needDeps && - proProvide.hashId !== undefined && - Object.keys(props).sort().join('-') === 'children-needDeps'; + const proProvide = useContext(ProConfigContext); /** * pro 的 类 @@ -340,11 +330,18 @@ export const ProConfigProvider: React.FC<{ */ const proComponentsCls = `.${getPrefixCls()}-pro`; - const salt = `${proComponentsCls}`; const antCls = '.' + getPrefixCls(); + const salt = `${proComponentsCls}`; + + /** + * 合并一下token,不然导致嵌套 token 失效 + */ + const proLayoutTokenMerge = useMemo(() => { + return getLayoutDesignToken(propsToken || {}, tokenContext.token || defaultToken); + }, [propsToken, tokenContext.token]); + const proProvideValue = useMemo(() => { - if (isNullProvide) return null; const localeName = locale?.locale; const key = findIntlKeyByAntdLocaleKey(localeName); // antd 的 key 存在的时候以 antd 的为主 @@ -353,37 +350,28 @@ export const ProConfigProvider: React.FC<{ ? intlMap[key!] : proProvide.intl || intlMap[key!]; - /** - * 合并一下token,不然导致嵌套 token 失效 - */ - const proLayoutTokenMerge = propsToken - ? getLayoutDesignToken( - merge(proProvide.token?.layout, propsToken.layout || {}), - tokenContext.token || defaultToken, - ) - : getLayoutDesignToken(proProvide.token?.layout || {}, tokenContext.token || defaultToken); - return { ...proProvide, - token: merge(proProvide.token, { + token: merge(proProvide.token, tokenContext.token, { proComponentsCls, antCls, + themeId: tokenContext.theme.id, layout: proLayoutTokenMerge, }), intl: intl || zhCNIntl, }; }, [ - isNullProvide, locale?.locale, proProvide, - propsToken, tokenContext.token, + tokenContext.theme.id, proComponentsCls, antCls, + proLayoutTokenMerge, ]); const finalToken = { - ...(proProvideValue?.token || {}), + ...(proProvideValue.token || {}), proComponentsCls, }; @@ -396,34 +384,39 @@ export const ProConfigProvider: React.FC<{ ); const hashId = useMemo(() => { + if (props.hashed === false) { + return ''; + } if (proProvide.hashed === false) return ''; if (process.env.NODE_ENV?.toLowerCase() !== 'test') return nativeHashId; return ''; - }, [nativeHashId, proProvide.hashed]); + }, [nativeHashId, proProvide.hashed, props.hashed]); const configProviderDom = useMemo(() => { - if (isNullProvide) return <>{children}; - // 自动注入 antd 的配置 - const configProvider = - locale === undefined - ? { - locale: zh_CN, - theme: { - hashId: hashId, - hashed: process.env.NODE_ENV?.toLowerCase() !== 'test' && proProvide.hashed, - }, - } - : {}; + const themeConfig = { + ...restConfig.theme, + hashId: hashId, + hashed: process.env.NODE_ENV?.toLowerCase() !== 'test' && proProvide.hashed, + }; const provide = ( - - + + <> {autoClearCache && } {children} - - + + ); return ( @@ -439,6 +432,43 @@ export const ProConfigProvider: React.FC<{ return new Map() }}>{configProviderDom}; }; +export const ProConfigProvider: React.FC<{ + children: React.ReactNode; + autoClearCache?: boolean; + token?: DeepPartial; + needDeps?: boolean; + valueTypeMap?: Record; + dark?: boolean; + hashed?: boolean; +}> = (props) => { + const { needDeps, dark, token } = props; + const proProvide = useContext(ProConfigContext); + const { locale, theme, ...rest } = useContext(AntdConfigProvider.ConfigContext); + + // 是不是不需要渲染 provide + const isNullProvide = + needDeps && + proProvide.hashId !== undefined && + Object.keys(props).sort().join('-') === 'children-needDeps'; + + if (isNullProvide) return <>{props.children}; + // 自动注入 antd 的配置 + const configProvider = { + ...rest, + locale: locale || zh_CN, + theme: { + ...theme, + algorithm: dark ? darkAlgorithm : defaultAlgorithm, + }, + }; + + return ( + + + + ); +}; + /** * It returns the intl object from the context if it exists, otherwise it returns the intl object for * the current locale @@ -446,7 +476,7 @@ export const ProConfigProvider: React.FC<{ */ export function useIntl(): IntlType { const { locale } = useContext(AntdConfigProvider.ConfigContext); - const { intl } = useContext(ConfigContext); + const { intl } = useContext(ProConfigContext); if (intl && intl.locale !== 'default') { return intl || zhCNIntl; @@ -459,8 +489,10 @@ export function useIntl(): IntlType { return zhCNIntl; } -const ProProvider = ConfigContext; +const ProProvider = ProConfigContext; + +ProProvider.displayName = 'ProProvider'; export { ProProvider }; -export default ConfigContext; +export default ProConfigContext; diff --git a/packages/provider/src/useStyle/index.ts b/packages/provider/src/useStyle/index.ts index 9eea6289c0ce..ceff17b47344 100644 --- a/packages/provider/src/useStyle/index.ts +++ b/packages/provider/src/useStyle/index.ts @@ -10,6 +10,7 @@ import { ProProvider } from '../index'; import type { ProTokenType } from '../typing/layoutToken'; import type { AliasToken } from './token'; import * as batToken from './token'; + /** * 把一个颜色设置一下透明度 * @example (#fff, 0.5) => rgba(255, 255, 255, 0.5) @@ -36,16 +37,17 @@ export type GenerateStyle< ComponentToken extends object = AliasToken, ReturnType = CSSInterpolation, > = (token: ComponentToken) => ReturnType; + /** * 如果 antd 里面没有,就用我 mock 的,这样 antd@4 和 antd@5 可以兼容 */ -const { useToken, darkAlgorithm, defaultAlgorithm } = { +const { useToken, darkAlgorithm, compactAlgorithm, defaultAlgorithm } = { ...batToken, // @ts-ignore ...(antdTheme || {}), -} as unknown as typeof batToken; +} as any; -export { useToken, darkAlgorithm, defaultAlgorithm }; +export { useToken, darkAlgorithm, compactAlgorithm, defaultAlgorithm }; export type UseStyleResult = { wrapSSR: (node: React.ReactElement) => React.ReactElement; @@ -54,6 +56,7 @@ export type UseStyleResult = { export type ProAliasToken = AliasToken & ProTokenType & { + themeId: number; /** * pro 的 className * @type {string} @@ -107,7 +110,9 @@ export function useStyle( ): UseStyleResult { const { token = {} as ProAliasToken, hashId = '', theme } = useContext(ProProvider); const { getPrefixCls } = useContext(AntdConfigProvider.ConfigContext); + token.antCls = `.${getPrefixCls()}`; + return { wrapSSR: useStyleRegister( { diff --git a/packages/provider/src/useStyle/token.ts b/packages/provider/src/useStyle/token.ts index 8a0fc9479127..858a4fee1d0d 100644 --- a/packages/provider/src/useStyle/token.ts +++ b/packages/provider/src/useStyle/token.ts @@ -403,7 +403,8 @@ export const token = { hashId: `pro-${hashCode(JSON.stringify(defaultToken))}`, }; -export const useToken = () => token; +export const useToken = () => token as any; export const darkAlgorithm = () => defaultToken; export const defaultAlgorithm = () => defaultToken; +export const compactAlgorithm = () => defaultToken; diff --git a/tests/__snapshots__/doc.test.ts.snap b/tests/__snapshots__/doc.test.ts.snap index 4d02093d9312..db992f8a8bff 100644 --- a/tests/__snapshots__/doc.test.ts.snap +++ b/tests/__snapshots__/doc.test.ts.snap @@ -3,23 +3,23 @@ exports[`docs demos 📸 renders ./docs/demos/customization-value-type.tsx correctly 1`] = `
- SchemaForm +
+ SchemaForm +
-
-
-
-
- ProTable +
+ ProTable +
-
-
-
-
- ProDescriptions +
+ ProDescriptions +
-
-
- - - - + + +
+ + + -
- - 链接 - - - - TradeCode 1 - - -
- - + - - -
-
+ 链接 + + + + TradeCode 1 + + +
+
- - 标签 - - - close + 标签 - close + + close + + + close + - - -
+ +
+
diff --git a/tests/descriptions/__snapshots__/editor.test.tsx.snap b/tests/descriptions/__snapshots__/editor.test.tsx.snap index efe325e7dafd..917f95efdb32 100644 --- a/tests/descriptions/__snapshots__/editor.test.tsx.snap +++ b/tests/descriptions/__snapshots__/editor.test.tsx.snap @@ -31,6 +31,7 @@ exports[`Descriptions 📝 columns support editable test 1`] = ` >
{ expect(fn).toHaveBeenCalledWith(44.33); expect(wrapper.render()).toMatchSnapshot(); }); + it('💵 moneySymbol with global locale', async () => { const fn = jest.fn(); const wrapper = mount<{ amount: string }>( diff --git a/tests/layout/__snapshots__/demo.test.ts.snap b/tests/layout/__snapshots__/demo.test.ts.snap index c049c1a11787..18ce4231070e 100644 --- a/tests/layout/__snapshots__/demo.test.ts.snap +++ b/tests/layout/__snapshots__/demo.test.ts.snap @@ -10018,252 +10018,60 @@ exports[`layout demos 📸 renders ./packages/layout/src/demos/base.tsx correctl class="ant-pro" >
- - - -
-
-
+
+
- - - - - -
- -
-
-
+
-
+
-
- - - -
-
- - - + - - + +
- - - -
-
-
-
+ + + +
+
+
- - - -
-
- +
+
- - -
- -
- + +
+
- 七妮妮 +
+ +
+ + + + + 七妮妮 + +
+
+
+
+
+
+
+
+
+
+ -
-
-
-
- -
- -
-
+
+
+
-
- -
- - - -
-
- - + + +
+ + + +
diff --git a/tests/layout/__snapshots__/mobile.test.tsx.snap b/tests/layout/__snapshots__/mobile.test.tsx.snap index 34813123d317..6bc2e789109f 100644 --- a/tests/layout/__snapshots__/mobile.test.tsx.snap +++ b/tests/layout/__snapshots__/mobile.test.tsx.snap @@ -100,6 +100,29 @@ exports[`mobile BasicLayout 📱 base use 1`] = `
+ + + + + - - - - -
@@ -388,6 +388,29 @@ exports[`mobile BasicLayout 📱 collapsed=false 1`] = `
+ + + + + - - - - -
@@ -587,18 +587,17 @@ exports[`mobile BasicLayout 📱 layout menuHeaderRender 1`] = `
- title + title
@@ -655,18 +655,17 @@ exports[`mobile BasicLayout 📱 layout menuHeaderRender 2`] = `
- title + title
@@ -727,13 +727,13 @@ exports[`mobile BasicLayout 📱 layout menuHeaderRender=false 1`] = ` class="ant-pro-global-header-collapsed-button " > @@ -883,6 +883,29 @@ exports[`mobile BasicLayout 📱 layout=mix 1`] = `
+ + + + + - - - - -
@@ -1175,6 +1175,29 @@ exports[`mobile BasicLayout 📱 layout=mix and splitMenus 1`] = `
+ + + + + - - - - -
diff --git a/tests/layout/index.test.tsx b/tests/layout/index.test.tsx index 03f60374974d..b14f98bb5426 100644 --- a/tests/layout/index.test.tsx +++ b/tests/layout/index.test.tsx @@ -44,7 +44,6 @@ describe('BasicLayout', () => { }} />, ); - wrapper.debug(); await waitForComponentToPaint(wrapper, 1000); expect(wrapper.baseElement.querySelector('.ant-skeleton')).toMatchSnapshot(); wrapper.unmount(); diff --git a/tests/table/filter.test.tsx b/tests/table/filter.test.tsx index 70e9b1df0a8f..f06d51fe5d89 100644 --- a/tests/table/filter.test.tsx +++ b/tests/table/filter.test.tsx @@ -53,7 +53,6 @@ describe('BasicTable Search', () => { await waitForComponentToPaint(html, 800); act(() => { - html.find('.ant-table-filter-dropdown').debug(); html.find('span.ant-table-filter-trigger').simulate('click'); html .find('.ant-table-filter-dropdown .ant-dropdown-menu-item') @@ -125,7 +124,6 @@ describe('BasicTable Search', () => { await waitForComponentToPaint(html, 800); act(() => { - html.find('.ant-table-filter-dropdown').debug(); html.find('span.ant-table-filter-trigger').simulate('click'); html .find('.ant-table-filter-dropdown .ant-dropdown-menu-item') @@ -209,7 +207,6 @@ describe('BasicTable Search', () => { await waitForComponentToPaint(html, 800); act(() => { - html.find('.ant-table-filter-dropdown').debug(); html.find('span.ant-table-filter-trigger').simulate('click'); html .find('.ant-table-filter-dropdown .ant-dropdown-menu-item') @@ -235,7 +232,6 @@ describe('BasicTable Search', () => { await waitForComponentToPaint(html, 800); act(() => { - html.find('.ant-table-filter-dropdown').debug(); html.find('span.ant-table-filter-trigger').simulate('click'); html .find('.ant-table-filter-dropdown .ant-dropdown-menu-item') diff --git a/tests/table/valueType.test.tsx b/tests/table/valueType.test.tsx index 1bcd943a6525..be59514ad660 100644 --- a/tests/table/valueType.test.tsx +++ b/tests/table/valueType.test.tsx @@ -1,4 +1,4 @@ -import ProProvider from '@ant-design/pro-provider'; +import { ProProvider } from '@ant-design/pro-provider'; import ProTable from '@ant-design/pro-table'; import { act, fireEvent, render as reactRender, render } from '@testing-library/react'; import { Input } from 'antd';