@difizen/mana-core
Version:
133 lines (116 loc) • 3.81 kB
text/typescript
import {
DisposableCollection,
Disposable,
Emitter,
objects,
isPromiseLike,
} from '@difizen/mana-common';
import { singleton, inject } from '@difizen/mana-syringe';
import { localStorageService } from '../common';
import type { StorageService } from '../common';
import { DefaultVariablePrefix } from './protocol';
import type { CssVariable, VariableDefinition } from './protocol';
import type { ExtraTokens } from './theme-service';
import { ThemeService } from './theme-service';
/**
* It should be implemented by an extension, e.g. by the monaco extension.
*/
export class BaseVariableRegistry {
protected readonly themeService: ThemeService;
protected get definitionList(): VariableDefinition[] {
return [...this.definitionMap.values()];
}
protected definitionMap: Map<string, VariableDefinition> = new Map();
protected storageService: StorageService = localStorageService;
protected readonly onDidChangeEmitter = new Emitter<void>();
readonly onDidChange = this.onDidChangeEmitter.event;
protected fireDidChange(): void {
this.onDidChangeEmitter.fire(undefined);
}
/**
* @deprecated using getDefinitionIds instead
*
*/
getVariables(): IterableIterator<string> {
return this.getDefinitionIds();
}
getDefinitionIds(): IterableIterator<string> {
return this.definitionMap.keys();
}
getCurrentCssVariables(): CssVariable[] {
const cssVars: CssVariable[] = [];
for (const id of this.getDefinitionIds()) {
const variable = this.toCurrentCssVariable(id);
if (variable) {
cssVars.push(variable);
}
}
return cssVars;
}
toCurrentCssVariable(id: string): CssVariable | undefined {
const name = this.toCssVariableName(id);
const maybeValue = this.storageService.getData<string>(name);
if (!isPromiseLike(maybeValue) && maybeValue) {
return { name, value: maybeValue };
}
const value = this.getCurrentDefinitionValue(id);
if (!value) {
return undefined;
}
return { name, value };
}
toCssVariableName(id: string, prefix?: string): string {
const def = this.definitionMap.get(id);
let currentPrefix = prefix;
if (!currentPrefix) {
currentPrefix = def?.prefix === undefined ? DefaultVariablePrefix : def?.prefix;
}
if (currentPrefix) {
return `--${currentPrefix}-${id.replace(/\./g, '-')}`;
}
return `--${id.replace(/\./g, '-')}`;
}
getCurrentDefinitionValue(id: string): string | undefined {
const theme = this.themeService.getActiveTheme();
const { type, extraTokens } = theme;
if (extraTokens && extraTokens.basic && extraTokens.basic[id]) {
return extraTokens.basic[id];
}
const definition = this.definitionMap.get(id);
if (definition && definition.defaults && definition.defaults[type]) {
return definition.defaults[type];
}
return undefined;
}
setCurrentDefinitionValue(
name: string,
value: string,
tokens: ExtraTokens = {},
): void {
objects.mixin(objects.deepClone(name), {
extraTokens: { ...tokens },
});
this.storageService.setData(name, value);
this.fireDidChange();
}
register(...definitions: VariableDefinition[]): Disposable {
const result = new DisposableCollection(
...definitions.map((definition) => this.doRegister(definition)),
);
this.fireDidChange();
return result;
}
protected doRegister(definition: VariableDefinition): Disposable {
this.definitionMap.set(definition.id, {
id: definition.id,
prefix: definition.prefix,
defaults: definition.defaults,
description: definition.description,
});
return Disposable.create(() => {
this.definitionMap.delete(definition.id);
});
}
}