diff --git a/angular.json b/angular.json index e405e52a79..2c2953cc4d 100644 --- a/angular.json +++ b/angular.json @@ -25,7 +25,47 @@ "src/favicon.ico" ], "styles": [ - "src/styles.scss" + "src/styles.scss", + { + "bundleName": "material-light", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-angular.css" + }, + { + "bundleName": "material-dark", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-angular-dark.css" + }, + { + "bundleName": "bootstrap-light", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-bootstrap-light.css" + }, + { + "bundleName": "bootstrap-dark", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-bootstrap-dark.css" + }, + { + "bundleName": "fluent-light", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-fluent-light.css" + }, + { + "bundleName": "fluent-dark", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-fluent-dark.css" + }, + { + "bundleName": "indigo-light", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-indigo-light.css" + }, + { + "bundleName": "indigo-dark", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-indigo-dark.css" + } ], "scripts": [], "vendorChunk": true, @@ -137,7 +177,47 @@ "projects/app-lob/src/assets" ], "styles": [ - "projects/app-lob/src/styles.scss" + "projects/app-lob/src/styles.scss", + { + "bundleName": "material-light", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-angular.css" + }, + { + "bundleName": "material-dark", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-angular-dark.css" + }, + { + "bundleName": "bootstrap-light", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-bootstrap-light.css" + }, + { + "bundleName": "bootstrap-dark", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-bootstrap-dark.css" + }, + { + "bundleName": "fluent-light", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-fluent-light.css" + }, + { + "bundleName": "fluent-dark", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-fluent-dark.css" + }, + { + "bundleName": "indigo-light", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-indigo-light.css" + }, + { + "bundleName": "indigo-dark", + "inject": false, + "input": "node_modules/igniteui-angular/styles/igniteui-indigo-dark.css" + } ], "scripts": [], "vendorChunk": true, diff --git a/projects/app-crm/src/index.html b/projects/app-crm/src/index.html index ff44e2a755..04411288d8 100644 --- a/projects/app-crm/src/index.html +++ b/projects/app-crm/src/index.html @@ -11,6 +11,7 @@ + diff --git a/projects/app-lob/src/app/app.component.ts b/projects/app-lob/src/app/app.component.ts index 20a1b9e2e2..e973daf068 100644 --- a/projects/app-lob/src/app/app.component.ts +++ b/projects/app-lob/src/app/app.component.ts @@ -1,7 +1,8 @@ import { DOCUMENT } from '@angular/common'; -import { Component, HostListener, Inject, OnInit } from '@angular/core'; +import { Component, Inject, OnInit } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; -import { filter, map, mergeMap } from 'rxjs/operators'; +import { filter, map } from 'rxjs/operators'; +import { ThemableDirective } from '../../../../src/app/common/themable-app.directive'; import { SEOService } from './seo.service'; @Component({ @@ -9,68 +10,29 @@ import { SEOService } from './seo.service'; styleUrls: ['./app.component.scss'], templateUrl: './app.component.html' }) -export class AppComponent implements OnInit { +export class AppComponent extends ThemableDirective implements OnInit { public title = 'app-lob'; - private isIE = !((window as any).ActiveXObject) && 'ActiveXObject' in window; - private theme = 'default-theme'; - private styleElem: HTMLStyleElement; - private typefacesLoaded = ['Titillium Web', 'Roboto']; - private typefaceUrl = 'https://fonts.googleapis.com/css?family='; - constructor(@Inject(DOCUMENT) private document: Document, private router: Router, - private activatedRoute: ActivatedRoute, private seoService: SEOService) { } + constructor( + @Inject(DOCUMENT) document: Document, + private router: Router, + private activatedRoute: ActivatedRoute, + private seoService: SEOService) { + super(document); + } public ngOnInit() { this.router.events.pipe( filter((event) => event instanceof NavigationEnd), map(() => { let route = this.activatedRoute.firstChild; - while (route.firstChild) {route = route.firstChild;} + while (route.firstChild) { route = route.firstChild; } return route; }) - ) - .subscribe((event) => { - this.seoService.updateHeadProperties(event.snapshot.data['title'] ?? event.parent.snapshot.data['title'], - event.snapshot.data['title'] ?? event.parent.snapshot.data['description'], window.location.href); - }); - this.createThemeStyle(); - } - - // eslint-disable-next-line @typescript-eslint/member-ordering - @HostListener('window:message', ['$event']) - private onMessage(e: MessageEvent) { - if (e.origin === e.data.origin && typeof e.data.themeStyle === 'string') { - this.styleElem.textContent = e.data.themeStyle; - - const typeface = window.getComputedStyle(this.document.body).fontFamily.replace(/[\'\"]/g, ''); - if (!(typeface.match(/,/g) || []).length && - !this.typefacesLoaded.includes(typeface)) { - this.typefacesLoaded.push(typeface); - this.createTypefaceLink(typeface); - } - } else if (e.origin === e.data.origin && typeof e.data.theme === 'string') { - this.document.body.classList.remove(this.theme); - this.document.body.classList.add(e.data.theme); - this.theme = e.data.theme; - } - } - - private createTypefaceLink(typeface: string) { - const typefaceElem = this.document.createElement('link'); - typefaceElem.rel = 'stylesheet'; - typefaceElem.id = 'ignteui-theme-typeface'; - typefaceElem.href = this.typefaceUrl + typeface.split(' ').join('+'); - document.head.insertBefore(typefaceElem, this.document.head.lastElementChild); - } - - private createThemeStyle() { - if (this.isIE) { - this.document.body.classList.add(this.theme); - } else { - this.styleElem = document.createElement('style'); - this.styleElem.id = 'igniteui-theme'; - document.head.insertBefore(this.styleElem, this.document.head.lastElementChild); - this.document.body.classList.add('custom-body'); - } + ).subscribe((event) => { + this.seoService.updateHeadProperties(event.snapshot.data['title'] ?? event.parent.snapshot.data['title'], + event.snapshot.data['title'] ?? event.parent.snapshot.data['description'], window.location.href); + }); + super.ngOnInit(); } } diff --git a/projects/app-lob/src/app/index/docs-layout.component.ts b/projects/app-lob/src/app/index/docs-layout.component.ts index 302e90a544..02e7edc567 100644 --- a/projects/app-lob/src/app/index/docs-layout.component.ts +++ b/projects/app-lob/src/app/index/docs-layout.component.ts @@ -1,59 +1,11 @@ -import { DOCUMENT } from '@angular/common'; -import { Component, HostListener, Inject, OnInit } from '@angular/core'; +import { Component } from '@angular/core'; +import { ThemableDirective } from '../../../../../src/app/common/themable-app.directive'; @Component({ selector: 'app-docs-layout', styleUrls: ['./docs-layout.component.scss'], template: `` }) +export class DocsLayoutComponent extends ThemableDirective { -export class DocsLayoutComponent implements OnInit { - private isIE = !((window as any).ActiveXObject) && 'ActiveXObject' in window; - private theme = 'default-theme'; - private styleElem: HTMLStyleElement; - private typefacesLoaded = ['Titillium Web', 'Roboto']; - private typefaceUrl = 'https://fonts.googleapis.com/css?family='; - - constructor(@Inject(DOCUMENT) private document: Document) {} - - @HostListener('window:message', ['$event']) - private onMessage(e: MessageEvent) { - if (e.origin === e.data.origin && typeof e.data.themeStyle === 'string') { - this.styleElem.textContent = e.data.themeStyle; - - const typeface = window.getComputedStyle(this.document.body).fontFamily.replace(/\'/g, ''); - if (!(typeface.match(/,/g) || []).length && - !this.typefacesLoaded.includes(typeface)) { - this.typefacesLoaded.push(typeface); - this.createTypefaceLink(typeface); - } - } else if (e.origin === e.data.origin && typeof e.data.theme === 'string') { - this.document.body.classList.remove(this.theme); - this.document.body.classList.add(e.data.theme); - this.theme = e.data.theme; - } - } - - public ngOnInit() { - this.createThemeStyle(); - } - - private createThemeStyle() { - if (this.isIE) { - this.document.body.classList.add(this.theme); - } else { - this.styleElem = document.createElement('style'); - this.styleElem.id = 'igniteui-theme'; - document.head.insertBefore(this.styleElem, this.document.head.lastElementChild); - this.document.body.classList.add('custom-body'); - } - } - - private createTypefaceLink(typeface: string) { - const typefaceElem = this.document.createElement('link'); - typefaceElem.rel = 'stylesheet'; - typefaceElem.id = 'ignteui-theme-typeface'; - typefaceElem.href = this.typefaceUrl + typeface.split(' ').join('+'); - document.head.insertBefore(typefaceElem, this.document.head.lastElementChild); - } } diff --git a/projects/app-lob/src/index.html b/projects/app-lob/src/index.html index 44cb36c740..1ac7e7e2a5 100644 --- a/projects/app-lob/src/index.html +++ b/projects/app-lob/src/index.html @@ -20,6 +20,7 @@ + diff --git a/projects/app-lob/src/styles.scss b/projects/app-lob/src/styles.scss index aae2eec21e..bda341c331 100644 --- a/projects/app-lob/src/styles.scss +++ b/projects/app-lob/src/styles.scss @@ -8,12 +8,7 @@ body { overflow: hidden; margin: 0; } -@include core(); -@include typography(); -@include theme( - $palette: $palette, - $schema: $schema -); + :root { @include palette($palette); } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 1683c62f1b..0aab854aab 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,59 +1,11 @@ -import { DOCUMENT } from '@angular/common'; -import { Component, HostListener, Inject, OnInit } from '@angular/core'; +import { Component } from '@angular/core' +import { ThemableDirective } from './common/themable-app.directive'; @Component({ selector: 'app-root', styleUrls: ['./app.component.scss'], templateUrl: './app.component.html' }) -export class AppComponent implements OnInit { +export class AppComponent extends ThemableDirective { public title = 'Samples'; - private isIE = !((window as any).ActiveXObject) && 'ActiveXObject' in window; - private theme = 'default-theme'; - private styleElem: HTMLStyleElement; - private typefacesLoaded = ['Titillium Web', 'Roboto']; - private typefaceUrl = 'https://fonts.googleapis.com/css?family='; - - constructor(@Inject(DOCUMENT) private document: Document) {} - - public ngOnInit() { - this.createThemeStyle(); - } - - // eslint-disable-next-line @typescript-eslint/member-ordering - @HostListener('window:message', ['$event']) - private onMessage(e: MessageEvent) { - if (e.origin === e.data.origin && typeof e.data.themeStyle === 'string') { - this.styleElem.textContent = e.data.themeStyle; - const typeface = window.getComputedStyle(this.document.body).fontFamily.replace(/[\'\"]/g, ''); - if (!(typeface.match(/,/g) || []).length && - !this.typefacesLoaded.includes(typeface)) { - this.typefacesLoaded.push(typeface); - this.createTypefaceLink(typeface); - } - } else if (e.origin === e.data.origin && typeof e.data.theme === 'string') { - this.document.body.classList.remove(this.theme); - this.document.body.classList.add(e.data.theme); - this.theme = e.data.theme; - } - } - - private createTypefaceLink(typeface: string) { - const typefaceElem = this.document.createElement('link'); - typefaceElem.rel = 'stylesheet'; - typefaceElem.id = 'ignteui-theme-typeface'; - typefaceElem.href = this.typefaceUrl + typeface.split(' ').join('+'); - document.head.insertBefore(typefaceElem, this.document.head.lastElementChild); - } - - private createThemeStyle() { - if (this.isIE) { - this.document.body.classList.add(this.theme); - } else { - this.styleElem = document.createElement('style'); - this.styleElem.id = 'igniteui-theme'; - document.head.insertBefore(this.styleElem, this.document.head.lastElementChild); - this.document.body.classList.add('custom-body'); - } - } } diff --git a/src/app/common/themable-app.directive.ts b/src/app/common/themable-app.directive.ts new file mode 100644 index 0000000000..7c189adf65 --- /dev/null +++ b/src/app/common/themable-app.directive.ts @@ -0,0 +1,82 @@ +import { DOCUMENT } from '@angular/common'; +import { Directive, HostListener, Inject, OnInit } from '@angular/core'; + +const PREBUILT_THEME_MAP = { + 'igx-theme': 'material-light', + 'igx-dark-theme': 'material-dark', + 'igx-fluent-theme': 'fluent-light', + 'igx-fluent-dark-theme': 'fluent-dark', + 'igx-bootstrap-theme': 'bootstrap-light', + 'igx-bootstrap-dark-theme': 'bootstrap-dark', + 'igx-indigo-light-theme': 'indigo-light', + 'igx-indigo-dark-theme': 'indigo-dark' +} + +@Directive() +export abstract class ThemableDirective implements OnInit { + private theme = 'igx-theme'; + private linkElem: HTMLLinkElement; + private styleElem: HTMLStyleElement; + private typefacesLoaded = ['Titillium Web', 'Roboto', 'Nunito Sans']; + private typefaceUrl = 'https://fonts.googleapis.com/css?family='; + + constructor(@Inject(DOCUMENT) private document: Document) { } + + public ngOnInit() { + this.updateThemeLink(PREBUILT_THEME_MAP[this.theme]); + this.createThemeStyle(); + } + + // eslint-disable-next-line @typescript-eslint/member-ordering + @HostListener('window:message', ['$event']) + private onMessage(e: MessageEvent) { + if (e.origin === e.data.origin && typeof e.data.themeStyle === 'string') { + const theme = JSON.parse(e.data.themeStyle); + this.updateThemeLink(PREBUILT_THEME_MAP[theme.globalTheme]); + this.styleElem.textContent = theme.data; + const typeface = theme.typeface.family; + if (!(typeface.match(/,/g) || []).length && + !this.typefacesLoaded.includes(typeface)) { + this.typefacesLoaded.push(typeface); + this.createTypefaceLink(typeface); + } + } else if (e.origin === e.data.origin && typeof e.data.theme === 'string') { + this.document.body.classList.remove(this.theme); + this.document.body.classList.add(e.data.theme); + this.theme = e.data.theme; + } + } + + private createTypefaceLink(typeface: string) { + const typefaceElem = this.document.createElement('link'); + typefaceElem.rel = 'stylesheet'; + typefaceElem.id = 'ignteui-theme-typeface'; + typefaceElem.href = this.typefaceUrl + typeface.split(' ').join('+'); + document.head.insertBefore(typefaceElem, this.document.head.lastElementChild); + } + + private updateThemeLink(name: string) { + const elem = document.createElement('link'); + elem.rel = 'stylesheet'; + elem.id = 'igniteui-theme'; + elem.href = `${name}.css`; + if (!this.linkElem) { + document.head.insertBefore(elem, this.document.head.lastElementChild); + this.linkElem = elem; + this.document.body.classList.add('custom-body'); + } else { + elem.onload = () => { + this.linkElem.remove(); + this.linkElem = elem; + }; + this.linkElem.parentNode.insertBefore(elem, this.linkElem); + } + } + + private createThemeStyle() { + this.styleElem = document.createElement('style'); + this.styleElem.id = 'igniteui-theme'; + document.head.insertBefore(this.styleElem, this.document.head.lastElementChild); + this.document.body.classList.add('custom-body'); + } +} diff --git a/src/app/data-entries/input-group/base-input.component.ts b/src/app/data-entries/input-group/base-input.component.ts index 3b518c71f8..8e925044b2 100644 --- a/src/app/data-entries/input-group/base-input.component.ts +++ b/src/app/data-entries/input-group/base-input.component.ts @@ -12,15 +12,17 @@ export class BaseInputGroupSampleComponent { @HostListener('window:message', ['$event']) private onMessage(e: MessageEvent) { - if (e.origin === e.data.origin && e.data.themeName) { - this.applyInputTypeForTheme(e.data.themeName); + if (e.origin === e.data.origin && e.data.themeStyle) { + const theme = JSON.parse(e.data.themeStyle); + this.applyInputTypeForTheme(theme.globalTheme); } } private applyInputTypeForTheme(theme: string) { const themeName = theme.split('-')[1]; switch (themeName) { - case 'theme': this.setInputType('line'); break; + case 'theme': + case 'dark': this.setInputType('line'); break; case 'fluent': this.setInputType('fluent'); break; case 'bootstrap': this.setInputType('bootstrap'); break; default: break; diff --git a/src/index.html b/src/index.html index 9920eced30..e22aecc54b 100644 --- a/src/index.html +++ b/src/index.html @@ -11,6 +11,7 @@ + diff --git a/src/styles.scss b/src/styles.scss index 82df00bb3a..c025985a64 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -10,13 +10,6 @@ body { margin: 0; } -@include core(); -@include typography(); -@include theme( - $palette: $palette, - $schema: $schema -); - :root { @include palette($palette); }