/// /// Copyright 2015-2026 Micro Focus or one of its affiliates. /// /// Licensed under the Apache License, Version 2.0 (the "License"); /// you may not use this file except in compliance with the License. /// You may obtain a copy of the License at /// /// http://www.apache.org/licenses/LICENSE-2.0 /// /// Unless required by applicable law or agreed to in writing, software /// distributed under the License is distributed on an "AS IS" BASIS, /// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. /// See the License for the specific language governing permissions and /// limitations under the License. /// import { inject, Injectable } from '@angular/core'; import { ColorSet, colorSets, COLOR_SET_TOKEN } from './color-sets/index'; import { ThemeColor } from './theme-color'; @Injectable() export class ColorService { private _colorSet = inject(COLOR_SET_TOKEN, { optional: true }); /** Set the default theme to the Keppel colorset */ private _theme: Readonly; /** Allow the color set to be provided in a forRoot function otherwise set it to the Keppel theme by default */ constructor() { // resolve the theme based on the colorset this._theme = this.getTheme(this._colorSet); } /** * Get a ThemeColor object from a color name * @param colorName The name of the color from the color palette */ getColor(colorName: ColorIdentifier): ThemeColor { // get the matching ThemeColor from the active theme const themeColor = this._theme[this.resolveColorName(colorName)]; // if there is not a match then throw an error if (!themeColor) { throw new Error('Color not found: ' + colorName); } return new ThemeColor( themeColor.getRed(), themeColor.getGreen(), themeColor.getBlue(), themeColor.getAlpha() ); } /** * Get the active color set */ getColorSet(): ColorSet { return this._colorSet; } /** * Define the current color set and produce a Theme from it */ setColorSet(colorSet: ColorSet): void { this._colorSet = colorSet; this._theme = this.getTheme(colorSet); } /** * Resolve a color value. This may be the name of a color from the color set * or it may simply be a hex or rgb(a) color value. This function will return * a CSS color value regardless of which one of these formats it is * @param value The color name, hex code or rgb(a) value to resolve * @returns If the color is the name of a color in the set, the `rgba` color will be returned, otherwise the original CSS value will be returned. */ resolve(value: string): string { if (!value) { return; } const colorName = this.resolveColorName(value); for (const color in this._theme) { if (colorName === color.toLowerCase()) { return this.getColor(colorName).toRgba(); } } return value; } /** * Converts a color name to an appropriate ColorSet name. For example * a color may be written in lower-camel-case, however color sets are in * kebab-case. This will convert to the appropriate naming format * @param colorName The color name to resolve */ resolveColorName(colorName: string = ''): string { return colorName.replace(/\s+/g, '-').toLowerCase(); } /** Determine if the current colorset has a specific color */ colorExists(name: string): boolean { return !!Object.keys(this._theme).find(colorName => colorName === this.resolveColorName(name)); } /** Create a theme from a colorset */ private getTheme(colorSet: ColorSet): Readonly { // create a new theme object const theme: Theme = {}; // ensure we have a colorset if (!colorSet) { colorSet = colorSets.keppel; } // iterate over each hex code and convert it to a theme color for (const color in colorSet.colorValueSet) { theme[color] = ThemeColor.parse(colorSet.colorValueSet[color]); } return theme; } } export interface Theme { [name: string]: ThemeColor; } export type ColorIdentifier = string;