diff --git a/components/cascader/__tests__/index.test.tsx b/components/cascader/__tests__/index.test.tsx index 77cdcdfafd..aada06b0dd 100644 --- a/components/cascader/__tests__/index.test.tsx +++ b/components/cascader/__tests__/index.test.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { Button, Input, Space } from 'antd'; import type { SingleValueType } from 'rc-cascader/lib/Cascader'; import type { DefaultOptionType } from '..'; @@ -803,4 +804,41 @@ describe('Cascader', () => { errSpy.mockRestore(); }); + + it('Cascader ContextIsolator', () => { + const { container } = render( + + { + return ( +
+ {menu} + + +
+ ); + }} + options={[ + { value: 'jack', label: 'Jack' }, + { value: 'lucy', label: 'Lucy' }, + ]} + /> + +
, + ); + + const compactButton = container.querySelector('.test-button'); + const popupElement = document.querySelector('.ant-select-dropdown'); + // selector should have compact + expect(compactButton).toBeInTheDocument(); + expect(compactButton!.className.includes('compact')).toBeTruthy(); + // popupRender element haven't compact + expect(popupElement).toBeInTheDocument(); + const button = popupElement!.querySelector('button'); + const input = popupElement!.querySelector('input'); + expect(button!.className.includes('compact')).toBeFalsy(); + expect(input!.className.includes('compact')).toBeFalsy(); + }); }); diff --git a/components/cascader/index.tsx b/components/cascader/index.tsx index 281713f24e..e5bcbaa36b 100644 --- a/components/cascader/index.tsx +++ b/components/cascader/index.tsx @@ -31,6 +31,7 @@ import useVariant from '../form/hooks/useVariants'; import mergedBuiltinPlacements from '../select/mergedBuiltinPlacements'; import useSelectStyle from '../select/style'; import useIcons from '../select/useIcons'; +import usePopupRender from '../select/usePopupRender'; import useShowArrow from '../select/useShowArrow'; import { useCompactItemContext } from '../space/Compact'; import useBase from './hooks/useBase'; @@ -292,7 +293,8 @@ const Cascader = React.forwardRef>((props, ref) cssVarCls, ); - const mergedPopupRender = popupRender || dropdownRender; + const mergedPopupRender = usePopupRender(popupRender || dropdownRender); + const mergedPopupMenuColumnStyle = popupMenuColumnStyle || dropdownMenuColumnStyle; const mergedOnOpenChange = onOpenChange || onDropdownVisibleChange; const mergedPopupStyle = styles?.popup?.root || contextStyles.popup?.root || dropdownStyle; diff --git a/components/select/__tests__/index.test.tsx b/components/select/__tests__/index.test.tsx index 2f7ece51e7..921cf335ad 100644 --- a/components/select/__tests__/index.test.tsx +++ b/components/select/__tests__/index.test.tsx @@ -1,14 +1,15 @@ import React from 'react'; import { CloseOutlined } from '@ant-design/icons'; +import { Button, Input, Space } from 'antd'; import type { SelectProps } from '..'; import Select from '..'; -import Form from '../../form'; import { resetWarned } from '../../_util/warning'; import focusTest from '../../../tests/shared/focusTest'; import mountTest from '../../../tests/shared/mountTest'; import rtlTest from '../../../tests/shared/rtlTest'; import { act, fireEvent, render } from '../../../tests/utils'; +import Form from '../../form'; const { Option } = Select; @@ -290,4 +291,42 @@ describe('Select', () => { errSpy.mockRestore(); }); }); + + it('Select ContextIsolator', () => { + const { container } = render( + + + + ); + }} + options={[ + { value: 'jack', label: 'Jack' }, + { value: 'lucy', label: 'Lucy' }, + ]} + /> + + , + ); + + const compactButton = container.querySelector('.test-button'); + const popupElement = document.querySelector('.ant-select-dropdown'); + // selector should have compact + expect(compactButton).toBeInTheDocument(); + expect(compactButton!.className.includes('compact')).toBeTruthy(); + // popupRender element haven't compact + expect(popupElement).toBeInTheDocument(); + const button = popupElement!.querySelector('button'); + const input = popupElement!.querySelector('input'); + expect(button!.className.includes('compact')).toBeFalsy(); + expect(input!.className.includes('compact')).toBeFalsy(); + }); }); diff --git a/components/select/index.tsx b/components/select/index.tsx index c69049cef1..8614293704 100755 --- a/components/select/index.tsx +++ b/components/select/index.tsx @@ -29,6 +29,7 @@ import { useToken } from '../theme/internal'; import mergedBuiltinPlacements from './mergedBuiltinPlacements'; import useStyle from './style'; import useIcons from './useIcons'; +import usePopupRender from './usePopupRender'; import useShowArrow from './useShowArrow'; type RawValue = string | number; @@ -203,7 +204,9 @@ const InternalSelect = < popupMatchSelectWidth ?? dropdownMatchSelectWidth ?? contextPopupMatchSelectWidth; const mergedPopupStyle = styles?.popup?.root || contextStyles.popup?.root || dropdownStyle; - const mergedPopupRender = popupRender || dropdownRender; + + const mergedPopupRender = usePopupRender(popupRender || dropdownRender); + const mergedOnOpenChange = onOpenChange || onDropdownVisibleChange; // ===================== Form Status ===================== diff --git a/components/select/usePopupRender.tsx b/components/select/usePopupRender.tsx new file mode 100644 index 0000000000..e3a24086cb --- /dev/null +++ b/components/select/usePopupRender.tsx @@ -0,0 +1,18 @@ +import React from 'react'; + +import ContextIsolator from '../_util/ContextIsolator'; + +type RenderFunction = (...args: T) => React.ReactNode; + +function usePopupRender( + renderFn?: RenderFunction, +): ((...args: T) => React.ReactElement) | undefined { + return React.useMemo(() => { + if (!renderFn) { + return undefined; + } + return (...args: T) => {renderFn(...args)}; + }, [renderFn]); +} + +export default usePopupRender; diff --git a/components/tree-select/__tests__/index.test.tsx b/components/tree-select/__tests__/index.test.tsx index 3fc73b042a..d477f777ad 100644 --- a/components/tree-select/__tests__/index.test.tsx +++ b/components/tree-select/__tests__/index.test.tsx @@ -1,11 +1,12 @@ import React from 'react'; +import { Button, Input, Space } from 'antd'; import TreeSelect, { TreeNode } from '..'; import { resetWarned } from '../../_util/warning'; import focusTest from '../../../tests/shared/focusTest'; import mountTest from '../../../tests/shared/mountTest'; import rtlTest from '../../../tests/shared/rtlTest'; -import { render, fireEvent } from '../../../tests/utils'; +import { fireEvent, render } from '../../../tests/utils'; describe('TreeSelect', () => { focusTest(TreeSelect, { refFocus: true }); @@ -162,4 +163,41 @@ describe('TreeSelect', () => { errSpy.mockRestore(); }); + + it('TreeSelect ContextIsolator', () => { + const { container } = render( + + { + return ( +
+ {menu} + + +
+ ); + }} + treeData={[ + { value: 'jack', title: 'Jack', children: [{ value: 'Emily', title: 'Emily' }] }, + { value: 'lucy', title: 'Lucy' }, + ]} + /> + +
, + ); + const compactButton = container.querySelector('.test-button'); + const popupElement = document.querySelector('.ant-select-dropdown'); + // selector should have compact + expect(compactButton).toBeInTheDocument(); + expect(compactButton!.className.includes('compact')).toBeTruthy(); + // popupRender element haven't compact + expect(popupElement).toBeInTheDocument(); + const button = popupElement!.querySelector('button'); + const input = popupElement!.querySelector('input'); + expect(button!.className.includes('compact')).toBeFalsy(); + expect(input!.className.includes('compact')).toBeFalsy(); + }); }); diff --git a/components/tree-select/index.tsx b/components/tree-select/index.tsx index 99fbc85814..d825cb28c1 100644 --- a/components/tree-select/index.tsx +++ b/components/tree-select/index.tsx @@ -16,6 +16,7 @@ import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils'; import { devUseWarning } from '../_util/warning'; import { ConfigContext } from '../config-provider'; import type { Variant } from '../config-provider'; +import { useComponentConfig } from '../config-provider/context'; import DefaultRenderEmpty from '../config-provider/defaultRenderEmpty'; import DisabledContext from '../config-provider/DisabledContext'; import useCSSVarCls from '../config-provider/hooks/useCSSVarCls'; @@ -26,6 +27,7 @@ import useVariant from '../form/hooks/useVariants'; import mergedBuiltinPlacements from '../select/mergedBuiltinPlacements'; import useSelectStyle from '../select/style'; import useIcons from '../select/useIcons'; +import usePopupRender from '../select/usePopupRender'; import useShowArrow from '../select/useShowArrow'; import { useCompactItemContext } from '../space/Compact'; import { useToken } from '../theme/internal'; @@ -33,7 +35,6 @@ import type { AntTreeNodeProps, TreeProps } from '../tree'; import type { SwitcherIcon } from '../tree/Tree'; import SwitcherIconCom from '../tree/utils/iconUtil'; import useStyle from './style'; -import { useComponentConfig } from '../config-provider/context'; type RawValue = string | number; @@ -226,7 +227,9 @@ const InternalTreeSelect =