diff --git a/src/lib/api/core/base-adapter.spec.ts b/src/lib/api/core/base-adapter.spec.ts index c675e5d76..c68a1ec72 100644 --- a/src/lib/api/core/base-adapter.spec.ts +++ b/src/lib/api/core/base-adapter.spec.ts @@ -9,12 +9,12 @@ import {ElementRef} from '@angular/core'; import {BaseFxDirectiveAdapter} from './base-adapter'; import {expect} from '../../utils/testing/custom-matchers'; import {MediaMonitor} from '../../media-query/media-monitor'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; describe('BaseFxDirectiveAdapter class', () => { let component; beforeEach(() => { - component = new BaseFxDirectiveAdapter('', {} as MediaMonitor, {} as ElementRef, {} as StyleService); // tslint:disable-line:max-line-length + component = new BaseFxDirectiveAdapter('', {} as MediaMonitor, {} as ElementRef, {} as StyleUtils); // tslint:disable-line:max-line-length }); describe('cacheInput', () => { it('should call _cacheInputArray when source is an array', () => { diff --git a/src/lib/api/core/base-adapter.ts b/src/lib/api/core/base-adapter.ts index 2d78721d7..885b0173f 100644 --- a/src/lib/api/core/base-adapter.ts +++ b/src/lib/api/core/base-adapter.ts @@ -11,7 +11,7 @@ import {BaseFxDirective} from './base'; import {ResponsiveActivation} from './responsive-activation'; import {MediaQuerySubscriber} from '../../media-query/media-change'; import {MediaMonitor} from '../../media-query/media-monitor'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** @@ -49,7 +49,7 @@ export class BaseFxDirectiveAdapter extends BaseFxDirective { constructor(protected _baseKey: string, // non-responsive @Input property name protected _mediaMonitor: MediaMonitor, protected _elementRef: ElementRef, - protected _styler: StyleService) { + protected _styler: StyleUtils) { super(_mediaMonitor, _elementRef, _styler); } diff --git a/src/lib/api/core/base.ts b/src/lib/api/core/base.ts index 68c77a66f..439f4ad88 100644 --- a/src/lib/api/core/base.ts +++ b/src/lib/api/core/base.ts @@ -16,8 +16,8 @@ import { import {buildLayoutCSS} from '../../utils/layout-validator'; import { StyleDefinition, - StyleService, -} from '../../utils/styling/styler'; + StyleUtils, +} from '../../utils/styling/style-utils'; import {ResponsiveActivation, KeyOptions} from '../core/responsive-activation'; import {MediaMonitor} from '../../media-query/media-monitor'; @@ -63,7 +63,7 @@ export abstract class BaseFxDirective implements OnDestroy, OnChanges { */ constructor(protected _mediaMonitor: MediaMonitor, protected _elementRef: ElementRef, - protected _styler: StyleService) { + protected _styler: StyleUtils) { } // ********************************************* diff --git a/src/lib/api/ext/class.spec.ts b/src/lib/api/ext/class.spec.ts index c28228aaf..62b6c2cad 100644 --- a/src/lib/api/ext/class.spec.ts +++ b/src/lib/api/ext/class.spec.ts @@ -22,7 +22,7 @@ import {BreakPointRegistry} from '../../media-query/breakpoints/break-point-regi import {ClassDirective} from './class'; import {MediaQueriesModule} from '../../media-query/_module'; import {ServerStylesheet} from '../../utils/styling/server-stylesheet'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; describe('class directive', () => { let fixture: ComponentFixture; @@ -52,7 +52,7 @@ describe('class directive', () => { BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, ServerStylesheet, - StyleService, + StyleUtils, ] }); }); diff --git a/src/lib/api/ext/class.ts b/src/lib/api/ext/class.ts index 4f5605eb2..8611285c9 100644 --- a/src/lib/api/ext/class.ts +++ b/src/lib/api/ext/class.ts @@ -27,7 +27,7 @@ import {BaseFxDirectiveAdapter} from '../core/base-adapter'; import {MediaChange} from '../../media-query/media-change'; import {MediaMonitor} from '../../media-query/media-monitor'; import {RendererAdapter} from '../core/renderer-adapter'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** NgClass allowed inputs **/ export type NgClassType = string | string[] | Set | {[klass: string]: any}; @@ -94,7 +94,7 @@ export class ClassDirective extends BaseFxDirective protected _ngEl: ElementRef, protected _renderer: Renderer2, @Optional() @Self() private _ngClassInstance: NgClass, - protected _styler: StyleService) { + protected _styler: StyleUtils) { super(monitor, _ngEl, _styler); this._configureAdapters(); } diff --git a/src/lib/api/ext/hide.spec.ts b/src/lib/api/ext/hide.spec.ts index e421aed18..fa9f8bd6c 100644 --- a/src/lib/api/ext/hide.spec.ts +++ b/src/lib/api/ext/hide.spec.ts @@ -23,19 +23,19 @@ import {ShowHideDirective} from './show-hide'; import {MediaQueriesModule} from '../../media-query/_module'; import {ServerStylesheet} from '../../utils/styling/server-stylesheet'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; describe('hide directive', () => { let fixture: ComponentFixture; let matchMedia: MockMatchMedia; - let styler: StyleService; + let styler: StyleUtils; let platformId: Object; let createTestComponent = (template: string) => { fixture = makeCreateTestComponent(() => TestHideComponent)(template); - inject([MatchMedia, StyleService, PLATFORM_ID], - (_matchMedia: MockMatchMedia, _styler: StyleService, _platformId: Object) => { + inject([MatchMedia, StyleUtils, PLATFORM_ID], + (_matchMedia: MockMatchMedia, _styler: StyleUtils, _platformId: Object) => { matchMedia = _matchMedia; styler = _styler; platformId = _platformId; @@ -69,7 +69,7 @@ describe('hide directive', () => { BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, ServerStylesheet, - StyleService, + StyleUtils, {provide: SERVER_TOKEN, useValue: true}, ] }); diff --git a/src/lib/api/ext/img-src.spec.ts b/src/lib/api/ext/img-src.spec.ts index 25f4bf284..b6f031daf 100644 --- a/src/lib/api/ext/img-src.spec.ts +++ b/src/lib/api/ext/img-src.spec.ts @@ -20,7 +20,7 @@ import {expectEl, makeCreateTestComponent, queryFor} from '../../utils/testing/h import {expect} from '../../utils/testing/custom-matchers'; import {_dom as _} from '../../utils/testing/dom-tools'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; const SRC_URLS = { 'xs': [ @@ -54,13 +54,13 @@ describe('img-src directive', () => { let fixture: ComponentFixture; let matchMedia: MockMatchMedia; let platformId: Object; - let styler: StyleService; + let styler: StyleUtils; let componentWithTemplate = (template: string) => { fixture = makeCreateTestComponent(() => TestSrcComponent)(template); - inject([MatchMedia, PLATFORM_ID, StyleService], - (_matchMedia: MockMatchMedia, _platformId: Object, _styler: StyleService) => { + inject([MatchMedia, PLATFORM_ID, StyleUtils], + (_matchMedia: MockMatchMedia, _platformId: Object, _styler: StyleUtils) => { matchMedia = _matchMedia; platformId = _platformId; styler = _styler; diff --git a/src/lib/api/ext/img-src.ts b/src/lib/api/ext/img-src.ts index 305104ae0..a3deefcc1 100644 --- a/src/lib/api/ext/img-src.ts +++ b/src/lib/api/ext/img-src.ts @@ -19,7 +19,7 @@ import {isPlatformServer} from '@angular/common'; import {BaseFxDirective} from '../core/base'; import {MediaMonitor} from '../../media-query/media-monitor'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; /** @@ -62,7 +62,7 @@ export class ImgSrcDirective extends BaseFxDirective implements OnInit, OnChange constructor(protected _elRef: ElementRef, protected _monitor: MediaMonitor, - protected _styler: StyleService, + protected _styler: StyleUtils, @Inject(PLATFORM_ID) protected _platformId: Object, @Optional() @Inject(SERVER_TOKEN) protected _serverModuleLoaded: boolean) { super(_monitor, _elRef, _styler); @@ -108,7 +108,7 @@ export class ImgSrcDirective extends BaseFxDirective implements OnInit, OnChange if (this.hasResponsiveKeys) { let url = this.activatedValue || this.defaultSrc; if (isPlatformServer(this._platformId) && this._serverModuleLoaded) { - this._styler.applyStyleToElement(this.nativeElement, 'content', url ? `url(${url})` : ''); + this._styler.applyStyleToElement(this.nativeElement, {'content': url ? `url(${url})` : ''}); } else { this.nativeElement.setAttribute('src', String(url)); } diff --git a/src/lib/api/ext/show-hide.ts b/src/lib/api/ext/show-hide.ts index fe57cb005..71d1692a9 100644 --- a/src/lib/api/ext/show-hide.ts +++ b/src/lib/api/ext/show-hide.ts @@ -25,7 +25,7 @@ import {BaseFxDirective} from '../core/base'; import {MediaChange} from '../../media-query/media-change'; import {MediaMonitor} from '../../media-query/media-monitor'; import {LayoutDirective} from '../flexbox/layout'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; const FALSY = ['false', false, 0]; @@ -107,7 +107,7 @@ export class ShowHideDirective extends BaseFxDirective implements OnInit, OnChan constructor(monitor: MediaMonitor, @Optional() @Self() protected layout: LayoutDirective, protected elRef: ElementRef, - protected styleUtils: StyleService, + protected styleUtils: StyleUtils, @Inject(PLATFORM_ID) protected platformId: Object, @Optional() @Inject(SERVER_TOKEN) protected serverModuleLoaded: boolean) { diff --git a/src/lib/api/ext/show.spec.ts b/src/lib/api/ext/show.spec.ts index 805621745..d8c63033b 100644 --- a/src/lib/api/ext/show.spec.ts +++ b/src/lib/api/ext/show.spec.ts @@ -19,19 +19,19 @@ import {FlexLayoutModule} from '../../module'; import {customMatchers} from '../../utils/testing/custom-matchers'; import {makeCreateTestComponent, expectNativeEl} from '../../utils/testing/helpers'; import {ServerStylesheet} from '../../utils/styling/server-stylesheet'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; describe('show directive', () => { let fixture: ComponentFixture; let matchMedia: MockMatchMedia; - let styler: StyleService; + let styler: StyleUtils; let platformId: Object; let createTestComponent = (template) => { fixture = makeCreateTestComponent(() => TestShowComponent)(template); - inject([MatchMedia, StyleService, PLATFORM_ID], - (_matchMedia: MockMatchMedia, _styler: StyleService, _platformId: Object) => { + inject([MatchMedia, StyleUtils, PLATFORM_ID], + (_matchMedia: MockMatchMedia, _styler: StyleUtils, _platformId: Object) => { matchMedia = _matchMedia; styler = _styler; platformId = _platformId; @@ -49,7 +49,7 @@ describe('show directive', () => { BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, ServerStylesheet, - StyleService, + StyleUtils, {provide: SERVER_TOKEN, useValue: true} ] }); diff --git a/src/lib/api/ext/style.spec.ts b/src/lib/api/ext/style.spec.ts index 1a2f4f996..4dcdb60b8 100644 --- a/src/lib/api/ext/style.spec.ts +++ b/src/lib/api/ext/style.spec.ts @@ -23,16 +23,16 @@ import { makeCreateTestComponent, expectNativeEl } from '../../utils/testing/helpers'; import {ServerStylesheet} from '../../utils/styling/server-stylesheet'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; describe('style directive', () => { let fixture: ComponentFixture; let matchMedia: MockMatchMedia; - let styler: StyleService; + let styler: StyleUtils; let createTestComponent = (template) => { fixture = makeCreateTestComponent(() => TestStyleComponent)(template); - inject([MatchMedia, StyleService], (_matchMedia: MockMatchMedia, _styler: StyleService) => { + inject([MatchMedia, StyleUtils], (_matchMedia: MockMatchMedia, _styler: StyleUtils) => { matchMedia = _matchMedia; styler = _styler; })(); @@ -49,7 +49,7 @@ describe('style directive', () => { BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, ServerStylesheet, - StyleService, + StyleUtils, ] }); }); diff --git a/src/lib/api/ext/style.ts b/src/lib/api/ext/style.ts index c47926d26..d1c3d585d 100644 --- a/src/lib/api/ext/style.ts +++ b/src/lib/api/ext/style.ts @@ -36,7 +36,7 @@ import { ngStyleUtils as _ } from '../../utils/styling/style-transforms'; import {RendererAdapter} from '../core/renderer-adapter'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** @@ -92,7 +92,7 @@ export class StyleDirective extends BaseFxDirective protected _renderer: Renderer2, protected _differs: KeyValueDiffers, @Optional() @Self() private _ngStyleInstance: NgStyle, - protected _styler: StyleService) { + protected _styler: StyleUtils) { super(monitor, _ngEl, _styler); this._configureAdapters(); diff --git a/src/lib/api/flexbox/flex-align.ts b/src/lib/api/flexbox/flex-align.ts index 2dacd6986..5acd0df91 100644 --- a/src/lib/api/flexbox/flex-align.ts +++ b/src/lib/api/flexbox/flex-align.ts @@ -18,7 +18,7 @@ import { import {BaseFxDirective} from '../core/base'; import {MediaChange} from '../../media-query/media-change'; import {MediaMonitor} from '../../media-query/media-monitor'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** * 'flex-align' flexbox styling directive @@ -56,7 +56,7 @@ export class FlexAlignDirective extends BaseFxDirective implements OnInit, OnCha /* tslint:enable */ constructor(monitor: MediaMonitor, elRef: ElementRef, - styleUtils: StyleService) { + styleUtils: StyleUtils) { super(monitor, elRef, styleUtils); } diff --git a/src/lib/api/flexbox/flex-fill.ts b/src/lib/api/flexbox/flex-fill.ts index 0cfc4694a..812732641 100644 --- a/src/lib/api/flexbox/flex-fill.ts +++ b/src/lib/api/flexbox/flex-fill.ts @@ -9,7 +9,7 @@ import {Directive, ElementRef} from '@angular/core'; import {MediaMonitor} from '../../media-query/media-monitor'; import {BaseFxDirective} from '../core/base'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; const FLEX_FILL_CSS = { 'margin': 0, @@ -32,7 +32,7 @@ const FLEX_FILL_CSS = { export class FlexFillDirective extends BaseFxDirective { constructor(monitor: MediaMonitor, public elRef: ElementRef, - styleUtils: StyleService) { + styleUtils: StyleUtils) { super(monitor, elRef, styleUtils); this._applyStyleToElement(FLEX_FILL_CSS); } diff --git a/src/lib/api/flexbox/flex-offset.spec.ts b/src/lib/api/flexbox/flex-offset.spec.ts index 70574cc8a..66d9e70e4 100644 --- a/src/lib/api/flexbox/flex-offset.spec.ts +++ b/src/lib/api/flexbox/flex-offset.spec.ts @@ -25,20 +25,20 @@ import { expectEl, expectNativeEl, } from '../../utils/testing/helpers'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; describe('flex-offset directive', () => { let fixture: ComponentFixture; let fakeDocument: {body: {dir?: string}, documentElement: {dir?: string}}; - let styler: StyleService; + let styler: StyleUtils; let platform: Platform; let platformId: Object; let componentWithTemplate = (template: string) => { fixture = makeCreateTestComponent(() => TestFlexComponent)(template); - inject([StyleService, Platform, PLATFORM_ID], - (_styler: StyleService, _platform: Platform, _platformId: Object) => { + inject([StyleUtils, Platform, PLATFORM_ID], + (_styler: StyleUtils, _platform: Platform, _platformId: Object) => { styler = _styler; platform = _platform; platformId = _platformId; @@ -57,7 +57,7 @@ describe('flex-offset directive', () => { BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, {provide: DIR_DOCUMENT, useValue: fakeDocument}, - StyleService, + StyleUtils, {provide: SERVER_TOKEN, useValue: true} ] }); diff --git a/src/lib/api/flexbox/flex-offset.ts b/src/lib/api/flexbox/flex-offset.ts index 9574902e7..7e41f870b 100644 --- a/src/lib/api/flexbox/flex-offset.ts +++ b/src/lib/api/flexbox/flex-offset.ts @@ -25,7 +25,7 @@ import {MediaChange} from '../../media-query/media-change'; import {MediaMonitor} from '../../media-query/media-monitor'; import {LayoutDirective} from './layout'; import {isFlowHorizontal} from '../../utils/layout-validator'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** * 'flex-offset' flexbox styling directive @@ -63,7 +63,7 @@ export class FlexOffsetDirective extends BaseFxDirective implements OnInit, OnCh elRef: ElementRef, @Optional() @SkipSelf() protected _container: LayoutDirective, private _directionality: Directionality, - styleUtils: StyleService) { + styleUtils: StyleUtils) { super(monitor, elRef, styleUtils); this._directionWatcher = diff --git a/src/lib/api/flexbox/flex-order.ts b/src/lib/api/flexbox/flex-order.ts index 44a0c75cd..407cb52ef 100644 --- a/src/lib/api/flexbox/flex-order.ts +++ b/src/lib/api/flexbox/flex-order.ts @@ -18,7 +18,7 @@ import { import {BaseFxDirective} from '../core/base'; import {MediaChange} from '../../media-query/media-change'; import {MediaMonitor} from '../../media-query/media-monitor'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** * 'flex-order' flexbox styling directive @@ -54,7 +54,7 @@ export class FlexOrderDirective extends BaseFxDirective implements OnInit, OnCha /* tslint:enable */ constructor(monitor: MediaMonitor, elRef: ElementRef, - styleUtils: StyleService) { + styleUtils: StyleUtils) { super(monitor, elRef, styleUtils); } diff --git a/src/lib/api/flexbox/flex.spec.ts b/src/lib/api/flexbox/flex.spec.ts index 1daa1b1f0..6c86bf929 100644 --- a/src/lib/api/flexbox/flex.spec.ts +++ b/src/lib/api/flexbox/flex.spec.ts @@ -26,21 +26,21 @@ import { queryFor, expectEl, } from '../../utils/testing/helpers'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; describe('flex directive', () => { let fixture: ComponentFixture; let matchMedia: MockMatchMedia; - let styler: StyleService; + let styler: StyleUtils; let platform: Platform; let platformId: Object; let componentWithTemplate = (template: string) => { fixture = makeCreateTestComponent(() => TestFlexComponent)(template); - inject([MatchMedia, StyleService, Platform, PLATFORM_ID], - (_matchMedia: MockMatchMedia, _styler: StyleService, _platform: Platform, + inject([MatchMedia, StyleUtils, Platform, PLATFORM_ID], + (_matchMedia: MockMatchMedia, _styler: StyleUtils, _platform: Platform, _platformId: Object) => { matchMedia = _matchMedia; styler = _styler; @@ -60,7 +60,7 @@ describe('flex directive', () => { BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, - StyleService, + StyleUtils, {provide: SERVER_TOKEN, useValue: true} ] }); @@ -588,8 +588,8 @@ describe('flex directive', () => { }); describe('with API directive queries', () => { - it('should query the ViewChild `fxLayout` directive properly', inject([StyleService], - (styleService: StyleService) => { + it('should query the ViewChild `fxLayout` directive properly', inject([StyleUtils], + (_styler: StyleUtils) => { fixture = TestBed.createComponent(TestQueryWithFlexComponent); fixture.detectChanges(); @@ -599,18 +599,18 @@ describe('flex directive', () => { expect(layout.activatedValue).toBe(''); expectNativeEl(fixture).toHaveStyle({ 'flex-direction': 'row' - }, styleService); + }, _styler); layout.activatedValue = 'column'; expect(layout.activatedValue).toBe('column'); expectNativeEl(fixture).toHaveStyle({ 'flex-direction': 'column' - }, styleService); + }, _styler); }) ); - it('should query the ViewChild `fxFlex` directive properly', inject([StyleService], - (styleService: StyleService) => { + it('should query the ViewChild `fxFlex` directive properly', inject([StyleUtils], + (_styler: StyleUtils) => { fixture = TestBed.createComponent(TestQueryWithFlexComponent); fixture.detectChanges(); @@ -622,7 +622,7 @@ describe('flex directive', () => { let nodes = queryFor(fixture, '[fxFlex]'); expect(nodes.length).toEqual(1); - expectEl(nodes[0]).toHaveStyle({'max-width': '50%'}, styleService); + expectEl(nodes[0]).toHaveStyle({'max-width': '50%'}, _styler); // Test for raw value assignments that are converted to percentages flex.activatedValue = '35'; @@ -630,7 +630,7 @@ describe('flex directive', () => { nodes = queryFor(fixture, '[fxFlex]'); expect(nodes.length).toEqual(1); - expectEl(nodes[0]).toHaveStyle({'max-width': '35%'}, styleService); + expectEl(nodes[0]).toHaveStyle({'max-width': '35%'}, _styler); // Test for pixel value assignments flex.activatedValue = '27.5px'; @@ -638,13 +638,13 @@ describe('flex directive', () => { nodes = queryFor(fixture, '[fxFlex]'); expect(nodes.length).toEqual(1); - expectEl(nodes[0]).toHaveStyle({'max-width': '27.5px'}, styleService); + expectEl(nodes[0]).toHaveStyle({'max-width': '27.5px'}, _styler); }) ); it('should restore `fxFlex` value after breakpoint activations', - inject([MatchMedia, StyleService], - (_matchMedia: MockMatchMedia, styleService: StyleService) => { + inject([MatchMedia, StyleUtils], + (_matchMedia: MockMatchMedia, _styler: StyleUtils) => { fixture = TestBed.createComponent(TestQueryWithFlexComponent); fixture.detectChanges(); @@ -657,7 +657,7 @@ describe('flex directive', () => { let nodes = queryFor(fixture, '[fxFlex]'); expect(nodes.length).toEqual(1); - expectEl(nodes[0]).toHaveStyle({'max-width': '35%'}, styleService); + expectEl(nodes[0]).toHaveStyle({'max-width': '35%'}, _styler); _matchMedia.activate('sm'); fixture.detectChanges(); @@ -665,7 +665,7 @@ describe('flex directive', () => { // Test for breakpoint value changes expect(flex.activatedValue).toBe('71%'); nodes = queryFor(fixture, '[fxFlex]'); - expectEl(nodes[0]).toHaveStyle({'max-width': '71%'}, styleService); + expectEl(nodes[0]).toHaveStyle({'max-width': '71%'}, _styler); _matchMedia.activate('lg'); fixture.detectChanges(); @@ -673,7 +673,7 @@ describe('flex directive', () => { // Confirm activatedValue was restored properly when `sm` deactivated expect(flex.activatedValue).toBe('35'); nodes = queryFor(fixture, '[fxFlex]'); - expectEl(nodes[0]).toHaveStyle({'max-width': '35%'}, styleService); + expectEl(nodes[0]).toHaveStyle({'max-width': '35%'}, _styler); }) ); }); diff --git a/src/lib/api/flexbox/flex.ts b/src/lib/api/flexbox/flex.ts index cfb3d1b2d..57edbd1c3 100644 --- a/src/lib/api/flexbox/flex.ts +++ b/src/lib/api/flexbox/flex.ts @@ -26,7 +26,7 @@ import {MediaMonitor} from '../../media-query/media-monitor'; import {LayoutDirective} from './layout'; import {validateBasis} from '../../utils/basis-validator'; import {isFlowHorizontal} from '../../utils/layout-validator'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** Built-in aliases for different flex-basis values. */ @@ -84,7 +84,7 @@ export class FlexDirective extends BaseFxDirective implements OnInit, OnChanges, constructor(monitor: MediaMonitor, elRef: ElementRef, @Optional() @SkipSelf() protected _container: LayoutDirective, - protected styleUtils: StyleService) { + protected styleUtils: StyleUtils) { super(monitor, elRef, styleUtils); this._cacheInput('flex', ''); diff --git a/src/lib/api/flexbox/layout-align.spec.ts b/src/lib/api/flexbox/layout-align.spec.ts index b6444113c..aeeb71b2d 100644 --- a/src/lib/api/flexbox/layout-align.spec.ts +++ b/src/lib/api/flexbox/layout-align.spec.ts @@ -20,19 +20,19 @@ import {FlexLayoutModule} from '../../module'; import {extendObject} from '../../utils/object-extend'; import {customMatchers} from '../../utils/testing/custom-matchers'; import {makeCreateTestComponent, expectNativeEl} from '../../utils/testing/helpers'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; describe('layout-align directive', () => { let fixture: ComponentFixture; let matchMedia: MockMatchMedia; let platform: Platform; - let styler: StyleService; + let styler: StyleUtils; let createTestComponent = (template: string) => { fixture = makeCreateTestComponent(() => TestLayoutAlignComponent)(template); - inject([MatchMedia, Platform, StyleService], - (_matchMedia: MockMatchMedia, _platform: Platform, _styler: StyleService) => { + inject([MatchMedia, Platform, StyleUtils], + (_matchMedia: MockMatchMedia, _platform: Platform, _styler: StyleUtils) => { matchMedia = _matchMedia; platform = _platform; styler = _styler; @@ -50,7 +50,7 @@ describe('layout-align directive', () => { BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, - StyleService, + StyleUtils, {provide: SERVER_TOKEN, useValue: true} ] }); diff --git a/src/lib/api/flexbox/layout-align.ts b/src/lib/api/flexbox/layout-align.ts index 71f6b08e2..838f54d87 100644 --- a/src/lib/api/flexbox/layout-align.ts +++ b/src/lib/api/flexbox/layout-align.ts @@ -25,7 +25,7 @@ import {MediaMonitor} from '../../media-query/media-monitor'; import {LayoutDirective} from './layout'; import {LAYOUT_VALUES, isFlowHorizontal} from '../../utils/layout-validator'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** * 'layout-align' flexbox styling directive @@ -70,7 +70,7 @@ export class LayoutAlignDirective extends BaseFxDirective implements OnInit, OnC monitor: MediaMonitor, elRef: ElementRef, @Optional() @Self() container: LayoutDirective, - styleUtils: StyleService) { + styleUtils: StyleUtils) { super(monitor, elRef, styleUtils); if (container) { // Subscribe to layout direction changes diff --git a/src/lib/api/flexbox/layout-gap.spec.ts b/src/lib/api/flexbox/layout-gap.spec.ts index 150a05f10..82bac1ee3 100644 --- a/src/lib/api/flexbox/layout-gap.spec.ts +++ b/src/lib/api/flexbox/layout-gap.spec.ts @@ -18,17 +18,17 @@ import {FlexLayoutModule} from '../../module'; import {customMatchers, expect} from '../../utils/testing/custom-matchers'; import {expectEl, makeCreateTestComponent, queryFor} from '../../utils/testing/helpers'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; describe('layout-gap directive', () => { let fixture: ComponentFixture; let fakeDocument: {body: {dir?: string}, documentElement: {dir?: string}}; - let styler: StyleService; + let styler: StyleUtils; let platformId: Object; let createTestComponent = (template: string, styles?: any) => { fixture = makeCreateTestComponent(() => TestLayoutGapComponent)(template, styles); - inject([StyleService, PLATFORM_ID], (_styler: StyleService, _platformId: Object) => { + inject([StyleUtils, PLATFORM_ID], (_styler: StyleUtils, _platformId: Object) => { styler = _styler; platformId = _platformId; })(); @@ -47,7 +47,7 @@ describe('layout-gap directive', () => { BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, - StyleService, + StyleUtils, {provide: SERVER_TOKEN, useValue: true} ] }); diff --git a/src/lib/api/flexbox/layout-gap.ts b/src/lib/api/flexbox/layout-gap.ts index 9ad4eb827..f4201c6e0 100644 --- a/src/lib/api/flexbox/layout-gap.ts +++ b/src/lib/api/flexbox/layout-gap.ts @@ -25,7 +25,7 @@ import {Directionality} from '../../bidi/directionality'; import {MediaChange} from '../../media-query/media-change'; import {MediaMonitor} from '../../media-query/media-monitor'; import {LAYOUT_VALUES} from '../../utils/layout-validator'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** * 'layout-padding' styling directive @@ -70,7 +70,7 @@ export class LayoutGapDirective extends BaseFxDirective implements AfterContentI @Optional() @Self() container: LayoutDirective, private _zone: NgZone, private _directionality: Directionality, - styleUtils: StyleService) { + styleUtils: StyleUtils) { super(monitor, elRef, styleUtils); if (container) { // Subscribe to layout direction changes diff --git a/src/lib/api/flexbox/layout.spec.ts b/src/lib/api/flexbox/layout.spec.ts index 626a48d0b..4e23860b7 100644 --- a/src/lib/api/flexbox/layout.spec.ts +++ b/src/lib/api/flexbox/layout.spec.ts @@ -17,18 +17,18 @@ import {FlexLayoutModule} from '../../module'; import {customMatchers} from '../../utils/testing/custom-matchers'; import {makeCreateTestComponent, expectNativeEl, expectEl} from '../../utils/testing/helpers'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; import {queryFor} from '../../utils/testing/helpers'; import {SERVER_TOKEN} from '../../utils/styling/server-token'; describe('layout directive', () => { let fixture: ComponentFixture; let matchMedia: MockMatchMedia; - let styler: StyleService; + let styler: StyleUtils; let createTestComponent = (template: string) => { fixture = makeCreateTestComponent(() => TestLayoutComponent)(template); - inject([MatchMedia, StyleService], (_matchMedia: MockMatchMedia, _styler: StyleService) => { + inject([MatchMedia, StyleUtils], (_matchMedia: MockMatchMedia, _styler: StyleUtils) => { matchMedia = _matchMedia; styler = _styler; })(); @@ -44,7 +44,7 @@ describe('layout directive', () => { providers: [ BreakPointRegistry, DEFAULT_BREAKPOINTS_PROVIDER, {provide: MatchMedia, useClass: MockMatchMedia}, - StyleService, + StyleUtils, {provide: SERVER_TOKEN, useValue: true} ] }); diff --git a/src/lib/api/flexbox/layout.ts b/src/lib/api/flexbox/layout.ts index 8f312b370..5a4ab0177 100644 --- a/src/lib/api/flexbox/layout.ts +++ b/src/lib/api/flexbox/layout.ts @@ -21,7 +21,7 @@ import {MediaChange} from '../../media-query/media-change'; import {MediaMonitor} from '../../media-query/media-monitor'; import {buildLayoutCSS} from '../../utils/layout-validator'; import {ReplaySubject} from 'rxjs/ReplaySubject'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../../utils/styling/style-utils'; /** * 'layout' flexbox styling directive * Defines the positioning flow direction for the child elements: row or column @@ -73,7 +73,7 @@ export class LayoutDirective extends BaseFxDirective implements OnInit, OnChange */ constructor(monitor: MediaMonitor, elRef: ElementRef, - styleUtils: StyleService) { + styleUtils: StyleUtils) { super(monitor, elRef, styleUtils); this._announcer = new ReplaySubject(1); this.layout$ = this._announcer.asObservable(); diff --git a/src/lib/media-query/_module.ts b/src/lib/media-query/_module.ts index 9fa89703f..acc00bb2a 100644 --- a/src/lib/media-query/_module.ts +++ b/src/lib/media-query/_module.ts @@ -7,11 +7,11 @@ */ import {NgModule} from '@angular/core'; -import {MatchMedia} from './match-media'; import {MediaMonitor} from './media-monitor'; import {OBSERVABLE_MEDIA_PROVIDER} from './observable-media-provider'; import {DEFAULT_BREAKPOINTS_PROVIDER} from './breakpoints/break-points-provider'; import {BreakPointRegistry} from './breakpoints/break-point-registry'; +import {MATCH_MEDIA_PROVIDER} from './match-media-provider'; /** * ***************************************************************** @@ -23,12 +23,10 @@ import {BreakPointRegistry} from './breakpoints/break-point-registry'; providers: [ DEFAULT_BREAKPOINTS_PROVIDER, // Supports developer overrides of list of known breakpoints BreakPointRegistry, // Registry of known/used BreakPoint(s) - MatchMedia, // Low-level service to publish observables w/ window.matchMedia() + MATCH_MEDIA_PROVIDER, // Low-level service to publish observables w/ window.matchMedia() MediaMonitor, // MediaQuery monitor service observes all known breakpoints OBSERVABLE_MEDIA_PROVIDER // easy subscription injectable `media$` matchMedia observable ] }) export class MediaQueriesModule { } - - diff --git a/src/lib/media-query/index.ts b/src/lib/media-query/index.ts index 5e59da0ad..d8439e3a3 100644 --- a/src/lib/media-query/index.ts +++ b/src/lib/media-query/index.ts @@ -20,5 +20,7 @@ export * from './media-monitor'; export * from './breakpoints/break-points-provider'; export * from './observable-media-provider'; export * from './media-monitor-provider'; +export * from './server-match-media'; +export * from './match-media-provider'; export * from './_module'; diff --git a/src/lib/media-query/match-media-provider.ts b/src/lib/media-query/match-media-provider.ts new file mode 100644 index 000000000..9703dd0d6 --- /dev/null +++ b/src/lib/media-query/match-media-provider.ts @@ -0,0 +1,39 @@ +/** + * @license + * Copyright Google LLC 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 + */ +import { + NgZone, + PLATFORM_ID, + InjectionToken, // tslint:disable-line:no-unused-variable +} from '@angular/core'; +import {DOCUMENT, isPlatformServer} from '@angular/common'; + +import {MatchMedia} from './match-media'; +import {ServerMatchMedia} from './server-match-media'; + +/** + * Create a version of MatchMedia compatible with the current + * platform + */ +export function MEDIA_QUERY_LIST_FACTORY(platformId: Object, + zone: NgZone, + _document: Document) { + if (isPlatformServer(platformId)) { + return new ServerMatchMedia(zone, _document); + } else { + return new MatchMedia(zone, _document); + } +} + +/** + * Export provider that uses a global service factory (above) + */ +export const MATCH_MEDIA_PROVIDER = { + provide: MatchMedia, + useFactory: MEDIA_QUERY_LIST_FACTORY, + deps: [PLATFORM_ID, NgZone, DOCUMENT] +}; diff --git a/src/lib/media-query/match-media.ts b/src/lib/media-query/match-media.ts index 7cea55dd9..f28f9e9a5 100644 --- a/src/lib/media-query/match-media.ts +++ b/src/lib/media-query/match-media.ts @@ -5,83 +5,13 @@ * 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 */ -import {Inject, Injectable, NgZone, PLATFORM_ID} from '@angular/core'; -import {DOCUMENT, isPlatformBrowser} from '@angular/common'; +import {Inject, Injectable, NgZone} from '@angular/core'; +import {DOCUMENT} from '@angular/common'; import {BehaviorSubject} from 'rxjs/BehaviorSubject'; import {Observable} from 'rxjs/Observable'; import {filter} from 'rxjs/operators/filter'; import {MediaChange} from './media-change'; -import {BreakPoint} from '../media-query/breakpoints/break-point'; - -/** - * Special server-only class to simulate a MediaQueryList and - * - supports manual activation to simulate mediaQuery matching - * - manages listeners - */ -export class ServerMediaQueryList implements MediaQueryList { - private _isActive = false; - private _listeners: Array = []; - - get matches(): boolean { - return this._isActive; - } - - get media(): string { - return this._mediaQuery; - } - - constructor(private _mediaQuery: string) { } - - /** - * - */ - destroy() { - this.deactivate(); - this._listeners = []; - } - - /** - * Notify all listeners that 'matches === TRUE' - */ - activate(): ServerMediaQueryList { - if (!this._isActive) { - this._isActive = true; - this._listeners.forEach((callback) => { - callback(this); - }); - } - return this; - } - - /** - * Notify all listeners that 'matches === false' - */ - deactivate(): ServerMediaQueryList { - if (this._isActive) { - this._isActive = false; - this._listeners.forEach((callback) => { - callback(this); - }); - } - return this; - } - - /** - * - */ - addListener(listener: MediaQueryListListener) { - if (this._listeners.indexOf(listener) === -1) { - this._listeners.push(listener); - } - if (this._isActive) { - listener(this); - } - } - - removeListener(_: MediaQueryListListener) { - } -} /** * MediaMonitor configures listeners to mediaQuery changes and publishes an Observable facade to @@ -92,36 +22,17 @@ export class ServerMediaQueryList implements MediaQueryList { */ @Injectable() export class MatchMedia { - protected _registry: Map; + protected _registry: Map; protected _source: BehaviorSubject; protected _observable$: Observable; constructor(protected _zone: NgZone, - @Inject(DOCUMENT) protected _document: any, - @Inject(PLATFORM_ID) protected _platformId: Object) { - this._registry = new Map(); + @Inject(DOCUMENT) protected _document: any) { + this._registry = new Map(); this._source = new BehaviorSubject(new MediaChange(true)); this._observable$ = this._source.asObservable(); } - /** - * Activate the specified breakpoint if we're on the server, no-op otherwise - */ - activateBreakpoint(bp: BreakPoint) { - if (!isPlatformBrowser(this._platformId)) { - (this._registry.get(bp.mediaQuery) as ServerMediaQueryList).activate(); - } - } - - /** - * Deactivate the specified breakpoint if we're on the server, no-op otherwise - */ - deactivateBreakpoint(bp: BreakPoint) { - if (!isPlatformBrowser(this._platformId)) { - (this._registry.get(bp.mediaQuery) as ServerMediaQueryList).deactivate(); - } - } - /** * For the specified mediaQuery? */ @@ -162,7 +73,7 @@ export class MatchMedia { list.forEach(query => { let mql = this._registry.get(query); - let onMQLEvent = (e: MediaQueryList|ServerMediaQueryList) => { + let onMQLEvent = (e: MediaQueryList) => { this._zone.run(() => { let change = new MediaChange(e.matches, query); this._source.next(change); @@ -186,11 +97,17 @@ export class MatchMedia { * Call window.matchMedia() to build a MediaQueryList; which * supports 0..n listeners for activation/deactivation */ - protected _buildMQL(query: string): MediaQueryList|ServerMediaQueryList { - let canListen = isPlatformBrowser(this._platformId) && - !!(window).matchMedia('all').addListener; - - return canListen ? (window).matchMedia(query) : new ServerMediaQueryList(query); + protected _buildMQL(query: string): MediaQueryList { + let canListen = !!(window).matchMedia('all').addListener; + + return canListen ? (window).matchMedia(query) : { + matches: query === 'all' || query === '', + media: query, + addListener: () => { + }, + removeListener: () => { + } + }; } /** diff --git a/src/lib/media-query/mock/mock-match-media.ts b/src/lib/media-query/mock/mock-match-media.ts index 12c3b0a3f..79a69e592 100644 --- a/src/lib/media-query/mock/mock-match-media.ts +++ b/src/lib/media-query/mock/mock-match-media.ts @@ -5,7 +5,7 @@ * 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 */ -import {Inject, Injectable, NgZone, PLATFORM_ID} from '@angular/core'; +import {Inject, Injectable, NgZone} from '@angular/core'; import {DOCUMENT} from '@angular/common'; import {MatchMedia} from '../match-media'; @@ -32,9 +32,8 @@ export class MockMatchMedia extends MatchMedia { constructor(_zone: NgZone, @Inject(DOCUMENT) _document: any, - private _breakpoints: BreakPointRegistry, - @Inject(PLATFORM_ID) _platformId: Object) { - super(_zone, _document, _platformId); + private _breakpoints: BreakPointRegistry) { + super(_zone, _document); this._actives = []; } diff --git a/src/lib/media-query/server-match-media.ts b/src/lib/media-query/server-match-media.ts new file mode 100644 index 000000000..a74d19b3e --- /dev/null +++ b/src/lib/media-query/server-match-media.ts @@ -0,0 +1,136 @@ +/** + * @license + * Copyright Google LLC 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 + */ +import {DOCUMENT} from '@angular/common'; +import {Inject, Injectable, NgZone} from '@angular/core'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; +import {MediaChange} from './media-change'; +import {BreakPoint} from './breakpoints/break-point'; +import {Observable} from 'rxjs/Observable'; +import {MatchMedia} from './match-media'; + +/** + * Special server-only class to simulate a MediaQueryList and + * - supports manual activation to simulate mediaQuery matching + * - manages listeners + */ +export class ServerMediaQueryList implements MediaQueryList { + private _isActive = false; + private _listeners: Array = []; + + get matches(): boolean { + return this._isActive; + } + + get media(): string { + return this._mediaQuery; + } + + constructor(private _mediaQuery: string) {} + + /** + * Destroy the current list by deactivating the + * listeners and clearing the internal list + */ + destroy() { + this.deactivate(); + this._listeners = []; + } + + /** + * Notify all listeners that 'matches === TRUE' + */ + activate(): ServerMediaQueryList { + if (!this._isActive) { + this._isActive = true; + this._listeners.forEach((callback) => { + callback(this); + }); + } + return this; + } + + /** + * Notify all listeners that 'matches === false' + */ + deactivate(): ServerMediaQueryList { + if (this._isActive) { + this._isActive = false; + this._listeners.forEach((callback) => { + callback(this); + }); + } + return this; + } + + /** + * Add a listener to our internal list to activate later + */ + addListener(listener: MediaQueryListListener) { + if (this._listeners.indexOf(listener) === -1) { + this._listeners.push(listener); + } + if (this._isActive) { + listener(this); + } + } + + /** + * Don't need to remove listeners in the server environment + */ + removeListener(_: MediaQueryListListener) { + } +} + +/** + * Special server-only implementation of MatchMedia that uses the above + * ServerMediaQueryList as its internal representation + * + * Also contains methods to activate and deactivate breakpoints + */ +@Injectable() +export class ServerMatchMedia extends MatchMedia { + protected _registry: Map; + protected _source: BehaviorSubject; + protected _observable$: Observable; + + constructor(protected _zone: NgZone, + @Inject(DOCUMENT) protected _document: any) { + super(_zone, _document); + this._registry = new Map(); + this._source = new BehaviorSubject(new MediaChange(true)); + this._observable$ = this._source.asObservable(); + } + + /** + * Activate the specified breakpoint if we're on the server, no-op otherwise + */ + activateBreakpoint(bp: BreakPoint) { + const lookupBreakpoint = this._registry.get(bp.mediaQuery); + if (lookupBreakpoint) { + lookupBreakpoint.activate(); + } + } + + /** + * Deactivate the specified breakpoint if we're on the server, no-op otherwise + */ + deactivateBreakpoint(bp: BreakPoint) { + const lookupBreakpoint = this._registry.get(bp.mediaQuery); + if (lookupBreakpoint) { + lookupBreakpoint.deactivate(); + } + } + + /** + * Call window.matchMedia() to build a MediaQueryList; which + * supports 0..n listeners for activation/deactivation + */ + protected _buildMQL(query: string): ServerMediaQueryList { + return new ServerMediaQueryList(query); + } +} diff --git a/src/lib/module.ts b/src/lib/module.ts index 20a184239..5666c035d 100644 --- a/src/lib/module.ts +++ b/src/lib/module.ts @@ -35,7 +35,7 @@ import {ImgSrcDirective} from './api/ext/img-src'; import {BidiModule} from './bidi/bidi-module'; import {BROWSER_PROVIDER} from './utils/styling/browser-provider'; -import {StyleService} from './utils/styling/styler'; +import {StyleUtils} from './utils/styling/style-utils'; import {ServerStylesheet} from './utils/styling/server-stylesheet'; import {SERVER_TOKEN} from './utils/styling/server-token'; @@ -74,7 +74,7 @@ const ALL_DIRECTIVES = [ DEFAULT_BREAKPOINTS_PROVIDER, // Extend defaults with internal custom breakpoints OBSERVABLE_MEDIA_PROVIDER, ServerStylesheet, - StyleService, + StyleUtils, BROWSER_PROVIDER, ] }) diff --git a/src/lib/server/server-provider.ts b/src/lib/server/server-provider.ts index ee77b34c9..407313f67 100644 --- a/src/lib/server/server-provider.ts +++ b/src/lib/server/server-provider.ts @@ -19,21 +19,25 @@ import { MatchMedia, ServerStylesheet, SERVER_TOKEN, + ServerMatchMedia } from '@angular/flex-layout'; let UNIQUE_CLASS = 0; -const DEBUG_FLAG = false; +const IS_DEBUG_MODE = false; /** * create @media queries based on a virtual stylesheet * * Adds a unique class to each element and stores it * in a shared classMap for later reuse + * @param stylesheet the virtual stylesheet that stores styles for each + * element + * @param mediaQuery the given @media CSS selector for the current breakpoint + * @param classMap the map of HTML elements to class names to avoid duplications */ -function formatStyle(stylesheet: Map>, - _document: Document, +function generateCss(stylesheet: Map>, mediaQuery: string, classMap: Map) { - let styleText = DEBUG_FLAG ? ` + let styleText = IS_DEBUG_MODE ? ` @media ${mediaQuery} {` : `@media ${mediaQuery}{`; stylesheet.forEach((styles, el) => { let className = classMap.get(el); @@ -42,57 +46,76 @@ function formatStyle(stylesheet: Map>, classMap.set(el, className); } el.classList.add(className); - styleText += DEBUG_FLAG ? ` + styleText += IS_DEBUG_MODE ? ` .${className} {` : `.${className}{`; styles.forEach((v, k) => { if (v) { - styleText += DEBUG_FLAG ? ` + styleText += IS_DEBUG_MODE ? ` ${k}: ${v};` : `${k}:${v};`; } }); - styleText += DEBUG_FLAG ? ` + styleText += IS_DEBUG_MODE ? ` }` : '}'; }); - styleText += DEBUG_FLAG ? ` + styleText += IS_DEBUG_MODE ? ` }\n` : '}'; return styleText; } /** - * Add or remove static styles depending on the current - * platform - * format the static @media queries for all breakpoints - * to be used on the server and append them to the + * Activate all of the registered breakpoints in sequence, and then + * retrieve the associated stylings from the virtual stylesheet + * @param serverSheet the virtual stylesheet that stores styles for each + * element + * @param matchMedia the service to activate/deactive breakpoints + * @param breakpoints the registered breakpoints to activate/deactivate */ -export function addStyles(serverSheet: ServerStylesheet, - matchMedia: MatchMedia, - _document: Document, - breakpoints: BreakPoint[]) { - // necessary because of angular/angular/issues/14485 - const res = () => { - const styleTag = _document.createElement('style'); - const classMap = new Map(); - const defaultStyles = new Map(serverSheet.stylesheet); - let styleText = formatStyle(defaultStyles, _document, 'all', classMap); +export function generateStaticFlexLayoutStyles(serverSheet: ServerStylesheet, + matchMedia: MatchMedia, + breakpoints: BreakPoint[]) { + // Store the custom classes in the following map, that way only + // one class gets allocated per HTMLElement, and each class can + // be referenced in the static media queries + const classMap = new Map(); - breakpoints.reverse(); - breakpoints.forEach((bp, i) => { - serverSheet.clearStyles(); - matchMedia.activateBreakpoint(bp); - const stylesheet = new Map(serverSheet.stylesheet); - if (stylesheet.size > 0) { - styleText += formatStyle(stylesheet, _document, bp.mediaQuery, classMap); - } - matchMedia.deactivateBreakpoint(breakpoints[i]); - }); + // Get the initial stylings for all of the directives, and initialize + // the fallback block of stylings, then reverse the breakpoints list + // to traverse in the proper order + const defaultStyles = new Map(serverSheet.stylesheet); + let styleText = generateCss(defaultStyles, 'all', classMap); + breakpoints.reverse(); + breakpoints.forEach((bp, i) => { + serverSheet.clearStyles(); + (matchMedia as ServerMatchMedia).activateBreakpoint(bp); + const stylesheet = new Map(serverSheet.stylesheet); + if (stylesheet.size > 0) { + styleText += generateCss(stylesheet, bp.mediaQuery, classMap); + } + (matchMedia as ServerMatchMedia).deactivateBreakpoint(breakpoints[i]); + }); + + return styleText; +} + +/** + * Create a style tag populated with the dynamic stylings from Flex + * components and attach it to the head of the DOM + */ +export function FLEX_SSR_SERIALIZER_FACTORY(serverSheet: ServerStylesheet, + matchMedia: MatchMedia, + _document: Document, + breakpoints: BreakPoint[]) { + return () => { + // This is the style tag that gets inserted into the head of the DOM, + // populated with the manual media queries + const styleTag = _document.createElement('style'); + const styleText = generateStaticFlexLayoutStyles(serverSheet, matchMedia, breakpoints); styleTag.classList.add(`${CLASS_NAME}ssr`); styleTag.textContent = styleText; _document.head.appendChild(styleTag); }; - - return res; } /** @@ -101,7 +124,7 @@ export function addStyles(serverSheet: ServerStylesheet, export const SERVER_PROVIDERS = [ { provide: BEFORE_APP_SERIALIZED, - useFactory: addStyles, + useFactory: FLEX_SSR_SERIALIZER_FACTORY, deps: [ ServerStylesheet, MatchMedia, diff --git a/src/lib/utils/styling/browser-provider.ts b/src/lib/utils/styling/browser-provider.ts index ca06b3779..04b67dad0 100644 --- a/src/lib/utils/styling/browser-provider.ts +++ b/src/lib/utils/styling/browser-provider.ts @@ -13,9 +13,13 @@ import { } from '@angular/core'; import {DOCUMENT, isPlatformBrowser} from '@angular/common'; +/** + * Find all of the server-generated stylings, if any, and remove them + * This will be in the form of inline classes and the style block in the + * head of the DOM + */ export function removeStyles(_document: Document, platformId: Object) { - // necessary because of angular/angular/issues/14485 - const res = () => { + return () => { if (isPlatformBrowser(platformId)) { const elements = Array.from(_document.querySelectorAll(`[class*=${CLASS_NAME}]`)); const classRegex = new RegExp(/\bflex-layout-.+?\b/, 'g'); @@ -25,8 +29,6 @@ export function removeStyles(_document: Document, platformId: Object) { }); } }; - - return res; } /** diff --git a/src/lib/utils/styling/index.ts b/src/lib/utils/styling/index.ts index fdf34bee5..1e06510cc 100644 --- a/src/lib/utils/styling/index.ts +++ b/src/lib/utils/styling/index.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -export * from './styler'; +export * from './style-utils'; export * from './style-transforms'; export * from './browser-provider'; export * from './server-stylesheet'; diff --git a/src/lib/utils/styling/server-stylesheet.ts b/src/lib/utils/styling/server-stylesheet.ts index e6c07532b..de9e32581 100644 --- a/src/lib/utils/styling/server-stylesheet.ts +++ b/src/lib/utils/styling/server-stylesheet.ts @@ -7,11 +7,20 @@ */ import {Injectable} from '@angular/core'; +/** + * Utility to emulate a CSS stylesheet + * + * This stores all of the styles for a given HTML element + * and returns them later + */ @Injectable() export class ServerStylesheet { readonly stylesheet = new Map>(); + /** + * Add an individual style to an HTML element + */ addStyleToElement(element: HTMLElement, style: string, value: string|number) { const stylesheet = this.stylesheet.get(element); if (stylesheet) { @@ -21,10 +30,16 @@ export class ServerStylesheet { } } + /** + * Clear the virtual stylesheet + */ clearStyles() { this.stylesheet.clear(); } + /** + * Retrieve a given style for an HTML element + */ getStyleForElement(el: HTMLElement, styleName: string): string|number { const styles = this.stylesheet.get(el); return (styles && styles.get(styleName)) || ''; diff --git a/src/lib/utils/styling/server-token.ts b/src/lib/utils/styling/server-token.ts index 4c9841420..683cee152 100644 --- a/src/lib/utils/styling/server-token.ts +++ b/src/lib/utils/styling/server-token.ts @@ -7,4 +7,10 @@ */ import {InjectionToken} from '@angular/core'; +/** + * Token that is provided to tell whether the FlexLayoutServerModule + * has been included in the bundle + * + * NOTE: This can be manually provided to disable styles when using SSR + */ export const SERVER_TOKEN = new InjectionToken('FlexLayoutServerLoaded'); diff --git a/src/lib/utils/styling/styler.spec.ts b/src/lib/utils/styling/style-utils.spec.ts similarity index 92% rename from src/lib/utils/styling/styler.spec.ts rename to src/lib/utils/styling/style-utils.spec.ts index 01c6eb49b..a42d2ca56 100644 --- a/src/lib/utils/styling/styler.spec.ts +++ b/src/lib/utils/styling/style-utils.spec.ts @@ -11,18 +11,18 @@ import {ComponentFixture, inject, TestBed} from '@angular/core/testing'; import {customMatchers} from '../testing/custom-matchers'; import {makeCreateTestComponent, expectNativeEl} from '../testing/helpers'; -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from './style-utils'; import {ServerStylesheet} from './server-stylesheet'; describe('styler', () => { - let styler: StyleService; + let styler: StyleUtils; let fixture: ComponentFixture; let platformId: Object; let componentWithTemplate = (template: string, styles?: any) => { fixture = makeCreateTestComponent(() => TestLayoutComponent)(template, styles); - inject([StyleService, PLATFORM_ID], (_styler: StyleService, _platformId: Object) => { + inject([StyleUtils, PLATFORM_ID], (_styler: StyleUtils, _platformId: Object) => { styler = _styler; platformId = _platformId; })(); @@ -35,7 +35,7 @@ describe('styler', () => { TestBed.configureTestingModule({ imports: [CommonModule], declarations: [TestLayoutComponent], - providers: [ServerStylesheet, StyleService] + providers: [ServerStylesheet, StyleUtils] }); }); diff --git a/src/lib/utils/styling/styler.ts b/src/lib/utils/styling/style-utils.ts similarity index 95% rename from src/lib/utils/styling/styler.ts rename to src/lib/utils/styling/style-utils.ts index 304431d0d..5b7a62135 100644 --- a/src/lib/utils/styling/styler.ts +++ b/src/lib/utils/styling/style-utils.ts @@ -13,7 +13,7 @@ import {ServerStylesheet} from './server-stylesheet'; import {SERVER_TOKEN} from './server-token'; @Injectable() -export class StyleService { +export class StyleUtils { constructor(@Optional() private _serverStylesheet: ServerStylesheet, @Optional() @Inject(SERVER_TOKEN) private _serverModuleLoaded: boolean, @@ -75,7 +75,7 @@ export class StyleService { /** * Determine the inline or inherited CSS style - * @TODO(CaerusKaru): platform-server has no implementation for getComputedStyle + * NOTE: platform-server has no implementation for getComputedStyle */ lookupStyle(element: HTMLElement, styleName: string, inlineOnly = false): string { let value = ''; @@ -123,6 +123,6 @@ export class StyleService { * Definition of a css style. Either a property name (e.g. "flex-basis") or an object * map of property name and value (e.g. {display: 'none', flex-order: 5}) */ -export type StyleDefinition = string | { [property: string]: string | number | null }; +export type StyleDefinition = { [property: string]: string | number | null }; const FALLBACK_STYLE = 'block'; diff --git a/src/lib/utils/testing/custom-matchers.ts b/src/lib/utils/testing/custom-matchers.ts index b423a6484..f20b765b7 100644 --- a/src/lib/utils/testing/custom-matchers.ts +++ b/src/lib/utils/testing/custom-matchers.ts @@ -5,7 +5,7 @@ * 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 */ -import {StyleService} from '../../utils/styling/styler'; +import {StyleUtils} from '../styling/style-utils'; declare var global: any; const _global = (typeof window === 'undefined' ? global : window); @@ -205,7 +205,7 @@ export const customMatchers: jasmine.CustomMatcherFactories = { * specified DOM element. */ function buildCompareStyleFunction(inlineOnly = true) { - return function (actual: any, styles: { [k: string]: string } | string, styler: StyleService) { + return function (actual: any, styles: { [k: string]: string } | string, styler: StyleUtils) { let found = {}; let allPassed: boolean;