@aesthetic/style
Version:
A low-level, high-performance, atomic-based CSS-in-JS style engine.
161 lines (123 loc) • 5.59 kB
JavaScript
// Bundled with Packemon: https://packemon.dev
// Platform: browser, Support: stable, Format: esm
import { arrayLoop, joinQueries, objectLoop } from '@aesthetic/utils';
import { c as createSheetManager, a as createStyleElements } from './bundle-f0e57f15.js';
export { c as createSheetManager, a as createStyleElements, g as getStyleElement } from './bundle-f0e57f15.js';
import { S as STYLE_RULE, M as MEDIA_RULE, a as SUPPORTS_RULE, F as FONT_FACE_RULE, K as KEYFRAMES_RULE, I as IMPORT_RULE, c as createCacheKey, b as createStyleEngine, f as formatVariable } from './bundle-30cd3868.js';
export { F as FONT_FACE_RULE, I as IMPORT_RULE, K as KEYFRAMES_RULE, e as KEYFRAME_RULE, M as MEDIA_RULE, S as STYLE_RULE, a as SUPPORTS_RULE, g as VARIANT_COMBO_PATTERN, V as VARIANT_PATTERN, c as createCacheKey, d as createCacheManager, x as createDeclaration, y as createDeclarationBlock, b as createStyleEngine, s as formatDeclaration, t as formatFontFace, u as formatImport, q as formatProperty, v as formatRule, r as formatValue, f as formatVariable, w as formatVariableBlock, h as insertAtRule, j as insertImportRule, i as insertRule, k as isAtRule, l as isImportRule, m as isNestedSelector, n as isUnitlessProperty, o as isValidValue, p as isVariable } from './bundle-30cd3868.js'; // eslint-disable-next-line unicorn/better-regex, unicorn/no-unsafe-regex
const RULE_PATTERN = /^\.(\w+)((?::|\[|>|~|\+|\*)[^{]+)?\s*\{\s*([^:]+):\s*([^}]+)\s*\}$/i;
const FONT_FAMILY = /font-family:([^;]+)/;
const IMPORT_URL = /url\(["']?([^)]+)["']?\)/;
function addRuleToCache(engine, rule, rank, media = '', supports = '') {
const [, className, rawSelector = '', property, rawValue] = rule.match(RULE_PATTERN); // Has trailing spaces
const selector = rawSelector.trim(); // Has trailing semi-colon
const value = rawValue.slice(0, -1);
engine.cacheManager.write(createCacheKey(property, value, {
media,
selector,
supports
}), {
rank,
result: className
});
}
function hydrate(engine, sheet) {
let rank = 0;
const gatherStack = (rule, prevMedia = '', prevSupports = '') => {
const condition = rule.conditionText || rule.media.mediaText;
let media = prevMedia;
let supports = prevSupports;
if (rule.type === MEDIA_RULE) {
media = joinQueries(media, condition);
} else if (rule.type === SUPPORTS_RULE) {
supports = joinQueries(supports, condition);
}
arrayLoop(rule.cssRules, child => {
if (child.type === STYLE_RULE) {
addRuleToCache(engine, child.cssText, rank, media, supports);
} else if (child.type === MEDIA_RULE || child.type === SUPPORTS_RULE) {
gatherStack(child, media, supports);
}
});
};
arrayLoop(sheet.cssRules, (rule, currentRank) => {
// Standard
if (rule.type === STYLE_RULE) {
if (!rule.cssText.startsWith(':root')) {
addRuleToCache(engine, rule.cssText, currentRank);
}
return;
} // Conditions
if (rule.type === MEDIA_RULE || rule.type === SUPPORTS_RULE) {
rank = currentRank;
gatherStack(rule);
return;
} // Globals
const css = rule.cssText;
let cacheKey = '';
if (rule.type === FONT_FACE_RULE) {
const fontFamilyName = css.match(FONT_FAMILY);
if (fontFamilyName) {
cacheKey = fontFamilyName[1].trim();
}
}
if (rule.type === KEYFRAMES_RULE) {
cacheKey = css.slice(0, css.indexOf('{')).replace('@keyframes', '').trim();
}
if (rule.type === IMPORT_RULE) {
const importPath = css.match(IMPORT_URL);
if (importPath) {
[cacheKey] = importPath;
}
}
if (cacheKey) {
engine.cacheManager.write(cacheKey, {
result: ''
});
}
});
}
function hydrateStyles(engine) {
const styles = document.querySelectorAll('style[data-aesthetic-hydrate-index]');
arrayLoop(styles, style => {
hydrate(engine, style.sheet);
if (engine.ruleCount === -1) {
engine.ruleCount = Number(style.getAttribute('data-aesthetic-rule-count'));
} // Remove so that we avoid unnecessary hydration
style.removeAttribute('data-aesthetic-hydrate-index');
style.removeAttribute('data-aesthetic-rule-count');
});
return styles.length > 0;
}
/**
* @copyright 2020, Miles Johnson
* @license https://opensource.org/licenses/MIT
*/
function setDirection(direction) {
document.documentElement.setAttribute('dir', direction);
} // Set CSS variables to :root
function setRootVariables(vars) {
objectLoop(vars, (value, key) => {
document.documentElement.style.setProperty(formatVariable(key), String(value));
});
} // Set active theme class names on the `body`
function setTheme(classNames) {
document.body.className = classNames.join(' ');
}
function createClientEngine(options = {}) {
const direction = document.documentElement.getAttribute('dir') ?? document.body.getAttribute('dir') ?? 'ltr';
const engine = createStyleEngine({
direction,
sheetManager: createSheetManager(createStyleElements()),
...options
}); // Match against browser preferences
engine.prefersColorScheme = scheme => matchMedia(`(prefers-color-scheme: ${scheme})`).matches;
engine.prefersContrastLevel = level => matchMedia(`(prefers-contrast: ${level})`).matches; // Handle DOM specific logic
engine.setDirection = setDirection;
engine.setRootVariables = setRootVariables;
engine.setTheme = setTheme; // Attempt to hydrate styles immediately
hydrateStyles(engine);
return engine;
}
export { createClientEngine };
//# sourceMappingURL=index.js.map