Skip to content

Commit 2af861f

Browse files
authored
feat: autoAlign pos (#405)
* feat: autoAlign pos * chore: fix lint * test: add test case
1 parent cf29179 commit 2af861f

File tree

6 files changed

+125
-12
lines changed

6 files changed

+125
-12
lines changed

docs/examples/inside.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
/* eslint no-console:0 */
22
import React from 'react';
33
import '../../assets/index.less';
4-
import Trigger from '../../src';
4+
import Trigger, { BuildInPlacements } from '../../src';
55

6-
export const builtinPlacements = {
6+
const experimentalConfig = {
7+
_experimental: {
8+
dynamicInset: true,
9+
},
10+
};
11+
12+
export const builtinPlacements: BuildInPlacements = {
713
top: {
814
points: ['bc', 'tc'],
915
overflow: {
1016
shiftX: 0,
1117
adjustY: true,
1218
},
1319
offset: [0, 0],
20+
...experimentalConfig,
1421
},
1522
topLeft: {
1623
points: ['bl', 'tl'],
@@ -19,6 +26,7 @@ export const builtinPlacements = {
1926
adjustY: true,
2027
},
2128
offset: [0, 0],
29+
...experimentalConfig,
2230
},
2331
topRight: {
2432
points: ['br', 'tr'],
@@ -27,6 +35,7 @@ export const builtinPlacements = {
2735
adjustY: true,
2836
},
2937
offset: [0, 0],
38+
...experimentalConfig,
3039
},
3140
left: {
3241
points: ['cr', 'cl'],
@@ -35,6 +44,7 @@ export const builtinPlacements = {
3544
shiftY: true,
3645
},
3746
offset: [0, 0],
47+
...experimentalConfig,
3848
},
3949
leftTop: {
4050
points: ['tr', 'tl'],
@@ -43,6 +53,7 @@ export const builtinPlacements = {
4353
adjustY: true,
4454
},
4555
offset: [0, 0],
56+
...experimentalConfig,
4657
},
4758
leftBottom: {
4859
points: ['br', 'bl'],
@@ -51,6 +62,7 @@ export const builtinPlacements = {
5162
adjustY: true,
5263
},
5364
offset: [0, 0],
65+
...experimentalConfig,
5466
},
5567
right: {
5668
points: ['cl', 'cr'],
@@ -59,6 +71,7 @@ export const builtinPlacements = {
5971
shiftY: true,
6072
},
6173
offset: [0, 0],
74+
...experimentalConfig,
6275
},
6376
bottom: {
6477
points: ['tc', 'bc'],
@@ -67,6 +80,7 @@ export const builtinPlacements = {
6780
adjustY: true,
6881
},
6982
offset: [0, 0],
83+
...experimentalConfig,
7084
},
7185
};
7286

@@ -106,6 +120,9 @@ export default () => {
106120
style={{
107121
width: `300vw`,
108122
height: `300vh`,
123+
// width: 500,
124+
// height: 500,
125+
background: `rgba(0, 0, 255, 0.1)`,
109126
display: 'flex',
110127
alignItems: 'center',
111128
justifyContent: 'center',

src/Popup/index.tsx

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ export interface PopupProps {
5151
ready: boolean;
5252
offsetX: number;
5353
offsetY: number;
54+
offsetR: number;
55+
offsetB: number;
5456
onAlign: VoidFunction;
5557
onPrepare: () => Promise<void>;
5658

@@ -103,6 +105,8 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
103105
ready,
104106
offsetX,
105107
offsetY,
108+
offsetR,
109+
offsetB,
106110
onAlign,
107111
onPrepare,
108112

@@ -136,16 +140,38 @@ const Popup = React.forwardRef<HTMLDivElement, PopupProps>((props, ref) => {
136140
}
137141

138142
// >>>>> Offset
139-
const offsetStyle: React.CSSProperties =
140-
ready || !open
141-
? {
142-
left: offsetX,
143-
top: offsetY,
144-
}
145-
: {
146-
left: '-1000vw',
147-
top: '-1000vh',
148-
};
143+
const AUTO = 'auto' as const;
144+
145+
const offsetStyle: React.CSSProperties = {
146+
left: '-1000vw',
147+
top: '-1000vh',
148+
right: AUTO,
149+
bottom: AUTO,
150+
};
151+
152+
// Set align style
153+
if (ready || !open) {
154+
const { points, _experimental } = align;
155+
const dynamicInset = _experimental?.dynamicInset;
156+
const alignRight = dynamicInset && points[0][1] === 'r';
157+
const alignBottom = dynamicInset && points[0][0] === 'b';
158+
159+
if (alignRight) {
160+
offsetStyle.right = offsetR;
161+
offsetStyle.left = AUTO;
162+
} else {
163+
offsetStyle.left = offsetX;
164+
offsetStyle.right = AUTO;
165+
}
166+
167+
if (alignBottom) {
168+
offsetStyle.bottom = offsetB;
169+
offsetStyle.top = AUTO;
170+
} else {
171+
offsetStyle.top = offsetY;
172+
offsetStyle.bottom = AUTO;
173+
}
174+
}
149175

150176
// >>>>> Misc
151177
const miscStyle: React.CSSProperties = {};

src/hooks/useAlign.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ export default function useAlign(
9999
ready: boolean,
100100
offsetX: number,
101101
offsetY: number,
102+
offsetR: number,
103+
offsetB: number,
102104
arrowX: number,
103105
arrowY: number,
104106
scaleX: number,
@@ -110,6 +112,8 @@ export default function useAlign(
110112
ready: boolean;
111113
offsetX: number;
112114
offsetY: number;
115+
offsetR: number;
116+
offsetB: number;
113117
arrowX: number;
114118
arrowY: number;
115119
scaleX: number;
@@ -119,6 +123,8 @@ export default function useAlign(
119123
ready: false,
120124
offsetX: 0,
121125
offsetY: 0,
126+
offsetR: 0,
127+
offsetB: 0,
122128
arrowX: 0,
123129
arrowY: 0,
124130
scaleX: 1,
@@ -160,6 +166,8 @@ export default function useAlign(
160166

161167
const originLeft = popupElement.style.left;
162168
const originTop = popupElement.style.top;
169+
const originRight = popupElement.style.right;
170+
const originBottom = popupElement.style.bottom;
163171

164172
const doc = popupElement.ownerDocument;
165173
const win = getWin(popupElement);
@@ -173,6 +181,8 @@ export default function useAlign(
173181
// Reset first
174182
popupElement.style.left = '0';
175183
popupElement.style.top = '0';
184+
popupElement.style.right = 'auto';
185+
popupElement.style.bottom = 'auto';
176186

177187
// Calculate align style, we should consider `transform` case
178188
let targetRect: Rect;
@@ -244,9 +254,19 @@ export default function useAlign(
244254
? visibleRegionArea
245255
: visibleArea;
246256

257+
// Record right & bottom align data
258+
popupElement.style.left = 'auto';
259+
popupElement.style.top = 'auto';
260+
popupElement.style.right = '0';
261+
popupElement.style.bottom = '0';
262+
263+
const popupMirrorRect = popupElement.getBoundingClientRect();
264+
247265
// Reset back
248266
popupElement.style.left = originLeft;
249267
popupElement.style.top = originTop;
268+
popupElement.style.right = originRight;
269+
popupElement.style.bottom = originBottom;
250270

251271
// Calculate scale
252272
const scaleX = toNum(
@@ -622,10 +642,18 @@ export default function useAlign(
622642

623643
onPopupAlign?.(popupEle, nextAlignInfo);
624644

645+
// Additional calculate right & bottom position
646+
const offsetX4Right =
647+
popupMirrorRect.right - popupRect.x - (nextOffsetX + popupRect.width);
648+
const offsetY4Bottom =
649+
popupMirrorRect.bottom - popupRect.y - (nextOffsetY + popupRect.height);
650+
625651
setOffsetInfo({
626652
ready: true,
627653
offsetX: nextOffsetX / scaleX,
628654
offsetY: nextOffsetY / scaleY,
655+
offsetR: offsetX4Right / scaleX,
656+
offsetB: offsetY4Bottom / scaleY,
629657
arrowX: nextArrowX / scaleX,
630658
arrowY: nextArrowY / scaleY,
631659
scaleX,
@@ -667,6 +695,8 @@ export default function useAlign(
667695
offsetInfo.ready,
668696
offsetInfo.offsetX,
669697
offsetInfo.offsetY,
698+
offsetInfo.offsetR,
699+
offsetInfo.offsetB,
670700
offsetInfo.arrowX,
671701
offsetInfo.arrowY,
672702
offsetInfo.scaleX,

src/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ export function generateTrigger(
359359
ready,
360360
offsetX,
361361
offsetY,
362+
offsetR,
363+
offsetB,
362364
arrowX,
363365
arrowY,
364366
scaleX,
@@ -659,6 +661,8 @@ export function generateTrigger(
659661
ready={ready}
660662
offsetX={offsetX}
661663
offsetY={offsetY}
664+
offsetR={offsetR}
665+
offsetB={offsetB}
662666
onAlign={triggerAlign}
663667
// Stretch
664668
stretch={stretch}

src/interface.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ export interface AlignType {
2828
* Such as ['tr','cc'], align top right point of source node with center point of target node.
2929
* Point can be 't'(top), 'b'(bottom), 'c'(center), 'l'(left), 'r'(right) */
3030
points?: (string | AlignPoint)[];
31+
32+
/**
33+
* @private Do not use in your production code
34+
*/
35+
_experimental?: {
36+
/**
37+
* @private Do not use in your production code. Auto adjust align logic
38+
*/
39+
dynamicInset?: boolean;
40+
};
41+
3142
/**
3243
* offset source node by offset[0] in x and offset[1] in y.
3344
* If offset contains percentage string value, it is relative to sourceNode region.

tests/align.test.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ describe('Trigger.Align', () => {
2323
y: 100,
2424
width: 100,
2525
height: 100,
26+
right: 200,
27+
bottom: 200,
2628
}),
2729
});
2830

@@ -233,4 +235,27 @@ describe('Trigger.Align', () => {
233235
top: `50px`,
234236
});
235237
});
238+
239+
it('support dynamicInset', async () => {
240+
render(
241+
<Trigger
242+
popupVisible
243+
popup={<span className="bamboo" />}
244+
popupAlign={{
245+
points: ['bc', 'tc'],
246+
_experimental: {
247+
dynamicInset: true,
248+
},
249+
}}
250+
>
251+
<div />
252+
</Trigger>,
253+
);
254+
255+
await awaitFakeTimer();
256+
257+
expect(document.querySelector('.rc-trigger-popup')).toHaveStyle({
258+
bottom: `100px`,
259+
});
260+
});
236261
});

0 commit comments

Comments
 (0)