Skip to content

Commit

Permalink
feature: add dropdown vertical position setting
Browse files Browse the repository at this point in the history
  • Loading branch information
smurygin committed Jul 13, 2023
1 parent db9ed11 commit f4677f4
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ <h3 demoAnchor>Opening a dropdown as context menu</h3>
[disabled]="disabled$ | async"
[widthType]="widthType$ | async"
[horizontalPosition]="horizontalPosition$ | async"
[verticalPosition]="verticalPosition$ | async"
></demo-dropdown-example-1>
</demo-example-viewer-content>
<demo-example-viewer-section-label>pupaDropdown Properties</demo-example-viewer-section-label>
Expand Down Expand Up @@ -77,6 +78,21 @@ <h3 demoAnchor>Opening a dropdown as context menu</h3>
[options]="horizontalPositionOptions"
></demo-props-radio-select>
</demo-example-viewer-property>

<demo-example-viewer-property
name="pupaDropdownTemplateHorizontalPosition"
type="VerticalConnectionPos"
decoratorName="input"
>
<ng-container *demoExampleViewerPropertyDescription>
<div>Sets vertical position of dropdown.</div>
</ng-container>
<demo-props-radio-select
#verticalPosition$
direction="row"
[options]="verticalPositionOptions"
></demo-props-radio-select>
</demo-example-viewer-property>
</demo-example-viewer-section>
</demo-example-viewer>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,16 @@ export class DropdownDemoComponent {
value: 'end',
},
];

public readonly verticalPositionOptions: PropsOption[] = [
{
caption: 'bottom',
value: 'bottom',
isDefault: true,
},
{
caption: 'top',
value: 'top',
},
];
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit
<pupa-icon [name]="(dropdown.opened$ | async) ? 'app-chevron-up' : 'app-chevron-down'"></pupa-icon>

<ng-container *pupaDropdownTemplate="dropdown; widthType: widthType; horizontalPosition: horizontalPosition">
<ng-container
*pupaDropdownTemplate="
dropdown;
widthType: widthType;
horizontalPosition: horizontalPosition;
verticalPosition: verticalPosition
"
>
<div>sample content</div>
<div>🎳</div>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HorizontalConnectionPos } from '@angular/cdk/overlay';
import { HorizontalConnectionPos, VerticalConnectionPos } from '@angular/cdk/overlay';
import { ChangeDetectionStrategy, Component, Input, ViewEncapsulation } from '@angular/core';
import { DropdownWidthType } from '@bimeister/pupakit.kit';

