94233: use actual CSS variables in theme

This commit is contained in:
lotte
2022-09-12 17:42:37 +02:00
parent e4f483c308
commit f70fc7b87a
19 changed files with 226 additions and 64 deletions

View File

@@ -2,7 +2,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { MenuService } from '../../../shared/menu/menu.service'; import { MenuService } from '../../../shared/menu/menu.service';
import { MenuServiceStub } from '../../../shared/testing/menu-service.stub'; import { MenuServiceStub } from '../../../shared/testing/menu-service.stub';
import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service';
import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub'; import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub';
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopAnimationsModule } from '@angular/platform-browser/animations';

View File

@@ -6,7 +6,7 @@ import { ScriptDataService } from '../../core/data/processes/script-data.service
import { AdminSidebarComponent } from './admin-sidebar.component'; import { AdminSidebarComponent } from './admin-sidebar.component';
import { MenuService } from '../../shared/menu/menu.service'; import { MenuService } from '../../shared/menu/menu.service';
import { MenuServiceStub } from '../../shared/testing/menu-service.stub'; import { MenuServiceStub } from '../../shared/testing/menu-service.stub';
import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../../shared/sass-helper/css-variable.service';
import { CSSVariableServiceStub } from '../../shared/testing/css-variable-service.stub'; import { CSSVariableServiceStub } from '../../shared/testing/css-variable-service.stub';
import { AuthServiceStub } from '../../shared/testing/auth-service.stub'; import { AuthServiceStub } from '../../shared/testing/auth-service.stub';
import { AuthService } from '../../core/auth/auth.service'; import { AuthService } from '../../core/auth/auth.service';

View File

