Skip to content

Commit 66419c0

Browse files
authored
feat: offset support ptg and fix targetOffset logic (#378)
* feat: support ptg * test: add test case * chore: add react
1 parent cd8d7b6 commit 66419c0

File tree

5 files changed

+59
-8
lines changed

5 files changed

+59
-8
lines changed

src/Popup/Mask.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import classNames from 'classnames';
22
import type { CSSMotionProps } from 'rc-motion';
33
import CSSMotion from 'rc-motion';
4+
import * as React from 'react';
45

56
export interface MaskProps {
67
prefixCls: string;

src/hooks/useAlign.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,35 @@ import type {
88
AlignPointLeftRight,
99
AlignPointTopBottom,
1010
AlignType,
11+
OffsetType,
1112
} from '../interface';
1213
import { collectScroller, getVisibleArea, getWin, toNum } from '../util';
1314

1415
type Rect = Record<'x' | 'y' | 'width' | 'height', number>;
1516

1617
type Points = [topBottom: AlignPointTopBottom, leftRight: AlignPointLeftRight];
1718

19+
function getUnitOffset(size: number, offset: OffsetType = 0) {
20+
const offsetStr = `${offset}`;
21+
const cells = offsetStr.match(/^(.*)\%$/);
22+
if (cells) {
23+
return size * (parseFloat(cells[1]) / 100);
24+
}
25+
return parseFloat(offsetStr);
26+
}
27+
28+
function getNumberOffset(
29+
rect: { width: number; height: number },
30+
offset?: OffsetType[],
31+
) {
32+
const [offsetX, offsetY] = offset || [];
33+
34+
return [
35+
getUnitOffset(rect.width, offsetX),
36+
getUnitOffset(rect.height, offsetY),
37+
];
38+
}
39+
1840
function splitPoints(points: string = ''): Points {
1941
return [points[0] as any, points[1] as any];
2042
}
@@ -229,11 +251,14 @@ export default function useAlign(
229251

230252
// Offset
231253
const { offset, targetOffset } = placementInfo;
232-
const [popupOffsetX = 0, popupOffsetY = 0] = offset || [];
233-
const [targetOffsetX = 0, targetOffsetY = 0] = targetOffset || [];
254+
const [popupOffsetX, popupOffsetY] = getNumberOffset(popupRect, offset);
255+
const [targetOffsetX, targetOffsetY] = getNumberOffset(
256+
targetRect,
257+
targetOffset,
258+
);
234259

235-
targetRect.x += targetOffsetX;
236-
targetRect.y += targetOffsetY;
260+
targetRect.x -= targetOffsetX;
261+
targetRect.y -= targetOffsetY;
237262

238263
// Points
239264
const [popupPoint, targetPoint] = placementInfo.points || [];

src/interface.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export type AlignPointLeftRight = 'l' | 'r' | 'c';
2020
/** Two char of 't' 'b' 'c' 'l' 'r'. Example: 'lt' */
2121
export type AlignPoint = `${AlignPointTopBottom}${AlignPointLeftRight}`;
2222

23+
export type OffsetType = number | `${number}%`;
24+
2325
export interface AlignType {
2426
/**
2527
* move point of source node to align with point of target node.
@@ -30,12 +32,12 @@ export interface AlignType {
3032
* offset source node by offset[0] in x and offset[1] in y.
3133
* If offset contains percentage string value, it is relative to sourceNode region.
3234
*/
33-
offset?: number[];
35+
offset?: OffsetType[];
3436
/**
3537
* offset target node by offset[0] in x and offset[1] in y.
3638
* If targetOffset contains percentage string value, it is relative to targetNode region.
3739
*/
38-
targetOffset?: number[];
40+
targetOffset?: OffsetType[];
3941
/**
4042
* If adjustX field is true, will adjust source node in x direction if source node is invisible.
4143
* If adjustY field is true, will adjust source node in y direction if source node is invisible.

tests/align.test.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ describe('Trigger.Align', () => {
194194
}}
195195
popupPlacement="top"
196196
popupAlign={{
197-
targetOffset: [903, 1128],
197+
targetOffset: [-903, -1128],
198198
}}
199199
>
200200
<svg />
@@ -210,4 +210,27 @@ describe('Trigger.Align', () => {
210210
top: `978px`,
211211
});
212212
});
213+
214+
it('targetOffset support ptg', async () => {
215+
render(
216+
<Trigger
217+
popupVisible
218+
popup={<span className="bamboo" />}
219+
popupAlign={{
220+
targetOffset: ['50%', '-50%'],
221+
}}
222+
>
223+
<div />
224+
</Trigger>,
225+
);
226+
227+
await awaitFakeTimer();
228+
229+
// Correct this if I miss understand the value calculation
230+
// from https://github.com/yiminghe/dom-align/blob/master/src/getElFuturePos.js
231+
expect(document.querySelector('.rc-trigger-popup')).toHaveStyle({
232+
left: `-50px`,
233+
top: `50px`,
234+
});
235+
});
213236
});

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"target": "esnext",
44
"moduleResolution": "node",
55
"baseUrl": "./",
6-
"jsx": "preserve",
6+
"jsx": "react",
77
"declaration": true,
88
"skipLibCheck": true,
99
"esModuleInterop": true,

0 commit comments

Comments
 (0)