@aesthetic/core
Version:
Aesthetic is a powerful type-safe, framework agnostic, CSS-in-JS library for styling components.
87 lines (69 loc) • 2.31 kB
text/typescript
import { Engine, RenderOptions, ThemeRule } from '@aesthetic/types';
import { arrayLoop, isObject, objectLoop, toArray } from '@aesthetic/utils';
import { SheetRenderResult } from './types';
export function renderTheme<Input, Output>(
engine: Engine<Input, Output>,
theme: ThemeRule<Input>,
options: RenderOptions,
): SheetRenderResult<Output> {
const resultSheet: SheetRenderResult<Output> = { root: {} };
objectLoop(theme['@font-face'], (fontFaces, fontFamily) => {
arrayLoop(toArray(fontFaces), (fontFace) =>
engine.renderFontFace({ ...fontFace, fontFamily }, options),
);
});
arrayLoop(toArray(theme['@import']), (importPath) => engine.renderImport(importPath!, options));
objectLoop(theme['@keyframes'], (keyframes, animationName) => {
engine.renderKeyframes(keyframes, animationName, options);
});
if (theme['@root']) {
resultSheet.root!.result = engine.renderRuleGrouped(theme['@root'], {
...options,
type: 'global',
}).result;
}
if (theme['@variables']) {
engine.setRootVariables(theme['@variables']);
}
return resultSheet;
}
export function renderComponent<Input, Output>(
engine: Engine<Input, Output>,
styles: Record<string, Input>,
options: RenderOptions,
): SheetRenderResult<Output> {
const resultSheet: SheetRenderResult<Output> = {};
const rankings = {};
objectLoop(styles, (style, selector) => {
// eslint-disable-next-line no-multi-assign
const meta = (resultSheet[selector] ||= {});
// At-rule
if (selector.startsWith('@')) {
if (__DEV__) {
throw new SyntaxError(
`At-rules may not be defined at the root of a style sheet, found "${selector}".`,
);
}
// Rule
} else if (isObject(style)) {
const result = engine.renderRule(style, { ...options, debugName: selector, rankings });
meta.result = result.result;
if (result.variants.length > 0) {
const types = new Set<string>();
arrayLoop(result.variants, (variant) => {
arrayLoop(variant.types, (type) => {
types.add(type.split(':')[0]);
});
});
meta.variants = result.variants;
meta.variantTypes = types;
}
// Unknown
} else if (__DEV__) {
throw new Error(
`Invalid rule for "${selector}". Must be an object (style declaration) or string (class name).`,
);
}
});
return resultSheet;
}