Expand All @@ -13,4 +13,5 @@ export class DropdownDemoExample1Component {
@Input() public disabled: boolean;
@Input() public widthType: DropdownWidthType;
@Input() public horizontalPosition: HorizontalConnectionPos;
@Input() public verticalPosition: VerticalConnectionPos;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export class DropdownDemoExample2Component {
target: coordinates,
widthType: 'auto',
horizontalPosition: 'center',
verticalPosition: 'bottom',
component: DropdownDemoContainerComponent,
injector: this.injector,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class DropdownDemoExample3Component {
target: [event.clientX, event.clientY],
widthType: 'auto',
horizontalPosition: 'center',
verticalPosition: 'bottom',
component: DropdownDemoContainerComponent,
injector: this.injector,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HorizontalConnectionPos } from '@angular/cdk/overlay';
import { HorizontalConnectionPos, VerticalConnectionPos } from '@angular/cdk/overlay';
import { Directive, Input, OnChanges, TemplateRef } from '@angular/core';
import { DropdownDirectiveParams } from '../../../declarations/interfaces/dropdown-directive-params.interface';
import { DropdownTemplateContext } from '../../../declarations/interfaces/dropdown-template-context.interface';
Expand All @@ -12,12 +12,14 @@ export class DropdownTemplateDirective implements OnChanges {
@Input() public pupaDropdownTemplate?: DropdownHost;
@Input() public pupaDropdownTemplateWidthType: DropdownWidthType = 'auto';
@Input() public pupaDropdownTemplateHorizontalPosition: HorizontalConnectionPos = 'start';
@Input() public pupaDropdownTemplateVerticalPosition: VerticalConnectionPos = 'bottom';

private get dropdownDirectiveParams(): DropdownDirectiveParams {
return {
templateRef: this.templateRef,
widthType: this.pupaDropdownTemplateWidthType,
horizontalPosition: this.pupaDropdownTemplateHorizontalPosition,
verticalPosition: this.pupaDropdownTemplateVerticalPosition,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export class DropdownDirective implements AfterViewInit, OnDestroy, DropdownHost
target: this.pupaDropdownRealTriggerElement ?? this.triggerRef.nativeElement,
widthType: this.params.widthType,
horizontalPosition: this.params.horizontalPosition,
verticalPosition: this.params.verticalPosition,
theme,
data: {
templateRef: this.params.templateRef,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,19 @@ export class TooltipContentComponent implements OnDestroy {
}

private calculateTooltipStyleTransform(): Subscription {
const offsetXPx$: Observable<number> = this.tooltipPosition$.pipe(
return zip(this.getTooltipOffsetXPx(), this.getTooltipOffsetYPx())
.pipe(
map(([offsetXPx, offsetYPx]: [number, number]) => `translate(${offsetXPx}px, ${offsetYPx}px)`),
distinctUntilChanged()
)
.subscribe((transformStyle: string) => {
this.styleTransform$.next(transformStyle);
this.detectChanges();
});
}

private getTooltipOffsetXPx(): Observable<number> {
return this.tooltipPosition$.pipe(
filterNotNil(),
map((tooltipPosition: ConnectedOverlayPositionChange) => tooltipPosition.connectionPair),
map((connectionPair: ConnectionPositionPair) => {
Expand All @@ -102,8 +114,10 @@ export class TooltipContentComponent implements OnDestroy {
}
})
);
}

const offsetYPx$: Observable<number> = this.tooltipPosition$.pipe(
private getTooltipOffsetYPx(): Observable<number> {
return this.tooltipPosition$.pipe(
filterNotNil(),
map((tooltipPosition: ConnectedOverlayPositionChange) => tooltipPosition.connectionPair),
map((connectionPair: ConnectionPositionPair) => {
Expand All @@ -117,16 +131,6 @@ export class TooltipContentComponent implements OnDestroy {
}
})
);

return zip(offsetXPx$, offsetYPx$)
.pipe(
map(([offsetXPx, offsetYPx]: [number, number]) => `translate(${offsetXPx}px, ${offsetYPx}px)`),
distinctUntilChanged()
)
.subscribe((transformStyle: string) => {
this.styleTransform$.next(transformStyle);
this.detectChanges();
});
}

private detectChanges(): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HorizontalConnectionPos } from '@angular/cdk/overlay';
import { HorizontalConnectionPos, VerticalConnectionPos } from '@angular/cdk/overlay';
import { ComponentType } from '@angular/cdk/portal';
import { Injector } from '@angular/core';
import { Position, Theme } from '@bimeister/pupakit.common';
Expand All @@ -8,6 +8,7 @@ export interface DropdownConfig<TComponent, TData> {
target: HTMLElement | Position;
widthType: DropdownWidthType;
horizontalPosition: HorizontalConnectionPos;
verticalPosition: VerticalConnectionPos;
data?: TData;
component?: ComponentType<TComponent>;
injector?: Injector;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HorizontalConnectionPos } from '@angular/cdk/overlay';
import { HorizontalConnectionPos, VerticalConnectionPos } from '@angular/cdk/overlay';
import { TemplateRef } from '@angular/core';
import { DropdownWidthType } from '../types/dropdown-width.type';
import { DropdownTemplateContext } from './dropdown-template-context.interface';
Expand All @@ -7,4 +7,5 @@ export interface DropdownDirectiveParams {
templateRef: TemplateRef<DropdownTemplateContext>;
widthType: DropdownWidthType;
horizontalPosition: HorizontalConnectionPos;
verticalPosition: VerticalConnectionPos;
}
53 changes: 23 additions & 30 deletions projects/kit/src/services/dropdowns.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
ConnectionPositionPair,
FlexibleConnectedPositionStrategy,
HorizontalConnectionPos,
Overlay,
OverlayRef,
VerticalConnectionPos,
} from '@angular/cdk/overlay';
import { ConnectionPositionPair, FlexibleConnectedPositionStrategy, Overlay, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { Injectable, Injector } from '@angular/core';
import { getUuid, isNil, Uuid } from '@bimeister/utilities';
Expand All @@ -21,8 +14,17 @@ import { DropdownContainerData } from '../declarations/interfaces/dropdown-conta
import { DropdownDataType } from '../declarations/types/utility-types/dropdown-data.utility-type';
import { OVERLAY_VIEWPORT_MARGIN_PX, Position, Theme } from '@bimeister/pupakit.common';

const HORIZONTAL_POSITIONS: HorizontalConnectionPos[] = ['center', 'end', 'start'];
const VERTICAL_POSITIONS: VerticalConnectionPos[] = ['top', 'bottom'];
const OVERLAY_POSITIONS: ConnectionPositionPair[] = [
new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' }),
new ConnectionPositionPair({ originX: 'center', originY: 'bottom' }, { overlayX: 'center', overlayY: 'top' }),
new ConnectionPositionPair({ originX: 'end', originY: 'bottom' }, { overlayX: 'end', overlayY: 'top' }),
new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'bottom' }),
new ConnectionPositionPair({ originX: 'center', originY: 'bottom' }, { overlayX: 'center', overlayY: 'bottom' }),
new ConnectionPositionPair({ originX: 'end', originY: 'bottom' }, { overlayX: 'end', overlayY: 'bottom' }),
new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' }),
new ConnectionPositionPair({ originX: 'center', originY: 'top' }, { overlayX: 'center', overlayY: 'bottom' }),
new ConnectionPositionPair({ originX: 'end', originY: 'top' }, { overlayX: 'end', overlayY: 'bottom' }),
];

@Injectable({ providedIn: 'root' })
export class DropdownsService {
Expand Down Expand Up @@ -115,7 +117,7 @@ export class DropdownsService {
.position()
.flexibleConnectedTo(target instanceof HTMLElement ? target : { x: target[0], y: target[1] })
.withFlexibleDimensions(false)
.withPositions(this.getOverlayPositionsByHorizontalPosition(config.horizontalPosition))
.withPositions(this.getOverlayPositions(config))
.withViewportMargin(OVERLAY_VIEWPORT_MARGIN_PX);
}

Expand All @@ -132,27 +134,18 @@ export class DropdownsService {
return 'auto';
}

private getOverlayPositionsByHorizontalPosition(
currentHorizontalPos: HorizontalConnectionPos
private getOverlayPositions<TComponent extends DropdownComponentBase<unknown>>(
config: DropdownConfig<TComponent, DropdownDataType<TComponent>>
): ConnectionPositionPair[] {
const sortedHorizontalPositions: HorizontalConnectionPos[] = HORIZONTAL_POSITIONS.sort(
(horizontalPos: HorizontalConnectionPos) => (horizontalPos === currentHorizontalPos ? -1 : 1)
);

const overlayPositions: ConnectionPositionPair[] = VERTICAL_POSITIONS.flatMap(
(verticalPos: VerticalConnectionPos) =>
sortedHorizontalPositions.map((horizontalPos: HorizontalConnectionPos) =>
this.getConnectionPositionPair(horizontalPos, verticalPos)
)
const sortedHorizontalPositions: ConnectionPositionPair[] = OVERLAY_POSITIONS.sort(
(position: ConnectionPositionPair) =>
position.overlayX === config.horizontalPosition &&
position.originY === config.verticalPosition &&
position.overlayY !== config.verticalPosition
? -1
: 1
);

return overlayPositions;
}

private getConnectionPositionPair(
overlayX: HorizontalConnectionPos,
overlayY: VerticalConnectionPos
): ConnectionPositionPair {
return new ConnectionPositionPair({ originX: overlayX, originY: 'bottom' }, { overlayX, overlayY });
return sortedHorizontalPositions;
}
}

0 comments on commit f4677f4

Please sign in to comment.