94233: applied feedback for css variables

This commit is contained in:
lotte
2022-09-16 12:40:04 +02:00
parent ac094aa623
commit 89ba24fc1c
5 changed files with 96 additions and 51 deletions

View File

@@ -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() {

View File

@@ -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<string, string>[];
export type CSSVariableAction = AddCSSVariableAction;
constructor(variables: KeyValuePair<string, string>[]) {
this.payload = variables;
}
}
export class ClearCSSVariablesAction implements Action {
type = CSSVariableActionTypes.CLEAR;
constructor() {
}
}
export type CSSVariableAction = AddCSSVariableAction | AddAllCSSVariablesAction | ClearCSSVariablesAction;

View File

@@ -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<string, string>) => {return {[key]: value}}));
} case CSSVariableActionTypes.CLEAR: {
return initialState;
}
default: {
return state;

View File

@@ -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<AppState>) {
}
@@ -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<string, string>[]) {
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<string> {
return this.store.pipe(select(themeVariableByNameSelector(name)));
}
/**
* Returns the CSSVariablesState of the store containing all variables
*/
getAllVariables() {
getAllVariables(): Observable<CSSVariablesState> {
return this.store.pipe(select(themeVariablesSelector));
}
@@ -50,6 +81,40 @@ export class CSSVariableService {
searchVariable(query: string, paginationOptions: PaginationComponentOptions): Observable<PaginatedList<KeyValuePair<string, string>>> {
return this.store.pipe(select(themePaginatedVariablesByQuery(query, paginationOptions)));
}
/**
* Get all custom properties on a page
* @return array<KeyValuePair<string, string>>
* ex; [{key: "--color-accent", value: "#b9f500"}, {key: "--color-text", value: "#252525"}, ...]
*/
getCSSVariablesFromStylesheets(document: Document): KeyValuePair<string, string>[]
{
// 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<string, string>;
}
)
// Discard any props that don't start with "--". Custom props are required to.
.filter(({ key }: KeyValuePair<string, string>) => key.indexOf('--') === 0);
return [...propValArr, ...props];
}, [])
),
[]
);
}
}
const themeVariablesSelector = (state: AppState) => state.cssVariables;

View File

@@ -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<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];
}, [])
),
[]
);
import { KeyValuePair } from '../key-value-pair.model';