/** * CSS Template Literal Utilities * Provides styled-components-like functionality for Fluent Grow */ let classCounter = 0; /** * Generates a unique class name */ function generateClassName(): string { return `fg-css-${(++classCounter).toString(36)}`; } /** * Injects CSS into the document head */ function injectCSS(css: string, className: string): void { if (typeof document === 'undefined') return; const styleId = `fluent-css-${className}`; // Check if style already exists if (document.getElementById(styleId)) return; const style = document.createElement('style'); style.id = styleId; style.textContent = css; document.head.appendChild(style); } /** * CSS template literal function * Usage: css`selector { property: value; }` */ export function css(strings: TemplateStringsArray, ...values: any[]): string { // Combine template strings with interpolated values const cssText = strings.reduce((result, string, i) => { const value = values[i] || ''; return result + string + value; }, ''); const className = generateClassName(); // Wrap CSS with the generated class if it doesn't already have a selector const wrappedCSS = cssText.trim().startsWith('.') || cssText.trim().startsWith('@') || cssText.trim().includes('{') ? cssText.replace(/^(\s*)([^{]+)(\s*{)/, `$1.${className} $2$3`) : `.${className} { ${cssText} }`; injectCSS(wrappedCSS, className); return className; } /** * Creates a stylesheet from an object */ export function createStyleSheet(styles: Record>): string { const className = generateClassName(); const cssRules = Object.entries(styles).map(([selector, rules]) => { if (typeof rules === 'string') { return `.${className}${selector} { ${rules} }`; } const declarations = Object.entries(rules) .map(([property, value]) => `${property}: ${value}`) .join('; '); return `.${className}${selector} { ${declarations} }`; }).join('\n'); injectCSS(cssRules, className); return className; } /** * Global CSS injection (no class wrapping) */ export function globalCSS(strings: TemplateStringsArray, ...values: any[]): void { const cssText = strings.reduce((result, string, i) => { const value = values[i] || ''; return result + string + value; }, ''); const id = `global-${generateClassName()}`; injectCSS(cssText, id); } /** * Keyframes animation helper */ export function keyframes(strings: TemplateStringsArray, ...values: any[]): string { const cssText = strings.reduce((result, string, i) => { const value = values[i] || ''; return result + string + value; }, ''); const animationName = `animation-${generateClassName()}`; const keyframeCSS = `@keyframes ${animationName} { ${cssText} }`; injectCSS(keyframeCSS, animationName); return animationName; } /** * Media query helper */ export function media(query: string, styles: string): string { const className = generateClassName(); const mediaCSS = `@media ${query} { .${className} { ${styles} } }`; injectCSS(mediaCSS, className); return className; } /** * Container query helper */ export function container(query: string, styles: string): string { const className = generateClassName(); const containerCSS = `@container ${query} { .${className} { ${styles} } }`; injectCSS(containerCSS, className); return className; }