diff --git a/src/Popup/Arrow.tsx b/src/Popup/Arrow.tsx index 8a2d6a34..324e9ef1 100644 --- a/src/Popup/Arrow.tsx +++ b/src/Popup/Arrow.tsx @@ -1,15 +1,17 @@ import * as React from 'react'; -import type { AlignType } from '../interface'; +import classNames from 'classnames'; +import type { AlignType, ArrowType } from '../interface'; export interface ArrowProps { prefixCls: string; align: AlignType; - arrowX?: number; - arrowY?: number; + arrow: ArrowType; } export default function Arrow(props: ArrowProps) { - const { prefixCls, align, arrowX = 0, arrowY = 0 } = props; + const { prefixCls, align, arrow } = props; + + const { x = 0, y = 0, className } = arrow || {}; const arrowRef = React.useRef(); @@ -33,7 +35,7 @@ export default function Arrow(props: ArrowProps) { // Top & Bottom if (popupTB === targetTB || !['t', 'b'].includes(popupTB)) { - alignStyle.top = arrowY; + alignStyle.top = y; } else if (popupTB === 't') { alignStyle.top = 0; } else { @@ -42,7 +44,7 @@ export default function Arrow(props: ArrowProps) { // Left & Right if (popupLR === targetLR || !['l', 'r'].includes(popupLR)) { - alignStyle.left = arrowX; + alignStyle.left = x; } else if (popupLR === 'l') { alignStyle.left = 0; } else { @@ -51,6 +53,6 @@ export default function Arrow(props: ArrowProps) { } return ( -
+
); } diff --git a/src/Popup/index.tsx b/src/Popup/index.tsx index 5162bd32..d20a6ff9 100644 --- a/src/Popup/index.tsx +++ b/src/Popup/index.tsx @@ -6,7 +6,7 @@ import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect'; import { composeRef } from 'rc-util/lib/ref'; import * as React from 'react'; import type { TriggerProps } from '../'; -import type { AlignType } from '../interface'; +import type { AlignType, ArrowType } from '../interface'; import Arrow from './Arrow'; import Mask from './Mask'; import PopupContent from './PopupContent'; @@ -26,9 +26,7 @@ export interface PopupProps { // Arrow align?: AlignType; - arrow?: boolean; - arrowX?: number; - arrowY?: number; + arrow?: ArrowType; // Open open: boolean; @@ -84,8 +82,6 @@ const Popup = React.forwardRef((props, ref) => { // Arrow arrow, align, - arrowX, - arrowY, // Motion motion, @@ -225,9 +221,8 @@ const Popup = React.forwardRef((props, ref) => { {arrow && ( )} {childNode} diff --git a/src/index.tsx b/src/index.tsx index 0d6bec8a..1e2c254f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -17,6 +17,8 @@ import useWatch from './hooks/useWatch'; import type { ActionType, AlignType, + ArrowType, + ArrowTypeOuter, AnimationType, BuildInPlacements, TransitionNameType, @@ -25,7 +27,7 @@ import Popup from './Popup'; import TriggerWrapper from './TriggerWrapper'; import { getAlignPopupClassName, getMotion, getWin } from './util'; -export type { BuildInPlacements, AlignType, ActionType }; +export type { BuildInPlacements, AlignType, ActionType, ArrowTypeOuter as ArrowType }; export interface TriggerRef { forceAlign: VoidFunction; @@ -104,7 +106,7 @@ export interface TriggerProps { alignPoint?: boolean; // Maybe we can support user pass position in the future // ==================== Arrow ==================== - arrow?: boolean; + arrow?: boolean | ArrowTypeOuter; // ================= Deprecated ================== /** @deprecated Add `className` on `children`. Please add `className` directly instead. */ @@ -625,6 +627,13 @@ export function generateTrigger( ...passedProps, }); + const innerArrow: ArrowType = arrow ? { + // true and Object likely + ...(arrow !== true ? arrow : {}), + x: arrowX, + y: arrowY + }: null; + // Render return ( <> @@ -667,13 +676,11 @@ export function generateTrigger( getPopupContainer={getPopupContainer} // Arrow align={alignInfo} - arrow={arrow} + arrow={innerArrow} // Align ready={ready} offsetX={offsetX} offsetY={offsetY} - arrowX={arrowX} - arrowY={arrowY} onAlign={triggerAlign} // Stretch stretch={stretch} diff --git a/src/interface.ts b/src/interface.ts index 90dcb483..6edf17fb 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -70,6 +70,15 @@ export interface AlignType { ignoreShake?: boolean; } +export interface ArrowTypeOuter { + className?: string; +} + +export type ArrowType = ArrowTypeOuter & { + x?: number; + y?: number; +} + export type BuildInPlacements = Record; export type StretchType = string; @@ -95,4 +104,4 @@ export interface MobileConfig { popupClassName?: string; popupStyle?: React.CSSProperties; popupRender?: (originNode: React.ReactNode) => React.ReactNode; -} +} \ No newline at end of file diff --git a/tests/arrow.test.jsx b/tests/arrow.test.jsx index 231ecea5..9947b268 100644 --- a/tests/arrow.test.jsx +++ b/tests/arrow.test.jsx @@ -163,5 +163,28 @@ describe('Trigger.Arrow', () => { expect(style.top).toBeFalsy(); expect(style.bottom).toBeFalsy(); }); + + it('arrow classname', async () => { + render( + trigger} + arrow={{ + className: 'abc', + }} + > +
+ , + ); + + await awaitFakeTimer(); + + const arrowDom = document.querySelector('.rc-trigger-popup-arrow'); + expect(arrowDom.classList.contains('abc')).toBeTruthy(); + }); }); });