From 89ba24fc1c1df13cfecdf12ebe59883901980d28 Mon Sep 17 00:00:00 2001 From: lotte Date: Fri, 16 Sep 2022 12:40:04 +0200 Subject: [PATCH] 94233: applied feedback for css variables --- src/app/app.component.ts | 6 +- .../sass-helper/css-variable.actions.ts | 20 +++++- .../sass-helper/css-variable.reducer.ts | 6 ++ .../sass-helper/css-variable.service.ts | 71 ++++++++++++++++++- .../shared/sass-helper/css-variable.utils.ts | 44 +----------- 5 files changed, 96 insertions(+), 51 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 0c38d2bd64..32753ce74c 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -48,7 +48,6 @@ import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service'; import { IdleModalComponent } from './shared/idle-modal/idle-modal.component'; import { getDefaultThemeConfig } from '../config/config.util'; import { AppConfig, APP_CONFIG } from 'src/config/app-config.interface'; -import { getCSSCustomPropIndex } from './shared/sass-helper/css-variable.utils'; @Component({ selector: 'ds-app', @@ -181,9 +180,8 @@ export class AppComponent implements OnInit, AfterViewInit { } private storeCSSVariables() { - getCSSCustomPropIndex(this.document).forEach(([prop, val]) => { - this.cssService.addCSSVariable(prop, val); - }); + this.cssService.clearCSSVariables(); + this.cssService.addCSSVariables(this.cssService.getCSSVariablesFromStylesheets(this.document)); } ngAfterViewInit() { diff --git a/src/app/shared/sass-helper/css-variable.actions.ts b/src/app/shared/sass-helper/css-variable.actions.ts index 144904646e..93225f9426 100644 --- a/src/app/shared/sass-helper/css-variable.actions.ts +++ b/src/app/shared/sass-helper/css-variable.actions.ts @@ -1,5 +1,6 @@ import { Action } from '@ngrx/store'; import { type } from '../ngrx/type'; +import { KeyValuePair } from '../key-value-pair.model'; /** * For each action type in an action group, make a simple @@ -11,6 +12,8 @@ import { type } from '../ngrx/type'; */ export const CSSVariableActionTypes = { ADD: type('dspace/css-variables/ADD'), + ADD_ALL: type('dspace/css-variables/ADD_ALL'), + CLEAR: type('dspace/css-variables/CLEAR'), }; export class AddCSSVariableAction implements Action { @@ -24,5 +27,20 @@ export class AddCSSVariableAction implements Action { this.payload = {name, value}; } } +export class AddAllCSSVariablesAction implements Action { + type = CSSVariableActionTypes.ADD_ALL; + payload: KeyValuePair[]; -export type CSSVariableAction = AddCSSVariableAction; + constructor(variables: KeyValuePair[]) { + this.payload = variables; + } +} + +export class ClearCSSVariablesAction implements Action { + type = CSSVariableActionTypes.CLEAR; + + constructor() { + } +} + +export type CSSVariableAction = AddCSSVariableAction | AddAllCSSVariablesAction | ClearCSSVariablesAction; diff --git a/src/app/shared/sass-helper/css-variable.reducer.ts b/src/app/shared/sass-helper/css-variable.reducer.ts index a2d150dabf..405cbf5df4 100644 --- a/src/app/shared/sass-helper/css-variable.reducer.ts +++ b/src/app/shared/sass-helper/css-variable.reducer.ts @@ -1,4 +1,5 @@ import { CSSVariableAction, CSSVariableActionTypes } from './css-variable.actions'; +import { KeyValuePair } from '../key-value-pair.model'; export interface CSSVariablesState { [name: string]: string; @@ -16,6 +17,11 @@ export function cssVariablesReducer(state = initialState, action: CSSVariableAct case CSSVariableActionTypes.ADD: { const variable = action.payload; return Object.assign({}, state, { [variable.name]: variable.value }); + } case CSSVariableActionTypes.ADD_ALL: { + const variables = action.payload; + return Object.assign({}, state, ...variables.map(({ key, value }: KeyValuePair) => {return {[key]: value}})); + } case CSSVariableActionTypes.CLEAR: { + return initialState; } default: { return state; diff --git a/src/app/shared/sass-helper/css-variable.service.ts b/src/app/shared/sass-helper/css-variable.service.ts index bdcba8503e..9ba9dfca3c 100644 --- a/src/app/shared/sass-helper/css-variable.service.ts +++ b/src/app/shared/sass-helper/css-variable.service.ts @@ -1,19 +1,35 @@ 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 { AddAllCSSVariablesAction, AddCSSVariableAction, ClearCSSVariablesAction } 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'; +import { CSSVariablesState } from './css-variable.reducer'; /** * This service deals with adding and retrieving CSS variables to and from the store */ @Injectable() export class CSSVariableService { + 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 + */ + isStyleRule = (rule) => rule.type === 1; + constructor( protected store: Store) { } @@ -27,18 +43,33 @@ export class CSSVariableService { this.store.dispatch(new AddCSSVariableAction(name, value)); } + /** + * Adds multiples CSS variables to the store + * @param variables The key-value pairs with the CSS variables to be added + */ + addCSSVariables(variables: KeyValuePair[]) { + this.store.dispatch(new AddAllCSSVariablesAction(variables)); + } + + /** + * Clears all CSS variables ƒrom the store + */ + clearCSSVariables() { + this.store.dispatch(new ClearCSSVariablesAction()); + } + /** * Returns the value of a specific CSS key * @param name The name/key of the CSS value */ - getVariable(name: string) { + getVariable(name: string): Observable { return this.store.pipe(select(themeVariableByNameSelector(name))); } /** * Returns the CSSVariablesState of the store containing all variables */ - getAllVariables() { + getAllVariables(): Observable { return this.store.pipe(select(themeVariablesSelector)); } @@ -50,6 +81,40 @@ export class CSSVariableService { searchVariable(query: string, paginationOptions: PaginationComponentOptions): Observable>> { return this.store.pipe(select(themePaginatedVariablesByQuery(query, paginationOptions))); } + + /** + * Get all custom properties on a page + * @return array> + * ex; [{key: "--color-accent", value: "#b9f500"}, {key: "--color-text", value: "#252525"}, ...] + */ + getCSSVariablesFromStylesheets(document: Document): KeyValuePair[] + { + // styleSheets is array-like, so we convert it to an array. + // Filter out any stylesheets not on this domain + return [...document.styleSheets] + .filter(this.isSameDomain) + .reduce( + (finalArr, sheet) => + finalArr.concat( + // cssRules is array-like, so we convert it to an array + [...sheet.cssRules].filter(this.isStyleRule).reduce((propValArr, rule: any) => { + const props = [...rule.style] + .map((propName) => { + return { + key: propName.trim(), + value: rule.style.getPropertyValue(propName).trim() + } as KeyValuePair; + } + ) + // Discard any props that don't start with "--". Custom props are required to. + .filter(({ key }: KeyValuePair) => key.indexOf('--') === 0); + + return [...propValArr, ...props]; + }, []) + ), + [] + ); + } } const themeVariablesSelector = (state: AppState) => state.cssVariables; diff --git a/src/app/shared/sass-helper/css-variable.utils.ts b/src/app/shared/sass-helper/css-variable.utils.ts index 63a93b8bc4..05e3074f98 100644 --- a/src/app/shared/sass-helper/css-variable.utils.ts +++ b/src/app/shared/sass-helper/css-variable.utils.ts @@ -1,46 +1,4 @@ // 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 - * 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]; - }, []) - ), - [] - ); +import { KeyValuePair } from '../key-value-pair.model';