File

src/dialog/overflow-menu/overflow-menu-pane.component.ts

Description

Extend the Dialog component to create an overflow menu.

Not used directly. See overflow-menu.component and overflow-menu.directive for more

Extends

Dialog

Implements

AfterViewInit

Metadata

Index

Properties
Methods
Inputs
Outputs
HostListeners

Constructor

constructor(elementRef: ElementRef, i18n: I18n, experimental: ExperimentalService, animationFrameService: AnimationFrameService, elementService: ElementService)
Parameters :
Name Type Optional
elementRef ElementRef No
i18n I18n No
experimental ExperimentalService No
animationFrameService AnimationFrameService No
elementService ElementService No

Inputs

dialogConfig
Type : DialogConfig
Inherited from Dialog
Defined in Dialog:41

Receives DialogConfig interface object with properties of Dialog explicitly defined.

Outputs

close
Type : EventEmitter<CloseMeta>
Inherited from Dialog
Defined in Dialog:36

Emits event that handles the closing of a Dialog object.

HostListeners

keydown
Arguments : '$event'
keydown(event: KeyboardEvent)
Inherited from Dialog
Defined in Dialog:82
document:click
Arguments : '$event'
document:click(event)
Inherited from Dialog
Defined in Dialog:229

Sets up a event Listener to close Dialog if click event occurs outside Dialog object.

Parameters :
Name Optional
event No

Methods

afterDialogViewInit
afterDialogViewInit()
Inherited from Dialog
Defined in Dialog:135
Returns : void
hostkeys
hostkeys(event: KeyboardEvent)
Decorators :
@HostListener('keydown', ['$event'])
Parameters :
Name Type Optional
event KeyboardEvent No
Returns : void
Protected listItems
listItems()
Returns : any
onClose
onClose(event)
Parameters :
Name Optional
event No
Returns : void
onDialogInit
onDialogInit()
Inherited from Dialog
Defined in Dialog:53
Returns : void
clickClose
clickClose(event)
Decorators :
@HostListener('document:click', ['$event'])
Inherited from Dialog
Defined in Dialog:229

Sets up a event Listener to close Dialog if click event occurs outside Dialog object.

Parameters :
Name Optional
event No
Returns : void
Public doClose
doClose(meta: CloseMeta)
Inherited from Dialog
Defined in Dialog:242

Closes Dialog object by emitting the close event upwards to parents.

Parameters :
Name Type Optional Default value
meta CloseMeta No { reason: CloseReasons.interaction }
Returns : void
escapeClose
escapeClose(event: KeyboardEvent)
Decorators :
@HostListener('keydown', ['$event'])
Inherited from Dialog
Defined in Dialog:206

Sets up a KeyboardEvent to close Dialog with Escape key.

Parameters :
Name Type Optional
event KeyboardEvent No
Returns : void
ngAfterViewInit
ngAfterViewInit()
Inherited from Dialog
Defined in Dialog:105

After the DOM is ready, focus is set and dialog is placed in respect to the parent element.

Returns : void
ngOnDestroy
ngOnDestroy()
Inherited from Dialog
Defined in Dialog:249

At destruction of component, Dialog unsubscribes from all the subscriptions.

Returns : void
ngOnInit
ngOnInit()
Inherited from Dialog
Defined in Dialog:93

Initialize the Dialog, set the placement and gap, and add a Subscription to resize events.

Returns : void
placeDialog
placeDialog()
Inherited from Dialog
Defined in Dialog:162

Uses the position service to position the Dialog in screen space

Returns : void

Properties

Protected addGap
Type : object
Default value : { "left": pos => position.addOffset(pos, 0, -this.dialogConfig.gap), "right": pos => position.addOffset(pos, 0, this.dialogConfig.gap), "top": pos => position.addOffset(pos, -this.dialogConfig.gap), "bottom": pos => position.addOffset(pos, this.dialogConfig.gap), "left-bottom": pos => position.addOffset(pos, 0, -this.dialogConfig.gap), "right-bottom": pos => position.addOffset(pos, 0, this.dialogConfig.gap) }
Inherited from Dialog
Defined in Dialog:65

Handles offsetting the Dialog item based on the defined position to not obscure the content beneath.

Protected animationFrameSubscription
Default value : new Subscription()
Inherited from Dialog
Defined in Dialog:59
Public data
Type : object
Default value : {}
Inherited from Dialog
Defined in Dialog:50

Stores the data received from dialogConfig.

dialog
Type : ElementRef
Decorators :
@ViewChild('dialog')
Inherited from Dialog
Defined in Dialog:45

Maintains a reference to the view DOM element of the Dialog.

Public placement
Type : string
Inherited from Dialog
Defined in Dialog:55

The placement of the Dialog is received from the Position service.

Protected placements
Type : Positions
Default value : {}
Inherited from Dialog
Defined in Dialog:77

Extra placements. Child classes can add to this for use in placeDialog.

