Skip to content

Commit aeda4c9

Browse files
yoyo837afc163
andauthored
feat: arrow add className support (#366)
* feat: arrow add arrowClassName support * feat: 收起到对象 * test: fix test * chore: semicolon * chore: x and y * Update src/Popup/Arrow.tsx Co-authored-by: afc163 <[email protected]> * chore: if * chore: improve * Semicolon --------- Co-authored-by: afc163 <[email protected]>
1 parent 1650d85 commit aeda4c9

File tree

5 files changed

+57
-21
lines changed

5 files changed

+57
-21
lines changed

src/Popup/Arrow.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import * as React from 'react';
2-
import type { AlignType } from '../interface';
2+
import classNames from 'classnames';
3+
import type { AlignType, ArrowType } from '../interface';
34

45
export interface ArrowProps {
56
prefixCls: string;
67
align: AlignType;
7-
arrowX?: number;
8-
arrowY?: number;
8+
arrow: ArrowType;
99
}
1010

1111
export default function Arrow(props: ArrowProps) {
12-
const { prefixCls, align, arrowX = 0, arrowY = 0 } = props;
12+
const { prefixCls, align, arrow } = props;
13+
14+
const { x = 0, y = 0, className } = arrow || {};
1315

1416
const arrowRef = React.useRef<HTMLDivElement>();
1517

@@ -33,7 +35,7 @@ export default function Arrow(props: ArrowProps) {
3335

3436
// Top & Bottom
3537
if (popupTB === targetTB || !['t', 'b'].includes(popupTB)) {
36-
alignStyle.top = arrowY;
38+
alignStyle.top = y;
3739
} else if (popupTB === 't') {
3840
alignStyle.top = 0;
3941
} else {
@@ -42,7 +44,7 @@ export default function Arrow(props: ArrowProps) {
4244

4345
// Left & Right
4446
if (popupLR === targetLR || !['l', 'r'].includes(popupLR)) {
45-
alignStyle.left = arrowX;
47+
alignStyle.left = x;
4648
} else if (popupLR === 'l') {
4749
alignStyle.left = 0;
4850
} else {
@@ -51,6 +53,6 @@ export default function Arrow(props: ArrowProps) {
5153
}
5254

5355
return (
54-
<div ref={arrowRef} className={`${prefixCls}-arrow`} style={alignStyle} />
56+
<div ref={arrowRef} className={classNames(`${prefixCls}-arrow`, className)} style={alignStyle} />
5557
);
5658
}

src/Popup/index.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
66
import { composeRef } from 'rc-util/lib/ref';
77
import * as React from 'react';
88
import type { TriggerProps } from '../';
9-
import type { AlignType } from '../interface';
9+
import type { AlignType, ArrowType } from '../interface';
1010
import Arrow from './Arrow';
1111
import Mask from './Mask';
1212
import PopupContent from './PopupContent';
@@ -26,9 +26,7 @@ export interface PopupProps {
2626

2727
// Arrow
2828
align?: AlignType;
29-
arrow?: boolean;
30-
arrowX?: number;
31-
arrowY?: number;
29+
arrow?: ArrowType;
3230

3331
// Open
3432
open: boolean;
@@ -84,8 +82,6 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
8482
// Arrow
8583
arrow,
8684
align,
87-
arrowX,
88-
arrowY,
8985

9086
// Motion
9187
motion,
@@ -225,9 +221,8 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
225221
{arrow && (
226222
<Arrow
227223
prefixCls={prefixCls}
224+
arrow={arrow}
228225
align={align}
229-
arrowX={arrowX}
230-
arrowY={arrowY}
231226
/>
232227
)}
233228
<PopupContent cache={!open}>{childNode}</PopupContent>

src/index.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import useWatch from './hooks/useWatch';
1717
import type {
1818
ActionType,
1919
AlignType,
20+
ArrowType,
21+
ArrowTypeOuter,
2022
AnimationType,
2123
BuildInPlacements,
2224
TransitionNameType,
@@ -25,7 +27,7 @@ import Popup from './Popup';
2527
import TriggerWrapper from './TriggerWrapper';
2628
import { getAlignPopupClassName, getMotion, getWin } from './util';
2729

28-
export type { BuildInPlacements, AlignType, ActionType };
30+
export type { BuildInPlacements, AlignType, ActionType, ArrowTypeOuter as ArrowType };
2931

3032
export interface TriggerRef {
3133
forceAlign: VoidFunction;
@@ -104,7 +106,7 @@ export interface TriggerProps {
104106
alignPoint?: boolean; // Maybe we can support user pass position in the future
105107

106108
// ==================== Arrow ====================
107-
arrow?: boolean;
109+
arrow?: boolean | ArrowTypeOuter;
108110

109111
// ================= Deprecated ==================
110112
/** @deprecated Add `className` on `children`. Please add `className` directly instead. */
@@ -625,6 +627,13 @@ export function generateTrigger(
625627
...passedProps,
626628
});
627629

630+
const innerArrow: ArrowType = arrow ? {
631+
// true and Object likely
632+
...(arrow !== true ? arrow : {}),
633+
x: arrowX,
634+
y: arrowY
635+
}: null;
636+
628637
// Render
629638
return (
630639
<>
@@ -667,13 +676,11 @@ export function generateTrigger(
667676
getPopupContainer={getPopupContainer}
668677
// Arrow
669678
align={alignInfo}
670-
arrow={arrow}
679+
arrow={innerArrow}
671680
// Align
672681
ready={ready}
673682
offsetX={offsetX}
674683
offsetY={offsetY}
675-
arrowX={arrowX}
676-
arrowY={arrowY}
677684
onAlign={triggerAlign}
678685
// Stretch
679686
stretch={stretch}

src/interface.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ export interface AlignType {
7070
ignoreShake?: boolean;
7171
}
7272

73+
export interface ArrowTypeOuter {
74+
className?: string;
75+
}
76+
77+
export type ArrowType = ArrowTypeOuter & {
78+
x?: number;
79+
y?: number;
80+
}
81+
7382
export type BuildInPlacements = Record<string, AlignType>;
7483

7584
export type StretchType = string;
@@ -95,4 +104,4 @@ export interface MobileConfig {
95104
popupClassName?: string;
96105
popupStyle?: React.CSSProperties;
97106
popupRender?: (originNode: React.ReactNode) => React.ReactNode;
98-
}
107+
}

tests/arrow.test.jsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,5 +163,28 @@ describe('Trigger.Arrow', () => {
163163
expect(style.top).toBeFalsy();
164164
expect(style.bottom).toBeFalsy();
165165
});
166+
167+
it('arrow classname', async () => {
168+
render(
169+
<Trigger
170+
popupVisible
171+
popupAlign={{
172+
points: ['cl', 'cr'],
173+
autoArrow: false,
174+
}}
175+
popup={<strong>trigger</strong>}
176+
arrow={{
177+
className: 'abc',
178+
}}
179+
>
180+
<div />
181+
</Trigger>,
182+
);
183+
184+
await awaitFakeTimer();
185+
186+
const arrowDom = document.querySelector('.rc-trigger-popup-arrow');
187+
expect(arrowDom.classList.contains('abc')).toBeTruthy();
188+
});
166189
});
167190
});

0 commit comments

Comments
 (0)