UNPKG

@material-git/sidenav

Version:
486 lines (482 loc) 23.7 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/common'), require('@material-git/core')) : typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/common', '@material-git/core'], factory) : (factory((global.md = global.md || {}, global.md.sidenav = global.md.sidenav || {}),global.ng.core,global.ng.common,global.md.core)); }(this, (function (exports,_angular_core,_angular_common,_angular2Material_core) { 'use strict'; var __extends = (window && window.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var __decorate = (window && window.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (window && window.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (window && window.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; /** Exception thrown when two MdSidenav are matching the same side. */ var MdDuplicatedSidenavError = (function (_super) { __extends(MdDuplicatedSidenavError, _super); function MdDuplicatedSidenavError(align) { _super.call(this, "A sidenav was already declared for 'align=\"" + align + "\"'"); } return MdDuplicatedSidenavError; }(_angular2Material_core.MdError)); /** * <md-sidenav> component. * * This component corresponds to the drawer of the sidenav. * * Please refer to README.md for examples on how to use it. */ var MdSidenav = (function () { /** * @param _elementRef The DOM element reference. Used for transition and width calculation. * If not available we do not hook on transitions. */ function MdSidenav(_elementRef) { this._elementRef = _elementRef; /** Alignment of the sidenav (direction neutral); whether 'start' or 'end'. */ this.align = 'start'; /** Mode of the sidenav; whether 'over' or 'side'. */ this.mode = 'over'; /** Whether the sidenav is opened. */ this._opened = false; /** Event emitted when the sidenav is being opened. Use this to synchronize animations. */ this.onOpenStart = new _angular_core.EventEmitter(); /** Event emitted when the sidenav is fully opened. */ this.onOpen = new _angular_core.EventEmitter(); /** Event emitted when the sidenav is being closed. Use this to synchronize animations. */ this.onCloseStart = new _angular_core.EventEmitter(); /** Event emitted when the sidenav is fully closed. */ this.onClose = new _angular_core.EventEmitter(); this._transition = false; } Object.defineProperty(MdSidenav.prototype, "opened", { /** * Whether the sidenav is opened. We overload this because we trigger an event when it * starts or end. */ get: function () { return this._opened; }, set: function (v) { this.toggle(v); }, enumerable: true, configurable: true }); /** Open this sidenav, and return a Promise that will resolve when it's fully opened (or get * rejected if it didn't). */ MdSidenav.prototype.open = function () { return this.toggle(true); }; /** * Close this sidenav, and return a Promise that will resolve when it's fully closed (or get * rejected if it didn't). */ MdSidenav.prototype.close = function () { return this.toggle(false); }; /** * Toggle this sidenav. This is equivalent to calling open() when it's already opened, or * close() when it's closed. * @param isOpen */ MdSidenav.prototype.toggle = function (isOpen) { var _this = this; if (isOpen === void 0) { isOpen = !this.opened; } // Shortcut it if we're already opened. if (isOpen === this.opened) { if (!this._transition) { return Promise.resolve(null); } else { return isOpen ? this._openPromise : this._closePromise; } } this._opened = isOpen; this._transition = true; if (isOpen) { this.onOpenStart.emit(null); } else { this.onCloseStart.emit(null); } if (isOpen) { if (this._openPromise == null) { this._openPromise = new Promise(function (resolve, reject) { _this._openPromiseResolve = resolve; _this._openPromiseReject = reject; }); } return this._openPromise; } else { if (this._closePromise == null) { this._closePromise = new Promise(function (resolve, reject) { _this._closePromiseResolve = resolve; _this._closePromiseReject = reject; }); } return this._closePromise; } }; /** * When transition has finished, set the internal state for classes and emit the proper event. * The event passed is actually of type TransitionEvent, but that type is not available in * Android so we use any. */ MdSidenav.prototype._onTransitionEnd = function (transitionEvent) { if (transitionEvent.target == this._elementRef.nativeElement && transitionEvent.propertyName.endsWith('transform')) { this._transition = false; if (this._opened) { if (this._openPromise != null) { this._openPromiseResolve(); } if (this._closePromise != null) { this._closePromiseReject(); } this.onOpen.emit(null); } else { if (this._closePromise != null) { this._closePromiseResolve(); } if (this._openPromise != null) { this._openPromiseReject(); } this.onClose.emit(null); } this._openPromise = null; this._closePromise = null; } }; Object.defineProperty(MdSidenav.prototype, "_isClosing", { get: function () { return !this._opened && this._transition; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenav.prototype, "_isOpening", { get: function () { return this._opened && this._transition; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenav.prototype, "_isClosed", { get: function () { return !this._opened && !this._transition; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenav.prototype, "_isOpened", { get: function () { return this._opened && !this._transition; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenav.prototype, "_isEnd", { get: function () { return this.align == 'end'; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenav.prototype, "_modeSide", { get: function () { return this.mode == 'side'; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenav.prototype, "_modeOver", { get: function () { return this.mode == 'over'; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenav.prototype, "_modePush", { get: function () { return this.mode == 'push'; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenav.prototype, "_width", { /** TODO: internal (needed by MdSidenavLayout). */ get: function () { if (this._elementRef.nativeElement) { return this._elementRef.nativeElement.offsetWidth; } return 0; }, enumerable: true, configurable: true }); __decorate([ _angular_core.Input(), __metadata('design:type', Object) ], MdSidenav.prototype, "align", void 0); __decorate([ _angular_core.Input(), __metadata('design:type', Object) ], MdSidenav.prototype, "mode", void 0); __decorate([ _angular_core.Input('opened'), _angular2Material_core.BooleanFieldValue(), __metadata('design:type', Boolean) ], MdSidenav.prototype, "_opened", void 0); __decorate([ _angular_core.Output('open-start'), __metadata('design:type', Object) ], MdSidenav.prototype, "onOpenStart", void 0); __decorate([ _angular_core.Output('open'), __metadata('design:type', Object) ], MdSidenav.prototype, "onOpen", void 0); __decorate([ _angular_core.Output('close-start'), __metadata('design:type', Object) ], MdSidenav.prototype, "onCloseStart", void 0); __decorate([ _angular_core.Output('close'), __metadata('design:type', Object) ], MdSidenav.prototype, "onClose", void 0); __decorate([ _angular_core.HostBinding('class.md-sidenav-closing'), __metadata('design:type', Object) ], MdSidenav.prototype, "_isClosing", null); __decorate([ _angular_core.HostBinding('class.md-sidenav-opening'), __metadata('design:type', Object) ], MdSidenav.prototype, "_isOpening", null); __decorate([ _angular_core.HostBinding('class.md-sidenav-closed'), __metadata('design:type', Object) ], MdSidenav.prototype, "_isClosed", null); __decorate([ _angular_core.HostBinding('class.md-sidenav-opened'), __metadata('design:type', Object) ], MdSidenav.prototype, "_isOpened", null); __decorate([ _angular_core.HostBinding('class.md-sidenav-end'), __metadata('design:type', Object) ], MdSidenav.prototype, "_isEnd", null); __decorate([ _angular_core.HostBinding('class.md-sidenav-side'), __metadata('design:type', Object) ], MdSidenav.prototype, "_modeSide", null); __decorate([ _angular_core.HostBinding('class.md-sidenav-over'), __metadata('design:type', Object) ], MdSidenav.prototype, "_modeOver", null); __decorate([ _angular_core.HostBinding('class.md-sidenav-push'), __metadata('design:type', Object) ], MdSidenav.prototype, "_modePush", null); MdSidenav = __decorate([ _angular_core.Component({selector: 'md-sidenav', template: '<ng-content></ng-content>', host: { '(transitionend)': '_onTransitionEnd($event)', }, changeDetection: _angular_core.ChangeDetectionStrategy.OnPush, encapsulation: _angular_core.ViewEncapsulation.None, }), __metadata('design:paramtypes', [_angular_core.ElementRef]) ], MdSidenav); return MdSidenav; }()); /** * <md-sidenav-layout> component. * * This is the parent component to one or two <md-sidenav>s that validates the state internally * and coordinate the backdrop and content styling. */ var MdSidenavLayout = (function () { function MdSidenavLayout(_dir, _element, _renderer) { var _this = this; this._dir = _dir; this._element = _element; this._renderer = _renderer; // If a `Dir` directive exists up the tree, listen direction changes and update the left/right // properties to point to the proper start/end. if (_dir != null) { _dir.dirChange.subscribe(function () { return _this._validateDrawers(); }); } } Object.defineProperty(MdSidenavLayout.prototype, "start", { get: function () { return this._start; }, enumerable: true, configurable: true }); Object.defineProperty(MdSidenavLayout.prototype, "end", { get: function () { return this._end; }, enumerable: true, configurable: true }); /** TODO: internal */ MdSidenavLayout.prototype.ngAfterContentInit = function () { var _this = this; // On changes, assert on consistency. this._sidenavs.changes.subscribe(function () { return _this._validateDrawers(); }); this._sidenavs.forEach(function (sidenav) { return _this._watchSidenavToggle(sidenav); }); this._validateDrawers(); }; /* * Subscribes to sidenav events in order to set a class on the main layout element when the sidenav * is open and the backdrop is visible. This ensures any overflow on the layout element is properly * hidden. */ MdSidenavLayout.prototype._watchSidenavToggle = function (sidenav) { var _this = this; if (!sidenav || sidenav.mode === 'side') { return; } sidenav.onOpen.subscribe(function () { return _this._setLayoutClass(sidenav, true); }); sidenav.onClose.subscribe(function () { return _this._setLayoutClass(sidenav, false); }); }; /* Toggles the 'md-sidenav-opened' class on the main 'md-sidenav-layout' element. */ MdSidenavLayout.prototype._setLayoutClass = function (sidenav, bool) { this._renderer.setElementClass(this._element.nativeElement, 'md-sidenav-opened', bool); }; /** Validate the state of the sidenav children components. */ MdSidenavLayout.prototype._validateDrawers = function () { var _this = this; this._start = this._end = null; // Ensure that we have at most one start and one end sidenav. this._sidenavs.forEach(function (sidenav) { if (sidenav.align == 'end') { if (_this._end != null) { throw new MdDuplicatedSidenavError('end'); } _this._end = sidenav; } else { if (_this._start != null) { throw new MdDuplicatedSidenavError('start'); } _this._start = sidenav; } }); this._right = this._left = null; // Detect if we're LTR or RTL. if (this._dir == null || this._dir.value == 'ltr') { this._left = this._start; this._right = this._end; } else { this._left = this._end; this._right = this._start; } }; MdSidenavLayout.prototype._closeModalSidenav = function () { if (this._start != null && this._start.mode != 'side') { this._start.close(); } if (this._end != null && this._end.mode != 'side') { this._end.close(); } }; MdSidenavLayout.prototype._isShowingBackdrop = function () { return (this._isSidenavOpen(this._start) && this._start.mode != 'side') || (this._isSidenavOpen(this._end) && this._end.mode != 'side'); }; MdSidenavLayout.prototype._isSidenavOpen = function (side) { return side != null && side.opened; }; /** * Return the width of the sidenav, if it's in the proper mode and opened. * This may relayout the view, so do not call this often. * @param sidenav * @param mode */ MdSidenavLayout.prototype._getSidenavEffectiveWidth = function (sidenav, mode) { return (this._isSidenavOpen(sidenav) && sidenav.mode == mode) ? sidenav._width : 0; }; MdSidenavLayout.prototype._getMarginLeft = function () { return this._getSidenavEffectiveWidth(this._left, 'side'); }; MdSidenavLayout.prototype._getMarginRight = function () { return this._getSidenavEffectiveWidth(this._right, 'side'); }; MdSidenavLayout.prototype._getPositionLeft = function () { return this._getSidenavEffectiveWidth(this._left, 'push'); }; MdSidenavLayout.prototype._getPositionRight = function () { return this._getSidenavEffectiveWidth(this._right, 'push'); }; /** * Returns the horizontal offset for the content area. There should never be a value for both * left and right, so by subtracting the right value from the left value, we should always get * the appropriate offset. */ MdSidenavLayout.prototype._getPositionOffset = function () { return this._getPositionLeft() - this._getPositionRight(); }; /** * This is using [ngStyle] rather than separate [style...] properties because [style.transform] * doesn't seem to work right now. */ MdSidenavLayout.prototype._getStyles = function () { return { marginLeft: this._getMarginLeft() + "px", marginRight: this._getMarginRight() + "px", transform: "translate3d(" + this._getPositionOffset() + "px, 0, 0)" }; }; __decorate([ _angular_core.ContentChildren(MdSidenav), __metadata('design:type', _angular_core.QueryList) ], MdSidenavLayout.prototype, "_sidenavs", void 0); MdSidenavLayout = __decorate([ _angular_core.Component({selector: 'md-sidenav-layout', // Do not use ChangeDetectionStrategy.OnPush. It does not work for this component because // technically it is a sibling of MdSidenav (on the content tree) and isn't updated when MdSidenav // changes its state. template: "<div class=\"md-sidenav-backdrop\" (click)=\"_closeModalSidenav()\" [class.md-sidenav-shown]=\"_isShowingBackdrop()\"></div> <ng-content select=\"md-sidenav\"></ng-content> <div class=\"md-sidenav-content\" [ngStyle]=\"_getStyles()\"> <ng-content></ng-content> </div> ", styles: ["md-sidenav-layout { position: relative; transform: translate3d(0, 0, 0); box-sizing: border-box; -webkit-overflow-scrolling: touch; display: block; overflow: hidden; } md-sidenav-layout[fullscreen] { position: fixed; top: 0; left: 0; right: 0; bottom: 0; } md-sidenav-layout[fullscreen].md-sidenav-opened { overflow: hidden; } .md-sidenav-backdrop { position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: block; z-index: 2; visibility: hidden; } .md-sidenav-backdrop.md-sidenav-shown { visibility: visible; } .md-sidenav-content { position: relative; transform: translate3d(0, 0, 0); display: block; height: 100%; overflow: auto; } md-sidenav { position: relative; transform: translate3d(0, 0, 0); display: block; position: absolute; top: 0; bottom: 0; z-index: 3; min-width: 5%; overflow-y: auto; transform: translate3d(-100%, 0, 0); } md-sidenav.md-sidenav-closed { visibility: hidden; } md-sidenav.md-sidenav-closing { transform: translate3d(-100%, 0, 0); will-change: transform; } md-sidenav.md-sidenav-opening { box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); visibility: visible; transform: translate3d(0, 0, 0); will-change: transform; } md-sidenav.md-sidenav-opened { box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); transform: translate3d(0, 0, 0); } md-sidenav.md-sidenav-side { z-index: 1; } md-sidenav.md-sidenav-end { right: 0; transform: translate3d(100%, 0, 0); } md-sidenav.md-sidenav-end.md-sidenav-closed { visibility: hidden; } md-sidenav.md-sidenav-end.md-sidenav-closing { transform: translate3d(100%, 0, 0); will-change: transform; } md-sidenav.md-sidenav-end.md-sidenav-opening { box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); visibility: visible; transform: translate3d(0, 0, 0); will-change: transform; } md-sidenav.md-sidenav-end.md-sidenav-opened { box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); transform: translate3d(0, 0, 0); } [dir='rtl'] md-sidenav { transform: translate3d(100%, 0, 0); } [dir='rtl'] md-sidenav.md-sidenav-closed { visibility: hidden; } [dir='rtl'] md-sidenav.md-sidenav-closing { transform: translate3d(100%, 0, 0); will-change: transform; } [dir='rtl'] md-sidenav.md-sidenav-opening { box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); visibility: visible; transform: translate3d(0, 0, 0); will-change: transform; } [dir='rtl'] md-sidenav.md-sidenav-opened { box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); transform: translate3d(0, 0, 0); } [dir='rtl'] md-sidenav.md-sidenav-end { left: 0; right: auto; transform: translate3d(-100%, 0, 0); } [dir='rtl'] md-sidenav.md-sidenav-end.md-sidenav-closed { visibility: hidden; } [dir='rtl'] md-sidenav.md-sidenav-end.md-sidenav-closing { transform: translate3d(-100%, 0, 0); will-change: transform; } [dir='rtl'] md-sidenav.md-sidenav-end.md-sidenav-opening { box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); visibility: visible; transform: translate3d(0, 0, 0); will-change: transform; } [dir='rtl'] md-sidenav.md-sidenav-end.md-sidenav-opened { box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12); transform: translate3d(0, 0, 0); } /*# sourceMappingURL=sidenav.css.map */ ", "md-sidenav { transition: transform 400ms cubic-bezier(0.25, 0.8, 0.25, 1); } .md-sidenav-content { transition: transform 400ms cubic-bezier(0.25, 0.8, 0.25, 1); } .md-sidenav-backdrop.md-sidenav-shown { transition: background-color 400ms cubic-bezier(0.25, 0.8, 0.25, 1); } /*# sourceMappingURL=sidenav-transitions.css.map */ "], encapsulation: _angular_core.ViewEncapsulation.None, }), __param(0, _angular_core.Optional()), __metadata('design:paramtypes', [_angular2Material_core.Dir, _angular_core.ElementRef, _angular_core.Renderer]) ], MdSidenavLayout); return MdSidenavLayout; }()); var MdSidenavModule = (function () { function MdSidenavModule() { } MdSidenavModule.forRoot = function () { return { ngModule: MdSidenavModule, providers: [] }; }; MdSidenavModule = __decorate([ _angular_core.NgModule({ imports: [_angular_common.CommonModule], exports: [MdSidenavLayout, MdSidenav], declarations: [MdSidenavLayout, MdSidenav], }), __metadata('design:paramtypes', []) ], MdSidenavModule); return MdSidenavModule; }()); exports.MdDuplicatedSidenavError = MdDuplicatedSidenavError; exports.MdSidenav = MdSidenav; exports.MdSidenavLayout = MdSidenavLayout; exports.MdSidenavModule = MdSidenavModule; Object.defineProperty(exports, '__esModule', { value: true }); })));