// @flow import RuleList from '../RuleList' import type {CSSMediaRule, Rule, RuleOptions, ToCssOptions, JssStyle, ContainerRule} from '../types' const defaultToStringOptions = { indent: 1, children: true } const atRegExp = /@([\w-]+)/ /** * Conditional rule for @media, @supports */ export class ConditionalRule implements ContainerRule { type: string = 'conditional' at: string key: string query: string rules: RuleList options: RuleOptions isProcessed: boolean = false renderable: ?CSSMediaRule constructor(key: string, styles: Object, options: RuleOptions) { this.key = key const atMatch = key.match(atRegExp) this.at = atMatch ? atMatch[1] : 'unknown' // Key might contain a unique suffix in case the `name` passed by user was duplicate. this.query = options.name || `@${this.at}` this.options = options this.rules = new RuleList({...options, parent: this}) for (const name in styles) { this.rules.add(name, styles[name]) } this.rules.process() } /** * Get a rule. */ getRule(name: string): Rule { return this.rules.get(name) } /** * Get index of a rule. */ indexOf(rule: Rule): number { return this.rules.indexOf(rule) } /** * Create and register rule, run plugins. */ addRule(name: string, style: JssStyle, options?: RuleOptions): Rule | null { const rule = this.rules.add(name, style, options) if (!rule) return null this.options.jss.plugins.onProcessRule(rule) return rule } /** * Generates a CSS string. */ toString(options?: ToCssOptions = defaultToStringOptions): string { if (options.indent == null) options.indent = defaultToStringOptions.indent if (options.children == null) options.children = defaultToStringOptions.children if (options.children === false) { return `${this.query} {}` } const children = this.rules.toString(options) return children ? `${this.query} {\n${children}\n}` : '' } } const keyRegExp = /@media|@supports\s+/ export default { onCreateRule(key: string, styles: JssStyle, options: RuleOptions): ConditionalRule | null { return keyRegExp.test(key) ? new ConditionalRule(key, styles, options) : null } }