@tenphi/tasty 0.1.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +329 -126
- package/dist/config.d.ts +2 -1
- package/dist/config.js +6 -3
- package/dist/config.js.map +1 -1
- package/dist/pipeline/conditions.js +22 -1
- package/dist/pipeline/conditions.js.map +1 -1
- package/dist/pipeline/index.js +2 -1
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/materialize.js +76 -3
- package/dist/pipeline/materialize.js.map +1 -1
- package/dist/pipeline/parseStateKey.js +23 -2
- package/dist/pipeline/parseStateKey.js.map +1 -1
- package/dist/states/index.d.ts +1 -1
- package/dist/states/index.js +29 -2
- package/dist/states/index.js.map +1 -1
- package/dist/styles/types.d.ts +4 -2
- package/dist/utils/resolve-recipes.js +16 -12
- package/dist/utils/resolve-recipes.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materialize.js","names":[],"sources":["../../src/pipeline/materialize.ts"],"sourcesContent":["/**\n * CSS Materialization\n *\n * Converts condition trees into CSS selectors and at-rules.\n * This is the final stage that produces actual CSS output.\n */\n\nimport { Lru } from '../parser/lru';\n\nimport type {\n ConditionNode,\n ContainerCondition,\n MediaCondition,\n ModifierCondition,\n OwnCondition,\n PseudoCondition,\n RootCondition,\n StateCondition,\n SupportsCondition,\n} from './conditions';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Parsed media condition for structured analysis and combination\n */\nexport interface ParsedMediaCondition {\n /** Subtype for structured analysis */\n subtype: 'dimension' | 'feature' | 'type';\n /** Whether this is a negated condition */\n negated: boolean;\n /** The condition part for CSS output (e.g., \"(width < 600px)\", \"print\") */\n condition: string;\n /** For dimension queries: dimension name */\n dimension?: 'width' | 'height' | 'inline-size' | 'block-size';\n /** For dimension queries: lower bound value */\n lowerBound?: {\n value: string;\n valueNumeric: number | null;\n inclusive: boolean;\n };\n /** For dimension queries: upper bound value */\n upperBound?: {\n value: string;\n valueNumeric: number | null;\n inclusive: boolean;\n };\n /** For feature queries: feature name */\n feature?: string;\n /** For feature queries: feature value */\n featureValue?: string;\n /** For type queries: media type */\n mediaType?: 'print' | 'screen' | 'all' | 'speech';\n}\n\n/**\n * Parsed container condition for structured analysis and combination\n */\nexport interface ParsedContainerCondition {\n /** Container name (undefined = unnamed/nearest container) */\n name?: string;\n /** The condition part (e.g., \"(width < 600px)\" or \"style(--variant: danger)\") */\n condition: string;\n /** Whether this is a negated condition */\n negated: boolean;\n /** Subtype for structured analysis */\n subtype: 'dimension' | 'style' | 'raw';\n /** For style queries: property name (without --) */\n property?: string;\n /** For style queries: property value (undefined = existence check) */\n propertyValue?: string;\n}\n\n/**\n * Parsed supports condition for structured analysis and combination\n */\nexport interface ParsedSupportsCondition {\n /** Subtype: 'feature' for property support, 'selector' for selector() support */\n subtype: 'feature' | 'selector';\n /** The condition string (e.g., \"display: grid\" or \":has(*)\") */\n condition: string;\n /** Whether this is a negated condition */\n negated: boolean;\n}\n\n/**\n * Parsed modifier condition for structured analysis\n */\nexport interface ParsedModifierCondition {\n /** Attribute name (e.g., 'data-hovered', 'data-size') */\n attribute: string;\n /** Value if present (e.g., 'large', 'danger') */\n value?: string;\n /** Operator for value matching (default '=') */\n operator?: '=' | '^=' | '$=' | '*=';\n /** Whether this is negated (:not(...)) */\n negated: boolean;\n}\n\n/**\n * Parsed pseudo-class condition for structured analysis\n */\nexport interface ParsedPseudoCondition {\n /** The pseudo-class (e.g., ':hover', ':focus-visible', ':has(> Icon)') */\n pseudo: string;\n /** Whether this is negated (:not(...)) */\n negated: boolean;\n}\n\n/**\n * Parsed root condition for structured analysis\n */\nexport interface ParsedRootCondition {\n /** The selector part (e.g., '[data-theme=\"dark\"]') */\n selector: string;\n /** Whether this is negated (:root:not(...)) */\n negated: boolean;\n}\n\n/**\n * A single selector variant (one term in a DNF expression)\n */\nexport interface SelectorVariant {\n /** Structured modifier conditions */\n modifierConditions: ParsedModifierCondition[];\n\n /** Structured pseudo conditions */\n pseudoConditions: ParsedPseudoCondition[];\n\n /** Structured own conditions (for sub-element states) */\n ownConditions: (ParsedModifierCondition | ParsedPseudoCondition)[];\n\n /** Parsed media conditions for structured combination */\n mediaConditions: ParsedMediaCondition[];\n\n /** Parsed container conditions for structured combination */\n containerConditions: ParsedContainerCondition[];\n\n /** Parsed supports conditions for @supports at-rules */\n supportsConditions: ParsedSupportsCondition[];\n\n /** Structured root conditions */\n rootConditions: ParsedRootCondition[];\n\n /** Whether to wrap in @starting-style */\n startingStyle: boolean;\n}\n\n/**\n * CSS output components extracted from a condition\n * Supports multiple variants for OR conditions (DNF form)\n */\nexport interface CSSComponents {\n /** Selector variants - OR means multiple variants, AND means single variant with combined selectors */\n variants: SelectorVariant[];\n\n /** Whether condition is impossible (should skip) */\n isImpossible: boolean;\n}\n\n/**\n * Final CSS rule output\n */\nexport interface CSSRule {\n /** Single selector or array of selector fragments (for OR conditions) */\n selector: string | string[];\n declarations: string;\n atRules?: string[];\n rootPrefix?: string;\n}\n\n// ============================================================================\n// Caching\n// ============================================================================\n\nconst conditionCache = new Lru<string, CSSComponents>(3000);\n\n// ============================================================================\n// Main Functions\n// ============================================================================\n\n/**\n * Convert a condition tree to CSS components\n */\nexport function conditionToCSS(node: ConditionNode): CSSComponents {\n // Check cache\n const key = getConditionKey(node);\n const cached = conditionCache.get(key);\n if (cached) {\n return cached;\n }\n\n const result = conditionToCSSInner(node);\n\n // Cache result\n conditionCache.set(key, result);\n\n return result;\n}\n\n/**\n * Clear the condition cache (for testing)\n */\nexport function clearConditionCache(): void {\n conditionCache.clear();\n}\n\n// ============================================================================\n// Inner Implementation\n// ============================================================================\n\n/**\n * Create an empty selector variant\n */\nfunction emptyVariant(): SelectorVariant {\n return {\n modifierConditions: [],\n pseudoConditions: [],\n ownConditions: [],\n mediaConditions: [],\n containerConditions: [],\n supportsConditions: [],\n rootConditions: [],\n startingStyle: false,\n };\n}\n\nfunction conditionToCSSInner(node: ConditionNode): CSSComponents {\n // Base case: TRUE condition - single empty variant (matches everything)\n if (node.kind === 'true') {\n return {\n variants: [emptyVariant()],\n isImpossible: false,\n };\n }\n\n // Base case: FALSE condition - no variants (matches nothing)\n if (node.kind === 'false') {\n return {\n variants: [],\n isImpossible: true,\n };\n }\n\n // State condition\n if (node.kind === 'state') {\n return stateToCSS(node);\n }\n\n // Compound condition\n if (node.kind === 'compound') {\n if (node.operator === 'AND') {\n return andToCSS(node.children);\n } else {\n return orToCSS(node.children);\n }\n }\n\n // Fallback - single empty variant\n return {\n variants: [emptyVariant()],\n isImpossible: false,\n };\n}\n\n/**\n * Convert a state condition to CSS\n */\nfunction stateToCSS(state: StateCondition): CSSComponents {\n switch (state.type) {\n case 'media': {\n // Media conditions can return multiple variants for negated ranges (OR branches)\n const mediaResults = mediaToParsed(state);\n const variants = mediaResults.map((mediaCond) => {\n const v = emptyVariant();\n v.mediaConditions.push(mediaCond);\n return v;\n });\n return { variants, isImpossible: false };\n }\n\n default: {\n const variant: SelectorVariant = emptyVariant();\n\n switch (state.type) {\n case 'modifier':\n variant.modifierConditions.push(modifierToParsed(state));\n break;\n\n case 'pseudo':\n variant.pseudoConditions.push(pseudoToParsed(state));\n break;\n\n case 'container':\n variant.containerConditions.push(containerToParsed(state));\n break;\n\n case 'supports':\n variant.supportsConditions.push(supportsToParsed(state));\n break;\n\n case 'root':\n variant.rootConditions.push(rootToParsed(state));\n break;\n\n case 'own':\n variant.ownConditions.push(...ownToParsed(state));\n break;\n\n case 'starting':\n variant.startingStyle = !state.negated;\n break;\n }\n\n return {\n variants: [variant],\n isImpossible: false,\n };\n }\n }\n}\n\n/**\n * Convert modifier condition to parsed structure\n */\nfunction modifierToParsed(state: ModifierCondition): ParsedModifierCondition {\n return {\n attribute: state.attribute,\n value: state.value,\n operator: state.operator,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert parsed modifier to CSS selector string (for final output)\n */\nexport function modifierToCSS(mod: ParsedModifierCondition): string {\n let selector: string;\n\n if (mod.value !== undefined) {\n // Value attribute: [data-attr=\"value\"]\n const op = mod.operator || '=';\n selector = `[${mod.attribute}${op}\"${mod.value}\"]`;\n } else {\n // Boolean attribute: [data-attr]\n selector = `[${mod.attribute}]`;\n }\n\n if (mod.negated) {\n return `:not(${selector})`;\n }\n return selector;\n}\n\n/**\n * Convert pseudo condition to parsed structure\n */\nfunction pseudoToParsed(state: PseudoCondition): ParsedPseudoCondition {\n return {\n pseudo: state.pseudo,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert parsed pseudo to CSS selector string (for final output)\n */\nexport function pseudoToCSS(pseudo: ParsedPseudoCondition): string {\n if (pseudo.negated) {\n // Wrap in :not() if not already\n if (pseudo.pseudo.startsWith(':not(')) {\n // Double negation - remove :not()\n return pseudo.pseudo.slice(5, -1);\n }\n return `:not(${pseudo.pseudo})`;\n }\n return pseudo.pseudo;\n}\n\n/**\n * Convert media condition to parsed structure(s)\n * Returns an array because negated ranges produce OR branches (two separate conditions)\n */\nfunction mediaToParsed(state: MediaCondition): ParsedMediaCondition[] {\n if (state.subtype === 'type') {\n // @media:print → @media print (or @media not print)\n const mediaType = state.mediaType || 'all';\n return [\n {\n subtype: 'type',\n negated: state.negated ?? false,\n condition: mediaType,\n mediaType: state.mediaType,\n },\n ];\n } else if (state.subtype === 'feature') {\n // @media(prefers-contrast: high) → @media (prefers-contrast: high)\n let condition: string;\n if (state.featureValue) {\n condition = `(${state.feature}: ${state.featureValue})`;\n } else {\n condition = `(${state.feature})`;\n }\n return [\n {\n subtype: 'feature',\n negated: state.negated ?? false,\n condition,\n feature: state.feature,\n featureValue: state.featureValue,\n },\n ];\n } else {\n // Dimension query - negation is handled by inverting the condition\n // because \"not (width < x)\" doesn't work reliably in browsers\n return dimensionToMediaParsed(\n state.dimension || 'width',\n state.lowerBound,\n state.upperBound,\n state.negated ?? false,\n );\n }\n}\n\n/**\n * Convert dimension bounds to parsed media condition(s)\n * Uses CSS Media Queries Level 4 `not (condition)` syntax for negation.\n */\nfunction dimensionToMediaParsed(\n dimension: 'width' | 'height' | 'inline-size' | 'block-size',\n lowerBound?: {\n value: string;\n valueNumeric: number | null;\n inclusive: boolean;\n },\n upperBound?: {\n value: string;\n valueNumeric: number | null;\n inclusive: boolean;\n },\n negated?: boolean,\n): ParsedMediaCondition[] {\n // Build the condition string\n let condition: string;\n if (lowerBound && upperBound) {\n const lowerOp = lowerBound.inclusive ? '<=' : '<';\n const upperOp = upperBound.inclusive ? '<=' : '<';\n condition = `(${lowerBound.value} ${lowerOp} ${dimension} ${upperOp} ${upperBound.value})`;\n } else if (upperBound) {\n const op = upperBound.inclusive ? '<=' : '<';\n condition = `(${dimension} ${op} ${upperBound.value})`;\n } else if (lowerBound) {\n const op = lowerBound.inclusive ? '>=' : '>';\n condition = `(${dimension} ${op} ${lowerBound.value})`;\n } else {\n condition = `(${dimension})`;\n }\n\n // For negation, we use CSS `not (condition)` syntax in buildAtRulesFromVariant\n return [\n {\n subtype: 'dimension',\n negated: negated ?? false,\n condition,\n dimension,\n lowerBound,\n upperBound,\n },\n ];\n}\n\n/**\n * Convert container condition to parsed structure\n * This enables structured analysis for contradiction detection and condition combining\n */\nfunction containerToParsed(\n state: ContainerCondition,\n): ParsedContainerCondition {\n let condition: string;\n\n if (state.subtype === 'style') {\n // Style query: style(--prop: value)\n if (state.propertyValue) {\n condition = `style(--${state.property}: ${state.propertyValue})`;\n } else {\n condition = `style(--${state.property})`;\n }\n } else if (state.subtype === 'raw') {\n // Raw function query: passed through verbatim (e.g., scroll-state(stuck: top))\n condition = state.rawCondition!;\n } else {\n // Dimension query\n condition = dimensionToContainerCondition(\n state.dimension || 'width',\n state.lowerBound,\n state.upperBound,\n );\n }\n\n return {\n name: state.containerName,\n condition,\n negated: state.negated ?? false,\n subtype: state.subtype,\n property: state.property,\n propertyValue: state.propertyValue,\n };\n}\n\n/**\n * Convert dimension bounds to container query condition (single string)\n * Container queries support \"not (condition)\", so no need to invert manually\n */\nfunction dimensionToContainerCondition(\n dimension: string,\n lowerBound?: { value: string; inclusive: boolean },\n upperBound?: { value: string; inclusive: boolean },\n): string {\n if (lowerBound && upperBound) {\n const lowerOp = lowerBound.inclusive ? '<=' : '<';\n const upperOp = upperBound.inclusive ? '<=' : '<';\n return `(${lowerBound.value} ${lowerOp} ${dimension} ${upperOp} ${upperBound.value})`;\n } else if (upperBound) {\n const op = upperBound.inclusive ? '<=' : '<';\n return `(${dimension} ${op} ${upperBound.value})`;\n } else if (lowerBound) {\n const op = lowerBound.inclusive ? '>=' : '>';\n return `(${dimension} ${op} ${lowerBound.value})`;\n }\n return '(width)'; // Fallback\n}\n\n/**\n * Convert supports condition to parsed structure\n */\nfunction supportsToParsed(state: SupportsCondition): ParsedSupportsCondition {\n return {\n subtype: state.subtype,\n condition: state.condition,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert root condition to parsed structure\n */\nfunction rootToParsed(state: RootCondition): ParsedRootCondition {\n return {\n selector: state.selector,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert parsed root conditions to CSS selector prefix (for final output)\n */\nexport function rootConditionsToCSS(\n roots: ParsedRootCondition[],\n): string | undefined {\n if (roots.length === 0) return undefined;\n\n // Combine all root conditions into a single :root prefix\n // e.g., :root[data-theme=\"dark\"]:not([data-mode=\"light\"])\n let prefix = ':root';\n for (const root of roots) {\n if (root.negated) {\n prefix += `:not(${root.selector})`;\n } else {\n prefix += root.selector;\n }\n }\n return prefix;\n}\n\n/**\n * Convert own condition to parsed structures for sub-element\n */\nfunction ownToParsed(\n state: OwnCondition,\n): (ParsedModifierCondition | ParsedPseudoCondition)[] {\n const innerCSS = conditionToCSS(state.innerCondition);\n\n if (innerCSS.isImpossible || innerCSS.variants.length === 0) {\n return [];\n }\n\n // Collect all modifier/pseudo conditions from all variants\n const allConditions: (ParsedModifierCondition | ParsedPseudoCondition)[] = [];\n for (const variant of innerCSS.variants) {\n for (const mod of variant.modifierConditions) {\n // Apply outer negation\n allConditions.push({\n ...mod,\n negated: state.negated ? !mod.negated : mod.negated,\n });\n }\n for (const pseudo of variant.pseudoConditions) {\n // Apply outer negation\n allConditions.push({\n ...pseudo,\n negated: state.negated ? !pseudo.negated : pseudo.negated,\n });\n }\n }\n\n return allConditions;\n}\n\n/**\n * Get unique key for a modifier condition\n */\nfunction getModifierKey(mod: ParsedModifierCondition): string {\n const base = mod.value\n ? `${mod.attribute}${mod.operator || '='}${mod.value}`\n : mod.attribute;\n return mod.negated ? `!${base}` : base;\n}\n\n/**\n * Get unique key for a pseudo condition\n */\nfunction getPseudoKey(pseudo: ParsedPseudoCondition): string {\n return pseudo.negated ? `!${pseudo.pseudo}` : pseudo.pseudo;\n}\n\n/**\n * Get unique key for a root condition\n */\nfunction getRootKey(root: ParsedRootCondition): string {\n return root.negated ? `!${root.selector}` : root.selector;\n}\n\n/**\n * Deduplicate modifier conditions\n */\nfunction dedupeModifierConditions(\n conditions: ParsedModifierCondition[],\n): ParsedModifierCondition[] {\n const seen = new Set<string>();\n const result: ParsedModifierCondition[] = [];\n for (const c of conditions) {\n const key = getModifierKey(c);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate pseudo conditions\n */\nfunction dedupePseudoConditions(\n conditions: ParsedPseudoCondition[],\n): ParsedPseudoCondition[] {\n const seen = new Set<string>();\n const result: ParsedPseudoCondition[] = [];\n for (const c of conditions) {\n const key = getPseudoKey(c);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate root conditions\n */\nfunction dedupeRootConditions(\n conditions: ParsedRootCondition[],\n): ParsedRootCondition[] {\n const seen = new Set<string>();\n const result: ParsedRootCondition[] = [];\n for (const c of conditions) {\n const key = getRootKey(c);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate own conditions (modifiers or pseudos)\n */\nfunction dedupeOwnConditions(\n conditions: (ParsedModifierCondition | ParsedPseudoCondition)[],\n): (ParsedModifierCondition | ParsedPseudoCondition)[] {\n const seen = new Set<string>();\n const result: (ParsedModifierCondition | ParsedPseudoCondition)[] = [];\n for (const c of conditions) {\n const key =\n 'attribute' in c\n ? `mod:${getModifierKey(c)}`\n : `pseudo:${getPseudoKey(c)}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Check for modifier contradiction: same attribute with opposite negation\n */\nfunction hasModifierContradiction(\n conditions: ParsedModifierCondition[],\n): boolean {\n const byKey = new Map<string, boolean>(); // base key -> isPositive\n\n for (const mod of conditions) {\n const baseKey = mod.value\n ? `${mod.attribute}${mod.operator || '='}${mod.value}`\n : mod.attribute;\n const existing = byKey.get(baseKey);\n if (existing !== undefined && existing !== !mod.negated) {\n return true; // Same attribute with opposite negation\n }\n byKey.set(baseKey, !mod.negated);\n }\n return false;\n}\n\n/**\n * Check for pseudo contradiction: same pseudo with opposite negation\n */\nfunction hasPseudoContradiction(conditions: ParsedPseudoCondition[]): boolean {\n const byKey = new Map<string, boolean>(); // pseudo -> isPositive\n\n for (const pseudo of conditions) {\n const existing = byKey.get(pseudo.pseudo);\n if (existing !== undefined && existing !== !pseudo.negated) {\n return true; // Same pseudo with opposite negation\n }\n byKey.set(pseudo.pseudo, !pseudo.negated);\n }\n return false;\n}\n\n/**\n * Check for root condition contradiction: same selector with opposite negation\n */\nfunction hasRootContradiction(conditions: ParsedRootCondition[]): boolean {\n const byKey = new Map<string, boolean>(); // selector -> isPositive\n\n for (const root of conditions) {\n const existing = byKey.get(root.selector);\n if (existing !== undefined && existing !== !root.negated) {\n return true; // Same selector with opposite negation\n }\n byKey.set(root.selector, !root.negated);\n }\n return false;\n}\n\n/**\n * Check for own condition contradiction\n */\nfunction hasOwnConditionContradiction(\n conditions: (ParsedModifierCondition | ParsedPseudoCondition)[],\n): boolean {\n const modifiers: ParsedModifierCondition[] = [];\n const pseudos: ParsedPseudoCondition[] = [];\n\n for (const c of conditions) {\n if ('attribute' in c) {\n modifiers.push(c);\n } else {\n pseudos.push(c);\n }\n }\n\n return hasModifierContradiction(modifiers) || hasPseudoContradiction(pseudos);\n}\n\n/**\n * Merge two selector variants (AND operation)\n * Deduplicates conditions and checks for contradictions\n */\nfunction mergeVariants(\n a: SelectorVariant,\n b: SelectorVariant,\n): SelectorVariant | null {\n // Merge media conditions and check for contradictions\n const mergedMedia = dedupeMediaConditions([\n ...a.mediaConditions,\n ...b.mediaConditions,\n ]);\n if (hasMediaContradiction(mergedMedia)) {\n return null; // Impossible variant\n }\n\n // Merge root conditions and check for contradictions\n const mergedRoots = dedupeRootConditions([\n ...a.rootConditions,\n ...b.rootConditions,\n ]);\n if (hasRootContradiction(mergedRoots)) {\n return null; // Impossible variant\n }\n\n // Merge modifier conditions and check for contradictions\n const mergedModifiers = dedupeModifierConditions([\n ...a.modifierConditions,\n ...b.modifierConditions,\n ]);\n if (hasModifierContradiction(mergedModifiers)) {\n return null; // Impossible variant\n }\n\n // Merge pseudo conditions and check for contradictions\n const mergedPseudos = dedupePseudoConditions([\n ...a.pseudoConditions,\n ...b.pseudoConditions,\n ]);\n if (hasPseudoContradiction(mergedPseudos)) {\n return null; // Impossible variant\n }\n\n // Merge own conditions and check for contradictions\n const mergedOwn = dedupeOwnConditions([\n ...a.ownConditions,\n ...b.ownConditions,\n ]);\n if (hasOwnConditionContradiction(mergedOwn)) {\n return null; // Impossible variant\n }\n\n // Merge container conditions and check for contradictions\n const mergedContainers = dedupeContainerConditions([\n ...a.containerConditions,\n ...b.containerConditions,\n ]);\n if (hasContainerStyleContradiction(mergedContainers)) {\n return null; // Impossible variant\n }\n\n // Merge supports conditions and check for contradictions\n const mergedSupports = dedupeSupportsConditions([\n ...a.supportsConditions,\n ...b.supportsConditions,\n ]);\n if (hasSupportsContradiction(mergedSupports)) {\n return null; // Impossible variant\n }\n\n return {\n modifierConditions: mergedModifiers,\n pseudoConditions: mergedPseudos,\n ownConditions: mergedOwn,\n mediaConditions: mergedMedia,\n containerConditions: mergedContainers,\n supportsConditions: mergedSupports,\n rootConditions: mergedRoots,\n startingStyle: a.startingStyle || b.startingStyle,\n };\n}\n\n/**\n * Deduplicate media conditions by their key (subtype + condition + negated)\n */\nfunction dedupeMediaConditions(\n conditions: ParsedMediaCondition[],\n): ParsedMediaCondition[] {\n const seen = new Set<string>();\n const result: ParsedMediaCondition[] = [];\n for (const c of conditions) {\n const key = `${c.subtype}|${c.condition}|${c.negated}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate container conditions by their key (name + condition + negated)\n */\nfunction dedupeContainerConditions(\n conditions: ParsedContainerCondition[],\n): ParsedContainerCondition[] {\n const seen = new Set<string>();\n const result: ParsedContainerCondition[] = [];\n for (const c of conditions) {\n const key = `${c.name ?? ''}|${c.condition}|${c.negated}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate supports conditions by their key (subtype + condition + negated)\n */\nfunction dedupeSupportsConditions(\n conditions: ParsedSupportsCondition[],\n): ParsedSupportsCondition[] {\n const seen = new Set<string>();\n const result: ParsedSupportsCondition[] = [];\n for (const c of conditions) {\n const key = `${c.subtype}|${c.condition}|${c.negated}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Check if supports conditions contain contradictions\n * e.g., @supports(display: grid) AND NOT @supports(display: grid)\n */\nfunction hasSupportsContradiction(\n conditions: ParsedSupportsCondition[],\n): boolean {\n const conditionMap = new Map<string, boolean>(); // key -> isPositive\n\n for (const cond of conditions) {\n const key = `${cond.subtype}|${cond.condition}`;\n const existing = conditionMap.get(key);\n if (existing !== undefined && existing !== !cond.negated) {\n return true; // Contradiction: positive AND negated\n }\n conditionMap.set(key, !cond.negated);\n }\n\n return false;\n}\n\n/**\n * Check if a set of media conditions contains contradictions\n * e.g., (prefers-color-scheme: light) AND NOT (prefers-color-scheme: light)\n * or (width >= 900px) AND (width < 600px)\n *\n * Uses parsed media conditions for efficient analysis without regex parsing.\n */\nfunction hasMediaContradiction(conditions: ParsedMediaCondition[]): boolean {\n // Track conditions by their key (condition string) to detect A and NOT A\n const featureConditions = new Map<string, boolean>(); // key -> isPositive\n const typeConditions = new Map<string, boolean>(); // mediaType -> isPositive\n const dimensionConditions = new Map<string, boolean>(); // condition -> isPositive\n\n // Track dimension conditions for range contradiction detection (non-negated only)\n const dimensionsByDim = new Map<\n string,\n { lowerBound: number | null; upperBound: number | null }\n >();\n\n for (const cond of conditions) {\n if (cond.subtype === 'type') {\n // Type query: check for direct contradiction (print AND NOT print)\n const key = cond.mediaType || 'all';\n const existing = typeConditions.get(key);\n if (existing !== undefined && existing !== !cond.negated) {\n return true; // Contradiction: positive AND negated\n }\n typeConditions.set(key, !cond.negated);\n } else if (cond.subtype === 'feature') {\n // Feature query: check for direct contradiction\n const key = cond.condition;\n const existing = featureConditions.get(key);\n if (existing !== undefined && existing !== !cond.negated) {\n return true; // Contradiction: positive AND negated\n }\n featureConditions.set(key, !cond.negated);\n } else if (cond.subtype === 'dimension') {\n // First, check for direct contradiction: (width < 600px) AND NOT (width < 600px)\n const condKey = cond.condition;\n const existing = dimensionConditions.get(condKey);\n if (existing !== undefined && existing !== !cond.negated) {\n return true; // Contradiction: positive AND negated\n }\n dimensionConditions.set(condKey, !cond.negated);\n\n // For range analysis, only consider non-negated conditions\n // Negated conditions are handled via the direct contradiction check above\n if (!cond.negated) {\n const dim = cond.dimension || 'width';\n let bounds = dimensionsByDim.get(dim);\n if (!bounds) {\n bounds = { lowerBound: null, upperBound: null };\n dimensionsByDim.set(dim, bounds);\n }\n\n // Track the effective bounds\n if (cond.lowerBound?.valueNumeric != null) {\n const value = cond.lowerBound.valueNumeric;\n if (bounds.lowerBound === null || value > bounds.lowerBound) {\n bounds.lowerBound = value;\n }\n }\n if (cond.upperBound?.valueNumeric != null) {\n const value = cond.upperBound.valueNumeric;\n if (bounds.upperBound === null || value < bounds.upperBound) {\n bounds.upperBound = value;\n }\n }\n\n // Check for impossible range\n if (\n bounds.lowerBound !== null &&\n bounds.upperBound !== null &&\n bounds.lowerBound >= bounds.upperBound\n ) {\n return true;\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Check if container conditions contain contradictions in style queries\n * e.g., style(--variant: danger) and style(--variant: success) together\n * Same property with different values = always false\n *\n * Uses parsed container conditions for efficient analysis without regex parsing.\n */\nfunction hasContainerStyleContradiction(\n conditions: ParsedContainerCondition[],\n): boolean {\n // Track style queries by property name\n // key: property name, value: { hasExistence: boolean, values: Set<string>, hasNegatedExistence: boolean }\n const styleQueries = new Map<\n string,\n { hasExistence: boolean; values: Set<string>; hasNegatedExistence: boolean }\n >();\n\n for (const cond of conditions) {\n // Only analyze style queries\n if (cond.subtype !== 'style' || !cond.property) {\n continue;\n }\n\n const property = cond.property;\n const value = cond.propertyValue;\n\n if (!styleQueries.has(property)) {\n styleQueries.set(property, {\n hasExistence: false,\n values: new Set(),\n hasNegatedExistence: false,\n });\n }\n\n const entry = styleQueries.get(property)!;\n\n if (cond.negated) {\n if (value === undefined) {\n // not style(--prop) - negated existence check\n entry.hasNegatedExistence = true;\n }\n // Negated value checks don't contradict positive value checks directly\n // They just mean \"not this value\"\n } else {\n if (value === undefined) {\n // style(--prop) - existence check\n entry.hasExistence = true;\n } else {\n // style(--prop: value) - value check\n entry.values.add(value);\n }\n }\n }\n\n // Check for contradictions\n for (const [, entry] of styleQueries) {\n // Contradiction: existence check + negated existence check\n if (entry.hasExistence && entry.hasNegatedExistence) {\n return true;\n }\n\n // Contradiction: multiple different values for same property\n // style(--variant: danger) AND style(--variant: success) is impossible\n if (entry.values.size > 1) {\n return true;\n }\n\n // Contradiction: negated existence + value check\n // not style(--variant) AND style(--variant: danger) is impossible\n if (entry.hasNegatedExistence && entry.values.size > 0) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Get a unique key for a variant (for deduplication)\n */\nfunction getVariantKey(v: SelectorVariant): string {\n const modifierKey = v.modifierConditions.map(getModifierKey).sort().join('|');\n const pseudoKey = v.pseudoConditions.map(getPseudoKey).sort().join('|');\n const ownKey = v.ownConditions\n .map((c) =>\n 'attribute' in c\n ? `mod:${getModifierKey(c)}`\n : `pseudo:${getPseudoKey(c)}`,\n )\n .sort()\n .join('|');\n const containerKey = v.containerConditions\n .map((c) => `${c.name ?? ''}:${c.negated ? '!' : ''}${c.condition}`)\n .sort()\n .join('|');\n const mediaKey = v.mediaConditions\n .map((c) => `${c.subtype}:${c.negated ? '!' : ''}${c.condition}`)\n .sort()\n .join('|');\n const supportsKey = v.supportsConditions\n .map((c) => `${c.subtype}:${c.negated ? '!' : ''}${c.condition}`)\n .sort()\n .join('|');\n const rootKey = v.rootConditions.map(getRootKey).sort().join('|');\n return [\n modifierKey,\n pseudoKey,\n ownKey,\n mediaKey,\n containerKey,\n supportsKey,\n rootKey,\n v.startingStyle ? '1' : '0',\n ].join('###');\n}\n\n/**\n * Check if variant A is a superset of variant B (A is more restrictive)\n *\n * If A has all of B's conditions plus more, then A is redundant\n * because B already covers the same cases (and more).\n *\n * Example:\n * A: :not([size=large]):not([size=medium]):not([size=small])\n * B: :not([size=large])\n * A is a superset of B, so A is redundant when B exists.\n */\nfunction isVariantSuperset(a: SelectorVariant, b: SelectorVariant): boolean {\n // Must have same context\n if (a.startingStyle !== b.startingStyle) return false;\n\n // Check if a.rootConditions is superset of b.rootConditions\n if (!isRootConditionsSuperset(a.rootConditions, b.rootConditions))\n return false;\n\n // Check if a.mediaConditions is superset of b.mediaConditions\n if (!isMediaConditionsSuperset(a.mediaConditions, b.mediaConditions))\n return false;\n\n // Check if a.containerConditions is superset of b.containerConditions\n if (\n !isContainerConditionsSuperset(a.containerConditions, b.containerConditions)\n )\n return false;\n\n // Check if a.supportsConditions is superset of b.supportsConditions\n if (!isSupportsConditionsSuperset(a.supportsConditions, b.supportsConditions))\n return false;\n\n // Check if a.modifierConditions is superset of b.modifierConditions\n if (!isModifierConditionsSuperset(a.modifierConditions, b.modifierConditions))\n return false;\n\n // Check if a.pseudoConditions is superset of b.pseudoConditions\n if (!isPseudoConditionsSuperset(a.pseudoConditions, b.pseudoConditions))\n return false;\n\n // Check if a.ownConditions is superset of b.ownConditions\n if (!isOwnConditionsSuperset(a.ownConditions, b.ownConditions)) return false;\n\n // A is a superset if it has all of B's items (possibly more)\n // and at least one category has strictly more items\n const aTotal =\n a.mediaConditions.length +\n a.containerConditions.length +\n a.supportsConditions.length +\n a.modifierConditions.length +\n a.pseudoConditions.length +\n a.rootConditions.length +\n a.ownConditions.length;\n const bTotal =\n b.mediaConditions.length +\n b.containerConditions.length +\n b.supportsConditions.length +\n b.modifierConditions.length +\n b.pseudoConditions.length +\n b.rootConditions.length +\n b.ownConditions.length;\n\n return aTotal > bTotal;\n}\n\n/**\n * Check if media conditions A is a superset of B\n */\nfunction isMediaConditionsSuperset(\n a: ParsedMediaCondition[],\n b: ParsedMediaCondition[],\n): boolean {\n const aKeys = new Set(\n a.map((c) => `${c.subtype}|${c.condition}|${c.negated}`),\n );\n for (const c of b) {\n const key = `${c.subtype}|${c.condition}|${c.negated}`;\n if (!aKeys.has(key)) return false;\n }\n return true;\n}\n\n/**\n * Check if container conditions A is a superset of B\n */\nfunction isContainerConditionsSuperset(\n a: ParsedContainerCondition[],\n b: ParsedContainerCondition[],\n): boolean {\n const aKeys = new Set(\n a.map((c) => `${c.name ?? ''}|${c.condition}|${c.negated}`),\n );\n for (const c of b) {\n const key = `${c.name ?? ''}|${c.condition}|${c.negated}`;\n if (!aKeys.has(key)) return false;\n }\n return true;\n}\n\n/**\n * Check if supports conditions A is a superset of B\n */\nfunction isSupportsConditionsSuperset(\n a: ParsedSupportsCondition[],\n b: ParsedSupportsCondition[],\n): boolean {\n const aKeys = new Set(\n a.map((c) => `${c.subtype}|${c.condition}|${c.negated}`),\n );\n for (const c of b) {\n const key = `${c.subtype}|${c.condition}|${c.negated}`;\n if (!aKeys.has(key)) return false;\n }\n return true;\n}\n\n/**\n * Check if modifier conditions A is a superset of B\n */\nfunction isModifierConditionsSuperset(\n a: ParsedModifierCondition[],\n b: ParsedModifierCondition[],\n): boolean {\n const aKeys = new Set(a.map(getModifierKey));\n for (const c of b) {\n if (!aKeys.has(getModifierKey(c))) return false;\n }\n return true;\n}\n\n/**\n * Check if pseudo conditions A is a superset of B\n */\nfunction isPseudoConditionsSuperset(\n a: ParsedPseudoCondition[],\n b: ParsedPseudoCondition[],\n): boolean {\n const aKeys = new Set(a.map(getPseudoKey));\n for (const c of b) {\n if (!aKeys.has(getPseudoKey(c))) return false;\n }\n return true;\n}\n\n/**\n * Check if root conditions A is a superset of B\n */\nfunction isRootConditionsSuperset(\n a: ParsedRootCondition[],\n b: ParsedRootCondition[],\n): boolean {\n const aKeys = new Set(a.map(getRootKey));\n for (const c of b) {\n if (!aKeys.has(getRootKey(c))) return false;\n }\n return true;\n}\n\n/**\n * Check if own conditions A is a superset of B\n */\nfunction isOwnConditionsSuperset(\n a: (ParsedModifierCondition | ParsedPseudoCondition)[],\n b: (ParsedModifierCondition | ParsedPseudoCondition)[],\n): boolean {\n const aKeys = new Set(\n a.map((c) =>\n 'attribute' in c\n ? `mod:${getModifierKey(c)}`\n : `pseudo:${getPseudoKey(c)}`,\n ),\n );\n for (const c of b) {\n const key =\n 'attribute' in c\n ? `mod:${getModifierKey(c)}`\n : `pseudo:${getPseudoKey(c)}`;\n if (!aKeys.has(key)) return false;\n }\n return true;\n}\n\n/**\n * Deduplicate variants\n *\n * Removes:\n * 1. Exact duplicates (same key)\n * 2. Superset variants (more restrictive selectors that are redundant)\n */\nfunction dedupeVariants(variants: SelectorVariant[]): SelectorVariant[] {\n // First pass: exact deduplication\n const seen = new Set<string>();\n const result: SelectorVariant[] = [];\n\n for (const v of variants) {\n const key = getVariantKey(v);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(v);\n }\n }\n\n // Second pass: remove supersets (more restrictive variants)\n // Sort by total condition count (fewer conditions = less restrictive = keep)\n result.sort((a, b) => {\n const aCount =\n a.modifierConditions.length +\n a.pseudoConditions.length +\n a.ownConditions.length +\n a.mediaConditions.length +\n a.containerConditions.length +\n a.supportsConditions.length +\n a.rootConditions.length;\n const bCount =\n b.modifierConditions.length +\n b.pseudoConditions.length +\n b.ownConditions.length +\n b.mediaConditions.length +\n b.containerConditions.length +\n b.supportsConditions.length +\n b.rootConditions.length;\n return aCount - bCount;\n });\n\n // Remove variants that are supersets of earlier (less restrictive) variants\n const filtered: SelectorVariant[] = [];\n for (const candidate of result) {\n let isRedundant = false;\n for (const kept of filtered) {\n if (isVariantSuperset(candidate, kept)) {\n isRedundant = true;\n break;\n }\n }\n if (!isRedundant) {\n filtered.push(candidate);\n }\n }\n\n return filtered;\n}\n\n/**\n * Combine AND conditions into CSS\n *\n * AND of conditions means cartesian product of variants:\n * (A1 | A2) & (B1 | B2) = A1&B1 | A1&B2 | A2&B1 | A2&B2\n *\n * Variants that result in contradictions (e.g., conflicting media rules)\n * are filtered out.\n */\nfunction andToCSS(children: ConditionNode[]): CSSComponents {\n // Start with a single empty variant\n let currentVariants: SelectorVariant[] = [emptyVariant()];\n\n for (const child of children) {\n const childCSS = conditionToCSSInner(child);\n\n if (childCSS.isImpossible || childCSS.variants.length === 0) {\n return { variants: [], isImpossible: true };\n }\n\n // Cartesian product: each current variant × each child variant\n const newVariants: SelectorVariant[] = [];\n for (const current of currentVariants) {\n for (const childVariant of childCSS.variants) {\n const merged = mergeVariants(current, childVariant);\n // Skip impossible variants (contradictions detected during merge)\n if (merged !== null) {\n newVariants.push(merged);\n }\n }\n }\n\n if (newVariants.length === 0) {\n return { variants: [], isImpossible: true };\n }\n\n // Deduplicate after each step to prevent exponential blowup\n currentVariants = dedupeVariants(newVariants);\n }\n\n return {\n variants: currentVariants,\n isImpossible: false,\n };\n}\n\n/**\n * Combine OR conditions into CSS\n *\n * OR in CSS means multiple selector variants (DNF).\n * Each variant becomes a separate selector in the comma-separated list,\n * or multiple CSS rules if they have different at-rules.\n *\n * Note: OR exclusivity is handled at the pipeline level (expandOrConditions),\n * so here we just collect all variants. Any remaining ORs in the condition\n * tree (e.g., from De Morgan expansion) are handled as simple alternatives.\n */\nfunction orToCSS(children: ConditionNode[]): CSSComponents {\n const allVariants: SelectorVariant[] = [];\n\n for (const child of children) {\n const childCSS = conditionToCSSInner(child);\n if (childCSS.isImpossible) continue;\n\n allVariants.push(...childCSS.variants);\n }\n\n if (allVariants.length === 0) {\n return { variants: [], isImpossible: true };\n }\n\n // Deduplicate variants\n return {\n variants: dedupeVariants(allVariants),\n isImpossible: false,\n };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Get a cache key for a condition\n */\nfunction getConditionKey(node: ConditionNode): string {\n if (node.kind === 'true') return 'TRUE';\n if (node.kind === 'false') return 'FALSE';\n if (node.kind === 'state') return node.uniqueId;\n if (node.kind === 'compound') {\n const childKeys = node.children.map(getConditionKey).sort();\n return `${node.operator}(${childKeys.join(',')})`;\n }\n return 'UNKNOWN';\n}\n\n/**\n * Build a complete CSS selector from a single variant\n */\nfunction buildCSSSelectorFromVariant(\n className: string,\n variant: SelectorVariant,\n selectorSuffix = '',\n): string {\n // Start with base class (doubled for specificity)\n let selector = `.${className}.${className}`;\n\n // Add modifier selectors\n for (const mod of variant.modifierConditions) {\n selector += modifierToCSS(mod);\n }\n\n // Add pseudo selectors\n for (const pseudo of variant.pseudoConditions) {\n selector += pseudoToCSS(pseudo);\n }\n\n // Add selector suffix (e.g., ' [data-element=\"Label\"]')\n selector += selectorSuffix;\n\n // Add own selectors (after sub-element)\n for (const own of variant.ownConditions) {\n if ('attribute' in own) {\n selector += modifierToCSS(own);\n } else {\n selector += pseudoToCSS(own);\n }\n }\n\n // Add root prefix if present\n const rootPrefix = rootConditionsToCSS(variant.rootConditions);\n if (rootPrefix) {\n selector = `${rootPrefix} ${selector}`;\n }\n\n return selector;\n}\n\n/**\n * Build at-rules array from a variant\n */\nexport function buildAtRulesFromVariant(variant: SelectorVariant): string[] {\n const atRules: string[] = [];\n\n // Add media rules - combine all conditions with \"and\"\n if (variant.mediaConditions.length > 0) {\n const conditionParts = variant.mediaConditions.map((c) => {\n if (c.subtype === 'type') {\n // Media type: print, screen, etc.\n return c.negated ? `not ${c.condition}` : c.condition;\n } else {\n // Feature or dimension: use not (condition) syntax for negation\n // MQ Level 4 requires parentheses around the condition for negation\n return c.negated ? `(not ${c.condition})` : c.condition;\n }\n });\n atRules.push(`@media ${conditionParts.join(' and ')}`);\n }\n\n // Add container rules - group by container name and combine with \"and\"\n if (variant.containerConditions.length > 0) {\n // Group conditions by container name (undefined = unnamed/nearest)\n const byName = new Map<string | undefined, ParsedContainerCondition[]>();\n for (const cond of variant.containerConditions) {\n const group = byName.get(cond.name) || [];\n group.push(cond);\n byName.set(cond.name, group);\n }\n\n // Build one @container rule per container name\n for (const [name, conditions] of byName) {\n // CSS Container Query syntax requires parentheses around negated conditions:\n // @container (not style(--x)) and style(--y) - NOT @container not style(--x) and style(--y)\n const conditionParts = conditions.map((c) =>\n c.negated ? `(not ${c.condition})` : c.condition,\n );\n const namePrefix = name ? `${name} ` : '';\n atRules.push(`@container ${namePrefix}${conditionParts.join(' and ')}`);\n }\n }\n\n // Add supports rules - combine all conditions with \"and\"\n if (variant.supportsConditions.length > 0) {\n const conditionParts = variant.supportsConditions.map((c) => {\n // Build the condition based on subtype\n // feature: (display: grid) or (not (display: grid))\n // selector: selector(:has(*)) or (not selector(:has(*)))\n if (c.subtype === 'selector') {\n const selectorCond = `selector(${c.condition})`;\n return c.negated ? `(not ${selectorCond})` : selectorCond;\n } else {\n const featureCond = `(${c.condition})`;\n return c.negated ? `(not ${featureCond})` : featureCond;\n }\n });\n atRules.push(`@supports ${conditionParts.join(' and ')}`);\n }\n\n // Add starting-style\n if (variant.startingStyle) {\n atRules.push('@starting-style');\n }\n\n return atRules;\n}\n\n/**\n * Get a string key for a variant's at-rules (for grouping)\n */\nfunction getAtRulesKey(variant: SelectorVariant): string {\n const atRules = buildAtRulesFromVariant(variant);\n return atRules.sort().join('|||');\n}\n\n/**\n * Materialize a computed rule into final CSS format\n *\n * Returns an array of CSSRules because OR conditions may require multiple rules\n * (when different branches have different at-rules)\n */\nfunction _materializeRule(\n condition: ConditionNode,\n declarations: Record<string, string>,\n selectorSuffix: string,\n className: string,\n): CSSRule[] {\n const components = conditionToCSS(condition);\n\n if (components.isImpossible || components.variants.length === 0) {\n return [];\n }\n\n const declarationsStr = Object.entries(declarations)\n .map(([prop, value]) => `${prop}: ${value};`)\n .join(' ');\n\n // Group variants by their at-rules (variants with same at-rules can be combined with commas)\n const byAtRules = new Map<string, SelectorVariant[]>();\n for (const variant of components.variants) {\n const key = getAtRulesKey(variant);\n const group = byAtRules.get(key) || [];\n group.push(variant);\n byAtRules.set(key, group);\n }\n\n // Generate one CSSRule per at-rules group\n const rules: CSSRule[] = [];\n for (const [, variants] of byAtRules) {\n // All variants in this group have the same at-rules, so combine selectors with commas\n const selectors = variants.map((v) =>\n buildCSSSelectorFromVariant(className, v, selectorSuffix),\n );\n const selector = selectors.join(', ');\n const atRules = buildAtRulesFromVariant(variants[0]);\n\n const rule: CSSRule = {\n selector,\n declarations: declarationsStr,\n };\n\n if (atRules.length > 0) {\n rule.atRules = atRules;\n }\n\n const rootPrefix = rootConditionsToCSS(variants[0].rootConditions);\n if (rootPrefix) {\n rule.rootPrefix = rootPrefix;\n }\n\n rules.push(rule);\n }\n\n return rules;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"materialize.js","names":[],"sources":["../../src/pipeline/materialize.ts"],"sourcesContent":["/**\n * CSS Materialization\n *\n * Converts condition trees into CSS selectors and at-rules.\n * This is the final stage that produces actual CSS output.\n */\n\nimport { Lru } from '../parser/lru';\n\nimport type {\n ConditionNode,\n ContainerCondition,\n MediaCondition,\n ModifierCondition,\n OwnCondition,\n ParentCondition,\n PseudoCondition,\n RootCondition,\n StateCondition,\n SupportsCondition,\n} from './conditions';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Parsed media condition for structured analysis and combination\n */\nexport interface ParsedMediaCondition {\n /** Subtype for structured analysis */\n subtype: 'dimension' | 'feature' | 'type';\n /** Whether this is a negated condition */\n negated: boolean;\n /** The condition part for CSS output (e.g., \"(width < 600px)\", \"print\") */\n condition: string;\n /** For dimension queries: dimension name */\n dimension?: 'width' | 'height' | 'inline-size' | 'block-size';\n /** For dimension queries: lower bound value */\n lowerBound?: {\n value: string;\n valueNumeric: number | null;\n inclusive: boolean;\n };\n /** For dimension queries: upper bound value */\n upperBound?: {\n value: string;\n valueNumeric: number | null;\n inclusive: boolean;\n };\n /** For feature queries: feature name */\n feature?: string;\n /** For feature queries: feature value */\n featureValue?: string;\n /** For type queries: media type */\n mediaType?: 'print' | 'screen' | 'all' | 'speech';\n}\n\n/**\n * Parsed container condition for structured analysis and combination\n */\nexport interface ParsedContainerCondition {\n /** Container name (undefined = unnamed/nearest container) */\n name?: string;\n /** The condition part (e.g., \"(width < 600px)\" or \"style(--variant: danger)\") */\n condition: string;\n /** Whether this is a negated condition */\n negated: boolean;\n /** Subtype for structured analysis */\n subtype: 'dimension' | 'style' | 'raw';\n /** For style queries: property name (without --) */\n property?: string;\n /** For style queries: property value (undefined = existence check) */\n propertyValue?: string;\n}\n\n/**\n * Parsed supports condition for structured analysis and combination\n */\nexport interface ParsedSupportsCondition {\n /** Subtype: 'feature' for property support, 'selector' for selector() support */\n subtype: 'feature' | 'selector';\n /** The condition string (e.g., \"display: grid\" or \":has(*)\") */\n condition: string;\n /** Whether this is a negated condition */\n negated: boolean;\n}\n\n/**\n * Parsed modifier condition for structured analysis\n */\nexport interface ParsedModifierCondition {\n /** Attribute name (e.g., 'data-hovered', 'data-size') */\n attribute: string;\n /** Value if present (e.g., 'large', 'danger') */\n value?: string;\n /** Operator for value matching (default '=') */\n operator?: '=' | '^=' | '$=' | '*=';\n /** Whether this is negated (:not(...)) */\n negated: boolean;\n}\n\n/**\n * Parsed pseudo-class condition for structured analysis\n */\nexport interface ParsedPseudoCondition {\n /** The pseudo-class (e.g., ':hover', ':focus-visible', ':has(> Icon)') */\n pseudo: string;\n /** Whether this is negated (:not(...)) */\n negated: boolean;\n}\n\n/**\n * Parsed root condition for structured analysis\n */\nexport interface ParsedRootCondition {\n /** The selector part (e.g., '[data-theme=\"dark\"]') */\n selector: string;\n /** Whether this is negated (:root:not(...)) */\n negated: boolean;\n}\n\n/**\n * Parsed parent condition for structured analysis\n */\nexport interface ParsedParentCondition {\n /** The selector part (e.g., '[data-hovered]') */\n selector: string;\n /** Whether this targets a direct parent (> combinator) */\n direct: boolean;\n /** Whether this is negated (:not([sel] *)) */\n negated: boolean;\n}\n\n/**\n * A single selector variant (one term in a DNF expression)\n */\nexport interface SelectorVariant {\n /** Structured modifier conditions */\n modifierConditions: ParsedModifierCondition[];\n\n /** Structured pseudo conditions */\n pseudoConditions: ParsedPseudoCondition[];\n\n /** Structured own conditions (for sub-element states) */\n ownConditions: (ParsedModifierCondition | ParsedPseudoCondition)[];\n\n /** Parsed media conditions for structured combination */\n mediaConditions: ParsedMediaCondition[];\n\n /** Parsed container conditions for structured combination */\n containerConditions: ParsedContainerCondition[];\n\n /** Parsed supports conditions for @supports at-rules */\n supportsConditions: ParsedSupportsCondition[];\n\n /** Structured root conditions */\n rootConditions: ParsedRootCondition[];\n\n /** Structured parent conditions */\n parentConditions: ParsedParentCondition[];\n\n /** Whether to wrap in @starting-style */\n startingStyle: boolean;\n}\n\n/**\n * CSS output components extracted from a condition\n * Supports multiple variants for OR conditions (DNF form)\n */\nexport interface CSSComponents {\n /** Selector variants - OR means multiple variants, AND means single variant with combined selectors */\n variants: SelectorVariant[];\n\n /** Whether condition is impossible (should skip) */\n isImpossible: boolean;\n}\n\n/**\n * Final CSS rule output\n */\nexport interface CSSRule {\n /** Single selector or array of selector fragments (for OR conditions) */\n selector: string | string[];\n declarations: string;\n atRules?: string[];\n rootPrefix?: string;\n}\n\n// ============================================================================\n// Caching\n// ============================================================================\n\nconst conditionCache = new Lru<string, CSSComponents>(3000);\n\n// ============================================================================\n// Main Functions\n// ============================================================================\n\n/**\n * Convert a condition tree to CSS components\n */\nexport function conditionToCSS(node: ConditionNode): CSSComponents {\n // Check cache\n const key = getConditionKey(node);\n const cached = conditionCache.get(key);\n if (cached) {\n return cached;\n }\n\n const result = conditionToCSSInner(node);\n\n // Cache result\n conditionCache.set(key, result);\n\n return result;\n}\n\n/**\n * Clear the condition cache (for testing)\n */\nexport function clearConditionCache(): void {\n conditionCache.clear();\n}\n\n// ============================================================================\n// Inner Implementation\n// ============================================================================\n\n/**\n * Create an empty selector variant\n */\nfunction emptyVariant(): SelectorVariant {\n return {\n modifierConditions: [],\n pseudoConditions: [],\n ownConditions: [],\n mediaConditions: [],\n containerConditions: [],\n supportsConditions: [],\n rootConditions: [],\n parentConditions: [],\n startingStyle: false,\n };\n}\n\nfunction conditionToCSSInner(node: ConditionNode): CSSComponents {\n // Base case: TRUE condition - single empty variant (matches everything)\n if (node.kind === 'true') {\n return {\n variants: [emptyVariant()],\n isImpossible: false,\n };\n }\n\n // Base case: FALSE condition - no variants (matches nothing)\n if (node.kind === 'false') {\n return {\n variants: [],\n isImpossible: true,\n };\n }\n\n // State condition\n if (node.kind === 'state') {\n return stateToCSS(node);\n }\n\n // Compound condition\n if (node.kind === 'compound') {\n if (node.operator === 'AND') {\n return andToCSS(node.children);\n } else {\n return orToCSS(node.children);\n }\n }\n\n // Fallback - single empty variant\n return {\n variants: [emptyVariant()],\n isImpossible: false,\n };\n}\n\n/**\n * Convert a state condition to CSS\n */\nfunction stateToCSS(state: StateCondition): CSSComponents {\n switch (state.type) {\n case 'media': {\n // Media conditions can return multiple variants for negated ranges (OR branches)\n const mediaResults = mediaToParsed(state);\n const variants = mediaResults.map((mediaCond) => {\n const v = emptyVariant();\n v.mediaConditions.push(mediaCond);\n return v;\n });\n return { variants, isImpossible: false };\n }\n\n default: {\n const variant: SelectorVariant = emptyVariant();\n\n switch (state.type) {\n case 'modifier':\n variant.modifierConditions.push(modifierToParsed(state));\n break;\n\n case 'pseudo':\n variant.pseudoConditions.push(pseudoToParsed(state));\n break;\n\n case 'container':\n variant.containerConditions.push(containerToParsed(state));\n break;\n\n case 'supports':\n variant.supportsConditions.push(supportsToParsed(state));\n break;\n\n case 'root':\n variant.rootConditions.push(rootToParsed(state));\n break;\n\n case 'parent':\n variant.parentConditions.push(parentToParsed(state));\n break;\n\n case 'own':\n variant.ownConditions.push(...ownToParsed(state));\n break;\n\n case 'starting':\n variant.startingStyle = !state.negated;\n break;\n }\n\n return {\n variants: [variant],\n isImpossible: false,\n };\n }\n }\n}\n\n/**\n * Convert modifier condition to parsed structure\n */\nfunction modifierToParsed(state: ModifierCondition): ParsedModifierCondition {\n return {\n attribute: state.attribute,\n value: state.value,\n operator: state.operator,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert parsed modifier to CSS selector string (for final output)\n */\nexport function modifierToCSS(mod: ParsedModifierCondition): string {\n let selector: string;\n\n if (mod.value !== undefined) {\n // Value attribute: [data-attr=\"value\"]\n const op = mod.operator || '=';\n selector = `[${mod.attribute}${op}\"${mod.value}\"]`;\n } else {\n // Boolean attribute: [data-attr]\n selector = `[${mod.attribute}]`;\n }\n\n if (mod.negated) {\n return `:not(${selector})`;\n }\n return selector;\n}\n\n/**\n * Convert pseudo condition to parsed structure\n */\nfunction pseudoToParsed(state: PseudoCondition): ParsedPseudoCondition {\n return {\n pseudo: state.pseudo,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert parsed pseudo to CSS selector string (for final output)\n */\nexport function pseudoToCSS(pseudo: ParsedPseudoCondition): string {\n if (pseudo.negated) {\n // Wrap in :not() if not already\n if (pseudo.pseudo.startsWith(':not(')) {\n // Double negation - remove :not()\n return pseudo.pseudo.slice(5, -1);\n }\n return `:not(${pseudo.pseudo})`;\n }\n return pseudo.pseudo;\n}\n\n/**\n * Convert media condition to parsed structure(s)\n * Returns an array because negated ranges produce OR branches (two separate conditions)\n */\nfunction mediaToParsed(state: MediaCondition): ParsedMediaCondition[] {\n if (state.subtype === 'type') {\n // @media:print → @media print (or @media not print)\n const mediaType = state.mediaType || 'all';\n return [\n {\n subtype: 'type',\n negated: state.negated ?? false,\n condition: mediaType,\n mediaType: state.mediaType,\n },\n ];\n } else if (state.subtype === 'feature') {\n // @media(prefers-contrast: high) → @media (prefers-contrast: high)\n let condition: string;\n if (state.featureValue) {\n condition = `(${state.feature}: ${state.featureValue})`;\n } else {\n condition = `(${state.feature})`;\n }\n return [\n {\n subtype: 'feature',\n negated: state.negated ?? false,\n condition,\n feature: state.feature,\n featureValue: state.featureValue,\n },\n ];\n } else {\n // Dimension query - negation is handled by inverting the condition\n // because \"not (width < x)\" doesn't work reliably in browsers\n return dimensionToMediaParsed(\n state.dimension || 'width',\n state.lowerBound,\n state.upperBound,\n state.negated ?? false,\n );\n }\n}\n\n/**\n * Convert dimension bounds to parsed media condition(s)\n * Uses CSS Media Queries Level 4 `not (condition)` syntax for negation.\n */\nfunction dimensionToMediaParsed(\n dimension: 'width' | 'height' | 'inline-size' | 'block-size',\n lowerBound?: {\n value: string;\n valueNumeric: number | null;\n inclusive: boolean;\n },\n upperBound?: {\n value: string;\n valueNumeric: number | null;\n inclusive: boolean;\n },\n negated?: boolean,\n): ParsedMediaCondition[] {\n // Build the condition string\n let condition: string;\n if (lowerBound && upperBound) {\n const lowerOp = lowerBound.inclusive ? '<=' : '<';\n const upperOp = upperBound.inclusive ? '<=' : '<';\n condition = `(${lowerBound.value} ${lowerOp} ${dimension} ${upperOp} ${upperBound.value})`;\n } else if (upperBound) {\n const op = upperBound.inclusive ? '<=' : '<';\n condition = `(${dimension} ${op} ${upperBound.value})`;\n } else if (lowerBound) {\n const op = lowerBound.inclusive ? '>=' : '>';\n condition = `(${dimension} ${op} ${lowerBound.value})`;\n } else {\n condition = `(${dimension})`;\n }\n\n // For negation, we use CSS `not (condition)` syntax in buildAtRulesFromVariant\n return [\n {\n subtype: 'dimension',\n negated: negated ?? false,\n condition,\n dimension,\n lowerBound,\n upperBound,\n },\n ];\n}\n\n/**\n * Convert container condition to parsed structure\n * This enables structured analysis for contradiction detection and condition combining\n */\nfunction containerToParsed(\n state: ContainerCondition,\n): ParsedContainerCondition {\n let condition: string;\n\n if (state.subtype === 'style') {\n // Style query: style(--prop: value)\n if (state.propertyValue) {\n condition = `style(--${state.property}: ${state.propertyValue})`;\n } else {\n condition = `style(--${state.property})`;\n }\n } else if (state.subtype === 'raw') {\n // Raw function query: passed through verbatim (e.g., scroll-state(stuck: top))\n condition = state.rawCondition!;\n } else {\n // Dimension query\n condition = dimensionToContainerCondition(\n state.dimension || 'width',\n state.lowerBound,\n state.upperBound,\n );\n }\n\n return {\n name: state.containerName,\n condition,\n negated: state.negated ?? false,\n subtype: state.subtype,\n property: state.property,\n propertyValue: state.propertyValue,\n };\n}\n\n/**\n * Convert dimension bounds to container query condition (single string)\n * Container queries support \"not (condition)\", so no need to invert manually\n */\nfunction dimensionToContainerCondition(\n dimension: string,\n lowerBound?: { value: string; inclusive: boolean },\n upperBound?: { value: string; inclusive: boolean },\n): string {\n if (lowerBound && upperBound) {\n const lowerOp = lowerBound.inclusive ? '<=' : '<';\n const upperOp = upperBound.inclusive ? '<=' : '<';\n return `(${lowerBound.value} ${lowerOp} ${dimension} ${upperOp} ${upperBound.value})`;\n } else if (upperBound) {\n const op = upperBound.inclusive ? '<=' : '<';\n return `(${dimension} ${op} ${upperBound.value})`;\n } else if (lowerBound) {\n const op = lowerBound.inclusive ? '>=' : '>';\n return `(${dimension} ${op} ${lowerBound.value})`;\n }\n return '(width)'; // Fallback\n}\n\n/**\n * Convert supports condition to parsed structure\n */\nfunction supportsToParsed(state: SupportsCondition): ParsedSupportsCondition {\n return {\n subtype: state.subtype,\n condition: state.condition,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert root condition to parsed structure\n */\nfunction rootToParsed(state: RootCondition): ParsedRootCondition {\n return {\n selector: state.selector,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert parsed root conditions to CSS selector prefix (for final output)\n */\nexport function rootConditionsToCSS(\n roots: ParsedRootCondition[],\n): string | undefined {\n if (roots.length === 0) return undefined;\n\n // Combine all root conditions into a single :root prefix\n // e.g., :root[data-theme=\"dark\"]:not([data-mode=\"light\"])\n let prefix = ':root';\n for (const root of roots) {\n if (root.negated) {\n prefix += `:not(${root.selector})`;\n } else {\n prefix += root.selector;\n }\n }\n return prefix;\n}\n\n/**\n * Convert parent condition to parsed structure\n */\nfunction parentToParsed(state: ParentCondition): ParsedParentCondition {\n return {\n selector: state.selector,\n direct: state.direct,\n negated: state.negated ?? false,\n };\n}\n\n/**\n * Convert parsed parent condition to CSS selector fragment (for final output)\n *\n * Positive: :is([selector] *) or :is([selector] > *)\n * Negative: :not([selector] *) or :not([selector] > *)\n */\nexport function parentToCSS(parent: ParsedParentCondition): string {\n const combinator = parent.direct ? ' > *' : ' *';\n if (parent.negated) {\n return `:not(${parent.selector}${combinator})`;\n }\n return `:is(${parent.selector}${combinator})`;\n}\n\n/**\n * Convert own condition to parsed structures for sub-element\n */\nfunction ownToParsed(\n state: OwnCondition,\n): (ParsedModifierCondition | ParsedPseudoCondition)[] {\n const innerCSS = conditionToCSS(state.innerCondition);\n\n if (innerCSS.isImpossible || innerCSS.variants.length === 0) {\n return [];\n }\n\n // Collect all modifier/pseudo conditions from all variants\n const allConditions: (ParsedModifierCondition | ParsedPseudoCondition)[] = [];\n for (const variant of innerCSS.variants) {\n for (const mod of variant.modifierConditions) {\n // Apply outer negation\n allConditions.push({\n ...mod,\n negated: state.negated ? !mod.negated : mod.negated,\n });\n }\n for (const pseudo of variant.pseudoConditions) {\n // Apply outer negation\n allConditions.push({\n ...pseudo,\n negated: state.negated ? !pseudo.negated : pseudo.negated,\n });\n }\n }\n\n return allConditions;\n}\n\n/**\n * Get unique key for a modifier condition\n */\nfunction getModifierKey(mod: ParsedModifierCondition): string {\n const base = mod.value\n ? `${mod.attribute}${mod.operator || '='}${mod.value}`\n : mod.attribute;\n return mod.negated ? `!${base}` : base;\n}\n\n/**\n * Get unique key for a pseudo condition\n */\nfunction getPseudoKey(pseudo: ParsedPseudoCondition): string {\n return pseudo.negated ? `!${pseudo.pseudo}` : pseudo.pseudo;\n}\n\n/**\n * Get unique key for a root condition\n */\nfunction getRootKey(root: ParsedRootCondition): string {\n return root.negated ? `!${root.selector}` : root.selector;\n}\n\n/**\n * Deduplicate modifier conditions\n */\nfunction dedupeModifierConditions(\n conditions: ParsedModifierCondition[],\n): ParsedModifierCondition[] {\n const seen = new Set<string>();\n const result: ParsedModifierCondition[] = [];\n for (const c of conditions) {\n const key = getModifierKey(c);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate pseudo conditions\n */\nfunction dedupePseudoConditions(\n conditions: ParsedPseudoCondition[],\n): ParsedPseudoCondition[] {\n const seen = new Set<string>();\n const result: ParsedPseudoCondition[] = [];\n for (const c of conditions) {\n const key = getPseudoKey(c);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate root conditions\n */\nfunction dedupeRootConditions(\n conditions: ParsedRootCondition[],\n): ParsedRootCondition[] {\n const seen = new Set<string>();\n const result: ParsedRootCondition[] = [];\n for (const c of conditions) {\n const key = getRootKey(c);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Get unique key for a parent condition\n */\nfunction getParentKey(parent: ParsedParentCondition): string {\n const base = `${parent.direct ? '>' : ''}${parent.selector}`;\n return parent.negated ? `!${base}` : base;\n}\n\n/**\n * Deduplicate parent conditions\n */\nfunction dedupeParentConditions(\n conditions: ParsedParentCondition[],\n): ParsedParentCondition[] {\n const seen = new Set<string>();\n const result: ParsedParentCondition[] = [];\n for (const c of conditions) {\n const key = getParentKey(c);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate own conditions (modifiers or pseudos)\n */\nfunction dedupeOwnConditions(\n conditions: (ParsedModifierCondition | ParsedPseudoCondition)[],\n): (ParsedModifierCondition | ParsedPseudoCondition)[] {\n const seen = new Set<string>();\n const result: (ParsedModifierCondition | ParsedPseudoCondition)[] = [];\n for (const c of conditions) {\n const key =\n 'attribute' in c\n ? `mod:${getModifierKey(c)}`\n : `pseudo:${getPseudoKey(c)}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Check for modifier contradiction: same attribute with opposite negation\n */\nfunction hasModifierContradiction(\n conditions: ParsedModifierCondition[],\n): boolean {\n const byKey = new Map<string, boolean>(); // base key -> isPositive\n\n for (const mod of conditions) {\n const baseKey = mod.value\n ? `${mod.attribute}${mod.operator || '='}${mod.value}`\n : mod.attribute;\n const existing = byKey.get(baseKey);\n if (existing !== undefined && existing !== !mod.negated) {\n return true; // Same attribute with opposite negation\n }\n byKey.set(baseKey, !mod.negated);\n }\n return false;\n}\n\n/**\n * Check for pseudo contradiction: same pseudo with opposite negation\n */\nfunction hasPseudoContradiction(conditions: ParsedPseudoCondition[]): boolean {\n const byKey = new Map<string, boolean>(); // pseudo -> isPositive\n\n for (const pseudo of conditions) {\n const existing = byKey.get(pseudo.pseudo);\n if (existing !== undefined && existing !== !pseudo.negated) {\n return true; // Same pseudo with opposite negation\n }\n byKey.set(pseudo.pseudo, !pseudo.negated);\n }\n return false;\n}\n\n/**\n * Check for root condition contradiction: same selector with opposite negation\n */\nfunction hasRootContradiction(conditions: ParsedRootCondition[]): boolean {\n const byKey = new Map<string, boolean>(); // selector -> isPositive\n\n for (const root of conditions) {\n const existing = byKey.get(root.selector);\n if (existing !== undefined && existing !== !root.negated) {\n return true; // Same selector with opposite negation\n }\n byKey.set(root.selector, !root.negated);\n }\n return false;\n}\n\n/**\n * Check for parent condition contradiction: same selector+direct with opposite negation\n */\nfunction hasParentContradiction(conditions: ParsedParentCondition[]): boolean {\n const byKey = new Map<string, boolean>();\n\n for (const parent of conditions) {\n const baseKey = `${parent.direct ? '>' : ''}${parent.selector}`;\n const existing = byKey.get(baseKey);\n if (existing !== undefined && existing !== !parent.negated) {\n return true;\n }\n byKey.set(baseKey, !parent.negated);\n }\n return false;\n}\n\n/**\n * Check for own condition contradiction\n */\nfunction hasOwnConditionContradiction(\n conditions: (ParsedModifierCondition | ParsedPseudoCondition)[],\n): boolean {\n const modifiers: ParsedModifierCondition[] = [];\n const pseudos: ParsedPseudoCondition[] = [];\n\n for (const c of conditions) {\n if ('attribute' in c) {\n modifiers.push(c);\n } else {\n pseudos.push(c);\n }\n }\n\n return hasModifierContradiction(modifiers) || hasPseudoContradiction(pseudos);\n}\n\n/**\n * Merge two selector variants (AND operation)\n * Deduplicates conditions and checks for contradictions\n */\nfunction mergeVariants(\n a: SelectorVariant,\n b: SelectorVariant,\n): SelectorVariant | null {\n // Merge media conditions and check for contradictions\n const mergedMedia = dedupeMediaConditions([\n ...a.mediaConditions,\n ...b.mediaConditions,\n ]);\n if (hasMediaContradiction(mergedMedia)) {\n return null; // Impossible variant\n }\n\n // Merge root conditions and check for contradictions\n const mergedRoots = dedupeRootConditions([\n ...a.rootConditions,\n ...b.rootConditions,\n ]);\n if (hasRootContradiction(mergedRoots)) {\n return null; // Impossible variant\n }\n\n // Merge modifier conditions and check for contradictions\n const mergedModifiers = dedupeModifierConditions([\n ...a.modifierConditions,\n ...b.modifierConditions,\n ]);\n if (hasModifierContradiction(mergedModifiers)) {\n return null; // Impossible variant\n }\n\n // Merge pseudo conditions and check for contradictions\n const mergedPseudos = dedupePseudoConditions([\n ...a.pseudoConditions,\n ...b.pseudoConditions,\n ]);\n if (hasPseudoContradiction(mergedPseudos)) {\n return null; // Impossible variant\n }\n\n // Merge parent conditions and check for contradictions\n const mergedParents = dedupeParentConditions([\n ...a.parentConditions,\n ...b.parentConditions,\n ]);\n if (hasParentContradiction(mergedParents)) {\n return null; // Impossible variant\n }\n\n // Merge own conditions and check for contradictions\n const mergedOwn = dedupeOwnConditions([\n ...a.ownConditions,\n ...b.ownConditions,\n ]);\n if (hasOwnConditionContradiction(mergedOwn)) {\n return null; // Impossible variant\n }\n\n // Merge container conditions and check for contradictions\n const mergedContainers = dedupeContainerConditions([\n ...a.containerConditions,\n ...b.containerConditions,\n ]);\n if (hasContainerStyleContradiction(mergedContainers)) {\n return null; // Impossible variant\n }\n\n // Merge supports conditions and check for contradictions\n const mergedSupports = dedupeSupportsConditions([\n ...a.supportsConditions,\n ...b.supportsConditions,\n ]);\n if (hasSupportsContradiction(mergedSupports)) {\n return null; // Impossible variant\n }\n\n return {\n modifierConditions: mergedModifiers,\n pseudoConditions: mergedPseudos,\n ownConditions: mergedOwn,\n mediaConditions: mergedMedia,\n containerConditions: mergedContainers,\n supportsConditions: mergedSupports,\n rootConditions: mergedRoots,\n parentConditions: mergedParents,\n startingStyle: a.startingStyle || b.startingStyle,\n };\n}\n\n/**\n * Deduplicate media conditions by their key (subtype + condition + negated)\n */\nfunction dedupeMediaConditions(\n conditions: ParsedMediaCondition[],\n): ParsedMediaCondition[] {\n const seen = new Set<string>();\n const result: ParsedMediaCondition[] = [];\n for (const c of conditions) {\n const key = `${c.subtype}|${c.condition}|${c.negated}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate container conditions by their key (name + condition + negated)\n */\nfunction dedupeContainerConditions(\n conditions: ParsedContainerCondition[],\n): ParsedContainerCondition[] {\n const seen = new Set<string>();\n const result: ParsedContainerCondition[] = [];\n for (const c of conditions) {\n const key = `${c.name ?? ''}|${c.condition}|${c.negated}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Deduplicate supports conditions by their key (subtype + condition + negated)\n */\nfunction dedupeSupportsConditions(\n conditions: ParsedSupportsCondition[],\n): ParsedSupportsCondition[] {\n const seen = new Set<string>();\n const result: ParsedSupportsCondition[] = [];\n for (const c of conditions) {\n const key = `${c.subtype}|${c.condition}|${c.negated}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(c);\n }\n }\n return result;\n}\n\n/**\n * Check if supports conditions contain contradictions\n * e.g., @supports(display: grid) AND NOT @supports(display: grid)\n */\nfunction hasSupportsContradiction(\n conditions: ParsedSupportsCondition[],\n): boolean {\n const conditionMap = new Map<string, boolean>(); // key -> isPositive\n\n for (const cond of conditions) {\n const key = `${cond.subtype}|${cond.condition}`;\n const existing = conditionMap.get(key);\n if (existing !== undefined && existing !== !cond.negated) {\n return true; // Contradiction: positive AND negated\n }\n conditionMap.set(key, !cond.negated);\n }\n\n return false;\n}\n\n/**\n * Check if a set of media conditions contains contradictions\n * e.g., (prefers-color-scheme: light) AND NOT (prefers-color-scheme: light)\n * or (width >= 900px) AND (width < 600px)\n *\n * Uses parsed media conditions for efficient analysis without regex parsing.\n */\nfunction hasMediaContradiction(conditions: ParsedMediaCondition[]): boolean {\n // Track conditions by their key (condition string) to detect A and NOT A\n const featureConditions = new Map<string, boolean>(); // key -> isPositive\n const typeConditions = new Map<string, boolean>(); // mediaType -> isPositive\n const dimensionConditions = new Map<string, boolean>(); // condition -> isPositive\n\n // Track dimension conditions for range contradiction detection (non-negated only)\n const dimensionsByDim = new Map<\n string,\n { lowerBound: number | null; upperBound: number | null }\n >();\n\n for (const cond of conditions) {\n if (cond.subtype === 'type') {\n // Type query: check for direct contradiction (print AND NOT print)\n const key = cond.mediaType || 'all';\n const existing = typeConditions.get(key);\n if (existing !== undefined && existing !== !cond.negated) {\n return true; // Contradiction: positive AND negated\n }\n typeConditions.set(key, !cond.negated);\n } else if (cond.subtype === 'feature') {\n // Feature query: check for direct contradiction\n const key = cond.condition;\n const existing = featureConditions.get(key);\n if (existing !== undefined && existing !== !cond.negated) {\n return true; // Contradiction: positive AND negated\n }\n featureConditions.set(key, !cond.negated);\n } else if (cond.subtype === 'dimension') {\n // First, check for direct contradiction: (width < 600px) AND NOT (width < 600px)\n const condKey = cond.condition;\n const existing = dimensionConditions.get(condKey);\n if (existing !== undefined && existing !== !cond.negated) {\n return true; // Contradiction: positive AND negated\n }\n dimensionConditions.set(condKey, !cond.negated);\n\n // For range analysis, only consider non-negated conditions\n // Negated conditions are handled via the direct contradiction check above\n if (!cond.negated) {\n const dim = cond.dimension || 'width';\n let bounds = dimensionsByDim.get(dim);\n if (!bounds) {\n bounds = { lowerBound: null, upperBound: null };\n dimensionsByDim.set(dim, bounds);\n }\n\n // Track the effective bounds\n if (cond.lowerBound?.valueNumeric != null) {\n const value = cond.lowerBound.valueNumeric;\n if (bounds.lowerBound === null || value > bounds.lowerBound) {\n bounds.lowerBound = value;\n }\n }\n if (cond.upperBound?.valueNumeric != null) {\n const value = cond.upperBound.valueNumeric;\n if (bounds.upperBound === null || value < bounds.upperBound) {\n bounds.upperBound = value;\n }\n }\n\n // Check for impossible range\n if (\n bounds.lowerBound !== null &&\n bounds.upperBound !== null &&\n bounds.lowerBound >= bounds.upperBound\n ) {\n return true;\n }\n }\n }\n }\n\n return false;\n}\n\n/**\n * Check if container conditions contain contradictions in style queries\n * e.g., style(--variant: danger) and style(--variant: success) together\n * Same property with different values = always false\n *\n * Uses parsed container conditions for efficient analysis without regex parsing.\n */\nfunction hasContainerStyleContradiction(\n conditions: ParsedContainerCondition[],\n): boolean {\n // Track style queries by property name\n // key: property name, value: { hasExistence: boolean, values: Set<string>, hasNegatedExistence: boolean }\n const styleQueries = new Map<\n string,\n { hasExistence: boolean; values: Set<string>; hasNegatedExistence: boolean }\n >();\n\n for (const cond of conditions) {\n // Only analyze style queries\n if (cond.subtype !== 'style' || !cond.property) {\n continue;\n }\n\n const property = cond.property;\n const value = cond.propertyValue;\n\n if (!styleQueries.has(property)) {\n styleQueries.set(property, {\n hasExistence: false,\n values: new Set(),\n hasNegatedExistence: false,\n });\n }\n\n const entry = styleQueries.get(property)!;\n\n if (cond.negated) {\n if (value === undefined) {\n // not style(--prop) - negated existence check\n entry.hasNegatedExistence = true;\n }\n // Negated value checks don't contradict positive value checks directly\n // They just mean \"not this value\"\n } else {\n if (value === undefined) {\n // style(--prop) - existence check\n entry.hasExistence = true;\n } else {\n // style(--prop: value) - value check\n entry.values.add(value);\n }\n }\n }\n\n // Check for contradictions\n for (const [, entry] of styleQueries) {\n // Contradiction: existence check + negated existence check\n if (entry.hasExistence && entry.hasNegatedExistence) {\n return true;\n }\n\n // Contradiction: multiple different values for same property\n // style(--variant: danger) AND style(--variant: success) is impossible\n if (entry.values.size > 1) {\n return true;\n }\n\n // Contradiction: negated existence + value check\n // not style(--variant) AND style(--variant: danger) is impossible\n if (entry.hasNegatedExistence && entry.values.size > 0) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Get a unique key for a variant (for deduplication)\n */\nfunction getVariantKey(v: SelectorVariant): string {\n const modifierKey = v.modifierConditions.map(getModifierKey).sort().join('|');\n const pseudoKey = v.pseudoConditions.map(getPseudoKey).sort().join('|');\n const ownKey = v.ownConditions\n .map((c) =>\n 'attribute' in c\n ? `mod:${getModifierKey(c)}`\n : `pseudo:${getPseudoKey(c)}`,\n )\n .sort()\n .join('|');\n const containerKey = v.containerConditions\n .map((c) => `${c.name ?? ''}:${c.negated ? '!' : ''}${c.condition}`)\n .sort()\n .join('|');\n const mediaKey = v.mediaConditions\n .map((c) => `${c.subtype}:${c.negated ? '!' : ''}${c.condition}`)\n .sort()\n .join('|');\n const supportsKey = v.supportsConditions\n .map((c) => `${c.subtype}:${c.negated ? '!' : ''}${c.condition}`)\n .sort()\n .join('|');\n const rootKey = v.rootConditions.map(getRootKey).sort().join('|');\n const parentKey = v.parentConditions.map(getParentKey).sort().join('|');\n return [\n modifierKey,\n pseudoKey,\n ownKey,\n mediaKey,\n containerKey,\n supportsKey,\n rootKey,\n parentKey,\n v.startingStyle ? '1' : '0',\n ].join('###');\n}\n\n/**\n * Check if variant A is a superset of variant B (A is more restrictive)\n *\n * If A has all of B's conditions plus more, then A is redundant\n * because B already covers the same cases (and more).\n *\n * Example:\n * A: :not([size=large]):not([size=medium]):not([size=small])\n * B: :not([size=large])\n * A is a superset of B, so A is redundant when B exists.\n */\nfunction isVariantSuperset(a: SelectorVariant, b: SelectorVariant): boolean {\n // Must have same context\n if (a.startingStyle !== b.startingStyle) return false;\n\n // Check if a.rootConditions is superset of b.rootConditions\n if (!isRootConditionsSuperset(a.rootConditions, b.rootConditions))\n return false;\n\n // Check if a.mediaConditions is superset of b.mediaConditions\n if (!isMediaConditionsSuperset(a.mediaConditions, b.mediaConditions))\n return false;\n\n // Check if a.containerConditions is superset of b.containerConditions\n if (\n !isContainerConditionsSuperset(a.containerConditions, b.containerConditions)\n )\n return false;\n\n // Check if a.supportsConditions is superset of b.supportsConditions\n if (!isSupportsConditionsSuperset(a.supportsConditions, b.supportsConditions))\n return false;\n\n // Check if a.modifierConditions is superset of b.modifierConditions\n if (!isModifierConditionsSuperset(a.modifierConditions, b.modifierConditions))\n return false;\n\n // Check if a.pseudoConditions is superset of b.pseudoConditions\n if (!isPseudoConditionsSuperset(a.pseudoConditions, b.pseudoConditions))\n return false;\n\n // Check if a.ownConditions is superset of b.ownConditions\n if (!isOwnConditionsSuperset(a.ownConditions, b.ownConditions)) return false;\n\n // Check if a.parentConditions is superset of b.parentConditions\n if (!isParentConditionsSuperset(a.parentConditions, b.parentConditions))\n return false;\n\n // A is a superset if it has all of B's items (possibly more)\n // and at least one category has strictly more items\n const aTotal =\n a.mediaConditions.length +\n a.containerConditions.length +\n a.supportsConditions.length +\n a.modifierConditions.length +\n a.pseudoConditions.length +\n a.rootConditions.length +\n a.parentConditions.length +\n a.ownConditions.length;\n const bTotal =\n b.mediaConditions.length +\n b.containerConditions.length +\n b.supportsConditions.length +\n b.modifierConditions.length +\n b.pseudoConditions.length +\n b.rootConditions.length +\n b.parentConditions.length +\n b.ownConditions.length;\n\n return aTotal > bTotal;\n}\n\n/**\n * Check if media conditions A is a superset of B\n */\nfunction isMediaConditionsSuperset(\n a: ParsedMediaCondition[],\n b: ParsedMediaCondition[],\n): boolean {\n const aKeys = new Set(\n a.map((c) => `${c.subtype}|${c.condition}|${c.negated}`),\n );\n for (const c of b) {\n const key = `${c.subtype}|${c.condition}|${c.negated}`;\n if (!aKeys.has(key)) return false;\n }\n return true;\n}\n\n/**\n * Check if container conditions A is a superset of B\n */\nfunction isContainerConditionsSuperset(\n a: ParsedContainerCondition[],\n b: ParsedContainerCondition[],\n): boolean {\n const aKeys = new Set(\n a.map((c) => `${c.name ?? ''}|${c.condition}|${c.negated}`),\n );\n for (const c of b) {\n const key = `${c.name ?? ''}|${c.condition}|${c.negated}`;\n if (!aKeys.has(key)) return false;\n }\n return true;\n}\n\n/**\n * Check if supports conditions A is a superset of B\n */\nfunction isSupportsConditionsSuperset(\n a: ParsedSupportsCondition[],\n b: ParsedSupportsCondition[],\n): boolean {\n const aKeys = new Set(\n a.map((c) => `${c.subtype}|${c.condition}|${c.negated}`),\n );\n for (const c of b) {\n const key = `${c.subtype}|${c.condition}|${c.negated}`;\n if (!aKeys.has(key)) return false;\n }\n return true;\n}\n\n/**\n * Check if modifier conditions A is a superset of B\n */\nfunction isModifierConditionsSuperset(\n a: ParsedModifierCondition[],\n b: ParsedModifierCondition[],\n): boolean {\n const aKeys = new Set(a.map(getModifierKey));\n for (const c of b) {\n if (!aKeys.has(getModifierKey(c))) return false;\n }\n return true;\n}\n\n/**\n * Check if pseudo conditions A is a superset of B\n */\nfunction isPseudoConditionsSuperset(\n a: ParsedPseudoCondition[],\n b: ParsedPseudoCondition[],\n): boolean {\n const aKeys = new Set(a.map(getPseudoKey));\n for (const c of b) {\n if (!aKeys.has(getPseudoKey(c))) return false;\n }\n return true;\n}\n\n/**\n * Check if root conditions A is a superset of B\n */\nfunction isRootConditionsSuperset(\n a: ParsedRootCondition[],\n b: ParsedRootCondition[],\n): boolean {\n const aKeys = new Set(a.map(getRootKey));\n for (const c of b) {\n if (!aKeys.has(getRootKey(c))) return false;\n }\n return true;\n}\n\n/**\n * Check if parent conditions A is a superset of B\n */\nfunction isParentConditionsSuperset(\n a: ParsedParentCondition[],\n b: ParsedParentCondition[],\n): boolean {\n const aKeys = new Set(a.map(getParentKey));\n for (const c of b) {\n if (!aKeys.has(getParentKey(c))) return false;\n }\n return true;\n}\n\n/**\n * Check if own conditions A is a superset of B\n */\nfunction isOwnConditionsSuperset(\n a: (ParsedModifierCondition | ParsedPseudoCondition)[],\n b: (ParsedModifierCondition | ParsedPseudoCondition)[],\n): boolean {\n const aKeys = new Set(\n a.map((c) =>\n 'attribute' in c\n ? `mod:${getModifierKey(c)}`\n : `pseudo:${getPseudoKey(c)}`,\n ),\n );\n for (const c of b) {\n const key =\n 'attribute' in c\n ? `mod:${getModifierKey(c)}`\n : `pseudo:${getPseudoKey(c)}`;\n if (!aKeys.has(key)) return false;\n }\n return true;\n}\n\n/**\n * Deduplicate variants\n *\n * Removes:\n * 1. Exact duplicates (same key)\n * 2. Superset variants (more restrictive selectors that are redundant)\n */\nfunction dedupeVariants(variants: SelectorVariant[]): SelectorVariant[] {\n // First pass: exact deduplication\n const seen = new Set<string>();\n const result: SelectorVariant[] = [];\n\n for (const v of variants) {\n const key = getVariantKey(v);\n if (!seen.has(key)) {\n seen.add(key);\n result.push(v);\n }\n }\n\n // Second pass: remove supersets (more restrictive variants)\n // Sort by total condition count (fewer conditions = less restrictive = keep)\n result.sort((a, b) => {\n const aCount =\n a.modifierConditions.length +\n a.pseudoConditions.length +\n a.ownConditions.length +\n a.mediaConditions.length +\n a.containerConditions.length +\n a.supportsConditions.length +\n a.rootConditions.length +\n a.parentConditions.length;\n const bCount =\n b.modifierConditions.length +\n b.pseudoConditions.length +\n b.ownConditions.length +\n b.mediaConditions.length +\n b.containerConditions.length +\n b.supportsConditions.length +\n b.rootConditions.length +\n b.parentConditions.length;\n return aCount - bCount;\n });\n\n // Remove variants that are supersets of earlier (less restrictive) variants\n const filtered: SelectorVariant[] = [];\n for (const candidate of result) {\n let isRedundant = false;\n for (const kept of filtered) {\n if (isVariantSuperset(candidate, kept)) {\n isRedundant = true;\n break;\n }\n }\n if (!isRedundant) {\n filtered.push(candidate);\n }\n }\n\n return filtered;\n}\n\n/**\n * Combine AND conditions into CSS\n *\n * AND of conditions means cartesian product of variants:\n * (A1 | A2) & (B1 | B2) = A1&B1 | A1&B2 | A2&B1 | A2&B2\n *\n * Variants that result in contradictions (e.g., conflicting media rules)\n * are filtered out.\n */\nfunction andToCSS(children: ConditionNode[]): CSSComponents {\n // Start with a single empty variant\n let currentVariants: SelectorVariant[] = [emptyVariant()];\n\n for (const child of children) {\n const childCSS = conditionToCSSInner(child);\n\n if (childCSS.isImpossible || childCSS.variants.length === 0) {\n return { variants: [], isImpossible: true };\n }\n\n // Cartesian product: each current variant × each child variant\n const newVariants: SelectorVariant[] = [];\n for (const current of currentVariants) {\n for (const childVariant of childCSS.variants) {\n const merged = mergeVariants(current, childVariant);\n // Skip impossible variants (contradictions detected during merge)\n if (merged !== null) {\n newVariants.push(merged);\n }\n }\n }\n\n if (newVariants.length === 0) {\n return { variants: [], isImpossible: true };\n }\n\n // Deduplicate after each step to prevent exponential blowup\n currentVariants = dedupeVariants(newVariants);\n }\n\n return {\n variants: currentVariants,\n isImpossible: false,\n };\n}\n\n/**\n * Combine OR conditions into CSS\n *\n * OR in CSS means multiple selector variants (DNF).\n * Each variant becomes a separate selector in the comma-separated list,\n * or multiple CSS rules if they have different at-rules.\n *\n * Note: OR exclusivity is handled at the pipeline level (expandOrConditions),\n * so here we just collect all variants. Any remaining ORs in the condition\n * tree (e.g., from De Morgan expansion) are handled as simple alternatives.\n */\nfunction orToCSS(children: ConditionNode[]): CSSComponents {\n const allVariants: SelectorVariant[] = [];\n\n for (const child of children) {\n const childCSS = conditionToCSSInner(child);\n if (childCSS.isImpossible) continue;\n\n allVariants.push(...childCSS.variants);\n }\n\n if (allVariants.length === 0) {\n return { variants: [], isImpossible: true };\n }\n\n // Deduplicate variants\n return {\n variants: dedupeVariants(allVariants),\n isImpossible: false,\n };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Get a cache key for a condition\n */\nfunction getConditionKey(node: ConditionNode): string {\n if (node.kind === 'true') return 'TRUE';\n if (node.kind === 'false') return 'FALSE';\n if (node.kind === 'state') return node.uniqueId;\n if (node.kind === 'compound') {\n const childKeys = node.children.map(getConditionKey).sort();\n return `${node.operator}(${childKeys.join(',')})`;\n }\n return 'UNKNOWN';\n}\n\n/**\n * Build a complete CSS selector from a single variant\n */\nfunction buildCSSSelectorFromVariant(\n className: string,\n variant: SelectorVariant,\n selectorSuffix = '',\n): string {\n // Start with base class (doubled for specificity)\n let selector = `.${className}.${className}`;\n\n // Add modifier selectors\n for (const mod of variant.modifierConditions) {\n selector += modifierToCSS(mod);\n }\n\n // Add pseudo selectors\n for (const pseudo of variant.pseudoConditions) {\n selector += pseudoToCSS(pseudo);\n }\n\n // Add parent selectors (before sub-element suffix)\n for (const parent of variant.parentConditions) {\n selector += parentToCSS(parent);\n }\n\n // Add selector suffix (e.g., ' [data-element=\"Label\"]')\n selector += selectorSuffix;\n\n // Add own selectors (after sub-element)\n for (const own of variant.ownConditions) {\n if ('attribute' in own) {\n selector += modifierToCSS(own);\n } else {\n selector += pseudoToCSS(own);\n }\n }\n\n // Add root prefix if present\n const rootPrefix = rootConditionsToCSS(variant.rootConditions);\n if (rootPrefix) {\n selector = `${rootPrefix} ${selector}`;\n }\n\n return selector;\n}\n\n/**\n * Build at-rules array from a variant\n */\nexport function buildAtRulesFromVariant(variant: SelectorVariant): string[] {\n const atRules: string[] = [];\n\n // Add media rules - combine all conditions with \"and\"\n if (variant.mediaConditions.length > 0) {\n const conditionParts = variant.mediaConditions.map((c) => {\n if (c.subtype === 'type') {\n // Media type: print, screen, etc.\n return c.negated ? `not ${c.condition}` : c.condition;\n } else {\n // Feature or dimension: use not (condition) syntax for negation\n // MQ Level 4 requires parentheses around the condition for negation\n return c.negated ? `(not ${c.condition})` : c.condition;\n }\n });\n atRules.push(`@media ${conditionParts.join(' and ')}`);\n }\n\n // Add container rules - group by container name and combine with \"and\"\n if (variant.containerConditions.length > 0) {\n // Group conditions by container name (undefined = unnamed/nearest)\n const byName = new Map<string | undefined, ParsedContainerCondition[]>();\n for (const cond of variant.containerConditions) {\n const group = byName.get(cond.name) || [];\n group.push(cond);\n byName.set(cond.name, group);\n }\n\n // Build one @container rule per container name\n for (const [name, conditions] of byName) {\n // CSS Container Query syntax requires parentheses around negated conditions:\n // @container (not style(--x)) and style(--y) - NOT @container not style(--x) and style(--y)\n const conditionParts = conditions.map((c) =>\n c.negated ? `(not ${c.condition})` : c.condition,\n );\n const namePrefix = name ? `${name} ` : '';\n atRules.push(`@container ${namePrefix}${conditionParts.join(' and ')}`);\n }\n }\n\n // Add supports rules - combine all conditions with \"and\"\n if (variant.supportsConditions.length > 0) {\n const conditionParts = variant.supportsConditions.map((c) => {\n // Build the condition based on subtype\n // feature: (display: grid) or (not (display: grid))\n // selector: selector(:has(*)) or (not selector(:has(*)))\n if (c.subtype === 'selector') {\n const selectorCond = `selector(${c.condition})`;\n return c.negated ? `(not ${selectorCond})` : selectorCond;\n } else {\n const featureCond = `(${c.condition})`;\n return c.negated ? `(not ${featureCond})` : featureCond;\n }\n });\n atRules.push(`@supports ${conditionParts.join(' and ')}`);\n }\n\n // Add starting-style\n if (variant.startingStyle) {\n atRules.push('@starting-style');\n }\n\n return atRules;\n}\n\n/**\n * Get a string key for a variant's at-rules (for grouping)\n */\nfunction getAtRulesKey(variant: SelectorVariant): string {\n const atRules = buildAtRulesFromVariant(variant);\n return atRules.sort().join('|||');\n}\n\n/**\n * Materialize a computed rule into final CSS format\n *\n * Returns an array of CSSRules because OR conditions may require multiple rules\n * (when different branches have different at-rules)\n */\nfunction _materializeRule(\n condition: ConditionNode,\n declarations: Record<string, string>,\n selectorSuffix: string,\n className: string,\n): CSSRule[] {\n const components = conditionToCSS(condition);\n\n if (components.isImpossible || components.variants.length === 0) {\n return [];\n }\n\n const declarationsStr = Object.entries(declarations)\n .map(([prop, value]) => `${prop}: ${value};`)\n .join(' ');\n\n // Group variants by their at-rules (variants with same at-rules can be combined with commas)\n const byAtRules = new Map<string, SelectorVariant[]>();\n for (const variant of components.variants) {\n const key = getAtRulesKey(variant);\n const group = byAtRules.get(key) || [];\n group.push(variant);\n byAtRules.set(key, group);\n }\n\n // Generate one CSSRule per at-rules group\n const rules: CSSRule[] = [];\n for (const [, variants] of byAtRules) {\n // All variants in this group have the same at-rules, so combine selectors with commas\n const selectors = variants.map((v) =>\n buildCSSSelectorFromVariant(className, v, selectorSuffix),\n );\n const selector = selectors.join(', ');\n const atRules = buildAtRulesFromVariant(variants[0]);\n\n const rule: CSSRule = {\n selector,\n declarations: declarationsStr,\n };\n\n if (atRules.length > 0) {\n rule.atRules = atRules;\n }\n\n const rootPrefix = rootConditionsToCSS(variants[0].rootConditions);\n if (rootPrefix) {\n rule.rootPrefix = rootPrefix;\n }\n\n rules.push(rule);\n }\n\n return rules;\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Lru } from "../parser/lru.js";
|
|
2
2
|
import { camelToKebab } from "../utils/case-converter.js";
|
|
3
3
|
import { expandDimensionShorthands, expandTastyUnits, findTopLevelComma, resolvePredefinedState } from "../states/index.js";
|
|
4
|
-
import { and, createContainerDimensionCondition, createContainerRawCondition, createContainerStyleCondition, createMediaDimensionCondition, createMediaFeatureCondition, createMediaTypeCondition, createModifierCondition, createOwnCondition, createPseudoCondition, createRootCondition, createStartingCondition, createSupportsCondition, not, or, trueCondition } from "./conditions.js";
|
|
4
|
+
import { and, createContainerDimensionCondition, createContainerRawCondition, createContainerStyleCondition, createMediaDimensionCondition, createMediaFeatureCondition, createMediaTypeCondition, createModifierCondition, createOwnCondition, createParentCondition, createPseudoCondition, createRootCondition, createStartingCondition, createSupportsCondition, not, or, trueCondition } from "./conditions.js";
|
|
5
5
|
|
|
6
6
|
//#region src/pipeline/parseStateKey.ts
|
|
7
7
|
/**
|
|
@@ -20,7 +20,7 @@ const parseCache = new Lru(5e3);
|
|
|
20
20
|
* like @supports($, :has(*)) or @(scroll-state(stuck: top)).
|
|
21
21
|
* We use a pattern that allows one level of nesting: [^()]*(?:\([^)]*\))?[^)]*
|
|
22
22
|
*/
|
|
23
|
-
const STATE_TOKEN_PATTERN = /([&|!^])|([()])|(@media:[a-z]+)|(@media\([^)]+\))|(@supports\([^()]*(?:\([^)]*\))?[^)]*\))|(@root\([^)]+\))|(@own\([^)]+\))|(@\([^()]*(?:\([^)]*\))?[^)]*\))|(@starting)|(@[A-Za-z][A-Za-z0-9-]*)|([a-z][a-z0-9-]*(?:\^=|\$=|\*=|=)(?:"[^"]*"|'[^']*'|[^\s&|!^()]+))|([a-z][a-z0-9-]+)|(:[-a-z][a-z0-9-]*(?:\([^)]+\))?)|(\.[a-z][a-z0-9-]+)|(\[[^\]]+\])/gi;
|
|
23
|
+
const STATE_TOKEN_PATTERN = /([&|!^])|([()])|(@media:[a-z]+)|(@media\([^)]+\))|(@supports\([^()]*(?:\([^)]*\))?[^)]*\))|(@root\([^)]+\))|(@parent\([^)]+\))|(@own\([^)]+\))|(@\([^()]*(?:\([^)]*\))?[^)]*\))|(@starting)|(@[A-Za-z][A-Za-z0-9-]*)|([a-z][a-z0-9-]*(?:\^=|\$=|\*=|=)(?:"[^"]*"|'[^']*'|[^\s&|!^()]+))|([a-z][a-z0-9-]+)|(:[-a-z][a-z0-9-]*(?:\([^)]+\))?)|(\.[a-z][a-z0-9-]+)|(\[[^\]]+\])/gi;
|
|
24
24
|
/**
|
|
25
25
|
* Tokenize a state notation string
|
|
26
26
|
*/
|
|
@@ -183,6 +183,7 @@ var Parser = class {
|
|
|
183
183
|
if (value.startsWith("@media(")) return this.parseMediaQuery(value);
|
|
184
184
|
if (value.startsWith("@supports(")) return this.parseSupportsQuery(value);
|
|
185
185
|
if (value.startsWith("@root(")) return this.parseRootState(value);
|
|
186
|
+
if (value.startsWith("@parent(")) return this.parseParentState(value);
|
|
186
187
|
if (value.startsWith("@own(")) return this.parseOwnState(value);
|
|
187
188
|
if (value.startsWith("@(")) return this.parseContainerQuery(value);
|
|
188
189
|
if (value.startsWith("@") && /^@[A-Za-z][A-Za-z0-9-]*$/.test(value)) return this.parsePredefinedState(value);
|
|
@@ -296,6 +297,26 @@ var Parser = class {
|
|
|
296
297
|
return createRootCondition(buildRootSelector(content), false, raw);
|
|
297
298
|
}
|
|
298
299
|
/**
|
|
300
|
+
* Parse @parent(...) state
|
|
301
|
+
*
|
|
302
|
+
* Syntax:
|
|
303
|
+
* @parent(hovered) → :is([data-hovered] *)
|
|
304
|
+
* @parent(theme=dark) → :is([data-theme="dark"] *)
|
|
305
|
+
* @parent(hovered >) → :is([data-hovered] > *) (direct parent)
|
|
306
|
+
* @parent(.my-class) → :is(.my-class *)
|
|
307
|
+
*/
|
|
308
|
+
parseParentState(raw) {
|
|
309
|
+
const content = raw.slice(8, -1);
|
|
310
|
+
if (!content.trim()) return trueCondition();
|
|
311
|
+
let condition = content.trim();
|
|
312
|
+
let direct = false;
|
|
313
|
+
if (condition.endsWith(">")) {
|
|
314
|
+
direct = true;
|
|
315
|
+
condition = condition.slice(0, -1).trim();
|
|
316
|
+
}
|
|
317
|
+
return createParentCondition(buildRootSelector(condition), direct, false, raw);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
299
320
|
* Parse @supports(...) query
|
|
300
321
|
*
|
|
301
322
|
* Syntax:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseStateKey.js","names":[],"sources":["../../src/pipeline/parseStateKey.ts"],"sourcesContent":["/**\n * State Key Parser\n *\n * Parses state notation strings (like 'hovered & !disabled', '@media(w < 768px)')\n * into ConditionNode trees for processing in the pipeline.\n */\n\nimport { Lru } from '../parser/lru';\nimport type { StateParserContext } from '../states';\nimport {\n expandDimensionShorthands,\n expandTastyUnits,\n findTopLevelComma,\n resolvePredefinedState,\n} from '../states';\nimport { camelToKebab } from '../utils/case-converter';\n\nimport type { ConditionNode, NumericBound } from './conditions';\nimport {\n and,\n createContainerDimensionCondition,\n createContainerRawCondition,\n createContainerStyleCondition,\n createMediaDimensionCondition,\n createMediaFeatureCondition,\n createMediaTypeCondition,\n createModifierCondition,\n createOwnCondition,\n createPseudoCondition,\n createRootCondition,\n createStartingCondition,\n createSupportsCondition,\n not,\n or,\n trueCondition,\n} from './conditions';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ParseStateKeyOptions {\n context?: StateParserContext;\n isSubElement?: boolean;\n}\n\n// ============================================================================\n// Caching\n// ============================================================================\n\n// Cache for parsed state keys (key -> ConditionNode)\nconst parseCache = new Lru<string, ConditionNode>(5000);\n\n// ============================================================================\n// Tokenizer Patterns\n// ============================================================================\n\n/**\n * Pattern for tokenizing state notation.\n * Matches: operators, parentheses, @-prefixed states, value mods, boolean mods,\n * pseudo-classes, class selectors, and attribute selectors.\n *\n * Note: For @supports and @(...) container queries we need to handle nested parentheses\n * like @supports($, :has(*)) or @(scroll-state(stuck: top)).\n * We use a pattern that allows one level of nesting: [^()]*(?:\\([^)]*\\))?[^)]*\n */\nconst STATE_TOKEN_PATTERN =\n /([&|!^])|([()])|(@media:[a-z]+)|(@media\\([^)]+\\))|(@supports\\([^()]*(?:\\([^)]*\\))?[^)]*\\))|(@root\\([^)]+\\))|(@own\\([^)]+\\))|(@\\([^()]*(?:\\([^)]*\\))?[^)]*\\))|(@starting)|(@[A-Za-z][A-Za-z0-9-]*)|([a-z][a-z0-9-]*(?:\\^=|\\$=|\\*=|=)(?:\"[^\"]*\"|'[^']*'|[^\\s&|!^()]+))|([a-z][a-z0-9-]+)|(:[-a-z][a-z0-9-]*(?:\\([^)]+\\))?)|(\\.[a-z][a-z0-9-]+)|(\\[[^\\]]+\\])/gi;\n\n// ============================================================================\n// Token Types\n// ============================================================================\n\ntype TokenType = 'AND' | 'OR' | 'NOT' | 'XOR' | 'LPAREN' | 'RPAREN' | 'STATE';\n\ninterface Token {\n type: TokenType;\n value: string;\n raw: string;\n}\n\n// ============================================================================\n// Tokenizer\n// ============================================================================\n\n/**\n * Tokenize a state notation string\n */\nfunction tokenize(stateKey: string): Token[] {\n const tokens: Token[] = [];\n let match: RegExpExecArray | null;\n\n // Replace commas with | outside of parentheses (for compatibility)\n const normalized = replaceCommasOutsideParens(stateKey);\n\n STATE_TOKEN_PATTERN.lastIndex = 0;\n while ((match = STATE_TOKEN_PATTERN.exec(normalized)) !== null) {\n const fullMatch = match[0];\n\n if (match[1]) {\n // Operator: &, |, !, ^\n switch (fullMatch) {\n case '&':\n tokens.push({ type: 'AND', value: '&', raw: fullMatch });\n break;\n case '|':\n tokens.push({ type: 'OR', value: '|', raw: fullMatch });\n break;\n case '!':\n tokens.push({ type: 'NOT', value: '!', raw: fullMatch });\n break;\n case '^':\n tokens.push({ type: 'XOR', value: '^', raw: fullMatch });\n break;\n }\n } else if (match[2]) {\n // Parenthesis\n if (fullMatch === '(') {\n tokens.push({ type: 'LPAREN', value: '(', raw: fullMatch });\n } else {\n tokens.push({ type: 'RPAREN', value: ')', raw: fullMatch });\n }\n } else {\n // State token (all other capture groups)\n tokens.push({ type: 'STATE', value: fullMatch, raw: fullMatch });\n }\n }\n\n return tokens;\n}\n\n/**\n * Replace commas with | only outside of parentheses\n */\nfunction replaceCommasOutsideParens(str: string): string {\n let result = '';\n let depth = 0;\n\n for (const char of str) {\n if (char === '(') {\n depth++;\n result += char;\n } else if (char === ')') {\n depth--;\n result += char;\n } else if (char === ',' && depth === 0) {\n result += '|';\n } else {\n result += char;\n }\n }\n\n return result;\n}\n\n// ============================================================================\n// Recursive Descent Parser\n// ============================================================================\n\n/**\n * Parser state\n */\nclass Parser {\n private tokens: Token[];\n private pos = 0;\n private options: ParseStateKeyOptions;\n\n constructor(tokens: Token[], options: ParseStateKeyOptions) {\n this.tokens = tokens;\n this.options = options;\n }\n\n parse(): ConditionNode {\n if (this.tokens.length === 0) {\n return trueCondition();\n }\n const result = this.parseExpression();\n return result;\n }\n\n private current(): Token | undefined {\n return this.tokens[this.pos];\n }\n\n private advance(): Token | undefined {\n return this.tokens[this.pos++];\n }\n\n private match(type: TokenType): boolean {\n if (this.current()?.type === type) {\n this.advance();\n return true;\n }\n return false;\n }\n\n /**\n * Parse expression with operator precedence:\n * ! (NOT) > ^ (XOR) > | (OR) > & (AND)\n */\n private parseExpression(): ConditionNode {\n return this.parseAnd();\n }\n\n private parseAnd(): ConditionNode {\n let left = this.parseOr();\n\n while (this.current()?.type === 'AND') {\n this.advance();\n const right = this.parseOr();\n left = and(left, right);\n }\n\n return left;\n }\n\n private parseOr(): ConditionNode {\n let left = this.parseXor();\n\n while (this.current()?.type === 'OR') {\n this.advance();\n const right = this.parseXor();\n left = or(left, right);\n }\n\n return left;\n }\n\n private parseXor(): ConditionNode {\n let left = this.parseUnary();\n\n while (this.current()?.type === 'XOR') {\n this.advance();\n const right = this.parseUnary();\n // XOR: (A & !B) | (!A & B)\n left = or(and(left, not(right)), and(not(left), right));\n }\n\n return left;\n }\n\n private parseUnary(): ConditionNode {\n if (this.match('NOT')) {\n const operand = this.parseUnary();\n return not(operand);\n }\n return this.parsePrimary();\n }\n\n private parsePrimary(): ConditionNode {\n // Handle parentheses\n if (this.match('LPAREN')) {\n const expr = this.parseExpression();\n this.match('RPAREN'); // Consume closing paren (lenient if missing)\n return expr;\n }\n\n // Handle state tokens\n const token = this.current();\n if (token?.type === 'STATE') {\n this.advance();\n return this.parseStateToken(token.value);\n }\n\n // Fallback for empty/invalid - return TRUE\n return trueCondition();\n }\n\n /**\n * Parse a state token into a ConditionNode\n */\n private parseStateToken(value: string): ConditionNode {\n // @starting\n if (value === '@starting') {\n return createStartingCondition(false, value);\n }\n\n // @media:type (e.g., @media:print)\n if (value.startsWith('@media:')) {\n const mediaType = value.slice(7) as 'print' | 'screen' | 'all' | 'speech';\n return createMediaTypeCondition(mediaType, false, value);\n }\n\n // @media(...) - media query\n if (value.startsWith('@media(')) {\n return this.parseMediaQuery(value);\n }\n\n // @supports(...) - feature/selector support query\n if (value.startsWith('@supports(')) {\n return this.parseSupportsQuery(value);\n }\n\n // @root(...) - root state\n if (value.startsWith('@root(')) {\n return this.parseRootState(value);\n }\n\n // @own(...) - own state (sub-element)\n if (value.startsWith('@own(')) {\n return this.parseOwnState(value);\n }\n\n // @(...) - container query\n if (value.startsWith('@(')) {\n return this.parseContainerQuery(value);\n }\n\n // @name - predefined state\n if (value.startsWith('@') && /^@[A-Za-z][A-Za-z0-9-]*$/.test(value)) {\n return this.parsePredefinedState(value);\n }\n\n // Pseudo-class (e.g., :hover, :focus-visible, :nth-child(2n))\n if (value.startsWith(':')) {\n return createPseudoCondition(value, false, value);\n }\n\n // Class selector (e.g., .active)\n if (value.startsWith('.')) {\n return createPseudoCondition(value, false, value);\n }\n\n // Attribute selector (e.g., [disabled], [data-state=\"active\"])\n if (value.startsWith('[')) {\n return createPseudoCondition(value, false, value);\n }\n\n // Value modifier (e.g., theme=danger, size=large)\n if (value.includes('=')) {\n return this.parseValueModifier(value);\n }\n\n // Boolean modifier (e.g., hovered, disabled)\n return this.parseBooleanModifier(value);\n }\n\n /**\n * Parse @media(...) query\n */\n private parseMediaQuery(raw: string): ConditionNode {\n const content = raw.slice(7, -1); // Remove '@media(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Expand shorthands and units\n let condition = expandDimensionShorthands(content);\n condition = expandTastyUnits(condition);\n\n // Check for feature queries (contains ':' but not dimension comparison)\n if (\n condition.includes(':') &&\n !condition.includes('<') &&\n !condition.includes('>') &&\n !condition.includes('=')\n ) {\n // Feature query: @media(prefers-contrast: high)\n const colonIdx = condition.indexOf(':');\n const feature = condition.slice(0, colonIdx).trim();\n const featureValue = condition.slice(colonIdx + 1).trim();\n return createMediaFeatureCondition(feature, featureValue, false, raw);\n }\n\n // Boolean feature query: @media(prefers-reduced-motion)\n if (\n !condition.includes('<') &&\n !condition.includes('>') &&\n !condition.includes('=')\n ) {\n return createMediaFeatureCondition(\n condition.trim(),\n undefined,\n false,\n raw,\n );\n }\n\n // Dimension query - parse bounds\n const { dimension, lowerBound, upperBound } =\n this.parseDimensionCondition(condition);\n\n if (!dimension) {\n // Fallback for unparseable - treat as pseudo\n return createPseudoCondition(raw, false, raw);\n }\n\n return createMediaDimensionCondition(\n dimension as 'width' | 'height',\n lowerBound,\n upperBound,\n false,\n raw,\n );\n }\n\n /**\n * Parse dimension condition string (e.g., \"width < 768px\", \"600px <= width < 1200px\")\n */\n private parseDimensionCondition(condition: string): {\n dimension?: string;\n lowerBound?: NumericBound;\n upperBound?: NumericBound;\n } {\n // Range syntax: \"600px <= width < 1200px\"\n const rangeMatch = condition.match(\n /^(.+?)\\s*(<=|<)\\s*(width|height|inline-size|block-size)\\s*(<=|<)\\s*(.+)$/,\n );\n if (rangeMatch) {\n const [, lowerValue, lowerOp, dimension, upperOp, upperValue] =\n rangeMatch;\n return {\n dimension,\n lowerBound: {\n value: lowerValue.trim(),\n valueNumeric: parseNumericValue(lowerValue.trim()),\n inclusive: lowerOp === '<=',\n },\n upperBound: {\n value: upperValue.trim(),\n valueNumeric: parseNumericValue(upperValue.trim()),\n inclusive: upperOp === '<=',\n },\n };\n }\n\n // Simple comparison: \"width < 768px\"\n const simpleMatch = condition.match(\n /^(width|height|inline-size|block-size)\\s*(<=|>=|<|>|=)\\s*(.+)$/,\n );\n if (simpleMatch) {\n const [, dimension, operator, value] = simpleMatch;\n const numeric = parseNumericValue(value.trim());\n\n if (operator === '<' || operator === '<=') {\n return {\n dimension,\n upperBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: operator === '<=',\n },\n };\n } else if (operator === '>' || operator === '>=') {\n return {\n dimension,\n lowerBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: operator === '>=',\n },\n };\n } else if (operator === '=') {\n // Exact match: both bounds are the same and inclusive\n return {\n dimension,\n lowerBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: true,\n },\n upperBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: true,\n },\n };\n }\n }\n\n // Reversed: \"768px > width\"\n const reversedMatch = condition.match(\n /^(.+?)\\s*(<=|>=|<|>|=)\\s*(width|height|inline-size|block-size)$/,\n );\n if (reversedMatch) {\n const [, value, operator, dimension] = reversedMatch;\n const numeric = parseNumericValue(value.trim());\n\n // Reverse the operator\n if (operator === '<' || operator === '<=') {\n return {\n dimension,\n lowerBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: operator === '<=',\n },\n };\n } else if (operator === '>' || operator === '>=') {\n return {\n dimension,\n upperBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: operator === '>=',\n },\n };\n }\n }\n\n return {};\n }\n\n /**\n * Parse @root(...) state\n */\n private parseRootState(raw: string): ConditionNode {\n const content = raw.slice(6, -1); // Remove '@root(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Build selector from condition\n const selector = buildRootSelector(content);\n return createRootCondition(selector, false, raw);\n }\n\n /**\n * Parse @supports(...) query\n *\n * Syntax:\n * @supports(display: grid) → @supports (display: grid)\n * @supports($, :has(*)) → @supports selector(:has(*))\n */\n private parseSupportsQuery(raw: string): ConditionNode {\n const content = raw.slice(10, -1); // Remove '@supports(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Check for selector syntax: @supports($, :has(*))\n if (content.startsWith('$,')) {\n const selector = content.slice(2).trim(); // Remove '$,' prefix\n return createSupportsCondition('selector', selector, false, raw);\n }\n\n // Feature syntax: @supports(display: grid)\n return createSupportsCondition('feature', content, false, raw);\n }\n\n /**\n * Parse @own(...) state\n */\n private parseOwnState(raw: string): ConditionNode {\n const content = raw.slice(5, -1); // Remove '@own(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Parse the inner condition recursively\n const innerCondition = parseStateKey(content, this.options);\n return createOwnCondition(innerCondition, false, raw);\n }\n\n /**\n * Parse @(...) container query\n */\n private parseContainerQuery(raw: string): ConditionNode {\n const content = raw.slice(2, -1); // Remove '@(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Check for named container: @(layout, w < 600px)\n // Use parentheses-aware comma search so inner commas (e.g., scroll-state(a, b)) are skipped\n const commaIdx = findTopLevelComma(content);\n let containerName: string | undefined;\n let condition: string;\n\n if (commaIdx !== -1) {\n containerName = content.slice(0, commaIdx).trim();\n condition = content.slice(commaIdx + 1).trim();\n } else {\n condition = content.trim();\n }\n\n // Check for style query shorthand: @($variant=primary)\n if (condition.startsWith('$')) {\n const styleQuery = condition.slice(1); // Remove '$'\n const eqIdx = styleQuery.indexOf('=');\n\n if (eqIdx === -1) {\n // Existence check: @($variant)\n return createContainerStyleCondition(\n styleQuery,\n undefined,\n containerName,\n false,\n raw,\n );\n }\n\n const property = styleQuery.slice(0, eqIdx).trim();\n let propertyValue = styleQuery.slice(eqIdx + 1).trim();\n\n // Remove quotes if present\n if (\n (propertyValue.startsWith('\"') && propertyValue.endsWith('\"')) ||\n (propertyValue.startsWith(\"'\") && propertyValue.endsWith(\"'\"))\n ) {\n propertyValue = propertyValue.slice(1, -1);\n }\n\n return createContainerStyleCondition(\n property,\n propertyValue,\n containerName,\n false,\n raw,\n );\n }\n\n // Check for function-like syntax: scroll-state(...), style(...), etc.\n // Passes the condition through to CSS verbatim.\n if (/^[a-zA-Z][\\w-]*\\s*\\(/.test(condition)) {\n return createContainerRawCondition(condition, containerName, false, raw);\n }\n\n // Dimension query\n let expandedCondition = expandDimensionShorthands(condition);\n expandedCondition = expandTastyUnits(expandedCondition);\n\n const { dimension, lowerBound, upperBound } =\n this.parseDimensionCondition(expandedCondition);\n\n if (!dimension) {\n // Fallback\n return createPseudoCondition(raw, false, raw);\n }\n\n return createContainerDimensionCondition(\n dimension as 'width' | 'height',\n lowerBound,\n upperBound,\n containerName,\n false,\n raw,\n );\n }\n\n /**\n * Parse predefined state (@mobile, @dark, etc.)\n */\n private parsePredefinedState(raw: string): ConditionNode {\n const ctx = this.options.context;\n if (!ctx) {\n // No context - can't resolve predefined states\n return createPseudoCondition(raw, false, raw);\n }\n\n const resolved = resolvePredefinedState(raw, ctx);\n if (!resolved) {\n // Undefined predefined state - treat as modifier\n return createModifierCondition(\n `data-${camelToKebab(raw.slice(1))}`,\n undefined,\n '=',\n false,\n raw,\n );\n }\n\n // Parse the resolved value recursively\n return parseStateKey(resolved, this.options);\n }\n\n /**\n * Parse value modifier (e.g., theme=danger, size^=sm)\n */\n private parseValueModifier(raw: string): ConditionNode {\n // Match operators: =, ^=, $=, *=\n const opMatch = raw.match(/^([a-z][a-z0-9-]*)(\\^=|\\$=|\\*=|=)(.+)$/i);\n if (!opMatch) {\n return createModifierCondition(\n `data-${camelToKebab(raw)}`,\n undefined,\n '=',\n false,\n raw,\n );\n }\n\n const [, key, operator, value] = opMatch;\n let cleanValue = value;\n\n // Remove quotes if present\n if (\n (cleanValue.startsWith('\"') && cleanValue.endsWith('\"')) ||\n (cleanValue.startsWith(\"'\") && cleanValue.endsWith(\"'\"))\n ) {\n cleanValue = cleanValue.slice(1, -1);\n }\n\n return createModifierCondition(\n `data-${camelToKebab(key)}`,\n cleanValue,\n operator as '=' | '^=' | '$=' | '*=',\n false,\n raw,\n );\n }\n\n /**\n * Parse boolean modifier (e.g., hovered, disabled)\n */\n private parseBooleanModifier(raw: string): ConditionNode {\n return createModifierCondition(\n `data-${camelToKebab(raw)}`,\n undefined,\n '=',\n false,\n raw,\n );\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Parse a numeric value from a CSS value string\n */\nfunction parseNumericValue(value: string): number | null {\n const match = value.match(/^(\\d+(?:\\.\\d+)?)(px|em|rem|vh|vw|%)?$/);\n if (match) {\n return parseFloat(match[1]);\n }\n return null;\n}\n\n/**\n * Build a root state selector from a condition string\n */\nfunction buildRootSelector(condition: string): string {\n // Handle class selector: .className\n if (condition.startsWith('.')) {\n return condition;\n }\n\n // Handle attribute selector: [attr]\n if (condition.startsWith('[')) {\n return condition;\n }\n\n // Handle value mod: theme=dark\n if (condition.includes('=')) {\n const [key, value] = condition.split('=');\n return `[data-${camelToKebab(key.trim())}=\"${value.trim()}\"]`;\n }\n\n // Boolean mod: camelCase -> [data-camel-case]\n return `[data-${camelToKebab(condition)}]`;\n}\n\n// ============================================================================\n// Main Export\n// ============================================================================\n\n/**\n * Parse a state key string into a ConditionNode\n */\nexport function parseStateKey(\n stateKey: string,\n options: ParseStateKeyOptions = {},\n): ConditionNode {\n // Handle empty/default state\n if (!stateKey || !stateKey.trim()) {\n return trueCondition();\n }\n\n const trimmed = stateKey.trim();\n\n // Build cache key including local predefined states (they affect parsing)\n // Global predefined states are set once at initialization and don't change\n const ctx = options.context;\n const localStatesKey =\n ctx && Object.keys(ctx.localPredefinedStates).length > 0\n ? JSON.stringify(ctx.localPredefinedStates)\n : '';\n const cacheKey = JSON.stringify([\n trimmed,\n options.isSubElement,\n localStatesKey,\n ]);\n\n // Check cache\n const cached = parseCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n // Tokenize and parse\n const tokens = tokenize(trimmed);\n const parser = new Parser(tokens, options);\n const result = parser.parse();\n\n // Cache result\n parseCache.set(cacheKey, result);\n\n return result;\n}\n\n/**\n * Clear the parse cache (for testing)\n */\nexport function clearParseCache(): void {\n parseCache.clear();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parseStateKey.js","names":[],"sources":["../../src/pipeline/parseStateKey.ts"],"sourcesContent":["/**\n * State Key Parser\n *\n * Parses state notation strings (like 'hovered & !disabled', '@media(w < 768px)')\n * into ConditionNode trees for processing in the pipeline.\n */\n\nimport { Lru } from '../parser/lru';\nimport type { StateParserContext } from '../states';\nimport {\n expandDimensionShorthands,\n expandTastyUnits,\n findTopLevelComma,\n resolvePredefinedState,\n} from '../states';\nimport { camelToKebab } from '../utils/case-converter';\n\nimport type { ConditionNode, NumericBound } from './conditions';\nimport {\n and,\n createContainerDimensionCondition,\n createContainerRawCondition,\n createContainerStyleCondition,\n createMediaDimensionCondition,\n createMediaFeatureCondition,\n createMediaTypeCondition,\n createModifierCondition,\n createOwnCondition,\n createParentCondition,\n createPseudoCondition,\n createRootCondition,\n createStartingCondition,\n createSupportsCondition,\n not,\n or,\n trueCondition,\n} from './conditions';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ParseStateKeyOptions {\n context?: StateParserContext;\n isSubElement?: boolean;\n}\n\n// ============================================================================\n// Caching\n// ============================================================================\n\n// Cache for parsed state keys (key -> ConditionNode)\nconst parseCache = new Lru<string, ConditionNode>(5000);\n\n// ============================================================================\n// Tokenizer Patterns\n// ============================================================================\n\n/**\n * Pattern for tokenizing state notation.\n * Matches: operators, parentheses, @-prefixed states, value mods, boolean mods,\n * pseudo-classes, class selectors, and attribute selectors.\n *\n * Note: For @supports and @(...) container queries we need to handle nested parentheses\n * like @supports($, :has(*)) or @(scroll-state(stuck: top)).\n * We use a pattern that allows one level of nesting: [^()]*(?:\\([^)]*\\))?[^)]*\n */\nconst STATE_TOKEN_PATTERN =\n /([&|!^])|([()])|(@media:[a-z]+)|(@media\\([^)]+\\))|(@supports\\([^()]*(?:\\([^)]*\\))?[^)]*\\))|(@root\\([^)]+\\))|(@parent\\([^)]+\\))|(@own\\([^)]+\\))|(@\\([^()]*(?:\\([^)]*\\))?[^)]*\\))|(@starting)|(@[A-Za-z][A-Za-z0-9-]*)|([a-z][a-z0-9-]*(?:\\^=|\\$=|\\*=|=)(?:\"[^\"]*\"|'[^']*'|[^\\s&|!^()]+))|([a-z][a-z0-9-]+)|(:[-a-z][a-z0-9-]*(?:\\([^)]+\\))?)|(\\.[a-z][a-z0-9-]+)|(\\[[^\\]]+\\])/gi;\n\n// ============================================================================\n// Token Types\n// ============================================================================\n\ntype TokenType = 'AND' | 'OR' | 'NOT' | 'XOR' | 'LPAREN' | 'RPAREN' | 'STATE';\n\ninterface Token {\n type: TokenType;\n value: string;\n raw: string;\n}\n\n// ============================================================================\n// Tokenizer\n// ============================================================================\n\n/**\n * Tokenize a state notation string\n */\nfunction tokenize(stateKey: string): Token[] {\n const tokens: Token[] = [];\n let match: RegExpExecArray | null;\n\n // Replace commas with | outside of parentheses (for compatibility)\n const normalized = replaceCommasOutsideParens(stateKey);\n\n STATE_TOKEN_PATTERN.lastIndex = 0;\n while ((match = STATE_TOKEN_PATTERN.exec(normalized)) !== null) {\n const fullMatch = match[0];\n\n if (match[1]) {\n // Operator: &, |, !, ^\n switch (fullMatch) {\n case '&':\n tokens.push({ type: 'AND', value: '&', raw: fullMatch });\n break;\n case '|':\n tokens.push({ type: 'OR', value: '|', raw: fullMatch });\n break;\n case '!':\n tokens.push({ type: 'NOT', value: '!', raw: fullMatch });\n break;\n case '^':\n tokens.push({ type: 'XOR', value: '^', raw: fullMatch });\n break;\n }\n } else if (match[2]) {\n // Parenthesis\n if (fullMatch === '(') {\n tokens.push({ type: 'LPAREN', value: '(', raw: fullMatch });\n } else {\n tokens.push({ type: 'RPAREN', value: ')', raw: fullMatch });\n }\n } else {\n // State token (all other capture groups)\n tokens.push({ type: 'STATE', value: fullMatch, raw: fullMatch });\n }\n }\n\n return tokens;\n}\n\n/**\n * Replace commas with | only outside of parentheses\n */\nfunction replaceCommasOutsideParens(str: string): string {\n let result = '';\n let depth = 0;\n\n for (const char of str) {\n if (char === '(') {\n depth++;\n result += char;\n } else if (char === ')') {\n depth--;\n result += char;\n } else if (char === ',' && depth === 0) {\n result += '|';\n } else {\n result += char;\n }\n }\n\n return result;\n}\n\n// ============================================================================\n// Recursive Descent Parser\n// ============================================================================\n\n/**\n * Parser state\n */\nclass Parser {\n private tokens: Token[];\n private pos = 0;\n private options: ParseStateKeyOptions;\n\n constructor(tokens: Token[], options: ParseStateKeyOptions) {\n this.tokens = tokens;\n this.options = options;\n }\n\n parse(): ConditionNode {\n if (this.tokens.length === 0) {\n return trueCondition();\n }\n const result = this.parseExpression();\n return result;\n }\n\n private current(): Token | undefined {\n return this.tokens[this.pos];\n }\n\n private advance(): Token | undefined {\n return this.tokens[this.pos++];\n }\n\n private match(type: TokenType): boolean {\n if (this.current()?.type === type) {\n this.advance();\n return true;\n }\n return false;\n }\n\n /**\n * Parse expression with operator precedence:\n * ! (NOT) > ^ (XOR) > | (OR) > & (AND)\n */\n private parseExpression(): ConditionNode {\n return this.parseAnd();\n }\n\n private parseAnd(): ConditionNode {\n let left = this.parseOr();\n\n while (this.current()?.type === 'AND') {\n this.advance();\n const right = this.parseOr();\n left = and(left, right);\n }\n\n return left;\n }\n\n private parseOr(): ConditionNode {\n let left = this.parseXor();\n\n while (this.current()?.type === 'OR') {\n this.advance();\n const right = this.parseXor();\n left = or(left, right);\n }\n\n return left;\n }\n\n private parseXor(): ConditionNode {\n let left = this.parseUnary();\n\n while (this.current()?.type === 'XOR') {\n this.advance();\n const right = this.parseUnary();\n // XOR: (A & !B) | (!A & B)\n left = or(and(left, not(right)), and(not(left), right));\n }\n\n return left;\n }\n\n private parseUnary(): ConditionNode {\n if (this.match('NOT')) {\n const operand = this.parseUnary();\n return not(operand);\n }\n return this.parsePrimary();\n }\n\n private parsePrimary(): ConditionNode {\n // Handle parentheses\n if (this.match('LPAREN')) {\n const expr = this.parseExpression();\n this.match('RPAREN'); // Consume closing paren (lenient if missing)\n return expr;\n }\n\n // Handle state tokens\n const token = this.current();\n if (token?.type === 'STATE') {\n this.advance();\n return this.parseStateToken(token.value);\n }\n\n // Fallback for empty/invalid - return TRUE\n return trueCondition();\n }\n\n /**\n * Parse a state token into a ConditionNode\n */\n private parseStateToken(value: string): ConditionNode {\n // @starting\n if (value === '@starting') {\n return createStartingCondition(false, value);\n }\n\n // @media:type (e.g., @media:print)\n if (value.startsWith('@media:')) {\n const mediaType = value.slice(7) as 'print' | 'screen' | 'all' | 'speech';\n return createMediaTypeCondition(mediaType, false, value);\n }\n\n // @media(...) - media query\n if (value.startsWith('@media(')) {\n return this.parseMediaQuery(value);\n }\n\n // @supports(...) - feature/selector support query\n if (value.startsWith('@supports(')) {\n return this.parseSupportsQuery(value);\n }\n\n // @root(...) - root state\n if (value.startsWith('@root(')) {\n return this.parseRootState(value);\n }\n\n // @parent(...) - parent element state\n if (value.startsWith('@parent(')) {\n return this.parseParentState(value);\n }\n\n // @own(...) - own state (sub-element)\n if (value.startsWith('@own(')) {\n return this.parseOwnState(value);\n }\n\n // @(...) - container query\n if (value.startsWith('@(')) {\n return this.parseContainerQuery(value);\n }\n\n // @name - predefined state\n if (value.startsWith('@') && /^@[A-Za-z][A-Za-z0-9-]*$/.test(value)) {\n return this.parsePredefinedState(value);\n }\n\n // Pseudo-class (e.g., :hover, :focus-visible, :nth-child(2n))\n if (value.startsWith(':')) {\n return createPseudoCondition(value, false, value);\n }\n\n // Class selector (e.g., .active)\n if (value.startsWith('.')) {\n return createPseudoCondition(value, false, value);\n }\n\n // Attribute selector (e.g., [disabled], [data-state=\"active\"])\n if (value.startsWith('[')) {\n return createPseudoCondition(value, false, value);\n }\n\n // Value modifier (e.g., theme=danger, size=large)\n if (value.includes('=')) {\n return this.parseValueModifier(value);\n }\n\n // Boolean modifier (e.g., hovered, disabled)\n return this.parseBooleanModifier(value);\n }\n\n /**\n * Parse @media(...) query\n */\n private parseMediaQuery(raw: string): ConditionNode {\n const content = raw.slice(7, -1); // Remove '@media(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Expand shorthands and units\n let condition = expandDimensionShorthands(content);\n condition = expandTastyUnits(condition);\n\n // Check for feature queries (contains ':' but not dimension comparison)\n if (\n condition.includes(':') &&\n !condition.includes('<') &&\n !condition.includes('>') &&\n !condition.includes('=')\n ) {\n // Feature query: @media(prefers-contrast: high)\n const colonIdx = condition.indexOf(':');\n const feature = condition.slice(0, colonIdx).trim();\n const featureValue = condition.slice(colonIdx + 1).trim();\n return createMediaFeatureCondition(feature, featureValue, false, raw);\n }\n\n // Boolean feature query: @media(prefers-reduced-motion)\n if (\n !condition.includes('<') &&\n !condition.includes('>') &&\n !condition.includes('=')\n ) {\n return createMediaFeatureCondition(\n condition.trim(),\n undefined,\n false,\n raw,\n );\n }\n\n // Dimension query - parse bounds\n const { dimension, lowerBound, upperBound } =\n this.parseDimensionCondition(condition);\n\n if (!dimension) {\n // Fallback for unparseable - treat as pseudo\n return createPseudoCondition(raw, false, raw);\n }\n\n return createMediaDimensionCondition(\n dimension as 'width' | 'height',\n lowerBound,\n upperBound,\n false,\n raw,\n );\n }\n\n /**\n * Parse dimension condition string (e.g., \"width < 768px\", \"600px <= width < 1200px\")\n */\n private parseDimensionCondition(condition: string): {\n dimension?: string;\n lowerBound?: NumericBound;\n upperBound?: NumericBound;\n } {\n // Range syntax: \"600px <= width < 1200px\"\n const rangeMatch = condition.match(\n /^(.+?)\\s*(<=|<)\\s*(width|height|inline-size|block-size)\\s*(<=|<)\\s*(.+)$/,\n );\n if (rangeMatch) {\n const [, lowerValue, lowerOp, dimension, upperOp, upperValue] =\n rangeMatch;\n return {\n dimension,\n lowerBound: {\n value: lowerValue.trim(),\n valueNumeric: parseNumericValue(lowerValue.trim()),\n inclusive: lowerOp === '<=',\n },\n upperBound: {\n value: upperValue.trim(),\n valueNumeric: parseNumericValue(upperValue.trim()),\n inclusive: upperOp === '<=',\n },\n };\n }\n\n // Simple comparison: \"width < 768px\"\n const simpleMatch = condition.match(\n /^(width|height|inline-size|block-size)\\s*(<=|>=|<|>|=)\\s*(.+)$/,\n );\n if (simpleMatch) {\n const [, dimension, operator, value] = simpleMatch;\n const numeric = parseNumericValue(value.trim());\n\n if (operator === '<' || operator === '<=') {\n return {\n dimension,\n upperBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: operator === '<=',\n },\n };\n } else if (operator === '>' || operator === '>=') {\n return {\n dimension,\n lowerBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: operator === '>=',\n },\n };\n } else if (operator === '=') {\n // Exact match: both bounds are the same and inclusive\n return {\n dimension,\n lowerBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: true,\n },\n upperBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: true,\n },\n };\n }\n }\n\n // Reversed: \"768px > width\"\n const reversedMatch = condition.match(\n /^(.+?)\\s*(<=|>=|<|>|=)\\s*(width|height|inline-size|block-size)$/,\n );\n if (reversedMatch) {\n const [, value, operator, dimension] = reversedMatch;\n const numeric = parseNumericValue(value.trim());\n\n // Reverse the operator\n if (operator === '<' || operator === '<=') {\n return {\n dimension,\n lowerBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: operator === '<=',\n },\n };\n } else if (operator === '>' || operator === '>=') {\n return {\n dimension,\n upperBound: {\n value: value.trim(),\n valueNumeric: numeric,\n inclusive: operator === '>=',\n },\n };\n }\n }\n\n return {};\n }\n\n /**\n * Parse @root(...) state\n */\n private parseRootState(raw: string): ConditionNode {\n const content = raw.slice(6, -1); // Remove '@root(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Build selector from condition\n const selector = buildRootSelector(content);\n return createRootCondition(selector, false, raw);\n }\n\n /**\n * Parse @parent(...) state\n *\n * Syntax:\n * @parent(hovered) → :is([data-hovered] *)\n * @parent(theme=dark) → :is([data-theme=\"dark\"] *)\n * @parent(hovered >) → :is([data-hovered] > *) (direct parent)\n * @parent(.my-class) → :is(.my-class *)\n */\n private parseParentState(raw: string): ConditionNode {\n const content = raw.slice(8, -1); // Remove '@parent(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n let condition = content.trim();\n let direct = false;\n\n // Detect trailing > for direct parent mode\n if (condition.endsWith('>')) {\n direct = true;\n condition = condition.slice(0, -1).trim();\n }\n\n const selector = buildRootSelector(condition);\n return createParentCondition(selector, direct, false, raw);\n }\n\n /**\n * Parse @supports(...) query\n *\n * Syntax:\n * @supports(display: grid) → @supports (display: grid)\n * @supports($, :has(*)) → @supports selector(:has(*))\n */\n private parseSupportsQuery(raw: string): ConditionNode {\n const content = raw.slice(10, -1); // Remove '@supports(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Check for selector syntax: @supports($, :has(*))\n if (content.startsWith('$,')) {\n const selector = content.slice(2).trim(); // Remove '$,' prefix\n return createSupportsCondition('selector', selector, false, raw);\n }\n\n // Feature syntax: @supports(display: grid)\n return createSupportsCondition('feature', content, false, raw);\n }\n\n /**\n * Parse @own(...) state\n */\n private parseOwnState(raw: string): ConditionNode {\n const content = raw.slice(5, -1); // Remove '@own(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Parse the inner condition recursively\n const innerCondition = parseStateKey(content, this.options);\n return createOwnCondition(innerCondition, false, raw);\n }\n\n /**\n * Parse @(...) container query\n */\n private parseContainerQuery(raw: string): ConditionNode {\n const content = raw.slice(2, -1); // Remove '@(' and ')'\n if (!content.trim()) {\n return trueCondition();\n }\n\n // Check for named container: @(layout, w < 600px)\n // Use parentheses-aware comma search so inner commas (e.g., scroll-state(a, b)) are skipped\n const commaIdx = findTopLevelComma(content);\n let containerName: string | undefined;\n let condition: string;\n\n if (commaIdx !== -1) {\n containerName = content.slice(0, commaIdx).trim();\n condition = content.slice(commaIdx + 1).trim();\n } else {\n condition = content.trim();\n }\n\n // Check for style query shorthand: @($variant=primary)\n if (condition.startsWith('$')) {\n const styleQuery = condition.slice(1); // Remove '$'\n const eqIdx = styleQuery.indexOf('=');\n\n if (eqIdx === -1) {\n // Existence check: @($variant)\n return createContainerStyleCondition(\n styleQuery,\n undefined,\n containerName,\n false,\n raw,\n );\n }\n\n const property = styleQuery.slice(0, eqIdx).trim();\n let propertyValue = styleQuery.slice(eqIdx + 1).trim();\n\n // Remove quotes if present\n if (\n (propertyValue.startsWith('\"') && propertyValue.endsWith('\"')) ||\n (propertyValue.startsWith(\"'\") && propertyValue.endsWith(\"'\"))\n ) {\n propertyValue = propertyValue.slice(1, -1);\n }\n\n return createContainerStyleCondition(\n property,\n propertyValue,\n containerName,\n false,\n raw,\n );\n }\n\n // Check for function-like syntax: scroll-state(...), style(...), etc.\n // Passes the condition through to CSS verbatim.\n if (/^[a-zA-Z][\\w-]*\\s*\\(/.test(condition)) {\n return createContainerRawCondition(condition, containerName, false, raw);\n }\n\n // Dimension query\n let expandedCondition = expandDimensionShorthands(condition);\n expandedCondition = expandTastyUnits(expandedCondition);\n\n const { dimension, lowerBound, upperBound } =\n this.parseDimensionCondition(expandedCondition);\n\n if (!dimension) {\n // Fallback\n return createPseudoCondition(raw, false, raw);\n }\n\n return createContainerDimensionCondition(\n dimension as 'width' | 'height',\n lowerBound,\n upperBound,\n containerName,\n false,\n raw,\n );\n }\n\n /**\n * Parse predefined state (@mobile, @dark, etc.)\n */\n private parsePredefinedState(raw: string): ConditionNode {\n const ctx = this.options.context;\n if (!ctx) {\n // No context - can't resolve predefined states\n return createPseudoCondition(raw, false, raw);\n }\n\n const resolved = resolvePredefinedState(raw, ctx);\n if (!resolved) {\n // Undefined predefined state - treat as modifier\n return createModifierCondition(\n `data-${camelToKebab(raw.slice(1))}`,\n undefined,\n '=',\n false,\n raw,\n );\n }\n\n // Parse the resolved value recursively\n return parseStateKey(resolved, this.options);\n }\n\n /**\n * Parse value modifier (e.g., theme=danger, size^=sm)\n */\n private parseValueModifier(raw: string): ConditionNode {\n // Match operators: =, ^=, $=, *=\n const opMatch = raw.match(/^([a-z][a-z0-9-]*)(\\^=|\\$=|\\*=|=)(.+)$/i);\n if (!opMatch) {\n return createModifierCondition(\n `data-${camelToKebab(raw)}`,\n undefined,\n '=',\n false,\n raw,\n );\n }\n\n const [, key, operator, value] = opMatch;\n let cleanValue = value;\n\n // Remove quotes if present\n if (\n (cleanValue.startsWith('\"') && cleanValue.endsWith('\"')) ||\n (cleanValue.startsWith(\"'\") && cleanValue.endsWith(\"'\"))\n ) {\n cleanValue = cleanValue.slice(1, -1);\n }\n\n return createModifierCondition(\n `data-${camelToKebab(key)}`,\n cleanValue,\n operator as '=' | '^=' | '$=' | '*=',\n false,\n raw,\n );\n }\n\n /**\n * Parse boolean modifier (e.g., hovered, disabled)\n */\n private parseBooleanModifier(raw: string): ConditionNode {\n return createModifierCondition(\n `data-${camelToKebab(raw)}`,\n undefined,\n '=',\n false,\n raw,\n );\n }\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Parse a numeric value from a CSS value string\n */\nfunction parseNumericValue(value: string): number | null {\n const match = value.match(/^(\\d+(?:\\.\\d+)?)(px|em|rem|vh|vw|%)?$/);\n if (match) {\n return parseFloat(match[1]);\n }\n return null;\n}\n\n/**\n * Build a root state selector from a condition string\n */\nfunction buildRootSelector(condition: string): string {\n // Handle class selector: .className\n if (condition.startsWith('.')) {\n return condition;\n }\n\n // Handle attribute selector: [attr]\n if (condition.startsWith('[')) {\n return condition;\n }\n\n // Handle value mod: theme=dark\n if (condition.includes('=')) {\n const [key, value] = condition.split('=');\n return `[data-${camelToKebab(key.trim())}=\"${value.trim()}\"]`;\n }\n\n // Boolean mod: camelCase -> [data-camel-case]\n return `[data-${camelToKebab(condition)}]`;\n}\n\n// ============================================================================\n// Main Export\n// ============================================================================\n\n/**\n * Parse a state key string into a ConditionNode\n */\nexport function parseStateKey(\n stateKey: string,\n options: ParseStateKeyOptions = {},\n): ConditionNode {\n // Handle empty/default state\n if (!stateKey || !stateKey.trim()) {\n return trueCondition();\n }\n\n const trimmed = stateKey.trim();\n\n // Build cache key including local predefined states (they affect parsing)\n // Global predefined states are set once at initialization and don't change\n const ctx = options.context;\n const localStatesKey =\n ctx && Object.keys(ctx.localPredefinedStates).length > 0\n ? JSON.stringify(ctx.localPredefinedStates)\n : '';\n const cacheKey = JSON.stringify([\n trimmed,\n options.isSubElement,\n localStatesKey,\n ]);\n\n // Check cache\n const cached = parseCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n // Tokenize and parse\n const tokens = tokenize(trimmed);\n const parser = new Parser(tokens, options);\n const result = parser.parse();\n\n // Cache result\n parseCache.set(cacheKey, result);\n\n return result;\n}\n\n/**\n * Clear the parse cache (for testing)\n */\nexport function clearParseCache(): void {\n parseCache.clear();\n}\n"],"mappings":"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"}
|
package/dist/states/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import "../styles/types.js";
|
|
|
5
5
|
* Parsed advanced state information
|
|
6
6
|
*/
|
|
7
7
|
interface ParsedAdvancedState {
|
|
8
|
-
type: 'media' | 'container' | 'root' | 'own' | 'starting' | 'predefined' | 'modifier';
|
|
8
|
+
type: 'media' | 'container' | 'root' | 'parent' | 'own' | 'starting' | 'predefined' | 'modifier';
|
|
9
9
|
condition: string;
|
|
10
10
|
containerName?: string;
|
|
11
11
|
raw: string;
|