/*! © 2026 Yahoo, Inc. UDS v0.0.0-development */
require("../../../../_virtual/_rolldown/runtime.cjs");
const require_perf = require("../../css/perf.cjs");
const require_expressions = require("./ast/expressions.cjs");
let ts_morph = require("ts-morph");
//#region ../css/dist/purger/optimized/purgeFromCode.mjs
/*! © 2026 Yahoo, Inc. UDS CSS v0.0.0-development */
/**
* Get component info with all its dependencies (using pre-generated data)
*/
const getComponentWithDeps = (componentName) => {
	const visited = /* @__PURE__ */ new Set();
	const result = [];
	const collect = (name) => {
		if (visited.has(name)) return;
		visited.add(name);
		const info = resolveComponentInfo(name);
		if (!info) return;
		result.push(info);
		info.internalComponents.forEach((depName) => collect(depName));
	};
	collect(componentName);
	return result;
};
/**
* Auto-variants lookup (loaded at module init)
*/
let autoVariantsCache = null;
/**
* Pre-generated component data (loaded at module init)
*/
let componentCache = null;
/**
* Map of normalized component name -> actual component cache key
* Useful when internal components are imported without namespace separators
* (e.g., MenuItemBase vs Menu.ItemBase).
*/
let componentNameLookup = null;
const buildComponentNameLookup = (data) => {
	const lookup = {};
	Object.keys(data).forEach((key) => {
		const normalized = normalizeComponentName(key);
		if (!lookup[normalized]) lookup[normalized] = key;
	});
	return lookup;
};
const resolveComponentInfo = (name) => {
	if (componentCache && componentCache[name]) return componentCache[name];
	const normalized = normalizeComponentName(name);
	const mappedName = componentNameLookup?.[normalized];
	if (mappedName && componentCache) return componentCache[mappedName];
};
const getModuleSpecifierValue = (importDecl) => {
	return importDecl.getModuleSpecifierValue() ?? importDecl.getModuleSpecifier().getText().replace(/^['"]|['"]$/g, "");
};
const isTypeOnlyNamedImport = (importDecl, importName) => {
	if (importDecl.isTypeOnly()) return true;
	return importDecl.getNamedImports().find((namedImport) => namedImport.getName() === importName)?.isTypeOnly() ?? false;
};
const isUdsComponentModule = (moduleSpecifier) => {
	const cleaned = moduleSpecifier.replace(/^['"]|['"]$/g, "");
	return cleaned === "@yahoo/uds" || cleaned.startsWith("@yahoo/uds/");
};
/**
* Normalize component name to match autoVariants keys (fully lowercase, no
* punctuation). autoVariants keys lowercase the entire component label (e.g.
* `menucontentSizeRoot`), so full lowercasing keeps the normalized prefix
* aligned with those keys and makes namespace/flat aliases resolve consistently.
*/
const normalizeComponentName = (name) => {
	return name.replace(/\W/g, "").toLowerCase();
};
/**
* Fallback: infer prop -> variant key mapping from autoVariants when the
* generated component data misses it (e.g., helpers like buildAvatarRootClasses).
*/
const getAutoVariantKeysForProp = (componentName, propName) => {
	if (!autoVariantsCache) return [];
	const segments = componentName.match(/[A-Z][a-z0-9]*/g) ?? [];
	const candidates = new Set([normalizeComponentName(componentName)]);
	if (segments.length > 0) Array.from({ length: segments.length }, (_, index) => index + 1).forEach((i) => {
		const partial = segments.slice(0, i).join("");
		candidates.add(normalizeComponentName(partial));
	});
	const propLower = propName.toLowerCase();
	return Object.keys(autoVariantsCache).filter((key) => {
		const keyLower = key.toLowerCase();
		return Array.from(candidates).some((candidate) => keyLower.startsWith(candidate) && keyLower.includes(propLower));
	});
};
const getVariantKeysForProp = (componentInfo, propName) => {
	const keys = new Set(componentInfo.propToVariantKeys?.[propName] ?? []);
	getAutoVariantKeysForProp(componentInfo.name, propName).forEach((inferred) => keys.add(inferred));
	return [...keys];
};
const addVariantGroupClasses = (variantGroup, safelist) => {
	if (!variantGroup) return;
	Object.values(variantGroup).forEach((cls) => {
		safelist.push(cls.replaceAll("\\", ""));
	});
};
const getRuntimeDefaultPropValues = (componentInfo, propName, runtimeConfigValues) => {
	const selector = componentInfo.runtimeConfigDefaultProps?.[propName];
	if (!selector || !runtimeConfigValues) return [];
	const value = runtimeConfigValues[selector];
	return value === void 0 ? [] : [String(value)];
};
const getPropCandidateValues = (componentInfo, propName, userProps, options) => {
	const explicitValues = userProps.get(propName);
	if (explicitValues && explicitValues.size > 0) return [...explicitValues];
	const configuredDefault = options.variantDefaults?.[componentInfo.name]?.[propName];
	if (configuredDefault) return [configuredDefault];
	if (componentInfo.defaultProps[propName]) return [componentInfo.defaultProps[propName]];
	return getRuntimeDefaultPropValues(componentInfo, propName, options.runtimeConfigValues);
};
const resolveRuntimeSelectorValues = (selectorTemplate, componentInfo, userProps, options) => {
	const runtimeConfigValues = options.runtimeConfigValues;
	if (!runtimeConfigValues) return [];
	return [...selectorTemplate.matchAll(/\$\{(\w+)\}/g)].map((match) => match[1]).reduce((acc, propName) => {
		const propValues = getPropCandidateValues(componentInfo, propName, userProps, options);
		if (propValues.length === 0) return [];
		return acc.flatMap((selector) => propValues.map((value) => selector.replaceAll("${" + propName + "}", value)));
	}, [selectorTemplate]).flatMap((selector) => {
		const value = runtimeConfigValues[selector];
		return value === void 0 ? [] : [String(value)];
	});
};
const extractClassNamePrimitives = (sourceFile) => {
	const classes = [];
	sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxAttribute).forEach((attr) => {
		if (attr.getNameNode().getText() !== "className") return;
		const initializer = attr.getInitializer();
		if (!initializer) return;
		const values = [];
		if (ts_morph.Node.isStringLiteral(initializer)) values.push(initializer.getLiteralText());
		else if (ts_morph.Node.isJsxExpression(initializer)) {
			const expr = initializer.getExpression();
			if (expr) values.push(...require_expressions.extractStringLiterals(expr));
		}
		values.forEach((raw) => {
			classes.push(...raw.split(/\s+/).filter(Boolean));
		});
	});
	sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.PropertyAssignment).forEach((prop) => {
		if (prop.getName() !== "className") return;
		const initializer = prop.getInitializer();
		if (!initializer) return;
		require_expressions.extractStringLiterals(initializer).forEach((raw) => {
			classes.push(...raw.split(/\s+/).filter(Boolean));
		});
	});
	return classes;
};
const purgeFromCodeOptimized = async (code, options) => {
	const { variants, autoVariants, componentData } = options;
	if (!autoVariantsCache) autoVariantsCache = autoVariants;
	if (!componentCache) {
		componentCache = componentData;
		componentNameLookup = buildComponentNameLookup(componentData);
	}
	const startTime = performance.now();
	const perf = require_perf.isPerfEnabled();
	if (!/@yahoo\/uds\b/.test(code) && !options.includeAllClassNamePrimitives) return {
		safelist: [],
		imports: [],
		components: [],
		stats: {
			filesScanned: 1,
			timeMs: 0,
			classesGenerated: 0,
			spreadsTraced: 0,
			expressionsResolved: 0
		}
	};
	const projectCreateStart = performance.now();
	const sourceFile = new ts_morph.Project({ useInMemoryFileSystem: true }).createSourceFile(options.filePath ?? "input.tsx", code, { overwrite: true });
	const projectCreateMs = performance.now() - projectCreateStart;
	const stats = {
		filesScanned: 1,
		timeMs: 0,
		classesGenerated: 0,
		spreadsTraced: 0,
		expressionsResolved: 0
	};
	const importParseStart = performance.now();
	const imports = [];
	sourceFile.getImportDeclarations().forEach((importDecl) => {
		if (isUdsComponentModule(getModuleSpecifierValue(importDecl))) importDecl.getNamedImports().forEach((namedImport) => {
			if (!namedImport.isTypeOnly() && !importDecl.isTypeOnly()) imports.push(namedImport.getName());
		});
	});
	const importParseMs = performance.now() - importParseStart;
	const componentProps = /* @__PURE__ */ new Map();
	const componentUnresolvedSpreadProps = /* @__PURE__ */ new Map();
	const referencedComponents = /* @__PURE__ */ new Set();
	const getStylesExtractStart = performance.now();
	const getStylesProps = extractGetStylesCalls(sourceFile, stats, variants);
	const getStylesExtractMs = performance.now() - getStylesExtractStart;
	const jsxAnalysisStart = performance.now();
	const jsxElementsCache = sourceFile.getDescendants().filter((node) => ts_morph.Node.isJsxOpeningElement(node) || ts_morph.Node.isJsxSelfClosingElement(node));
	imports.forEach((imp) => {
		findComponentReferences(sourceFile, imp, jsxElementsCache).forEach((reference) => {
			const componentName = reference.getTagNameNode().getText() || imp;
			referencedComponents.add(componentName);
			const propsMap = componentProps.get(componentName) ?? /* @__PURE__ */ new Map();
			const unresolvedSpreadProps = componentUnresolvedSpreadProps.get(componentName) ?? /* @__PURE__ */ new Set();
			extractPropsFromReference(reference, stats, sourceFile).forEach(({ propName, values, fromSpread }) => {
				if (values.length > 0) {
					const existing = propsMap.get(propName) ?? /* @__PURE__ */ new Set();
					values.forEach((val) => existing.add(val));
					propsMap.set(propName, existing);
					return;
				}
				if (fromSpread) unresolvedSpreadProps.add(propName);
			});
			componentProps.set(componentName, propsMap);
			componentUnresolvedSpreadProps.set(componentName, unresolvedSpreadProps);
		});
		if (!componentProps.has(imp)) componentProps.set(imp, /* @__PURE__ */ new Map());
		if (!componentUnresolvedSpreadProps.has(imp)) componentUnresolvedSpreadProps.set(imp, /* @__PURE__ */ new Set());
	});
	const jsxAnalysisMs = performance.now() - jsxAnalysisStart;
	const safelistGenStart = performance.now();
	const allComponents = [];
	const seenComponents = /* @__PURE__ */ new Set();
	new Set([...imports, ...referencedComponents]).forEach((componentName) => {
		getComponentWithDeps(componentName).forEach((comp) => {
			if (!seenComponents.has(comp.name)) {
				seenComponents.add(comp.name);
				allComponents.push(comp);
			}
		});
	});
	const safelist = [];
	[...getStylesProps.entries()].forEach(([propName, values]) => {
		const variantGroup = variants[propName];
		if (variantGroup) values.forEach((value) => {
			const cls = variantGroup[value];
			if (cls) safelist.push(cls.replaceAll("\\", ""));
		});
	});
	allComponents.forEach((componentInfo) => {
		const userProps = componentProps.get(componentInfo.name) ?? /* @__PURE__ */ new Map();
		const unresolvedSpreadProps = componentUnresolvedSpreadProps.get(componentInfo.name) ?? /* @__PURE__ */ new Set();
		Object.entries(componentInfo.defaultProps).forEach(([propName, propValue]) => {
			if (userProps.has(propName)) return;
			const variantGroup = variants[propName];
			if (variantGroup) {
				const cls = variantGroup[propValue];
				if (cls) safelist.push(cls.replaceAll("\\", ""));
			}
			const variantKeys = getVariantKeysForProp(componentInfo, propName);
			if (variantKeys.length > 0) variantKeys.forEach((variantKey) => {
				const mappedVariantGroup = variants[variantKey] ?? autoVariantsCache[variantKey];
				if (mappedVariantGroup) {
					const cls = mappedVariantGroup[propValue];
					if (cls) safelist.push(cls.replaceAll("\\", ""));
				}
			});
		});
		Object.entries(componentInfo.getStylesLiterals).forEach(([propName, propValue]) => {
			const variantGroup = variants[propName.replace(/:\d+$/, "")];
			if (variantGroup) {
				const cls = variantGroup[propValue];
				if (cls) safelist.push(cls.replaceAll("\\", ""));
			}
		});
		Object.entries(componentInfo.runtimeConfigGetStyles ?? {}).forEach(([propName, selectors]) => {
			const variantGroup = variants[propName] ?? autoVariantsCache[propName];
			if (!variantGroup) return;
			selectors.forEach((selector) => {
				resolveRuntimeSelectorValues(selector, componentInfo, userProps, options).forEach((value) => {
					const cls = variantGroup[value];
					if (cls) safelist.push(cls.replaceAll("\\", ""));
				});
			});
		});
		if (componentInfo.cxLiterals) componentInfo.cxLiterals.forEach((cls) => safelist.push(cls));
		if (componentInfo.propToVariantKeys) {
			const componentDefaults = options.variantDefaults?.[componentInfo.name] ?? {};
			Object.keys(componentInfo.propToVariantKeys).forEach((propName) => {
				if (userProps.has(propName)) return;
				const defaultValues = componentDefaults[propName] ? [componentDefaults[propName]] : getRuntimeDefaultPropValues(componentInfo, propName, options.runtimeConfigValues);
				getVariantKeysForProp(componentInfo, propName).forEach((variantKey) => {
					const variantGroup = autoVariantsCache[variantKey];
					if (variantGroup) {
						if (variantGroup["default"]) safelist.push(variantGroup["default"]);
						defaultValues.forEach((defaultValue) => {
							if (variantGroup[defaultValue]) safelist.push(variantGroup[defaultValue]);
						});
					}
				});
			});
		}
		Object.entries(componentInfo.internalComponentProps).forEach(([_internalCompName, propsRecord]) => {
			Object.entries(propsRecord).forEach(([propName, propValues]) => {
				if (propName === "className") {
					propValues.forEach((propValue) => {
						propValue.split(/\s+/).filter(Boolean).forEach((cls) => safelist.push(cls));
					});
					return;
				}
				const variantGroup = variants[propName];
				if (variantGroup) propValues.forEach((propValue) => {
					const cls = variantGroup[propValue];
					if (cls) safelist.push(cls.replaceAll("\\", ""));
				});
			});
		});
		Object.entries(componentInfo.runtimeConfigInternalComponentProps ?? {}).forEach(([_internalCompName, propsRecord]) => {
			Object.entries(propsRecord).forEach(([propName, selectors]) => {
				const variantGroup = variants[propName];
				if (!variantGroup) return;
				selectors.forEach((selector) => {
					resolveRuntimeSelectorValues(selector, componentInfo, userProps, options).forEach((value) => {
						const cls = variantGroup[value];
						if (cls) safelist.push(cls.replaceAll("\\", ""));
					});
				});
			});
		});
		[...userProps.entries()].forEach(([propName, usedValues]) => {
			if (propName === "className") {
				[...usedValues].forEach((value) => {
					value.split(/\s+/).filter(Boolean).forEach((cls) => safelist.push(cls));
				});
				return;
			}
			const variantGroup = variants[propName];
			if (variantGroup) [...usedValues].forEach((value) => {
				const cls = variantGroup[value];
				if (cls) safelist.push(cls.replaceAll("\\", ""));
			});
			[componentInfo, ...getComponentWithDeps(componentInfo.name).slice(1)].forEach((comp) => {
				const variantKeys = getVariantKeysForProp(comp, propName);
				if (variantKeys.length > 0) variantKeys.forEach((variantKey) => {
					const mappedVariantGroup = variants[variantKey] ?? autoVariantsCache[variantKey];
					if (mappedVariantGroup) [...usedValues].forEach((value) => {
						const cls = mappedVariantGroup[value];
						if (cls) safelist.push(cls.replaceAll("\\", ""));
					});
				});
			});
		});
		unresolvedSpreadProps.forEach((propName) => {
			addVariantGroupClasses(variants[propName] ?? autoVariantsCache[propName], safelist);
			[componentInfo, ...getComponentWithDeps(componentInfo.name).slice(1)].forEach((comp) => {
				getVariantKeysForProp(comp, propName).forEach((variantKey) => {
					addVariantGroupClasses(variants[variantKey] ?? autoVariantsCache[variantKey], safelist);
				});
			});
		});
	});
	if (options.includeAllClassNamePrimitives) safelist.push(...extractClassNamePrimitives(sourceFile));
	const finalSafelist = [...new Set(safelist)].sort();
	const safelistGenerationMs = performance.now() - safelistGenStart;
	stats.timeMs = Math.round(performance.now() - startTime);
	stats.classesGenerated = finalSafelist.length;
	if (perf) {
		stats.projectCreateMs = Math.round(projectCreateMs * 100) / 100;
		stats.importParseMs = Math.round(importParseMs * 100) / 100;
		stats.getStylesExtractMs = Math.round(getStylesExtractMs * 100) / 100;
		stats.jsxAnalysisMs = Math.round(jsxAnalysisMs * 100) / 100;
		stats.safelistGenerationMs = Math.round(safelistGenerationMs * 100) / 100;
	}
	return {
		safelist: finalSafelist,
		imports,
		components: [...seenComponents],
		stats
	};
};
/**
* Find JSX references for a component in the source file
*/
const findComponentReferences = (sourceFile, componentName, jsxElementsCache) => {
	const references = [];
	const seenTags = /* @__PURE__ */ new Set();
	const allJsxElements = jsxElementsCache ?? sourceFile.getDescendants().filter((node) => ts_morph.Node.isJsxOpeningElement(node) || ts_morph.Node.isJsxSelfClosingElement(node));
	const collectMatchingTags = (localName) => {
		for (const node of allJsxElements) {
			const tagName = node.getTagNameNode().getText();
			if (tagName === localName || tagName.startsWith(`${localName}.`)) {
				const key = `${tagName}:${node.getStart()}`;
				if (!seenTags.has(key)) {
					seenTags.add(key);
					references.push(node);
				}
			}
		}
	};
	sourceFile.getImportDeclarations().forEach((importDecl) => {
		if (!isUdsComponentModule(getModuleSpecifierValue(importDecl))) return;
		importDecl.getNamedImports().forEach((namedImport) => {
			if (namedImport.getName() !== componentName || isTypeOnlyNamedImport(importDecl, componentName)) return;
			collectMatchingTags(namedImport.getAliasNode()?.getText() ?? componentName);
		});
	});
	return references;
};
/**
* Extract props from a JSX reference.
*/
const extractPropsFromReference = (reference, stats, sourceFile) => {
	const props = [];
	reference.getAttributes().forEach((attr) => {
		if (attr.asKind(ts_morph.SyntaxKind.JsxAttribute)) {
			const jsxAttr = attr.asKindOrThrow(ts_morph.SyntaxKind.JsxAttribute);
			const propName = jsxAttr.getNameNode().getText();
			const values = [];
			const initializer = jsxAttr.getInitializer();
			if (initializer && ts_morph.Node.isStringLiteral(initializer)) {
				values.push(initializer.getLiteralText());
				stats.expressionsResolved++;
			} else if (initializer && initializer.asKind(ts_morph.SyntaxKind.JsxExpression)) {
				const expression = initializer.asKindOrThrow(ts_morph.SyntaxKind.JsxExpression).getExpression();
				if (expression) {
					const resolved = require_expressions.extractStringLiterals(expression);
					values.push(...resolved);
					if (resolved.length > 0) stats.expressionsResolved++;
				}
			}
			props.push({
				propName,
				values,
				fromSpread: false
			});
		}
		if (attr.asKind(ts_morph.SyntaxKind.JsxSpreadAttribute)) {
			stats.spreadsTraced++;
			traceSpreadInFile(attr.asKindOrThrow(ts_morph.SyntaxKind.JsxSpreadAttribute).getExpression().getText(), sourceFile).forEach(([propName, values]) => {
				props.push({
					propName,
					values,
					fromSpread: true
				});
			});
		}
	});
	return props;
};
/**
* Trace spread props to their source within the same file.
*/
const traceSpreadInFile = (spreadName, sourceFile) => {
	const props = /* @__PURE__ */ new Map();
	const varDecl = sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).find((declaration) => declaration.getName() === spreadName);
	if (!varDecl) return [];
	const initializer = varDecl.getInitializer();
	if (!initializer) return [];
	getSpreadObjectLiteralCandidates(initializer).forEach((objLiteral) => {
		objLiteral.getProperties().forEach((prop) => {
			if (!prop.asKind(ts_morph.SyntaxKind.PropertyAssignment)) return;
			const propAssign = prop.asKindOrThrow(ts_morph.SyntaxKind.PropertyAssignment);
			const propName = propAssign.getName();
			const propInit = propAssign.getInitializer();
			const values = propInit ? require_expressions.extractStringLiterals(propInit) : [];
			const existingValues = props.get(propName) ?? /* @__PURE__ */ new Set();
			values.forEach((value) => existingValues.add(value));
			props.set(propName, existingValues);
		});
	});
	return [...props.entries()].map(([propName, values]) => [propName, [...values]]);
};
const getSpreadObjectLiteralCandidates = (node) => {
	if (ts_morph.Node.isObjectLiteralExpression(node)) return [node];
	if (ts_morph.Node.isParenthesizedExpression(node)) return getSpreadObjectLiteralCandidates(node.getExpression());
	if (ts_morph.Node.isAsExpression(node) || ts_morph.Node.isTypeAssertion(node) || ts_morph.Node.isSatisfiesExpression(node)) return getSpreadObjectLiteralCandidates(node.getExpression());
	if (ts_morph.Node.isConditionalExpression(node)) return [...getSpreadObjectLiteralCandidates(node.getWhenTrue()), ...getSpreadObjectLiteralCandidates(node.getWhenFalse())];
	return [];
};
/**
* Extract props from getStyles() calls in user code.
* This handles cases like:
*   const styles = getStyles({ backgroundColor: 'brand', spacing: '4' });
*/
const extractGetStylesCalls = (sourceFile, stats, variants) => {
	const props = /* @__PURE__ */ new Map();
	const VALID_VARIANTS = new Set(Object.keys(variants));
	sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).forEach((call) => {
		if (call.getExpression().getText() !== "getStyles") return;
		const args = call.getArguments();
		if (args.length === 0) return;
		const firstArg = args[0];
		if (!firstArg.asKind(ts_morph.SyntaxKind.ObjectLiteralExpression)) return;
		firstArg.asKindOrThrow(ts_morph.SyntaxKind.ObjectLiteralExpression).getProperties().forEach((prop) => {
			if (prop.asKind(ts_morph.SyntaxKind.PropertyAssignment)) {
				const propAssign = prop.asKindOrThrow(ts_morph.SyntaxKind.PropertyAssignment);
				const propName = propAssign.getName();
				const propInit = propAssign.getInitializer();
				if (propInit && VALID_VARIANTS.has(propName)) {
					const values = require_expressions.extractStringLiterals(propInit);
					if (values.length > 0) {
						const existing = props.get(propName) ?? /* @__PURE__ */ new Set();
						values.forEach((v) => existing.add(v));
						props.set(propName, existing);
						stats.expressionsResolved++;
					}
				}
			} else if (prop.asKind(ts_morph.SyntaxKind.ShorthandPropertyAssignment)) {
				const shorthand = prop.asKindOrThrow(ts_morph.SyntaxKind.ShorthandPropertyAssignment);
				const propName = shorthand.getName();
				if (VALID_VARIANTS.has(propName)) {
					const values = require_expressions.extractStringLiterals(shorthand.getNameNode());
					if (values.length > 0) {
						const existing = props.get(propName) ?? /* @__PURE__ */ new Set();
						values.forEach((v) => existing.add(v));
						props.set(propName, existing);
						stats.expressionsResolved++;
					}
				}
			}
		});
	});
	return props;
};
//#endregion
exports.purgeFromCodeOptimized = purgeFromCodeOptimized;
