mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(overlay): add the ability to set the default offsets on FlexibleConnectedPositionStrategy (#10555)
This commit is contained in:
committed by
Joey Perrott
parent
b47bfafad2
commit
bcff93e8e4
@@ -174,12 +174,7 @@ export class ConnectedPositionStrategy implements PositionStrategy {
|
||||
* @param offset New offset in the X axis.
|
||||
*/
|
||||
withOffsetX(offset: number): this {
|
||||
this._preferredPositions.forEach(position => {
|
||||
if (position.offsetX == null) {
|
||||
position.offsetX = offset;
|
||||
}
|
||||
});
|
||||
|
||||
this._positionStrategy.withDefaultOffsetX(offset);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -188,12 +183,7 @@ export class ConnectedPositionStrategy implements PositionStrategy {
|
||||
* @param offset New offset in the Y axis.
|
||||
*/
|
||||
withOffsetY(offset: number): this {
|
||||
this._preferredPositions.forEach(position => {
|
||||
if (position.offsetY == null) {
|
||||
position.offsetY = offset;
|
||||
}
|
||||
});
|
||||
|
||||
this._positionStrategy.withDefaultOffsetY(offset);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -385,6 +385,41 @@ describe('FlexibleConnectedPositionStrategy', () => {
|
||||
expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left + 10));
|
||||
});
|
||||
|
||||
it('should be able to set the default x offset', () => {
|
||||
const originRect = originElement.getBoundingClientRect();
|
||||
|
||||
positionStrategy.withDefaultOffsetX(20).withPositions([{
|
||||
originX: 'start',
|
||||
originY: 'top',
|
||||
overlayX: 'start',
|
||||
overlayY: 'top',
|
||||
}]);
|
||||
|
||||
attachOverlay({positionStrategy});
|
||||
|
||||
const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
|
||||
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.top));
|
||||
expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left + 20));
|
||||
});
|
||||
|
||||
it('should have the position offset x take precedence over the default offset x', () => {
|
||||
const originRect = originElement.getBoundingClientRect();
|
||||
|
||||
positionStrategy.withDefaultOffsetX(20).withPositions([{
|
||||
originX: 'start',
|
||||
originY: 'top',
|
||||
overlayX: 'start',
|
||||
overlayY: 'top',
|
||||
offsetX: 10
|
||||
}]);
|
||||
|
||||
attachOverlay({positionStrategy});
|
||||
|
||||
const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
|
||||
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.top));
|
||||
expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left + 10));
|
||||
});
|
||||
|
||||
it('should position a panel with the y offset provided', () => {
|
||||
const originRect = originElement.getBoundingClientRect();
|
||||
|
||||
@@ -403,6 +438,41 @@ describe('FlexibleConnectedPositionStrategy', () => {
|
||||
expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left));
|
||||
});
|
||||
|
||||
it('should be able to set the default y offset', () => {
|
||||
const originRect = originElement.getBoundingClientRect();
|
||||
|
||||
positionStrategy.withDefaultOffsetY(60).withPositions([{
|
||||
originX: 'start',
|
||||
originY: 'top',
|
||||
overlayX: 'start',
|
||||
overlayY: 'top',
|
||||
}]);
|
||||
|
||||
attachOverlay({positionStrategy});
|
||||
|
||||
const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
|
||||
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.top + 60));
|
||||
expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left));
|
||||
});
|
||||
|
||||
it('should have the position offset y take precedence over the default offset y', () => {
|
||||
const originRect = originElement.getBoundingClientRect();
|
||||
|
||||
positionStrategy.withDefaultOffsetY(60).withPositions([{
|
||||
originX: 'start',
|
||||
originY: 'top',
|
||||
overlayX: 'start',
|
||||
overlayY: 'top',
|
||||
offsetY: 50
|
||||
}]);
|
||||
|
||||
attachOverlay({positionStrategy});
|
||||
|
||||
const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
|
||||
expect(Math.floor(overlayRect.top)).toBe(Math.floor(originRect.top + 50));
|
||||
expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left));
|
||||
});
|
||||
|
||||
it('should allow for the fallback positions to specify their own offsets', () => {
|
||||
originElement.style.bottom = '0';
|
||||
originElement.style.left = '50%';
|
||||
|
||||
@@ -69,7 +69,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
|
||||
private _viewportRect: ClientRect;
|
||||
|
||||
/** Amount of space that must be maintained between the overlay and the edge of the viewport. */
|
||||
private _viewportMargin: number = 0;
|
||||
private _viewportMargin = 0;
|
||||
|
||||
/** The Scrollable containers used to check scrollable view properties on position change. */
|
||||
private scrollables: CdkScrollable[] = [];
|
||||
@@ -101,6 +101,12 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
|
||||
/** Subscription to viewport size changes. */
|
||||
private _resizeSubscription = Subscription.EMPTY;
|
||||
|
||||
/** Default offset for the overlay along the x axis. */
|
||||
private _offsetX = 0;
|
||||
|
||||
/** Default offset for the overlay along the y axis. */
|
||||
private _offsetY = 0;
|
||||
|
||||
/** Observable sequence of position changes. */
|
||||
positionChanges: Observable<ConnectedOverlayPositionChange> =
|
||||
this._positionChanges.asObservable();
|
||||
@@ -366,6 +372,24 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default offset for the overlay's connection point on the x-axis.
|
||||
* @param offset New offset in the X axis.
|
||||
*/
|
||||
withDefaultOffsetX(offset: number): this {
|
||||
this._offsetX = offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default offset for the overlay's connection point on the y-axis.
|
||||
* @param offset New offset in the Y axis.
|
||||
*/
|
||||
withDefaultOffsetY(offset: number): this {
|
||||
this._offsetY = offset;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the (x, y) coordinate of a connection point on the origin based on a relative position.
|
||||
*/
|
||||
@@ -431,14 +455,16 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
|
||||
position: ConnectedPosition): OverlayFit {
|
||||
|
||||
let {x, y} = point;
|
||||
let offsetX = this._getOffset(position, 'x');
|
||||
let offsetY = this._getOffset(position, 'y');
|
||||
|
||||
// Account for the offsets since they could push the overlay out of the viewport.
|
||||
if (position.offsetX) {
|
||||
x += position.offsetX;
|
||||
if (offsetX) {
|
||||
x += offsetX;
|
||||
}
|
||||
|
||||
if (position.offsetY) {
|
||||
y += position.offsetY;
|
||||
if (offsetY) {
|
||||
y += offsetY;
|
||||
}
|
||||
|
||||
// How much the overlay would overflow at this position, on each side.
|
||||
@@ -721,13 +747,15 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
|
||||
// cases where the element doesn't have anything to "push off of". Finally, this works
|
||||
// better both with flexible and non-flexible positioning.
|
||||
let transformString = ' ';
|
||||
let offsetX = this._getOffset(position, 'x');
|
||||
let offsetY = this._getOffset(position, 'y');
|
||||
|
||||
if (position.offsetX) {
|
||||
transformString += `translateX(${position.offsetX}px)`;
|
||||
if (offsetX) {
|
||||
transformString += `translateX(${offsetX}px)`;
|
||||
}
|
||||
|
||||
if (position.offsetY) {
|
||||
transformString += `translateY(${position.offsetY}px)`;
|
||||
if (offsetY) {
|
||||
transformString += `translateY(${offsetY}px)`;
|
||||
}
|
||||
|
||||
styles.transform = transformString.trim();
|
||||
@@ -869,6 +897,17 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
|
||||
private _isRtl() {
|
||||
return this._overlayRef.getConfig().direction === 'rtl';
|
||||
}
|
||||
|
||||
/** Retrieves the offset of a position along the x or y axis. */
|
||||
private _getOffset(position: ConnectedPosition, axis: 'x' | 'y') {
|
||||
if (axis === 'x') {
|
||||
// We don't do something like `position['offset' + axis]` in
|
||||
// order to avoid breking minifiers that rename properties.
|
||||
return position.offsetX == null ? this._offsetX : position.offsetX;
|
||||
}
|
||||
|
||||
return position.offsetY == null ? this._offsetY : position.offsetY;
|
||||
}
|
||||
}
|
||||
|
||||
/** A simple (x, y) coordinate. */
|
||||
|
||||
Reference in New Issue
Block a user