@@ -18,7 +18,7 @@ import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick
import { TextMenuItemModel } from '../../shared/menu/menu-item/models/text.model'; import { TextMenuItemModel } from '../../shared/menu/menu-item/models/text.model';
import { MenuComponent } from '../../shared/menu/menu.component'; import { MenuComponent } from '../../shared/menu/menu.component';
import { MenuService } from '../../shared/menu/menu.service'; import { MenuService } from '../../shared/menu/menu.service';
import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../../shared/sass-helper/css-variable.service';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { FeatureID } from '../../core/data/feature-authorization/feature-id'; import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute } from '@angular/router';
@@ -82,7 +82,7 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
this.createMenu(); this.createMenu();
super.ngOnInit(); super.ngOnInit();
this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth'); this.sidebarWidth = this.variableService.getVariable('--ds-sidebar-items-width');
this.authService.isAuthenticated() this.authService.isAuthenticated()
.subscribe((loggedIn: boolean) => { .subscribe((loggedIn: boolean) => {
if (loggedIn) { if (loggedIn) {

View File

@@ -3,7 +3,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ExpandableAdminSidebarSectionComponent } from './expandable-admin-sidebar-section.component'; import { ExpandableAdminSidebarSectionComponent } from './expandable-admin-sidebar-section.component';
import { MenuService } from '../../../shared/menu/menu.service'; import { MenuService } from '../../../shared/menu/menu.service';
import { MenuServiceStub } from '../../../shared/testing/menu-service.stub'; import { MenuServiceStub } from '../../../shared/testing/menu-service.stub';
import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service';
import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub'; import { CSSVariableServiceStub } from '../../../shared/testing/css-variable-service.stub';
import { of as observableOf } from 'rxjs'; import { of as observableOf } from 'rxjs';
import { Component } from '@angular/core'; import { Component } from '@angular/core';

View File

@@ -2,7 +2,7 @@ import { Component, Inject, Injector, OnInit } from '@angular/core';
import { rotate } from '../../../shared/animations/rotate'; import { rotate } from '../../../shared/animations/rotate';
import { AdminSidebarSectionComponent } from '../admin-sidebar-section/admin-sidebar-section.component'; import { AdminSidebarSectionComponent } from '../admin-sidebar-section/admin-sidebar-section.component';
import { slide } from '../../../shared/animations/slide'; import { slide } from '../../../shared/animations/slide';
import { CSSVariableService } from '../../../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../../../shared/sass-helper/css-variable.service';
import { bgColor } from '../../../shared/animations/bgColor'; import { bgColor } from '../../../shared/animations/bgColor';
import { MenuID } from '../../../shared/menu/initial-menus-state'; import { MenuID } from '../../../shared/menu/initial-menus-state';
import { MenuService } from '../../../shared/menu/menu.service'; import { MenuService } from '../../../shared/menu/menu.service';
@@ -65,7 +65,7 @@ export class ExpandableAdminSidebarSectionComponent extends AdminSidebarSectionC
*/ */
ngOnInit(): void { ngOnInit(): void {
super.ngOnInit(); super.ngOnInit();
this.sidebarActiveBg = this.variableService.getVariable('adminSidebarActiveBg'); this.sidebarActiveBg = this.variableService.getVariable('--ds-admin-sidebar-active-bg');
this.sidebarCollapsed = this.menuService.isMenuCollapsed(this.menuID); this.sidebarCollapsed = this.menuService.isMenuCollapsed(this.menuID);
this.sidebarPreviewCollapsed = this.menuService.isMenuPreviewCollapsed(this.menuID); this.sidebarPreviewCollapsed = this.menuService.isMenuPreviewCollapsed(this.menuID);
this.expanded = combineLatestObservable(this.active, this.sidebarCollapsed, this.sidebarPreviewCollapsed) this.expanded = combineLatestObservable(this.active, this.sidebarCollapsed, this.sidebarPreviewCollapsed)

View File

@@ -19,7 +19,7 @@ import { AngularticsProviderMock } from './shared/mocks/angulartics-provider.ser
import { AuthServiceMock } from './shared/mocks/auth.service.mock'; import { AuthServiceMock } from './shared/mocks/auth.service.mock';
import { AuthService } from './core/auth/auth.service'; import { AuthService } from './core/auth/auth.service';
import { MenuService } from './shared/menu/menu.service'; import { MenuService } from './shared/menu/menu.service';
import { CSSVariableService } from './shared/sass-helper/sass-helper.service'; import { CSSVariableService } from './shared/sass-helper/css-variable.service';
import { CSSVariableServiceStub } from './shared/testing/css-variable-service.stub'; import { CSSVariableServiceStub } from './shared/testing/css-variable-service.stub';
import { MenuServiceStub } from './shared/testing/menu-service.stub'; import { MenuServiceStub } from './shared/testing/menu-service.stub';
import { HostWindowService } from './shared/host-window.service'; import { HostWindowService } from './shared/host-window.service';

View File

@@ -31,7 +31,7 @@ import { HostWindowState } from './shared/search/host-window.reducer';
import { NativeWindowRef, NativeWindowService } from './core/services/window.service'; import { NativeWindowRef, NativeWindowService } from './core/services/window.service';
import { isAuthenticationBlocking } from './core/auth/selectors'; import { isAuthenticationBlocking } from './core/auth/selectors';
import { AuthService } from './core/auth/auth.service'; import { AuthService } from './core/auth/auth.service';
import { CSSVariableService } from './shared/sass-helper/sass-helper.service'; import { CSSVariableService } from './shared/sass-helper/css-variable.service';
import { MenuService } from './shared/menu/menu.service'; import { MenuService } from './shared/menu/menu.service';
import { HostWindowService } from './shared/host-window.service'; import { HostWindowService } from './shared/host-window.service';
import { HeadTagConfig, ThemeConfig } from '../config/theme.model'; import { HeadTagConfig, ThemeConfig } from '../config/theme.model';
@@ -48,6 +48,7 @@ import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service';
import { IdleModalComponent } from './shared/idle-modal/idle-modal.component'; import { IdleModalComponent } from './shared/idle-modal/idle-modal.component';
import { getDefaultThemeConfig } from '../config/config.util'; import { getDefaultThemeConfig } from '../config/config.util';
import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface';
import { getCSSCustomPropIndex } from './shared/sass-helper/css-variable.utils';
@Component({ @Component({
selector: 'ds-app', selector: 'ds-app',
@@ -161,7 +162,6 @@ export class AppComponent implements OnInit, AfterViewInit {
if (environment.debug) { if (environment.debug) {
console.info(environment); console.info(environment);
} }
this.storeCSSVariables();
} }
ngOnInit() { ngOnInit() {
@@ -181,18 +181,9 @@ export class AppComponent implements OnInit, AfterViewInit {
} }
private storeCSSVariables() { private storeCSSVariables() {
this.cssService.addCSSVariable('xlMin', '1200px'); getCSSCustomPropIndex(this.document).forEach(([prop, val]) => {
this.cssService.addCSSVariable('mdMin', '768px'); this.cssService.addCSSVariable(prop, val);
this.cssService.addCSSVariable('lgMin', '576px'); });
this.cssService.addCSSVariable('smMin', '0');
this.cssService.addCSSVariable('adminSidebarActiveBg', '#0f1b28');
this.cssService.addCSSVariable('sidebarItemsWidth', '250px');
this.cssService.addCSSVariable('collapsedSidebarWidth', '53.234px');
this.cssService.addCSSVariable('totalSidebarWidth', '303.234px');
// const vars = variables.locals || {};
// Object.keys(vars).forEach((name: string) => {
// this.cssService.addCSSVariable(name, vars[name]);
// })
} }
ngAfterViewInit() { ngAfterViewInit() {
@@ -282,6 +273,8 @@ export class AppComponent implements OnInit, AfterViewInit {
} }
// the fact that this callback is used, proves we're on the browser. // the fact that this callback is used, proves we're on the browser.
this.isThemeCSSLoading$.next(false); this.isThemeCSSLoading$.next(false);
this.storeCSSVariables();
}; };
head.appendChild(link); head.appendChild(link);
} }

View File

@@ -35,7 +35,7 @@ import {
ObjectSelectionListState, ObjectSelectionListState,
objectSelectionReducer objectSelectionReducer
} from './shared/object-select/object-select.reducer'; } from './shared/object-select/object-select.reducer';
import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/sass-helper.reducer'; import { cssVariablesReducer, CSSVariablesState } from './shared/sass-helper/css-variable.reducer';
import { hostWindowReducer, HostWindowState } from './shared/search/host-window.reducer'; import { hostWindowReducer, HostWindowState } from './shared/search/host-window.reducer';
import { import {

View File

@@ -23,7 +23,7 @@ import { NotificationsService } from '../shared/notifications/notifications.serv
import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service'; import { SelectableListService } from '../shared/object-list/selectable-list/selectable-list.service';
import { ObjectSelectService } from '../shared/object-select/object-select.service'; import { ObjectSelectService } from '../shared/object-select/object-select.service';
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model'; import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
import { CSSVariableService } from '../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../shared/sass-helper/css-variable.service';
import { SidebarService } from '../shared/sidebar/sidebar.service'; import { SidebarService } from '../shared/sidebar/sidebar.service';
import { UploaderService } from '../shared/uploader/uploader.service'; import { UploaderService } from '../shared/uploader/uploader.service';
import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service'; import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service';

View File

@@ -18,7 +18,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import { RouterMock } from '../shared/mocks/router.mock'; import { RouterMock } from '../shared/mocks/router.mock';
import { MockActivatedRoute } from '../shared/mocks/active-router.mock'; import { MockActivatedRoute } from '../shared/mocks/active-router.mock';
import { MenuService } from '../shared/menu/menu.service'; import { MenuService } from '../shared/menu/menu.service';
import { CSSVariableService } from '../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../shared/sass-helper/css-variable.service';
import { CSSVariableServiceStub } from '../shared/testing/css-variable-service.stub'; import { CSSVariableServiceStub } from '../shared/testing/css-variable-service.stub';
import { HostWindowService } from '../shared/host-window.service'; import { HostWindowService } from '../shared/host-window.service';
import { HostWindowServiceStub } from '../shared/testing/host-window-service.stub'; import { HostWindowServiceStub } from '../shared/testing/host-window-service.stub';

View File

@@ -11,7 +11,7 @@ import { MetadataService } from '../core/metadata/metadata.service';
import { HostWindowState } from '../shared/search/host-window.reducer'; import { HostWindowState } from '../shared/search/host-window.reducer';
import { NativeWindowRef, NativeWindowService } from '../core/services/window.service'; import { NativeWindowRef, NativeWindowService } from '../core/services/window.service';
import { AuthService } from '../core/auth/auth.service'; import { AuthService } from '../core/auth/auth.service';
import { CSSVariableService } from '../shared/sass-helper/sass-helper.service'; import { CSSVariableService } from '../shared/sass-helper/css-variable.service';
import { MenuService } from '../shared/menu/menu.service'; import { MenuService } from '../shared/menu/menu.service';
import { MenuID } from '../shared/menu/initial-menus-state'; import { MenuID } from '../shared/menu/initial-menus-state';
import { HostWindowService } from '../shared/host-window.service'; import { HostWindowService } from '../shared/host-window.service';
@@ -65,8 +65,8 @@ export class RootComponent implements OnInit {
ngOnInit() { ngOnInit() {
this.sidebarVisible = this.menuService.isMenuVisible(MenuID.ADMIN); this.sidebarVisible = this.menuService.isMenuVisible(MenuID.ADMIN);
this.collapsedSidebarWidth = this.cssService.getVariable('collapsedSidebarWidth'); this.collapsedSidebarWidth = this.cssService.getVariable('--ds-collapsed-sidebar-width');
this.totalSidebarWidth = this.cssService.getVariable('totalSidebarWidth'); this.totalSidebarWidth = this.cssService.getVariable('--ds-total-sidebar-width');
const sidebarCollapsed = this.menuService.isMenuCollapsed(MenuID.ADMIN); const sidebarCollapsed = this.menuService.isMenuCollapsed(MenuID.ADMIN);
this.slideSidebarOver = combineLatestObservable([sidebarCollapsed, this.windowService.isXsOrSm()]) this.slideSidebarOver = combineLatestObservable([sidebarCollapsed, this.windowService.isXsOrSm()])

View File

@@ -7,7 +7,7 @@ import { createSelector, select, Store } from '@ngrx/store';
import { hasValue } from './empty.util'; import { hasValue } from './empty.util';
import { AppState } from '../app.reducer'; import { AppState } from '../app.reducer';
import { CSSVariableService } from './sass-helper/sass-helper.service'; import { CSSVariableService } from './sass-helper/css-variable.service';
export enum WidthCategory { export enum WidthCategory {
XS, XS,
@@ -31,10 +31,10 @@ export class HostWindowService {
/* See _exposed_variables.scss */ /* See _exposed_variables.scss */
variableService.getAllVariables() variableService.getAllVariables()
.subscribe((variables) => { .subscribe((variables) => {
this.breakPoints.XL_MIN = parseInt(variables.xlMin, 10); this.breakPoints.XL_MIN = parseInt(variables['--bs-xl-min'], 10);
this.breakPoints.LG_MIN = parseInt(variables.lgMin, 10); this.breakPoints.LG_MIN = parseInt(variables['--bs-lg-min'], 10);
this.breakPoints.MD_MIN = parseInt(variables.mdMin, 10); this.breakPoints.MD_MIN = parseInt(variables['--bs-md-min'], 10);
this.breakPoints.SM_MIN = parseInt(variables.smMin, 10); this.breakPoints.SM_MIN = parseInt(variables['--bs-sm-min'], 10);
}); });
} }

View File

@@ -0,0 +1,4 @@
export interface KeyValuePair<K, V> {
key: K;
value: V;
}

View File

@@ -1,4 +1,4 @@
import { CSSVariableAction, CSSVariableActionTypes } from './sass-helper.actions'; import { CSSVariableAction, CSSVariableActionTypes } from './css-variable.actions';
export interface CSSVariablesState { export interface CSSVariablesState {
[name: string]: string; [name: string]: string;

View File

@@ -0,0 +1,78 @@
import { TestBed } from '@angular/core/testing';
import { CSSVariableService } from './css-variable.service';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { getTestScheduler } from 'jasmine-marbles';
import { buildPaginatedList } from '../../core/data/paginated-list.model';
import { PageInfo } from '../../core/shared/page-info.model';
import { KeyValuePair } from '../key-value-pair.model';
describe('CSSVariableService', () => {
let store: MockStore;
let service: CSSVariableService;
let initialState;
const varKey1 = '--test-1';
const varValue1 = 'test-value-1';
const varKey2 = '--test-2';
const varValue2 = 'test-value-2';
const varKey3 = '--test-3';
const varValue3 = 'test-value-3';
const queryInAll = 'test';
const queryFor3 = '3';
function init() {
initialState = {
['cssVariables']: {
[varKey1]: varValue1,
[varKey2]: varValue2,
[varKey3]: varValue3,
}
};
}
beforeEach(() => {
init();
TestBed.configureTestingModule({
providers: [
CSSVariableService,
provideMockStore({ initialState }),
],
});
service = TestBed.inject(CSSVariableService as any);
store = TestBed.inject(MockStore as any);
});
it('should create', () => {
expect(service).toBeTruthy();
});
fdescribe('searchVariable', () => {
it('should return the right keys and variables in a paginated list for query that returns all 3 results', () => {
const currentPage = 1;
const pageSize = 5;
const pageInfo = new PageInfo({ currentPage, elementsPerPage: pageSize, totalPages: 1, totalElements: 3 });
const page: KeyValuePair<string, string>[] = [{ key: varKey1, value: varValue1 }, { key: varKey2, value: varValue2 }, { key: varKey3, value: varValue3 }];
const result = buildPaginatedList(pageInfo, page);
getTestScheduler().expectObservable(service.searchVariable(queryInAll, { currentPage, pageSize } as any)).toBe('a', { a: result });
});
it('should return the right keys and variables in a paginated list for query that returns only the 3rd results', () => {
const currentPage = 1;
const pageSize = 5;
const pageInfo = new PageInfo({ currentPage, elementsPerPage: pageSize, totalPages: 1, totalElements: 1 });
const page: KeyValuePair<string, string>[] = [{ key: varKey3, value: varValue3 }];
const result = buildPaginatedList(pageInfo, page);
getTestScheduler().expectObservable(service.searchVariable(queryFor3, { currentPage, pageSize } as any)).toBe('a', { a: result });
});
it('should return the right keys and variables in a paginated list that\'s not longer than the page size', () => {
const currentPage = 1;
const pageSize = 2;
const pageInfo = new PageInfo({ currentPage, elementsPerPage: pageSize, totalPages: 2, totalElements: 3 });
const page: KeyValuePair<string, string>[] = [{ key: varKey1, value: varValue1 }, { key: varKey2, value: varValue2 }];
const result = buildPaginatedList(pageInfo, page);
getTestScheduler().expectObservable(service.searchVariable(queryInAll, { currentPage, pageSize } as any)).toBe('a', { a: result });
});
});
});

View File

@@ -0,0 +1,71 @@
import { Injectable } from '@angular/core';
import { AppState, keySelector } from '../../app.reducer';
import { createSelector, MemoizedSelector, select, Store } from '@ngrx/store';
import { AddCSSVariableAction } from './css-variable.actions';
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
import { buildPaginatedList, PaginatedList } from '../../core/data/paginated-list.model';
import { Observable } from 'rxjs';
import { hasValue } from '../empty.util';
import { KeyValuePair } from '../key-value-pair.model';
import { PageInfo } from '../../core/shared/page-info.model';
@Injectable()
export class CSSVariableService {
constructor(
protected store: Store<AppState>) {
}
addCSSVariable(name: string, value: string) {
this.store.dispatch(new AddCSSVariableAction(name, value));
}
getVariable(name: string) {
return this.store.pipe(select(themeVariableByNameSelector(name)));
}
getAllVariables() {
return this.store.pipe(select(themeVariablesSelector));
}
searchVariable(query: string, paginationOptions: PaginationComponentOptions): Observable<PaginatedList<KeyValuePair<string, string>>> {
return this.store.pipe(select(themePaginatedVariablesByQuery(query, paginationOptions)));
}
}
const themeVariablesSelector = (state: AppState) => state.cssVariables;
const themeVariableByNameSelector = (name: string): MemoizedSelector<AppState, string> => {
return keySelector<string>(name, themeVariablesSelector);
};
// Split this up into two memoized selectors so the query search gets cached separately from the pagination,
// since the entire list has to be retrieved every time anyway
const themePaginatedVariablesByQuery = (query: string, pagination: PaginationComponentOptions): MemoizedSelector<AppState, PaginatedList<KeyValuePair<string, string>>> => {
return createSelector(themeVariablesByQuery(query), (pairs) => {
if (hasValue(pairs)) {
const { currentPage, pageSize } = pagination;
const startIndex = (currentPage - 1) * pageSize;
const endIndex = startIndex + pageSize;
const pairsPage = pairs.slice(startIndex, endIndex);
const totalPages = Math.ceil(pairs.length / pageSize);
const pageInfo = new PageInfo({ currentPage, elementsPerPage: pageSize, totalElements: pairs.length, totalPages });
return buildPaginatedList(pageInfo, pairsPage);
} else {
return undefined;
}
});
};
const themeVariablesByQuery = (query: string): MemoizedSelector<AppState, KeyValuePair<string, string>[]> => {
return createSelector(themeVariablesSelector, (state) => {
if (hasValue(state)) {
return Object.keys(state)
.filter((key: string) => key.includes(query))
.map((key: string) => {
return { key, value: state[key] };
});
} else {
return undefined;
}
});
};

View File

@@ -0,0 +1,46 @@
// Uses code from https://css-tricks.com/how-to-get-all-custom-properties-on-a-page-in-javascript/
const isSameDomain = (styleSheet) => {
// Internal style blocks won't have an href value
if (!styleSheet.href) {
return true;
}
return styleSheet.href.indexOf(window.location.origin) === 0;
};
/*
Determine if the given rule is a CSSStyleRule
See: https://developer.mozilla.org/en-US/docs/Web/API/CSSRule#Type_constants
*/
const isStyleRule = (rule) => rule.type === 1;
/**
* Get all custom properties on a page
* @return array<array[string, string]>
* ex; [["--color-accent", "#b9f500"], ["--color-text", "#252525"], ...]
*/
export const getCSSCustomPropIndex = (document: Document) =>
// styleSheets is array-like, so we convert it to an array.
// Filter out any stylesheets not on this domain
[...document.styleSheets]
.filter(isSameDomain)
.reduce(
(finalArr, sheet) =>
finalArr.concat(
// cssRules is array-like, so we convert it to an array
[...sheet.cssRules].filter(isStyleRule).reduce((propValArr, rule: any) => {
const props = [...rule.style]
.map((propName) => [
propName.trim(),
rule.style.getPropertyValue(propName).trim()
])
// Discard any props that don't start with "--". Custom props are required to.
.filter(([propName]) => propName.indexOf('--') === 0);
return [...propValArr, ...props];
}, [])
),
[]
);

View File

@@ -1,30 +0,0 @@
import { Injectable } from '@angular/core';
import { AppState, keySelector } from '../../app.reducer';
import { MemoizedSelector, select, Store } from '@ngrx/store';
import { AddCSSVariableAction } from './sass-helper.actions';
@Injectable()
export class CSSVariableService {
constructor(
protected store: Store<AppState>) {
}
addCSSVariable(name: string, value: string) {
this.store.dispatch(new AddCSSVariableAction(name, value));
}
getVariable(name: string) {
return this.store.pipe(select(themeVariableByNameSelector(name)));
}
getAllVariables() {
return this.store.pipe(select(themeVariablesSelector));
}
}
const themeVariablesSelector = (state: AppState) => state.cssVariables;
const themeVariableByNameSelector = (name: string): MemoizedSelector<AppState, string> => {
return keySelector<string>(name, themeVariablesSelector);
};