Protected visibilitySubscription
Default value : new Subscription()
Inherited from Dialog
Defined in Dialog:57
import {
	Component,
	HostListener,
	ElementRef,
	AfterViewInit,
	Optional
} from "@angular/core";
import { Dialog } from "../dialog.component";
import { position } from "@carbon/utils-position";
import { isFocusInLastItem, isFocusInFirstItem } from "carbon-components-angular/common";
import { I18n } from "carbon-components-angular/i18n";
import { ExperimentalService } from "carbon-components-angular/experimental";
import { AnimationFrameService, ElementService } from "carbon-components-angular/utils";
import { CloseReasons } from "../dialog-config.interface";
import { closestAttr } from "carbon-components-angular/utils";

/**
 * Extend the `Dialog` component to create an overflow menu.
 *
 * Not used directly. See overflow-menu.component and overflow-menu.directive for more
 */
@Component({
	selector: "cds-overflow-menu-pane, ibm-overflow-menu-pane",
	template: `
		<ul
			[attr.id]="dialogConfig.compID"
			[attr.aria-label]="dialogConfig.menuLabel"
			[attr.data-floating-menu-direction]="placement ? placement : null"
			[ngClass]="{'cds--overflow-menu--flip': dialogConfig.flip}"
			role="menu"
			#dialog
			class="cds--overflow-menu-options cds--overflow-menu-options--open"
			(click)="onClose($event)"
			[attr.aria-label]="dialogConfig.menuLabel">
			<ng-template
				[ngTemplateOutlet]="dialogConfig.content"
				[ngTemplateOutletContext]="{overflowMenu: this}">
			</ng-template>
		</ul>
	`
})
export class OverflowMenuPane extends Dialog implements AfterViewInit {
	constructor(
		protected elementRef: ElementRef,
		protected i18n: I18n,
		protected experimental: ExperimentalService,
		@Optional() protected animationFrameService: AnimationFrameService = null,
		// mark `elementService` as optional since making it mandatory would be a breaking change
		@Optional() protected elementService: ElementService = null) {
		super(elementRef, elementService, animationFrameService);
	}

	onDialogInit() {
		const positionOverflowMenu = pos => {
			let offset;
			/*
			* 20 is half the width of the overflow menu trigger element.
			* we also move the element by half of it's own width, since
			* position service will try and center everything
			*/
			const closestRel = closestAttr("position", ["relative", "fixed", "absolute"], this.elementRef.nativeElement);
			const topFix = closestRel ? closestRel.getBoundingClientRect().top * -1 : 0;
			const leftFix = closestRel ? closestRel.getBoundingClientRect().left * -1 : 0;

			offset = Math.round(this.dialog.nativeElement.offsetWidth / 2) - 20;
			if (this.dialogConfig.flip) {
				return position.addOffset(pos, topFix, (-offset + leftFix));
			}
			return position.addOffset(pos, topFix, (offset + leftFix));
		};

		this.addGap["bottom"] = positionOverflowMenu;

		this.addGap["top"] = positionOverflowMenu;

		if (!this.dialogConfig.menuLabel) {
			this.dialogConfig.menuLabel = this.i18n.get().OVERFLOW_MENU.OVERFLOW;
		}
	}

	@HostListener("keydown", ["$event"])
	hostkeys(event: KeyboardEvent) {
		const listItems = this.listItems();

		switch (event.key) {
			case "ArrowDown":
				event.preventDefault();
				if (!isFocusInLastItem(event, listItems))  {
					const index = listItems.findIndex(item => item === event.target);
					listItems[index + 1].focus();
				} else {
					listItems[0].focus();
				}
				break;

			case "ArrowUp":
				event.preventDefault();
				if (!isFocusInFirstItem(event, listItems))  {
					const index = listItems.findIndex(item => item === event.target);
					listItems[index - 1].focus();
				} else {
					listItems[listItems.length - 1].focus();
				}
				break;

			case "Home":
				event.preventDefault();
				listItems[0].focus();
				break;

			case "End":
				event.preventDefault();
				listItems[listItems.length - 1].focus();
				break;

			case "Escape":
			case "Tab":
				event.stopImmediatePropagation();
				this.doClose({
					reason: CloseReasons.interaction,
					target: event.target
				});
				break;
			default: break;
		}
	}

	onClose(event) {
		this.doClose({
			reason: CloseReasons.interaction,
			target: event.target
		});
	}

	afterDialogViewInit() {
		const focusElementList = this.listItems();
		focusElementList.forEach(button => {
			// Allows user to set tabindex to 0.
			if (button.getAttribute("tabindex") === null) {
				button.tabIndex = -1;
			}
		});
		if (focusElementList[0]) {
			focusElementList[0].tabIndex = 0;
			focusElementList[0].focus();
		}
	}

	protected listItems() {
		const selector = ".cds--overflow-menu-options__option:not([disabled]) .cds--overflow-menu-options__btn";
		return Array.from<HTMLElement>(this.elementRef.nativeElement.querySelectorAll(selector));
	}
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""