@angular-mdc/web
Version:
516 lines (510 loc) • 15.9 kB
JavaScript
/**
* @license
* Copyright (c) Dominic Carretto
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/trimox/angular-mdc-web/blob/master/LICENSE
*/
import { EventEmitter, Directive, ChangeDetectorRef, NgZone, Optional, ElementRef, Input, Output, Component, ViewEncapsulation, ChangeDetectionStrategy, NgModule } from '@angular/core';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { Platform } from '@angular/cdk/platform';
import { Subject, fromEvent } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { MDCComponent } from '@angular-mdc/web/base';
import { Corner, MDCMenuSurfaceFoundation, util } from '@material/menu-surface';
/**
* @fileoverview added by tsickle
* Generated from: menu-surface/menu-surface-base.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const ANCHOR_CORNER_MAP = {
topEnd: Corner.TOP_END,
topStart: Corner.TOP_START,
bottomEnd: Corner.BOTTOM_END,
bottomStart: Corner.BOTTOM_START
};
/**
* @abstract
*/
class MdcMenuSurfaceBase extends MDCComponent {
/**
* @param {?} changeDetectorRef
* @param {?} platform
* @param {?} _ngZone
* @param {?} elementRef
*/
constructor(changeDetectorRef, platform, _ngZone, elementRef) {
super(elementRef);
this.changeDetectorRef = changeDetectorRef;
this.platform = platform;
this._ngZone = _ngZone;
this.elementRef = elementRef;
/**
* Emits whenever the component is destroyed.
*/
this._destroy = new Subject();
this._open = false;
this._anchorCorner = 'topStart';
this._quickOpen = false;
this._fixed = false;
this._coordinates = { x: 0, y: 0 };
this._anchorMargin = {};
this._hoistToBody = false;
/**
* Emits an event whenever the menu surface is opened.
*/
this.opened = new EventEmitter();
/**
* Emits an event whenever the menu surface is closed.
*/
this.closed = new EventEmitter();
/**
* Subscription to interaction events in menu-surface.
*/
this._windowClickSubscription = null;
}
/**
* @return {?}
*/
get open() {
return this._open;
}
/**
* @param {?} value
* @return {?}
*/
set open(value) {
/** @type {?} */
const newValue = coerceBooleanProperty(value);
if (newValue !== this._open) {
this._open = coerceBooleanProperty(value);
if (this._open) {
this._foundation.open();
}
else {
this._foundation.close();
}
}
}
/**
* @return {?}
*/
get anchorElement() {
return this._anchorElement;
}
/**
* @param {?} element
* @return {?}
*/
set anchorElement(element) {
this._anchorElement = element;
}
/**
* @return {?}
*/
get anchorCorner() {
return this._anchorCorner;
}
/**
* @param {?} value
* @return {?}
*/
set anchorCorner(value) {
this._anchorCorner = (value !== null && value !== void 0 ? value : 'topStart');
this._foundation.setAnchorCorner(ANCHOR_CORNER_MAP[this._anchorCorner]);
}
/**
* @return {?}
*/
get quickOpen() {
return this._quickOpen;
}
/**
* @param {?} value
* @return {?}
*/
set quickOpen(value) {
this._quickOpen = coerceBooleanProperty(value);
this._foundation.setQuickOpen(this._quickOpen);
}
/**
* @return {?}
*/
get fixed() {
return this._fixed;
}
/**
* @param {?} value
* @return {?}
*/
set fixed(value) {
this._fixed = coerceBooleanProperty(value);
if (this._fixed) {
this._getHostElement().classList.add('mdc-menu-surface--fixed');
}
else {
this._getHostElement().classList.remove('mdc-menu-surface--fixed');
}
this._foundation.setFixedPosition(this._fixed);
}
/**
* @return {?}
*/
get coordinates() {
return this._coordinates;
}
/**
* @param {?} value
* @return {?}
*/
set coordinates(value) {
this._coordinates = value;
this._foundation.setAbsolutePosition(value.x, value.y);
}
/**
* @return {?}
*/
get anchorMargin() {
return this._anchorMargin;
}
/**
* @param {?} value
* @return {?}
*/
set anchorMargin(value) {
this._anchorMargin = value;
this._foundation.setAnchorMargin(this._anchorMargin);
}
/**
* @return {?}
*/
get hoistToBody() {
return this._hoistToBody;
}
/**
* @param {?} value
* @return {?}
*/
set hoistToBody(value) {
this._hoistToBody = coerceBooleanProperty(value);
if (this._hoistToBody) {
this.setHoistToBody();
}
}
/**
* @return {?}
*/
getDefaultFoundation() {
/** @type {?} */
const adapter = {
addClass: (/**
* @param {?} className
* @return {?}
*/
(className) => this._getHostElement().classList.add(className)),
removeClass: (/**
* @param {?} className
* @return {?}
*/
(className) => this._getHostElement().classList.remove(className)),
hasClass: (/**
* @param {?} className
* @return {?}
*/
(className) => this._getHostElement().classList.contains(className)),
hasAnchor: (/**
* @return {?}
*/
() => !!this.anchorElement),
notifyClose: (/**
* @return {?}
*/
() => {
this.closed.emit();
this._deregisterWindowClickListener();
}),
notifyOpen: (/**
* @return {?}
*/
() => {
this.opened.emit();
this._registerWindowClickListener();
}),
isElementInContainer: (/**
* @param {?} el
* @return {?}
*/
(el) => this._getHostElement() === el || this._getHostElement().contains(el)),
isRtl: (/**
* @return {?}
*/
() => this.platform.isBrowser ?
window.getComputedStyle(this._getHostElement()).getPropertyValue('direction') === 'rtl' : false),
setTransformOrigin: (/**
* @param {?} origin
* @return {?}
*/
(origin) => this.platform.isBrowser ?
this._getHostElement().style[(/** @type {?} */ (`${util.getTransformPropertyName(window)}-origin`))] = origin : false),
isFocused: (/**
* @return {?}
*/
() => { var _a, _b; return _b = ((_a = document) === null || _a === void 0 ? void 0 : _a.activeElement) === this._getHostElement(), (_b !== null && _b !== void 0 ? _b : false); }),
saveFocus: (/**
* @return {?}
*/
() => { var _a, _b; return this._previousFocus = (_b = (_a = document) === null || _a === void 0 ? void 0 : _a.activeElement, (_b !== null && _b !== void 0 ? _b : undefined)); }),
restoreFocus: (/**
* @return {?}
*/
() => {
var _a;
if (this.platform.isBrowser) {
if (this._getHostElement().contains(document.activeElement)) {
(_a = ((/** @type {?} */ (this._previousFocus)))) === null || _a === void 0 ? void 0 : _a.focus();
}
}
}),
getInnerDimensions: (/**
* @return {?}
*/
() => ({ width: this._getHostElement().offsetWidth, height: this._getHostElement().offsetHeight })),
getAnchorDimensions: (/**
* @return {?}
*/
() => this.platform.isBrowser || !this.anchorElement ?
(/** @type {?} */ (this._anchorElement)).getBoundingClientRect() : { top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 }),
getWindowDimensions: (/**
* @return {?}
*/
() => ({
width: this.platform.isBrowser ? window.innerWidth : 0,
height: this.platform.isBrowser ? window.innerHeight : 0
})),
getBodyDimensions: (/**
* @return {?}
*/
() => ({
width: this.platform.isBrowser ? (/** @type {?} */ (document.body)).clientWidth : 0,
height: this.platform.isBrowser ? (/** @type {?} */ (document.body)).clientHeight : 0
})),
getWindowScroll: (/**
* @return {?}
*/
() => ({
x: this.platform.isBrowser ? window.pageXOffset : 0,
y: this.platform.isBrowser ? window.pageYOffset : 0
})),
setPosition: (/**
* @param {?} position
* @return {?}
*/
(position) => {
this._getHostElement().style.left = 'left' in position ? `${position.left}px` : '';
this._getHostElement().style.right = 'right' in position ? `${position.right}px` : '';
this._getHostElement().style.top = 'top' in position ? `${position.top}px` : '';
this._getHostElement().style.bottom = 'bottom' in position ? `${position.bottom}px` : '';
}),
setMaxHeight: (/**
* @param {?} height
* @return {?}
*/
(height) => this._getHostElement().style.maxHeight = height)
};
return new MDCMenuSurfaceFoundation(adapter);
}
/**
* @protected
* @return {?}
*/
initMenuSurface() {
var _a;
this._foundation.init();
this.anchorElement = (_a = this._getHostElement().parentElement, (_a !== null && _a !== void 0 ? _a : this.anchorElement));
this._registerKeydownListener();
}
/**
* @protected
* @return {?}
*/
destroyMenuSurface() {
this._destroy.next();
this._destroy.complete();
this._deregisterWindowClickListener();
// add platform check due to use of cancelAnimationFrame inside destroy()
if (this.platform.isBrowser) {
this._foundation.destroy();
}
if (this.hoistToBody) {
(/** @type {?} */ (document.body)).removeChild(this._getHostElement());
}
}
/**
* Removes the menu-surface from it's current location and appends it to the
* body to overcome any overflow:hidden issues.
* @protected
* @return {?}
*/
setHoistToBody() {
if (!this.platform.isBrowser) {
return;
}
/** @type {?} */
const parentEl = this._getHostElement().parentElement;
if (parentEl) {
(/** @type {?} */ (document.body)).appendChild(parentEl.removeChild(this._getHostElement()));
this._foundation.setIsHoisted(true);
}
}
/**
* @private
* @return {?}
*/
_registerKeydownListener() {
fromEvent(this._getHostElement(), 'keydown')
.pipe(takeUntil(this._destroy))
.subscribe((/**
* @param {?} evt
* @return {?}
*/
evt => {
this._foundation.handleKeydown(evt);
this._open = this._foundation.isOpen();
}));
}
/**
* @private
* @return {?}
*/
_registerWindowClickListener() {
if (!this.platform.isBrowser) {
return;
}
this._windowClickSubscription =
this._ngZone.runOutsideAngular((/**
* @return {?}
*/
() => fromEvent(window, 'click')
.subscribe((/**
* @param {?} evt
* @return {?}
*/
evt => this._ngZone.run((/**
* @return {?}
*/
() => {
this._foundation.handleBodyClick(evt);
this._open = this._foundation.isOpen();
}))))));
}
/**
* @private
* @return {?}
*/
_deregisterWindowClickListener() {
var _a;
(_a = this._windowClickSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
}
/**
* Retrieves the DOM element of the component host.
* @protected
* @return {?}
*/
_getHostElement() {
return this.elementRef.nativeElement;
}
}
MdcMenuSurfaceBase.decorators = [
{ type: Directive },
];
/** @nocollapse */
MdcMenuSurfaceBase.ctorParameters = () => [
{ type: ChangeDetectorRef },
{ type: Platform },
{ type: NgZone, decorators: [{ type: Optional }] },
{ type: ElementRef }
];
MdcMenuSurfaceBase.propDecorators = {
open: [{ type: Input }],
anchorElement: [{ type: Input }],
anchorCorner: [{ type: Input }],
quickOpen: [{ type: Input }],
fixed: [{ type: Input }],
coordinates: [{ type: Input }],
anchorMargin: [{ type: Input }],
hoistToBody: [{ type: Input }],
opened: [{ type: Output }],
closed: [{ type: Output }]
};
/**
* @fileoverview added by tsickle
* Generated from: menu-surface/menu-surface.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class MdcMenuSurface extends MdcMenuSurfaceBase {
/**
* @return {?}
*/
ngOnInit() {
this.initMenuSurface();
}
/**
* @return {?}
*/
ngOnDestroy() {
this.destroyMenuSurface();
}
}
MdcMenuSurface.decorators = [
{ type: Component, args: [{selector: 'mdc-menu-surface',
exportAs: 'mdcMenuSurface',
host: { 'class': 'mdc-menu-surface' },
template: '<ng-content></ng-content>',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
},] },
];
/**
* @fileoverview added by tsickle
* Generated from: menu-surface/menu-surface-anchor.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class MdcMenuSurfaceAnchor {
/**
* @param {?} elementRef
*/
constructor(elementRef) {
this.elementRef = elementRef;
}
}
MdcMenuSurfaceAnchor.decorators = [
{ type: Directive, args: [{
selector: '[mdcMenuSurfaceAnchor], mdc-menu-surface-anchor',
host: { 'class': 'mdc-menu-surface--anchor' }
},] },
];
/** @nocollapse */
MdcMenuSurfaceAnchor.ctorParameters = () => [
{ type: ElementRef }
];
/**
* @fileoverview added by tsickle
* Generated from: menu-surface/module.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @type {?} */
const MENU_SURFACE_DECLARATIONS = [
MdcMenuSurface,
MdcMenuSurfaceAnchor
];
class MdcMenuSurfaceModule {
}
MdcMenuSurfaceModule.decorators = [
{ type: NgModule, args: [{
exports: [MENU_SURFACE_DECLARATIONS],
declarations: [MENU_SURFACE_DECLARATIONS]
},] },
];
export { MdcMenuSurface, MdcMenuSurfaceAnchor, MdcMenuSurfaceBase, MdcMenuSurfaceModule };
//# sourceMappingURL=menu-surface.js.map