diff --git a/src/core/theme/theme.view.d.ts b/src/core/theme/theme.view.d.ts new file mode 100644 index 000000000..c1dc8ff14 --- /dev/null +++ b/src/core/theme/theme.view.d.ts @@ -0,0 +1,7 @@ +import { Model } from '../infrastructure/model'; + +export declare class ThemeView{ + constructor(model: Model); + + classList: string | Array; +} \ No newline at end of file diff --git a/src/core/theme/theme.view.js b/src/core/theme/theme.view.js new file mode 100644 index 000000000..eb166e5fd --- /dev/null +++ b/src/core/theme/theme.view.js @@ -0,0 +1,13 @@ +export class ThemeView{ + constructor(model){ + this.model=model; + } + + get classList() + { + return this.model.style().classList; + } +} + + + diff --git a/src/core/view/view.factory.js b/src/core/view/view.factory.js index c4cb1a4f5..bf4bf7bff 100644 --- a/src/core/view/view.factory.js +++ b/src/core/view/view.factory.js @@ -19,6 +19,7 @@ import { ScrollView } from '../scroll/scroll.view'; import { SelectionView } from '../selection/selection.view'; import { SortView } from '../sort/sort.view'; import { StyleView } from '../style/style.view'; +import { ThemeView } from '../theme/theme.view'; export function viewFactory( model, @@ -65,6 +66,7 @@ export function viewFactory( host.rowDetails = new RowDetailsView(modelProxy, table, navigationShortcut); host.selection = new SelectionView(modelProxy, table, selectionShortcut); host.style = new StyleView(modelProxy, table); + host.theme = new ThemeView(modelProxy); return () => { host.layout.dispose(); diff --git a/src/examples/theme-grid-dark/example-theme-grid-dark.component.html b/src/examples/theme-grid-dark/example-theme-grid-dark.component.html index 6e4442cbb..1114d8180 100644 --- a/src/examples/theme-grid-dark/example-theme-grid-dark.component.html +++ b/src/examples/theme-grid-dark/example-theme-grid-dark.component.html @@ -1,5 +1,7 @@ - + \ No newline at end of file diff --git a/src/lib/main/core/view/view-core.service.ts b/src/lib/main/core/view/view-core.service.ts index 8b920dc49..36653ac67 100644 --- a/src/lib/main/core/view/view-core.service.ts +++ b/src/lib/main/core/view/view-core.service.ts @@ -22,6 +22,7 @@ import { CommandManager } from 'ng2-qgrid/core/command/command.manager'; import { VScrollService } from '../../../main/core/scroll/vscroll.service'; import { GridService } from '../../../main/grid/grid.service'; import { RowView } from 'ng2-qgrid/core/row/row.view'; +import { ThemeView } from 'ng2-qgrid/core/theme/theme.view'; @Injectable() export class ViewCoreService implements OnDestroy { @@ -44,7 +45,8 @@ export class ViewCoreService implements OnDestroy { sort: SortView = null; style: StyleView = null; row: RowView = null; - + theme: ThemeView = null; + constructor( private gridServiceFactory: GridService, private vscroll: VScrollService diff --git a/src/lib/main/grid/grid.component.ts b/src/lib/main/grid/grid.component.ts index b807b25bf..27182cdd8 100644 --- a/src/lib/main/grid/grid.component.ts +++ b/src/lib/main/grid/grid.component.ts @@ -33,6 +33,7 @@ import { TableCommandManager } from 'ng2-qgrid/core/command/table.command.manage import { VisibilityModel } from 'ng2-qgrid/core/visibility/visibility.model'; import { Command } from 'ng2-qgrid/core/command/command'; import { GridModel } from '../../plugins/plugin.service'; +import {OverlayContainer} from '@angular/cdk/overlay'; import { DOCUMENT } from '@angular/platform-browser'; @Component({ @@ -111,8 +112,9 @@ export class GridComponent extends RootComponent implements OnInit { private element: ElementRef, private zone: NgZone, private layerService: LayerService, + private overlayContainer: OverlayContainer, + private theme: ThemeService, @Inject(DOCUMENT) private document: Document, - theme: ThemeService, ) { super(); @@ -147,7 +149,11 @@ export class GridComponent extends RootComponent implements OnInit { const model = this.root.model; const element = this.element.nativeElement; - + + element.classList.forEach(cssClass => { + this.overlayContainer.getContainerElement().classList.add(cssClass); + }); + model.style({ classList: Array.from(element.classList) }); diff --git a/src/plugin/pager/pager.view.js b/src/plugin/pager/pager.view.js index aee13366d..f3cd0bea8 100644 --- a/src/plugin/pager/pager.view.js +++ b/src/plugin/pager/pager.view.js @@ -25,10 +25,6 @@ export class PagerView { }); } - get theme() { - return this.model.style().classList - } - get resource() { return this.model.pagination().resource; } diff --git a/src/theme/basic/theme.module.ts b/src/theme/basic/theme.module.ts index 35ec3f225..d8f25e336 100644 --- a/src/theme/basic/theme.module.ts +++ b/src/theme/basic/theme.module.ts @@ -34,7 +34,7 @@ import { ] }) export class ThemeModule { - constructor(theme: ThemeService) { + constructor(private theme: ThemeService) { theme.name = 'basic'; theme.component = ThemeComponent; } diff --git a/src/theme/material/assets/dark.scss b/src/theme/material/assets/dark.scss index 32cc00f70..3fb7626b6 100644 --- a/src/theme/material/assets/dark.scss +++ b/src/theme/material/assets/dark.scss @@ -1,20 +1,148 @@ -.q-grid-dark { - //Custom colors +//Custom colors $color-less: rgba(0, 0, 0, 0); $dark: #424242; $dark-primary: #1eb980; $dark-accent: #616161; - $dark-focused: #5565A0; + $dark-focused: #118d5fc2; $dark-highlighted: #8d8d8d; $dark-surface: #363640; $dark-container: #3c3c46; $dark-text: #ffffff; $dark-header: rgba(255, 255, 255, 0.6); + $dark-label: rgba(255, 255, 255, 0.6); + $dark-label-focused: rgba(255, 255, 255, 0.2); + $dark-subscript: rgba(255, 255, 255, 0.6); $dark-divider: rgba(255, 255, 255, 0.12); + $dark-icon-button: #c8c8c8; + +//Custom palettes (generated using tool: http://mcg.mbitson.com) +/******************************************************************/ +$dark-brand-palette: ( + 50 : #e4f7f0, + 100 : #bcead9, + 200 : #8fdcc0, + 300 : #62cea6, + 400 : #40c493, + 500 : #1eb980, + 600 : #1ab278, + 700 : #16aa6d, + 800 : #12a263, + 900 : #0a9350, + A100 : #c1ffde, + A200 : #8effc3, + A400 : #5bffa7, + A700 : #41ff9a, + contrast: ( + 50 : #000000, + 100 : #000000, + 200 : #000000, + 300 : #000000, + 400 : #000000, + 500 : #000000, + 600 : #ffffff, + 700 : #ffffff, + 800 : #ffffff, + 900 : #ffffff, + A100 : #000000, + A200 : #000000, + A400 : #000000, + A700 : #000000, + ) +); + +$dark-accent-palette: ( + 50 : #ececec, + 100 : #d0d0d0, + 200 : #b0b0b0, + 300 : #8d8d8d, + 400 : #797979, + 500 : #616161, + 600 : #595959, + 700 : #4f4f4f, + 800 : #424242, + 900 : #333333, + A100 : #f39595, + A200 : #ee6868, + A400 : #ff2424, + A700 : #ff0a0a, + contrast: ( + 50 : #000000, + 100 : #000000, + 200 : #000000, + 300 : #000000, + 400 : #ffffff, + 500 : #ffffff, + 600 : #ffffff, + 700 : #ffffff, + 800 : #ffffff, + 900 : #ffffff, + A100 : #000000, + A200 : #000000, + A400 : #ffffff, + A700 : #ffffff, + ) +); + +// Define an alternate dark theme +//according this manual: https://github.com/angular/material2/blob/master/guides/theming.md. +/*****************************************************************************************************/ + +// Define the palettes for your theme using the Material Design palettes available in palette.scss +// (imported above). For each palette, you can optionally specify a default, lighter, and darker +// hue. Available color palettes: https://material.io/design/color/ +$q-grid-dark-primary: mat-palette($dark-brand-palette); +$q-grid-dark-accent: mat-palette($dark-accent-palette, 500, 300, 800); + +// The warn palette is optional (defaults to red). +$q-grid-dark-warn: mat-palette($dark-accent-palette, A400, A100, A700); + +// Create the theme object (a Sass map containing all of the palettes). +$q-grid-dark-theme: mat-dark-theme($q-grid-dark-primary, $q-grid-dark-accent, $q-grid-dark-warn); + +// Include the alternative theme styles inside of a block with a CSS class. You can make this +// CSS class whatever you want. In this example, any component inside of an element with +// `.q-grid-dark` will be affected by this alternate dark theme instead of the default theme. +.q-grid-dark { + @include angular-material-theme($q-grid-dark-theme); + + .mat-calendar-table-header{ + color: $dark-header; + } + .mat-calendar-body-label{ + color: $dark-label; + } + .mat-calendar-body-cell-content{ + color: $dark-text; + } + + .mat-calendar-table-header-divider::after{ + background-color: $dark-primary; + } + .mat-calendar-body-selected { + background-color: $dark-highlighted;; + } + + .mat-button, .mat-icon-button, .mat-stroked-button { + color: $dark-icon-button; + } + .mat-form-field { + font-weight: 300; + .mat-form-field-label{ + color: $dark-label; + } + } + + .mat-form-field.mat-focused { + .mat-form-field-label{ + color: $dark-label-focused; + } + } + .q-grid.q-grid-theme-material { background-color: $dark-surface; font-family: "Roboto Condensed", Roboto, "Helvetica Neue", sans-serif; font-weight: 300; + thead { box-shadow: 0 1px 0px $dark-divider; th { @@ -100,16 +228,21 @@ .q-grid-editor { color: $dark-text; background-color: $dark; + font-size: 13px; + .mat-input-element{ + font-family: "Roboto Condensed"; + font-weight: 300; + } } } .q-grid-icon { color: $dark-text; } .mat-hint { - color: $dark-text; + color: $dark-subscript; } .mat-form-field-underline { - background-color: $dark-text; + background-color: $dark-divider; } .mat-checkbox-frame { border-color: $dark-text; @@ -117,9 +250,6 @@ .mat-icon { color: $dark-text; } - .mat-form-field-ripple { - background-color: $dark-accent; - } } ul.q-grid-legend-list { color: $dark-text; @@ -155,58 +285,81 @@ } .mat-menu-content { background: $dark; - height: 500px; } - q-grid-column-chooser, - q-grid-column-filter { - .mat-card { - background-color: $dark; + + .q-grid-column-chooser { + .mat-menu-content { + height: 500px; + } + } + + .mat-focused { + .mat-form-field-ripple { + background-color: $dark-primary; + } + } + + .mat-form-field-underline { + background-color: $dark-divider; + } + + + .mat-card { + background-color: $dark; + color: $dark-text; + font-weight: 300; + .mat-card-title { + font-size: 16px; + } + .mat-button { color: $dark-text; + } + .mat-button:hover { + background-color: $dark-accent; + } + .mat-button.mat-primary { + background-color: $dark-accent; + } + .mat-form-field-label { + color: $dark-text; + } + .mat-input-underline { + color: #fff; + } + .mat-form-field { font-weight: 300; - .mat-card-title { - font-size: 16px; - } - .mat-button { - color: $dark-text; - } - .mat-button:hover { - background-color: $dark-accent; - } - .mat-button.mat-primary { - background-color: $dark-accent; - } - .mat-form-field-label { - color: $dark-text; - } - .mat-input-underline { - color: #fff; - } - .mat-form-field { - font-weight: 300; - } - .mat-form-field-underline { - background-color: $dark-divider; - } - .mat-form-field-ripple { - background-color: $dark-primary; - } - .mat-form-field-should-float label, - .q-grid-filter-by-item { - font-family: "Roboto Condensed", Roboto, "Helvetica Neue", sans-serif; - font-weight: 300; - } - .q-grid-filter-by-item { - color: $dark; - } - .mat-checkbox-checked.mat-accent .mat-checkbox-background, - .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background { - background-color: $dark-accent; - } - .q-grid-highlight-part { - background-color: $dark-highlighted; - color: $dark-text; + + .mat-focused { + .mat-form-field-ripple { + background-color: $dark-primary; + } } } + + .mat-form-field-underline { + background-color: $dark-divider; + } + + .mat-form-field-should-float label, + .q-grid-filter-by-item { + font-family: "Roboto Condensed", Roboto, "Helvetica Neue", sans-serif; + font-weight: 300; + } + .q-grid-filter-by-item { + color: $dark; + } + .mat-checkbox-checked.mat-accent .mat-checkbox-background, + .mat-checkbox-indeterminate.mat-accent .mat-checkbox-background { + background-color: $dark-accent; + } + .q-grid-highlight-part { + background-color: $dark-highlighted; + color: $dark-text; + } + } + + q-grid-column-chooser, + q-grid-column-filter { label { border-color: $dark-text; } @@ -233,4 +386,14 @@ .q-grid-cell-handler { outline-color: $dark-focused; } -} \ No newline at end of file +} + +mat-calendar.q-grid-dark{ + background-color: $dark-container; + font-family: "Roboto Condensed"; + font-weight: 300; +} + +mat-datepicker-content .q-grid-dark { + background: $dark-container; +} diff --git a/src/theme/material/components/theme-overlay/theme-overlay.directive.ts b/src/theme/material/components/theme-overlay/theme-overlay.directive.ts deleted file mode 100644 index b3e6c526c..000000000 --- a/src/theme/material/components/theme-overlay/theme-overlay.directive.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Directive, ElementRef, Renderer2, AfterViewInit } from '@angular/core'; -import { GridError, GridPlugin } from 'ng2-qgrid'; - -@Directive({ - selector: '[q-grid-theme-overlay]', - providers: [GridPlugin] -}) -export class ThemeOverlayDirective implements AfterViewInit { - - constructor( - private plugin: GridPlugin, - private element: ElementRef, - private renderer: Renderer2) { - } - - ngAfterViewInit(): void { - const { model } = this.plugin; - const element = this.element.nativeElement; - let parent = this.renderer.parentNode(element); - let overlayContainer: any = null; - - while (parent && !(parent.id && parent.id.startsWith('cdk-overlay'))) { - parent = this.renderer.parentNode(parent); - if (parent.nodeName === 'BODY') break; - } - - if (parent.nodeName !== 'BODY') { - overlayContainer = parent; - } - - if (!overlayContainer) { - throw new GridError( - 'theme-overlay.directive', - `cdk-overlay container is not found` - ); - } - - model.style().classList.forEach(cssClass => { - this.renderer.addClass(overlayContainer, cssClass); - }); - } -} diff --git a/src/theme/material/components/theme-overlay/theme-overlay.module.ts b/src/theme/material/components/theme-overlay/theme-overlay.module.ts deleted file mode 100644 index 49dff7865..000000000 --- a/src/theme/material/components/theme-overlay/theme-overlay.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NgModule } from '@angular/core'; -import { ThemeOverlayDirective } from './theme-overlay.directive'; - -@NgModule({ - declarations: [ - ThemeOverlayDirective - ], - exports: [ - ThemeOverlayDirective - ] -}) -export class ThemeOverlayModule { -} diff --git a/src/theme/material/index.scss b/src/theme/material/index.scss index 242a7db96..d7d9cfc5c 100644 --- a/src/theme/material/index.scss +++ b/src/theme/material/index.scss @@ -1,3 +1,11 @@ +@import '~@angular/material/theming'; +// Plus imports for other components in your app. + +// Include the common styles for Angular Material. We include this here so that you only +// have to load a single css file for Angular Material in your app. +// Be sure that you only ever include this mixin once! +@include mat-core(); + .q-grid.q-grid-theme-material { @import "assets/active"; @import "assets/backdrop"; diff --git a/src/theme/material/templates/plugin-column-filter-trigger.tpl.html b/src/theme/material/templates/plugin-column-filter-trigger.tpl.html index a3c4970df..a49df3776 100644 --- a/src/theme/material/templates/plugin-column-filter-trigger.tpl.html +++ b/src/theme/material/templates/plugin-column-filter-trigger.tpl.html @@ -8,7 +8,6 @@ {{size}} diff --git a/src/theme/material/templates/toolbar-top.tpl.html b/src/theme/material/templates/toolbar-top.tpl.html index f684768e3..cf7f2e8ad 100644 --- a/src/theme/material/templates/toolbar-top.tpl.html +++ b/src/theme/material/templates/toolbar-top.tpl.html @@ -20,7 +20,6 @@ diff --git a/src/theme/material/theme.module.ts b/src/theme/material/theme.module.ts index e66350eab..e36419fb7 100644 --- a/src/theme/material/theme.module.ts +++ b/src/theme/material/theme.module.ts @@ -5,7 +5,6 @@ import { ThemeComponent } from './theme.component'; import { SelectModule } from './components/select/select.module'; import { ChipsModule } from './components/chips/chips.module'; import { MenuModule } from './components/menu/menu.module'; -import { ThemeOverlayModule } from './components/theme-overlay/theme-overlay.module'; import { MatCardModule, MatIconModule, @@ -68,7 +67,6 @@ import { PluginModule, SelectModule, TemplateModule, - ThemeOverlayModule, VscrollModule, ], entryComponents: [ @@ -76,7 +74,7 @@ import { ] }) export class ThemeModule { - constructor(theme: ThemeService) { + constructor(private theme: ThemeService) { theme.name = 'material'; theme.component = ThemeComponent; }