UNPKG

apphouse

Version:

Component library for React that uses observable state management and theme-able components.

183 lines (158 loc) 4.52 kB
import { uuidv4 } from '@firebase/util'; import { makeAutoObservable } from 'mobx'; import { getColorFromColorString } from './utils/color.utils'; import { Color } from './Color'; import colorSort from 'color-sorter'; import { ColorType } from './utils/color.interface'; import { Colors, DEFAULT_THEME_MODE, PaletteType, ThemeModeType } from './palette.interface'; export class Palette { title: string; id: string; description?: string; mode: ThemeModeType; colors: Colors; sortColorsBy: 'key' | 'color'; /** * The theme id for which this palette is for */ themeId: string; /** * When palette is copied or imported from another theme it will have a * reference to the original theme id */ referenceThemeId: string; constructor(palette?: PaletteType) { this.title = palette?.title || 'Untitled Palette'; this.id = palette?.id || Palette.autoGenId(this.title); this.description = palette?.description; this.mode = palette?.mode || DEFAULT_THEME_MODE; this.sortColorsBy = 'key'; this.colors = Palette.colorify(palette?.colors); this.referenceThemeId = palette?.referenceThemeId || ''; this.themeId = palette?.themeId || ''; makeAutoObservable(this); } get objectify(): PaletteType { const colors: ColorType[] = []; Object.keys(this.colors).forEach((key) => { colors.push(this.colors[key].objectify); }); return { title: this.title || 'Untitled Palette', id: this.id, description: this.description || '', mode: this.mode, colors: colors, themeId: this.themeId || '', referenceThemeId: this.referenceThemeId || '' }; } static autoGenId = (title: string) => { if (!title) { return uuidv4(); } return title?.split(' ').join('-').toLocaleLowerCase(); }; get sortedColors() { const colors = this.colorsList; const colorsBykey: Colors = {}; colors.forEach((color) => { if (color.rgbString) { colorsBykey[color.rgbString] = color; } else { console.warn('Attempted to sort colors that do not exist'); } }); const rgbaColors = Object.keys(colorsBykey); const sortedColorKeys: string[] = colorSort(rgbaColors); const sortedColors: Color[] = []; sortedColorKeys.forEach((colorKey) => { sortedColors.push(colorsBykey[colorKey]); }); return sortedColors; } setTitle = (value: string) => { this.title = value; this.setId(Palette.autoGenId(value)); }; setId = (id: string) => { this.id = id; }; addColors = (colors: ColorType[]) => { colors.forEach((color) => { this.colors[color.id] = new Color(color); }); }; setColors = (colors: Record<string, ColorType>) => { Object.keys(colors).forEach((key) => { const color = colors[key]; if (typeof color === 'string') { // user may be attempting to add a raw color // let's attempt to normalize it const nColor = getColorFromColorString(color, key); if (nColor) { this.colors[key] = nColor; } } else { this.colors[key] = new Color(color); } }); }; appendColors = (colors: Colors) => { Object.keys(colors).forEach((key) => { let color = colors[key]; this.setColor(color); }); }; setColor = (color: Color) => { this.colors[color.id] = color; }; setMode = (mode: ThemeModeType) => { this.mode = mode; }; setDescription = (value: string) => { this.description = value; }; setReferenceThemeId = (id: string) => { this.referenceThemeId = id; }; get colorsList() { return Object.keys(this.colors).map((key) => this.colors[key]); } addColor = (key: string, value: ColorType) => { const color = new Color(value); this.colors[key] = color; }; removeColor = (key: string) => { if (this.colors[key]) { delete this.colors[key]; } }; deleteAllColors = () => { this.colors = {}; }; getColorFromKey = (key: string): string | undefined => { const color = this.colors[key]; return color?.rgbString; }; /** * ColorType[] --> Record<string, Color> * @param colors colors list * @returns the colors list in Color */ static colorify = (colors?: ColorType[]): Colors => { if (!colors) { return {}; } const _colors: Colors = {}; colors.forEach((color: ColorType) => { _colors[color.id] = new Color(color); }); return _colors; }; }