UNPKG

apphouse

Version:

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

199 lines (186 loc) 5.81 kB
import { CSSProperties } from 'glamor'; import { camelCase } from './string/camelCase'; import { colorsLookupTable } from '../themes/colors.lookup'; import { Theme } from '../themes/Theme'; import { getStyleTokenReferenceType, getValueReferenceStringFromObject, hasColorReference } from '../themes/utils/tokens.utils'; import { isSelector } from './CSS'; import { CssPropertyStyle, StyleTokenReference } from '../themes/style.interface'; /** * Get styles for focus events * @param keyboard styles for keyboard focus * @param mouse styles for mouse focus * @returns */ export function createFocusPseudoclassicSelector( keyboard: CSSProperties ): CSSProperties { return { ':focus': { outline: 'none', ...keyboard, ':focus-visible': { outline: 'none', ...keyboard }, ':not(:focus-visible)': { outline: 'none' // ...mouse } } }; } export const parseCssPropertyStyle = (value: CssPropertyStyle[]): string => { const v = value?.map((style) => { if (style.isSelector) { if (Array.isArray(style.value)) { return `"${style.property}": {${parseCssPropertyStyle(style.value)}}`; } return ''; } else { const property = camelCase(style?.property); return `"${property || ''}": "${style?.value || ''}"`; } }); return `${v.join(', ')}`; }; export const toCss = (value: CssPropertyStyle[]): object => { if (!value) { return {}; } try { return JSON.parse(`{${parseCssPropertyStyle(value)}}`); } catch (error) { console.log({ error, value }); return {}; } }; export class StyleUtils { /** * Convert Css Properties into CssPropertyStyle[] * @param value style in the format of CssProperties (css in JS) * @param lookup a lookup table to convert css properties to css property styles, if available * @param namespace to better create the style, we can namespace the style this is the value that * that will be used to create the base component * @returns CssPropertyStyle[] */ static toCssPropertyStyle = ( value: CSSProperties, lookup: { [id: string]: string }, namespace?: string ): CssPropertyStyle[] => { const convert = (v: CSSProperties): CssPropertyStyle[] => { return Object.keys(v).map((k) => { const currentValue = v[k]; const isColorKey = hasColorReference(k); if (isColorKey) { const itemInLookup: any = namespace ? colorsLookupTable[namespace] : undefined; let colorReference: string | undefined; if (itemInLookup) { colorReference = itemInLookup[k]; } const color = colorReference ? `theme.${colorReference}` : currentValue; const cssPropertyValue: CssPropertyStyle = { property: k, value: color, isSelector: isSelector(k), reference: colorReference ? { type: 'color', value: color, key: color } : null }; return cssPropertyValue; } if ( typeof currentValue !== 'string' && typeof currentValue !== 'number' ) { const cssPropertyValue: CssPropertyStyle = { property: k, value: convert(currentValue), isSelector: isSelector(k), reference: null }; return cssPropertyValue; } else { const referenceValue = getValueReferenceStringFromObject( currentValue, lookup, namespace ); const reference: StyleTokenReference | null = referenceValue && lookup[referenceValue] ? { type: getStyleTokenReferenceType(referenceValue), value: currentValue, key: referenceValue } : null; const cssPropertyValue: CssPropertyStyle = { property: k, value: referenceValue || currentValue, isSelector: isSelector(k), reference: reference }; return cssPropertyValue; } }); }; const css = convert(value); return css; }; // static toSnippetFromStyle = (style: Style): CssSnippet => { // const snippet = new CssSnippet({ // id: style.id, // value: style.code, // map: {}, // TODO: add map // baseComponent: style.baseComponent, // description: style.variant, // previewWithTag: style.previewWithTag, // permission: "private", // assuming private here but, TODO // }); // return snippet; // }; /** * Convert a themed or tokenized style to a css style with raw values * @param style with color or design tokens * @returns css style with raw values */ static toRawStyle = (style: CSSProperties, theme: Theme): CSSProperties => { const rawStyle: CSSProperties = {}; Object.keys(style).forEach((property) => { const value = style[property]; let rawValue = value; if (typeof value === 'string') { if (value.startsWith('theme.')) { // value is a color token // get the value from the theme Object.keys(theme.palette).forEach((paletteId) => { const palette = theme.palette[paletteId]; if (palette.id === paletteId) { // palette is the one we are looking for const colorKey = value.replace('theme.', ''); const color = palette.colors[colorKey]; rawValue = color; } }); } } rawStyle[property] = rawValue; }); return rawStyle; }; }