UNPKG

@angular/flex-layout

Version:
1,263 lines (1,234 loc) 165 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/platform-browser'), require('rxjs/add/operator/map'), require('rxjs/add/operator/filter'), require('@angular/core'), require('rxjs/BehaviorSubject'), require('@angular/common')) : typeof define === 'function' && define.amd ? define(['exports', '@angular/platform-browser', 'rxjs/add/operator/map', 'rxjs/add/operator/filter', '@angular/core', 'rxjs/BehaviorSubject', '@angular/common'], factory) : (factory((global.ng = global.ng || {}, global.ng.flexLayout = global.ng.flexLayout || {}),global.ng.platformBrowser,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.ng.core,global.Rx,global.ng.common)); }(this, (function (exports,_angular_platformBrowser,rxjs_add_operator_map,rxjs_add_operator_filter,_angular_core,rxjs_BehaviorSubject,_angular_common) { 'use strict'; /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ /** Applies CSS prefixes to appropriate style keys.*/ function applyCssPrefixes(target) { for (var key in target) { var value = target[key]; switch (key) { case 'display': target['display'] = value; // also need 'display : -webkit-box' and 'display : -ms-flexbox;' break; case 'flex': target['-ms-flex'] = value; target['-webkit-box-flex'] = value.split(" ")[0]; break; case 'flex-direction': value = value || "row"; target['flex-direction'] = value; target['-ms-flex-direction'] = value; target['-webkit-box-orient'] = toBoxOrient(value); target['-webkit-box-direction'] = toBoxDirection(value); break; case 'flex-wrap': target['-ms-flex-wrap'] = value; break; case 'order': if (isNaN(value)) { value = "0"; } target['order'] = value; target['-ms-flex-order'] = value; target['-webkit-box-ordinal-group'] = toBoxOrdinal(value); break; case 'justify-content': target['-ms-flex-pack'] = toBoxValue(value); target['-webkit-box-pack'] = toBoxValue(value); break; case 'align-items': target['-ms-flex-align'] = toBoxValue(value); target['-webkit-box-align'] = toBoxValue(value); break; case 'align-self': target['-ms-flex-item-align'] = toBoxValue(value); break; case 'align-content': target['-ms-align-content'] = toAlignContentValue(value); target['-ms-flex-line-pack'] = toAlignContentValue(value); break; } } return target; } function toAlignContentValue(value) { switch (value) { case "space-between": return "justify"; case "space-around": return "distribute"; default: return toBoxValue(value); } } /** Convert flex values flex-start, flex-end to start, end. */ function toBoxValue(value) { if (value === void 0) { value = ""; } return (value == 'flex-start') ? 'start' : ((value == 'flex-end') ? 'end' : value); } /** Convert flex Direction to Box orientation */ function toBoxOrient(flexDirection) { if (flexDirection === void 0) { flexDirection = 'row'; } return flexDirection.indexOf('column') === -1 ? 'horizontal' : 'vertical'; } /** Convert flex Direction to Box direction type */ function toBoxDirection(flexDirection) { if (flexDirection === void 0) { flexDirection = 'row'; } return flexDirection.indexOf('reverse') !== -1 ? 'reverse' : 'normal'; } /** Convert flex order to Box ordinal group */ function toBoxOrdinal(order) { if (order === void 0) { order = '0'; } var value = order ? parseInt(order) + 1 : 1; return isNaN(value) ? "0" : value.toString(); } /** * @license * Copyright Google Inc. All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ /** * Extends an object with the *enumerable* and *own* properties of one or more source objects, * similar to Object.assign. * * @param dest The object which will have properties copied to it. * @param sources The source objects from which properties will be copied. */ function extendObject(dest) { var sources = []; for (var _i = 1; _i < arguments.length; _i++) { sources[_i - 1] = arguments[_i]; } if (dest == null) { throw TypeError('Cannot convert undefined or null to object'); } for (var _a = 0, sources_1 = sources; _a < sources_1.length; _a++) { var source = sources_1[_a]; if (source != null) { for (var key in source) { if (source.hasOwnProperty(key)) { dest[key] = source[key]; } } } } return dest; } var KeyOptions = (function () { function KeyOptions(baseKey, defaultValue, inputKeys) { this.baseKey = baseKey; this.defaultValue = defaultValue; this.inputKeys = inputKeys; } return KeyOptions; }()); /** * ResponsiveActivation acts as a proxy between the MonitorMedia service (which emits mediaQuery * changes) and the fx API directives. The MQA proxies mediaQuery change events and notifies the * directive via the specified callback. * * - The MQA also determines which directive property should be used to determine the * current change 'value'... BEFORE the original `onMediaQueryChanges()` method is called. * - The `ngOnDestroy()` method is also head-hooked to enable auto-unsubscribe from the * MediaQueryServices. * * NOTE: these interceptions enables the logic in the fx API directives to remain terse and clean. */ var ResponsiveActivation = (function () { /** * Constructor */ function ResponsiveActivation(_options, _mediaMonitor, _onMediaChanges) { this._options = _options; this._mediaMonitor = _mediaMonitor; this._onMediaChanges = _onMediaChanges; this._subscribers = []; this._subscribers = this._configureChangeObservers(); } Object.defineProperty(ResponsiveActivation.prototype, "mediaMonitor", { /** * Accessor to the DI'ed directive property * Each directive instance has a reference to the MediaMonitor which is * used HERE to subscribe to mediaQuery change notifications. */ get: function () { return this._mediaMonitor; }, enumerable: true, configurable: true }); Object.defineProperty(ResponsiveActivation.prototype, "activatedInputKey", { /** * Determine which directive @Input() property is currently active (for the viewport size): * The key must be defined (in use) or fallback to the 'closest' overlapping property key * that is defined; otherwise the default property key will be used. * e.g. * if `<div fxHide fxHide.gt-sm="false">` is used but the current activated mediaQuery alias * key is `.md` then `.gt-sm` should be used instead */ get: function () { return this._activatedInputKey || this._options.baseKey; }, enumerable: true, configurable: true }); Object.defineProperty(ResponsiveActivation.prototype, "activatedInput", { /** * Get the currently activated @Input value or the fallback default @Input value */ get: function () { var key = this.activatedInputKey; return this.hasKeyValue(key) ? this._lookupKeyValue(key) : this._options.defaultValue; }, enumerable: true, configurable: true }); /** * Fast validator for presence of attribute on the host element */ ResponsiveActivation.prototype.hasKeyValue = function (key) { var value = this._options.inputKeys[key]; return typeof value !== 'undefined'; }; /** * Remove interceptors, restore original functions, and forward the onDestroy() call */ ResponsiveActivation.prototype.destroy = function () { this._subscribers.forEach(function (link) { link.unsubscribe(); }); this._subscribers = []; }; /** * For each *defined* API property, register a callback to `_onMonitorEvents( )` * Cache 1..n subscriptions for internal auto-unsubscribes when the the directive destructs */ ResponsiveActivation.prototype._configureChangeObservers = function () { var _this = this; var subscriptions = []; this._buildRegistryMap().forEach(function (bp) { if (_this._keyInUse(bp.key)) { // Inject directive default property key name: to let onMediaChange() calls // know which property is being triggered... var buildChanges = function (change) { change.property = _this._options.baseKey; return change; }; subscriptions.push(_this.mediaMonitor.observe(bp.alias) .map(buildChanges) .subscribe(function (change) { _this._onMonitorEvents(change); })); } }); return subscriptions; }; /** * Build mediaQuery key-hashmap; only for the directive properties that are actually defined/used * in the HTML markup */ ResponsiveActivation.prototype._buildRegistryMap = function () { var _this = this; return this.mediaMonitor.breakpoints .map(function (bp) { return extendObject({}, bp, { baseKey: _this._options.baseKey, key: _this._options.baseKey + bp.suffix // e.g. layoutGtSm, layoutMd, layoutGtLg }); }) .filter(function (bp) { return _this._keyInUse(bp.key); }); }; /** * Synchronizes change notifications with the current mq-activated @Input and calculates the * mq-activated input value or the default value */ ResponsiveActivation.prototype._onMonitorEvents = function (change) { if (change.property == this._options.baseKey) { change.value = this._calculateActivatedValue(change); this._onMediaChanges(change); } }; /** * Has the key been specified in the HTML markup and thus is intended * to participate in activation processes. */ ResponsiveActivation.prototype._keyInUse = function (key) { return this._lookupKeyValue(key) !== undefined; }; /** * Map input key associated with mediaQuery activation to closest defined input key * then return the values associated with the targeted input property * * !! change events may arrive out-of-order (activate before deactivate) * so make sure the deactivate is used ONLY when the keys match * (since a different activate may be in use) */ ResponsiveActivation.prototype._calculateActivatedValue = function (current) { var currentKey = this._options.baseKey + current.suffix; // e.g. suffix == 'GtSm', var newKey = this._activatedInputKey; // e.g. newKey == hideGtSm newKey = current.matches ? currentKey : ((newKey == currentKey) ? null : newKey); this._activatedInputKey = this._validateInputKey(newKey); return this.activatedInput; }; /** * For the specified input property key, validate it is defined (used in the markup) * If not see if a overlapping mediaQuery-related input key fallback has been defined * * NOTE: scans in the order defined by activeOverLaps (largest viewport ranges -> smallest ranges) */ ResponsiveActivation.prototype._validateInputKey = function (inputKey) { var _this = this; var items = this.mediaMonitor.activeOverlaps; var isMissingKey = function (key) { return !_this._keyInUse(key); }; if (isMissingKey(inputKey)) { items.some(function (bp) { var key = _this._options.baseKey + bp.suffix; if (!isMissingKey(key)) { inputKey = key; return true; // exit .some() } return false; }); } return inputKey; }; /** * Get the value (if any) for the directive instances @Input property (aka key) */ ResponsiveActivation.prototype._lookupKeyValue = function (key) { return this._options.inputKeys[key]; }; return ResponsiveActivation; }()); var getDOM = _angular_platformBrowser.__platform_browser_private__.getDOM; /** Abstract base class for the Layout API styling directives. */ var BaseFxDirective = (function () { /** * */ function BaseFxDirective(_mediaMonitor, _elementRef, _renderer) { this._mediaMonitor = _mediaMonitor; this._elementRef = _elementRef; this._renderer = _renderer; /** * Dictionary of input keys with associated values */ this._inputMap = {}; this._display = this._getDisplayStyle(); } // ********************************************* // Accessor Methods // ********************************************* /** * Access the current value (if any) of the @Input property. */ BaseFxDirective.prototype._queryInput = function (key) { return this._inputMap[key]; }; // ********************************************* // Lifecycle Methods // ********************************************* BaseFxDirective.prototype.ngOnDestroy = function () { if (this._mqActivation) { this._mqActivation.destroy(); } this._mediaMonitor = null; }; // ********************************************* // Protected Methods // ********************************************* /** * Was the directive's default selector used ? * If not, use the fallback value! */ BaseFxDirective.prototype._getDefaultVal = function (key, fallbackVal) { var val = this._queryInput(key); var hasDefaultVal = (val !== undefined && val !== null); return (hasDefaultVal && val !== '') ? val : fallbackVal; }; /** * Quick accessor to the current HTMLElement's `display` style * Note: this allows use to preserve the original style * and optional restore it when the mediaQueries deactivate */ BaseFxDirective.prototype._getDisplayStyle = function (source) { var element = source || this._elementRef.nativeElement; var value = element.style['display'] || getDOM().getComputedStyle(element)['display']; return value.trim(); }; /** * Applies styles given via string pair or object map to the directive element. */ BaseFxDirective.prototype._applyStyleToElement = function (style, value, nativeElement) { var styles = {}; var element = nativeElement || this._elementRef.nativeElement; if (typeof style === 'string') { styles[style] = value; style = styles; } styles = applyCssPrefixes(style); // Iterate all properties in hashMap and set styles for (var key in styles) { this._renderer.setElementStyle(element, key, styles[key]); } }; /** * Applies styles given via string pair or object map to the directive element. */ BaseFxDirective.prototype._applyStyleToElements = function (style, elements) { var _this = this; var styles = applyCssPrefixes(style); elements.forEach(function (el) { // Iterate all properties in hashMap and set styles for (var key in styles) { _this._renderer.setElementStyle(el, key, styles[key]); } }); }; /** * Save the property value; which may be a complex object. * Complex objects support property chains */ BaseFxDirective.prototype._cacheInput = function (key, source) { if (typeof source === 'object') { for (var prop in source) { this._inputMap[prop] = source[prop]; } } else { this._inputMap[key] = source; } }; /** * Build a ResponsiveActivation object used to manage subscriptions to mediaChange notifications * and intelligent lookup of the directive's property value that corresponds to that mediaQuery * (or closest match). */ BaseFxDirective.prototype._listenForMediaQueryChanges = function (key, defaultValue, onMediaQueryChange) { var _this = this; var keyOptions = new KeyOptions(key, defaultValue, this._inputMap); return this._mqActivation = new ResponsiveActivation(keyOptions, this._mediaMonitor, function (change) { return onMediaQueryChange.call(_this, change); }); }; Object.defineProperty(BaseFxDirective.prototype, "childrenNodes", { /** * Special accessor to query for all child 'element' nodes regardless of type, class, etc. */ get: function () { var obj = this._elementRef.nativeElement.childNodes; var buffer = []; // iterate backwards ensuring that length is an UInt32 for (var i = obj.length; i--;) { buffer[i] = obj[i]; } return buffer; }, enumerable: true, configurable: true }); /** * Fast validator for presence of attribute on the host element */ BaseFxDirective.prototype.hasKeyValue = function (key) { return this._mqActivation.hasKeyValue(key); }; return BaseFxDirective; }()); var RESPONSIVE_ALIASES = [ 'xs', 'gt-xs', 'sm', 'gt-sm', 'md', 'gt-md', 'lg', 'gt-lg', 'xl' ]; var RAW_DEFAULTS = [ { alias: 'xs', suffix: 'Xs', overlapping: false, mediaQuery: 'screen and (max-width: 599px)' }, { alias: 'gt-xs', suffix: 'GtXs', overlapping: true, mediaQuery: 'screen and (min-width: 600px)' }, { alias: 'sm', suffix: 'Sm', overlapping: false, mediaQuery: 'screen and (min-width: 600px) and (max-width: 959px)' }, { alias: 'gt-sm', suffix: 'GtSm', overlapping: true, mediaQuery: 'screen and (min-width: 960px)' }, { alias: 'md', suffix: 'Md', overlapping: false, mediaQuery: 'screen and (min-width: 960px) and (max-width: 1279px)' }, { alias: 'gt-md', suffix: 'GtMd', overlapping: true, mediaQuery: 'screen and (min-width: 1280px)' }, { alias: 'lg', suffix: 'Lg', overlapping: false, mediaQuery: 'screen and (min-width: 1280px) and (max-width: 1919px)' }, { alias: 'gt-lg', suffix: 'GtLg', overlapping: true, mediaQuery: 'screen and (min-width: 1920px)' }, { alias: 'xl', suffix: 'Xl', overlapping: false, mediaQuery: 'screen and (min-width: 1920px) and (max-width: 5000px)' } ]; /** * Opaque Token unique to the flex-layout library. * Use this token when build a custom provider (see below). */ var BREAKPOINTS = new _angular_core.OpaqueToken('fxRawBreakpoints'); /** * Provider to return observable to ALL known BreakPoint(s) * Developers should build custom providers to override * this default BreakPointRegistry dataset provider * NOTE: !! custom breakpoints lists MUST contain the following aliases & suffixes: * [xs, gt-xs, sm, gt-sm, md, gt-md, lg, gt-lg, xl] */ var BreakPointsProvider = { provide: BREAKPOINTS, useValue: RAW_DEFAULTS }; var __decorate$2 = (this && this.__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$2 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; /** * Registry of 1..n MediaQuery breakpoint ranges * This is published as a provider and may be overriden from custom, application-specific ranges * */ var BreakPointRegistry = (function () { function BreakPointRegistry(_registry) { this._registry = _registry; } Object.defineProperty(BreakPointRegistry.prototype, "items", { /** * Accessor to raw list */ get: function () { return this._registry.slice(); }, enumerable: true, configurable: true }); /** * Search breakpoints by alias (e.g. gt-xs) */ BreakPointRegistry.prototype.findByAlias = function (alias) { return this._registry.find(function (bp) { return bp.alias == alias; }); }; BreakPointRegistry.prototype.findByQuery = function (query) { return this._registry.find(function (bp) { return bp.mediaQuery == query; }); }; Object.defineProperty(BreakPointRegistry.prototype, "overlappings", { /** * Get all the breakpoints whose ranges could overlapping `normal` ranges; * e.g. gt-sm overlaps md, lg, and xl */ get: function () { return this._registry.filter(function (it) { return it.overlapping == true; }); }, enumerable: true, configurable: true }); Object.defineProperty(BreakPointRegistry.prototype, "aliases", { /** * Get list of all registered (non-empty) breakpoint aliases */ get: function () { return this._registry.map(function (it) { return it.alias; }); }, enumerable: true, configurable: true }); Object.defineProperty(BreakPointRegistry.prototype, "suffixes", { /** * Aliases are mapped to properties using suffixes * e.g. 'gt-sm' for property 'layout' uses suffix 'GtSm' * for property layoutGtSM. */ get: function () { return this._registry.map(function (it) { return it.suffix; }); }, enumerable: true, configurable: true }); BreakPointRegistry = __decorate$2([ _angular_core.Injectable(), __param(0, _angular_core.Inject(BREAKPOINTS)), __metadata$2('design:paramtypes', [Array]) ], BreakPointRegistry); return BreakPointRegistry; }()); /** * Class instances emitted [to observers] for each mql notification */ var MediaChange = (function () { function MediaChange(matches, // Is the mq currently activated mediaQuery, // e.g. (min-width: 600px) and (max-width: 959px) mqAlias, // e.g. gt-sm, md, gt-lg suffix // e.g. GtSM, Md, GtLg ) { if (matches === void 0) { matches = false; } if (mediaQuery === void 0) { mediaQuery = 'all'; } if (mqAlias === void 0) { mqAlias = ''; } if (suffix === void 0) { suffix = ''; } this.matches = matches; this.mediaQuery = mediaQuery; this.mqAlias = mqAlias; this.suffix = suffix; } return MediaChange; }()); var __decorate$3 = (this && this.__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$3 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** * MediaMonitor configures listeners to mediaQuery changes and publishes an Observable facade to * convert mediaQuery change callbacks to subscriber notifications. These notifications will be * performed within the ng Zone to trigger change detections and component updates. * * NOTE: both mediaQuery activations and de-activations are announced in notifications */ var MatchMedia = (function () { function MatchMedia(_zone) { this._zone = _zone; this._registry = new Map(); this._source = new rxjs_BehaviorSubject.BehaviorSubject(new MediaChange(true)); this._observable$ = this._source.asObservable(); } /** * For the specified mediaQuery? */ MatchMedia.prototype.isActive = function (mediaQuery) { if (this._registry.has(mediaQuery)) { var mql = this._registry.get(mediaQuery); return mql.matches; } return false; }; /** * External observers can watch for all (or a specific) mql changes. * Typically used by the MediaQueryAdaptor; optionally available to components * who wish to use the MediaMonitor as mediaMonitor$ observable service. * * NOTE: if a mediaQuery is not specified, then ALL mediaQuery activations will * be announced. */ MatchMedia.prototype.observe = function (mediaQuery) { this.registerQuery(mediaQuery); return this._observable$.filter(function (change) { return mediaQuery ? (change.mediaQuery === mediaQuery) : true; }); }; /** * Based on the BreakPointRegistry provider, register internal listeners for each unique * mediaQuery. Each listener emits specific MediaChange data to observers */ MatchMedia.prototype.registerQuery = function (mediaQuery) { var _this = this; if (mediaQuery) { var mql = this._registry.get(mediaQuery); var onMQLEvent = function (e) { _this._zone.run(function () { var change = new MediaChange(e.matches, mediaQuery); _this._source.next(change); }); }; if (!mql) { mql = this._buildMQL(mediaQuery); mql.addListener(onMQLEvent); this._registry.set(mediaQuery, mql); } if (mql.matches) { onMQLEvent(mql); // Announce activate range for initial subscribers } } }; /** * Call window.matchMedia() to build a MediaQueryList; which * supports 0..n listeners for activation/deactivation */ MatchMedia.prototype._buildMQL = function (query) { prepareQueryCSS(query); var canListen = !!window.matchMedia('all').addListener; return canListen ? window.matchMedia(query) : { matches: query === 'all' || query === '', media: query, addListener: function () { }, removeListener: function () { } }; }; MatchMedia = __decorate$3([ _angular_core.Injectable(), __metadata$3('design:paramtypes', [_angular_core.NgZone]) ], MatchMedia); return MatchMedia; }()); /** * Private global registry for all dynamically-created, injected style tags * @see prepare(query) */ var ALL_STYLES = {}; /** * For Webkit engines that only trigger the MediaQueryListListener * when there is at least one CSS selector for the respective media query. * * @param query string The mediaQuery used to create a faux CSS selector * */ function prepareQueryCSS(query) { if (!ALL_STYLES[query]) { try { var style = document.createElement('style'); style.setAttribute('type', 'text/css'); if (!style['styleSheet']) { var cssText = "@media " + query + " {.fx-query-test{ }}"; style.appendChild(document.createTextNode(cssText)); } document.getElementsByTagName('head')[0].appendChild(style); // Store in private global registry ALL_STYLES[query] = style; } catch (e) { console.error(e); } } } /** * For the specified MediaChange, make sure it contains the breakpoint alias * and suffix (if available). */ function mergeAlias(dest, source) { return extendObject(dest, source ? { mqAlias: source.alias, suffix: source.suffix } : {}); } var __decorate$1 = (this && this.__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$1 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** * MediaMonitor uses the MatchMedia service to observe mediaQuery changes (both activations and * deactivations). These changes are are published as MediaChange notifications. * * Note: all notifications will be performed within the * ng Zone to trigger change detections and component updates. * * It is the MediaMonitor that: * - auto registers all known breakpoints * - injects alias information into each raw MediaChange event * - provides accessor to the currently active BreakPoint * - publish list of overlapping BreakPoint(s); used by ResponsiveActivation */ var MediaMonitor = (function () { function MediaMonitor(_breakpoints, _matchMedia) { this._breakpoints = _breakpoints; this._matchMedia = _matchMedia; this._registerBreakpoints(); } Object.defineProperty(MediaMonitor.prototype, "breakpoints", { /** * Read-only accessor to the list of breakpoints configured in the BreakPointRegistry provider */ get: function () { return this._breakpoints.items.slice(); }, enumerable: true, configurable: true }); Object.defineProperty(MediaMonitor.prototype, "activeOverlaps", { get: function () { var _this = this; var items = this._breakpoints.overlappings.reverse(); return items.filter(function (bp) { return _this._matchMedia.isActive(bp.mediaQuery); }); }, enumerable: true, configurable: true }); Object.defineProperty(MediaMonitor.prototype, "active", { get: function () { var _this = this; var found = null, items = this.breakpoints.reverse(); items.forEach(function (bp) { if (bp.alias !== '') { if (!found && _this._matchMedia.isActive(bp.mediaQuery)) { found = bp; } } }); var first = this.breakpoints[0]; return found || (this._matchMedia.isActive(first.mediaQuery) ? first : null); }, enumerable: true, configurable: true }); /** * For the specified mediaQuery alias, is the mediaQuery range active? */ MediaMonitor.prototype.isActive = function (alias) { var bp = this._breakpoints.findByAlias(alias) || this._breakpoints.findByQuery(alias); return this._matchMedia.isActive(bp ? bp.mediaQuery : alias); }; /** * External observers can watch for all (or a specific) mql changes. * If specific breakpoint is observed, only return *activated* events * otherwise return all events for BOTH activated + deactivated changes. */ MediaMonitor.prototype.observe = function (alias) { var bp = this._breakpoints.findByAlias(alias) || this._breakpoints.findByQuery(alias); var hasAlias = function (change) { return (bp ? change.mqAlias !== "" : true); }; // Note: the raw MediaChange events [from MatchMedia] do not contain important alias information return this._matchMedia .observe(bp ? bp.mediaQuery : alias) .map(function (change) { return mergeAlias(change, bp); }) .filter(hasAlias); }; /** * Immediate calls to matchMedia() to establish listeners * and prepare for immediate subscription notifications */ MediaMonitor.prototype._registerBreakpoints = function () { var _this = this; this._breakpoints.items.forEach(function (bp) { _this._matchMedia.registerQuery(bp.mediaQuery); }); }; MediaMonitor = __decorate$1([ _angular_core.Injectable(), __metadata$1('design:paramtypes', [BreakPointRegistry, MatchMedia]) ], MediaMonitor); return MediaMonitor; }()); var __decorate$5 = (this && this.__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$5 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** * Base class for MediaService and pseudo-token for */ var ObservableMedia = (function () { function ObservableMedia() { } return ObservableMedia; }()); /** * Class internalizes a MatchMedia service and exposes an Subscribable and Observable interface. * This an Observable with that exposes a feature to subscribe to mediaQuery * changes and a validator method (`isActive(<alias>)`) to test if a mediaQuery (or alias) is * currently active. * * !! Only mediaChange activations (not de-activations) are announced by the ObservableMedia * * This class uses the BreakPoint Registry to inject alias information into the raw MediaChange * notification. For custom mediaQuery notifications, alias information will not be injected and * those fields will be ''. * * !! This is not an actual Observable. It is a wrapper of an Observable used to publish additional * methods like `isActive(<alias>). To access the Observable and use RxJS operators, use * `.asObservable()` with syntax like media.asObservable().map(....). * * @usage * * // RxJS * import 'rxjs/add/operator/filter'; * import { ObservableMedia } from '@angular/flex-layout'; * * @Component({ ... }) * export class AppComponent { * status : string = ''; * * constructor( media:ObservableMedia ) { * let onChange = (change:MediaChange) => { * this.status = change ? `'${change.mqAlias}' = (${change.mediaQuery})` : ""; * }; * * // Subscribe directly or access observable to use filter/map operators * // e.g. * // media.subscribe(onChange); * * media.asObservable() * .filter((change:MediaChange) => true) // silly noop filter * .subscribe(onChange); * } * } */ var MediaService = (function () { function MediaService(mediaWatcher, breakpoints) { this.mediaWatcher = mediaWatcher; this.breakpoints = breakpoints; this._registerBreakPoints(); this.observable$ = this._buildObservable(); } /** * Test if specified query/alias is active. */ MediaService.prototype.isActive = function (alias) { var query = this._toMediaQuery(alias); return this.mediaWatcher.isActive(query); }; /** * Proxy to the Observable subscribe method */ MediaService.prototype.subscribe = function (next, error, complete) { return this.observable$.subscribe(next, error, complete); }; /** * Access to observable for use with operators like * .filter(), .map(), etc. */ MediaService.prototype.asObservable = function () { return this.observable$; }; // ************************************************ // Internal Methods // ************************************************ /** * Register all the mediaQueries registered in the BreakPointRegistry * This is needed so subscribers can be auto-notified of all standard, registered * mediaQuery activations */ MediaService.prototype._registerBreakPoints = function () { var _this = this; this.breakpoints.items.forEach(function (bp) { _this.mediaWatcher.registerQuery(bp.mediaQuery); return bp; }); }; /** * Prepare internal observable * NOTE: the raw MediaChange events [from MatchMedia] do not contain important alias information * these must be injected into the MediaChange */ MediaService.prototype._buildObservable = function () { var _this = this; return this.mediaWatcher.observe() .filter(function (change) { // Only pass/announce activations (not de-activations) return change.matches === true; }) .map(function (change) { // Inject associated (if any) alias information into the MediaChange event return mergeAlias(change, _this._findByQuery(change.mediaQuery)); }); }; /** * Breakpoint locator by alias */ MediaService.prototype._findByAlias = function (alias) { return this.breakpoints.findByAlias(alias); }; /** * Breakpoint locator by mediaQuery */ MediaService.prototype._findByQuery = function (query) { return this.breakpoints.findByQuery(query); }; /** * Find associated breakpoint (if any) */ MediaService.prototype._toMediaQuery = function (query) { var bp = this._findByAlias(query) || this._findByQuery(query); return bp ? bp.mediaQuery : query; }; MediaService = __decorate$5([ _angular_core.Injectable(), __metadata$5('design:paramtypes', [MatchMedia, BreakPointRegistry]) ], MediaService); return MediaService; }()); /** * Provider to return observable to ALL MediaQuery events * Developers should build custom providers to override this default MediaQuery Observable */ var ObservableMediaProvider = { provide: ObservableMedia, useClass: MediaService, deps: [MatchMedia, BreakPointRegistry] }; var __decorate$4 = (this && this.__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$4 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** * ***************************************************************** * Define module for the MediaQuery API * ***************************************************************** */ var MediaQueriesModule = (function () { function MediaQueriesModule() { } MediaQueriesModule = __decorate$4([ _angular_core.NgModule({ providers: [ MatchMedia, BreakPointsProvider, BreakPointRegistry, MediaMonitor, ObservableMediaProvider // easy subscription injectable `media$` matchMedia observable ] }), __metadata$4('design:paramtypes', []) ], MediaQueriesModule); return MediaQueriesModule; }()); var __extends$1 = (this && this.__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$7 = (this && this.__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$7 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var LAYOUT_VALUES = ['row', 'column', 'row-reverse', 'column-reverse']; /** * 'layout' flexbox styling directive * Defines the positioning flow direction for the child elements: row or column * Optional values: column or row (default) * @see https://css-tricks.com/almanac/properties/f/flex-direction/ * */ var LayoutDirective = (function (_super) { __extends$1(LayoutDirective, _super); /** * */ function LayoutDirective(monitor, elRef, renderer) { _super.call(this, monitor, elRef, renderer); this._announcer = new rxjs_BehaviorSubject.BehaviorSubject("row"); this.layout$ = this._announcer.asObservable(); } Object.defineProperty(LayoutDirective.prototype, "layout", { set: function (val) { this._cacheInput("layout", val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutXs", { set: function (val) { this._cacheInput('layoutXs', val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutGtXs", { set: function (val) { this._cacheInput('layoutGtXs', val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutSm", { set: function (val) { this._cacheInput('layoutSm', val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutGtSm", { set: function (val) { this._cacheInput('layoutGtSm', val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutMd", { set: function (val) { this._cacheInput('layoutMd', val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutGtMd", { set: function (val) { this._cacheInput('layoutGtMd', val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutLg", { set: function (val) { this._cacheInput('layoutLg', val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutGtLg", { set: function (val) { this._cacheInput('layoutGtLg', val); }, enumerable: true, configurable: true }); Object.defineProperty(LayoutDirective.prototype, "layoutXl", { set: function (val) { this._cacheInput('layoutXl', val); }, enumerable: true, configurable: true }); // ********************************************* // Lifecycle Methods // ********************************************* /** * On changes to any @Input properties... * Default to use the non-responsive Input value ('fxLayout') * Then conditionally override with the mq-activated Input's current value */ LayoutDirective.prototype.ngOnChanges = function (changes) { if (changes['layout'] != null || this._mqActivation) { this._updateWithDirection(); } }; /** * After the initial onChanges, build an mqActivation object that bridges * mql change events to onMediaQueryChange handlers */ LayoutDirective.prototype.ngOnInit = function () { var _this = this; this._listenForMediaQueryChanges('layout', 'row', function (changes) { _this._updateWithDirection(changes.value); }); this._updateWithDirection(); }; // ********************************************* // Protected methods // ********************************************* /** * Validate the direction value and then update the host's inline flexbox styles */ LayoutDirective.prototype._updateWithDirection = function (direction) { direction = direction || this._queryInput("layout") || 'row'; if (this._mqActivation) { direction = this._mqActivation.activatedInput; } direction = this._validateValue(direction); // Update styles and announce to subscribers the *new* direction this._applyStyleToElement(this._buildCSS(direction)); this._announcer.next(direction); }; /** * Build the CSS that should be assigned to the element instance * BUG: * * 1) min-height on a column flex container won’t apply to its flex item children in IE 10-11. * Use height instead if possible; height : <xxx>vh; * * @todo - update all child containers to have "box-sizing: border-box" * This way any padding or border specified on the child elements are * laid out and drawn inside that element's specified width and height. * */ LayoutDirective.prototype._buildCSS = function (value) { return { 'display': 'flex', 'box-sizing': 'border-box', 'flex-direction': value }; }; /** * Validate the value to be one of the acceptable value options * Use default fallback of "row" */ LayoutDirective.prototype._validateValue = function (value) { value = value ? value.toLowerCase() : ''; return LAYOUT_VALUES.find(function (x) { return x === value; }) ? value : LAYOUT_VALUES[0]; // "row" }; __decorate$7([ _angular_core.Input('fxLayout'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layout", null); __decorate$7([ _angular_core.Input('fxLayout.xs'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layoutXs", null); __decorate$7([ _angular_core.Input('fxLayout.gt-xs'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layoutGtXs", null); __decorate$7([ _angular_core.Input('fxLayout.sm'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layoutSm", null); __decorate$7([ _angular_core.Input('fxLayout.gt-sm'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layoutGtSm", null); __decorate$7([ _angular_core.Input('fxLayout.md'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layoutMd", null); __decorate$7([ _angular_core.Input('fxLayout.gt-md'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layoutGtMd", null); __decorate$7([ _angular_core.Input('fxLayout.lg'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layoutLg", null); __decorate$7([ _angular_core.Input('fxLayout.gt-lg'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDirective.prototype, "layoutGtLg", null); __decorate$7([ _angular_core.Input('fxLayout.xl'), __metadata$7('design:type', Object), __metadata$7('design:paramtypes', [Object]) ], LayoutDi