src/app/shared/components/visibility-menu/visibility-menu.component.ts
Menu for displaying visibility options
changeDetection | ChangeDetectionStrategy.OnPush |
selector | ccf-visibility-menu |
styleUrls | ./visibility-menu.component.scss |
templateUrl | ./visibility-menu.component.html |
Properties |
|
Methods |
Inputs |
Outputs |
HostBindings |
constructor(ga: GoogleAnalyticsService)
|
||||||||
Creates an instance of visibility menu component.
Parameters :
|
items | |
Type : VisibilityItem[]
|
|
Items to be displayed in the visibility menu |
selection | |
Type : VisibilityItem | undefined
|
|
The currently selected item |
hover | |
Type : EventEmitter
|
|
Emits the currently hovered item |
itemsChange | |
Type : EventEmitter
|
|
Emits whenever there is a change to one or more items. |
class |
Type : "ccf-visibility-menu"
|
Default value : 'ccf-visibility-menu'
|
HTML class name |
getId | ||||||||||||
getId(_index: number, item: VisibilityItem)
|
||||||||||||
Returns the id of an item
Parameters :
Returns :
string | number
id Id of the item |
mouseOut |
mouseOut()
|
Clears current selection and emits undefined in response to mouse out
Returns :
void
|
mouseOver | ||||||||
mouseOver(item: VisibilityItem)
|
||||||||
Changes current selection to hovered over item and emits the item
Parameters :
Returns :
void
|
resetItem |
resetItem()
|
Resets item to opacity 20 and visible
Returns :
void
|
setAllOpacity | ||||||||
setAllOpacity(value: number)
|
||||||||
Sets all items to the same opacity and makes them visible
Parameters :
Returns :
void
|
toggleVisibility | ||||||||
toggleVisibility(item: VisibilityItem)
|
||||||||
Toggles visibility of an item; opacity is reverted to the previous value if visibility toggled back on
Parameters :
Returns :
void
|
updateOpacity | ||||||||
updateOpacity(value: number | undefined)
|
||||||||
Updates opacity of the currently selected item (if one is selected) and emits the new items
Parameters :
Returns :
void
|
Readonly clsName |
Type : string
|
Default value : 'ccf-visibility-menu'
|
Decorators :
@HostBinding('class')
|
HTML class name |
import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, Output } from '@angular/core';
import { GoogleAnalyticsService } from 'ngx-google-analytics';
import { VisibilityItem } from '../../../core/models/visibility-item';
/**
* Menu for displaying visibility options
*/
@Component({
selector: 'ccf-visibility-menu',
templateUrl: './visibility-menu.component.html',
styleUrls: ['./visibility-menu.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VisibilityMenuComponent {
/**
* HTML class name
*/
@HostBinding('class') readonly clsName = 'ccf-visibility-menu';
/**
* Items to be displayed in the visibility menu
*/
@Input() items!: VisibilityItem[];
/**
* The currently selected item
*/
@Input() selection: VisibilityItem | undefined;
/**
* Emits the currently hovered item
*/
@Output() readonly hover = new EventEmitter<VisibilityItem | undefined>();
/**
* Emits whenever there is a change to one or more items.
*/
@Output() readonly itemsChange = new EventEmitter<VisibilityItem[]>();
/**
* Creates an instance of visibility menu component.
*
* @param ga Analytics service
*/
constructor(private readonly ga: GoogleAnalyticsService) {}
/**
* Toggles visibility of an item; opacity is reverted to the previous value if visibility toggled back on
*
* @param item Menu item
*/
toggleVisibility(item: VisibilityItem): void {
item = { ...item, visible: !item.visible };
if (this.selection && item.id === this.selection.id) {
this.selection = { ...this.selection, visible: item.visible };
}
this.ga.event('visibility_toggled', 'visibility_menu', '' + item.id, +item.visible);
this.updateOpacity(item.opacity);
}
/**
* Changes current selection to hovered over item and emits the item
*
* @param item Menu item
*/
mouseOver(item: VisibilityItem): void {
this.selection = item === this.selection ? undefined : item;
this.hover.emit(item);
}
/**
* Clears current selection and emits undefined in response to mouse out
*
* @param item Menu item
*/
mouseOut(): void {
this.selection = undefined;
this.hover.emit(undefined);
}
/**
* Updates opacity of the currently selected item (if one is selected) and emits the new items
*
* @param value Updated opacity value
*/
updateOpacity(value: number | undefined): void {
if (!this.selection) {
return;
}
const updatedSelection = { ...this.selection, opacity: value };
this.selection = updatedSelection;
if (updatedSelection.id === 'all') {
this.setAllOpacity(updatedSelection.opacity as number);
} else {
this.items = this.items.map((item) => (item.id === updatedSelection.id ? updatedSelection : item));
this.ga.event('opacity_update', 'visibility_menu', '' + updatedSelection.id, updatedSelection.opacity);
}
this.itemsChange.emit(this.items);
}
/**
* Resets item to opacity 20 and visible
*/
resetItem(): void {
if (this.selection) {
const updatedSelection = { ...this.selection, opacity: 20, visible: true };
this.selection = updatedSelection;
if (this.selection.id === 'all') {
this.setAllOpacity(updatedSelection.opacity);
} else {
this.items = this.items.map((item) => (item.id === updatedSelection.id ? updatedSelection : item));
this.ga.event('item_reset', 'visibility_menu', '' + updatedSelection.id);
}
this.itemsChange.emit(this.items);
}
}
/**
* Sets all items to the same opacity and makes them visible
*
* @param value Updated opacity value
*/
setAllOpacity(value: number): void {
this.items = this.items.map((i) => ({ ...i, opacity: value, visible: true }));
this.ga.event('all_items_opacity_update', 'visibility_menu', undefined, value);
this.itemsChange.emit(this.items);
}
/**
* Returns the id of an item
*
* @param index Index of item in items array
* @param item The item to get an id for
* @returns id Id of the item
*/
getId(_index: number, item: VisibilityItem): string | number {
return item.id;
}
}
<mat-icon
class="icon reset"
matRipple
[matRippleCentered]="true"
[matRippleUnbounded]="true"
(click)="setAllOpacity(20)"
*ngIf="items.length"
>refresh</mat-icon
>
<div
class="item-entry"
[class.selected]="selection ? getId(0, selection) === getId(0, item) : false"
(mouseenter)="mouseOver(item)"
(mouseleave)="mouseOut()"
*ngFor="let item of items; trackBy: getId"
>
<mat-icon class="opacity-icon" [class.fade]="!item.visible" svgIcon="app:opacity"></mat-icon>
<div class="item-name" [class.hidden]="item.id === selection?.id" title="{{ item.name }}">{{ item.name }}</div>
<div class="slider" [class.visible]="item.id === selection?.id" [class.hidden]="item.id !== selection?.id">
<ccf-opacity-slider
[opacity]="selection?.opacity ?? 20"
(opacityChange)="updateOpacity($event)"
(opacityReset)="resetItem()"
(visibilityToggle)="toggleVisibility(item)"
>
</ccf-opacity-slider>
</div>
</div>
./visibility-menu.component.scss
:host {
display: flex;
flex-direction: column;
margin-right: 0;
margin-left: 0;
max-height: 40vh;
overflow-y: auto;
scrollbar-width: thin;
.icon {
border-radius: 0.25rem;
}
.reset {
transform: scaleX(-1);
cursor: pointer;
transition: 0.6s;
position: absolute;
top: 3rem;
&:hover {
border-radius: 2px;
}
}
.item-entry {
display: flex;
height: 2.25rem;
align-items: center;
flex-shrink: 0;
position: relative;
.opacity {
cursor: pointer;
}
.opacity-icon {
z-index: 1;
transition: 0.6s;
&:hover {
border-radius: 2px;
}
}
.item-name {
user-select: none;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-left: 0.5rem;
opacity: 1;
transition-duration: 0.4s;
transition-timing-function: ease-in-out;
transition-property: opacity;
max-width: calc(100% - 2.5rem);
&.hidden {
opacity: 0;
}
}
.slider {
width: calc(100% - 2rem);
transition-duration: 0.3s;
transition-timing-function: ease-in-out;
transition-property: opacity;
left: 2rem;
position: absolute;
opacity: 1;
&.hidden {
opacity: 0;
transition-duration: 0.1s;
transition-timing-function: ease-in-out;
transition-property: opacity;
}
}
}
}