@yahoo/uds 3.120.0 → 3.121.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.
Files changed (66) hide show
  1. package/dist/components/client/Menu/Menu.ItemCheckbox.d.cts +1 -1
  2. package/dist/components/client/Menu/Menu.ItemCheckbox.d.ts +1 -1
  3. package/dist/components/client/Popover/Popover.cjs +1 -1
  4. package/dist/components/client/Popover/Popover.js +1 -1
  5. package/dist/components/client/Popover/PopoverContent.cjs +12 -17
  6. package/dist/components/client/Popover/PopoverContent.js +12 -17
  7. package/dist/components/client/Popover/UDSPopoverConfigProvider.cjs +13 -3
  8. package/dist/components/client/Popover/UDSPopoverConfigProvider.d.cts +13 -5
  9. package/dist/components/client/Popover/UDSPopoverConfigProvider.d.ts +13 -5
  10. package/dist/components/client/Popover/UDSPopoverConfigProvider.js +13 -3
  11. package/dist/components/client/Toast/UDSToastConfigProvider.d.cts +1 -1
  12. package/dist/components/client/Toast/UDSToastConfigProvider.d.ts +1 -1
  13. package/dist/index.d.cts +2 -2
  14. package/dist/index.d.ts +2 -2
  15. package/dist/runtime/popoverConfig.cjs +2 -0
  16. package/dist/runtime/popoverConfig.d.cts +3 -1
  17. package/dist/runtime/popoverConfig.d.ts +3 -1
  18. package/dist/runtime/popoverConfig.js +2 -0
  19. package/dist/styles/styler.d.cts +51 -51
  20. package/dist/styles/styler.d.ts +51 -51
  21. package/dist/tailwind/dist/commands/generateComponentData.cjs +5 -1
  22. package/dist/tailwind/dist/commands/generateComponentData.d.cts +3 -0
  23. package/dist/tailwind/dist/commands/generateComponentData.d.cts.map +1 -1
  24. package/dist/tailwind/dist/commands/generateComponentData.d.ts +3 -0
  25. package/dist/tailwind/dist/commands/generateComponentData.d.ts.map +1 -1
  26. package/dist/tailwind/dist/commands/generateComponentData.js +5 -1
  27. package/dist/tailwind/dist/commands/generateComponentData.js.map +1 -1
  28. package/dist/tailwind/dist/css/generate.cjs +2 -1
  29. package/dist/tailwind/dist/css/generate.d.cts.map +1 -1
  30. package/dist/tailwind/dist/css/generate.d.ts.map +1 -1
  31. package/dist/tailwind/dist/css/generate.js +3 -2
  32. package/dist/tailwind/dist/css/generate.js.map +1 -1
  33. package/dist/tailwind/dist/css/nodeUtils.cjs +7 -5
  34. package/dist/tailwind/dist/css/nodeUtils.js +7 -5
  35. package/dist/tailwind/dist/css/nodeUtils.js.map +1 -1
  36. package/dist/tailwind/dist/css/runner.cjs +4 -3
  37. package/dist/tailwind/dist/css/runner.js +5 -4
  38. package/dist/tailwind/dist/css/runner.js.map +1 -1
  39. package/dist/tailwind/dist/css/utils.cjs +62 -0
  40. package/dist/tailwind/dist/css/utils.js +62 -1
  41. package/dist/tailwind/dist/css/utils.js.map +1 -1
  42. package/dist/tailwind/dist/purger/optimized/purgeFromCode.cjs +104 -19
  43. package/dist/tailwind/dist/purger/optimized/purgeFromCode.d.cts +5 -0
  44. package/dist/tailwind/dist/purger/optimized/purgeFromCode.d.cts.map +1 -1
  45. package/dist/tailwind/dist/purger/optimized/purgeFromCode.d.ts +5 -0
  46. package/dist/tailwind/dist/purger/optimized/purgeFromCode.d.ts.map +1 -1
  47. package/dist/tailwind/dist/purger/optimized/purgeFromCode.js +104 -19
  48. package/dist/tailwind/dist/purger/optimized/purgeFromCode.js.map +1 -1
  49. package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.cjs +99 -10
  50. package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.js +99 -10
  51. package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.js.map +1 -1
  52. package/dist/tailwind/dist/runtimeConfig/hookMetadata.cjs +364 -0
  53. package/dist/tailwind/dist/runtimeConfig/hookMetadata.js +358 -0
  54. package/dist/tailwind/dist/runtimeConfig/hookMetadata.js.map +1 -0
  55. package/dist/tailwind/dist/types/dist/index.d.cts.map +1 -1
  56. package/dist/tailwind/dist/types/dist/index.d.ts.map +1 -1
  57. package/dist/tokens/index.d.cts +2 -2
  58. package/dist/tokens/index.d.ts +2 -2
  59. package/dist/tokens/types.d.cts +2 -2
  60. package/dist/tokens/types.d.ts +2 -2
  61. package/dist/types/dist/index.d.cts +2 -1
  62. package/dist/types/dist/index.d.ts +2 -1
  63. package/dist/uds/generated/componentData.cjs +858 -571
  64. package/dist/uds/generated/componentData.js +858 -571
  65. package/generated/componentData.json +1786 -1437
  66. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"purgeFromCode.js","names":[],"sources":["../../../src/purger/optimized/purgeFromCode.ts"],"sourcesContent":["import type { ImportDeclaration } from 'ts-morph';\nimport { Node, Project, SyntaxKind, ts } from 'ts-morph';\n\nimport { extractStringLiterals, findJsxReferences } from './ast';\nimport type { JsxElementWithAttributes, PurgeStats } from './types';\n\ninterface PurgeFromCodeResult {\n safelist: string[];\n imports: string[];\n components: string[];\n stats: PurgeStats;\n}\n\n/**\n * Serialized component info from pre-generated data\n */\ninterface SerializedComponentInfo {\n name: string;\n defaultProps: Record<string, string>;\n getStylesLiterals: Record<string, string>;\n cxLiterals?: string[];\n internalComponents: string[];\n internalComponentProps: Record<string, Record<string, string[]>>;\n propToVariantKeys: Record<string, string[]>;\n}\n\n/**\n * Get component info with all its dependencies (using pre-generated data)\n */\nconst getComponentWithDeps = (componentName: string): SerializedComponentInfo[] => {\n const visited = new Set<string>();\n const result: SerializedComponentInfo[] = [];\n\n const collect = (name: string): void => {\n if (visited.has(name)) {\n return;\n }\n visited.add(name);\n\n const info = resolveComponentInfo(name);\n if (!info) {\n return;\n }\n\n result.push(info);\n\n // Recursively collect internal component dependencies\n info.internalComponents.forEach((depName) => collect(depName));\n };\n\n collect(componentName);\n return result;\n};\n\n/**\n * Optimized purge from code string.\n *\n * This is a standalone implementation that:\n * - Analyzes UDS component source files to get accurate default props\n * - Includes defaults from internally used components\n * - Only depends on variants from src/styles/variants.ts (source of truth)\n * - Uses ts-morph for AST analysis\n *\n * Key behaviors:\n * - Includes classes for component default props (analyzed from source)\n * - Includes defaults for internal component dependencies\n * - Includes classes for explicitly used prop values\n * - Resolves ternary/logical expressions to extract all possible values\n * - Traces spreads to const objects in the same file\n * - Does NOT fall back to type properties for unresolved spreads\n */\n/**\n * Variant defaults per component from consumer's config\n * e.g., { Button: { size: 'md', variant: 'primary' }, Avatar: { size: 'md' } }\n */\ntype VariantDefaults = Record<string, Record<string, string>>;\n\ninterface PurgeFromCodeOptions {\n colorModes?: ('dark' | 'light')[];\n /** Variant defaults from consumer's config - used to include default CSS when prop not specified */\n variantDefaults?: VariantDefaults;\n variants: Record<string, Record<string, string>>;\n autoVariants: Record<string, Record<string, string>>;\n componentData: Record<string, SerializedComponentInfo>;\n includeAllClassNamePrimitives?: boolean;\n filePath?: string;\n}\n\n/**\n * Auto-variants lookup (loaded at module init)\n */\nlet autoVariantsCache = null as unknown as Record<string, Record<string, string>>;\n\n/**\n * Pre-generated component data (loaded at module init)\n */\nlet componentCache = null as unknown as Record<string, SerializedComponentInfo>;\n\n/**\n * Map of normalized component name -> actual component cache key\n * Useful when internal components are imported without namespace separators\n * (e.g., MenuItemBase vs Menu.ItemBase).\n */\nlet componentNameLookup: Record<string, string> | null = null;\n\nconst buildComponentNameLookup = (\n data: Record<string, SerializedComponentInfo>,\n): Record<string, string> => {\n const lookup: Record<string, string> = {};\n\n Object.keys(data).forEach((key) => {\n const normalized = normalizeComponentName(key);\n // Keep the first match to avoid arbitrary overwrites on collisions\n if (!lookup[normalized]) {\n lookup[normalized] = key;\n }\n });\n\n return lookup;\n};\n\nconst resolveComponentInfo = (name: string): SerializedComponentInfo | undefined => {\n if (componentCache && componentCache[name]) {\n return componentCache[name];\n }\n\n const normalized = normalizeComponentName(name);\n const mappedName = componentNameLookup?.[normalized];\n if (mappedName && componentCache) {\n return componentCache[mappedName];\n }\n\n return undefined;\n};\n\nconst getModuleSpecifierValue = (importDecl: ImportDeclaration): string => {\n return (\n importDecl.getModuleSpecifierValue() ??\n importDecl\n .getModuleSpecifier()\n .getText()\n .replace(/^['\"]|['\"]$/g, '')\n );\n};\n\nconst isTypeOnlyNamedImport = (importDecl: ImportDeclaration, importName: string): boolean => {\n if (importDecl.isTypeOnly()) {\n return true;\n }\n\n return (\n importDecl\n .getNamedImports()\n .find((namedImport) => namedImport.getName() === importName)\n ?.isTypeOnly() ?? false\n );\n};\n\nconst isUdsComponentModule = (moduleSpecifier: string): boolean => {\n const cleaned = moduleSpecifier.replace(/^['\"]|['\"]$/g, '');\n return cleaned === '@yahoo/uds' || cleaned.startsWith('@yahoo/uds/');\n};\n\n/**\n * Normalize component name to match autoVariants keys (lower camel, no punctuation).\n */\nconst normalizeComponentName = (name: string): string => {\n const cleaned = name.replace(/\\W/g, '');\n return cleaned.charAt(0).toLowerCase() + cleaned.slice(1);\n};\n\n/**\n * Fallback: infer prop -> variant key mapping from autoVariants when the\n * generated component data misses it (e.g., helpers like buildAvatarRootClasses).\n */\nconst getAutoVariantKeysForProp = (componentName: string, propName: string): string[] => {\n if (!autoVariantsCache) {\n return [];\n }\n\n const segments = componentName.match(/[A-Z][a-z0-9]*/g) ?? [];\n const candidates = new Set<string>([normalizeComponentName(componentName)]);\n\n // Add progressively shorter prefixes (e.g., AvatarImage -> avatar, avatarimage)\n if (segments.length > 0) {\n Array.from({ length: segments.length }, (_, index) => index + 1).forEach((i) => {\n const partial = segments.slice(0, i).join('');\n candidates.add(normalizeComponentName(partial));\n });\n }\n\n const propLower = propName.toLowerCase();\n\n return Object.keys(autoVariantsCache).filter((key) => {\n const keyLower = key.toLowerCase();\n return Array.from(candidates).some(\n (candidate) => keyLower.startsWith(candidate) && keyLower.includes(propLower),\n );\n });\n};\n\nconst getVariantKeysForProp = (\n componentInfo: SerializedComponentInfo,\n propName: string,\n): string[] => {\n const keys = new Set(componentInfo.propToVariantKeys?.[propName] ?? []);\n\n getAutoVariantKeysForProp(componentInfo.name, propName).forEach((inferred) => keys.add(inferred));\n\n return [...keys];\n};\n\nconst extractClassNamePrimitives = (\n sourceFile: ReturnType<Project['createSourceFile']>,\n): string[] => {\n const classes: string[] = [];\n\n // JSX className attributes\n sourceFile.getDescendantsOfKind(SyntaxKind.JsxAttribute).forEach((attr) => {\n if (attr.getNameNode().getText() !== 'className') {\n return;\n }\n\n const initializer = attr.getInitializer();\n if (!initializer) {\n return;\n }\n\n const values: string[] = [];\n\n if (Node.isStringLiteral(initializer)) {\n values.push(initializer.getLiteralText());\n } else if (Node.isJsxExpression(initializer)) {\n const expr = initializer.getExpression();\n if (expr) {\n values.push(...extractStringLiterals(expr));\n }\n }\n\n values.forEach((raw) => {\n classes.push(...raw.split(/\\s+/).filter(Boolean));\n });\n });\n\n // Plain object property assignments like const props = { className: '...' }\n sourceFile.getDescendantsOfKind(SyntaxKind.PropertyAssignment).forEach((prop) => {\n if (prop.getName() !== 'className') {\n return;\n }\n\n const initializer = prop.getInitializer();\n if (!initializer) {\n return;\n }\n\n const rawValues = extractStringLiterals(initializer);\n rawValues.forEach((raw) => {\n classes.push(...raw.split(/\\s+/).filter(Boolean));\n });\n });\n\n return classes;\n};\n\nconst purgeFromCodeOptimized = async (\n code: string,\n options: PurgeFromCodeOptions,\n): Promise<PurgeFromCodeResult> => {\n const { variants, autoVariants, componentData } = options;\n\n if (!autoVariantsCache) {\n autoVariantsCache = autoVariants;\n }\n\n if (!componentCache) {\n componentCache = componentData;\n componentNameLookup = buildComponentNameLookup(componentData);\n }\n\n const startTime = performance.now();\n\n const project = new Project({ useInMemoryFileSystem: true });\n const sourceFile = project.createSourceFile(options.filePath ?? 'input.tsx', code, {\n overwrite: true,\n });\n\n const stats: PurgeStats = {\n filesScanned: 1,\n timeMs: 0,\n classesGenerated: 0,\n spreadsTraced: 0,\n expressionsResolved: 0,\n };\n\n // Parse UDS imports\n const imports: string[] = [];\n sourceFile.getImportDeclarations().forEach((importDecl) => {\n const moduleSpec = getModuleSpecifierValue(importDecl);\n if (isUdsComponentModule(moduleSpec)) {\n importDecl.getNamedImports().forEach((namedImport) => {\n if (!namedImport.isTypeOnly() && !importDecl.isTypeOnly()) {\n imports.push(namedImport.getName());\n }\n });\n }\n });\n\n // Track all resolved prop values per component\n const componentProps = new Map<string, Map<string, Set<string>>>();\n const referencedComponents = new Set<string>();\n\n // Extract props from getStyles() calls in user code\n const getStylesProps = extractGetStylesCalls(sourceFile, stats, variants);\n\n // Find all JSX elements that use UDS components\n imports.forEach((imp) => {\n const references = findComponentReferences(sourceFile, imp);\n\n references.forEach((reference) => {\n const tagName = reference.getTagNameNode().getText();\n const componentName = tagName || imp;\n\n referencedComponents.add(componentName);\n\n const propsMap = componentProps.get(componentName) ?? new Map<string, Set<string>>();\n const props = extractPropsFromReference(reference, stats, sourceFile);\n\n props.forEach(([propName, values]) => {\n if (values.length > 0) {\n const existing = propsMap.get(propName) ?? new Set();\n values.forEach((val) => existing.add(val));\n propsMap.set(propName, existing);\n }\n });\n\n componentProps.set(componentName, propsMap);\n });\n\n if (!componentProps.has(imp)) {\n componentProps.set(imp, new Map());\n }\n });\n\n // Collect all components (including dependencies)\n const allComponents: SerializedComponentInfo[] = [];\n const seenComponents = new Set<string>();\n\n const componentsToProcess = new Set<string>([...imports, ...referencedComponents]);\n\n componentsToProcess.forEach((componentName) => {\n const componentsWithDeps = getComponentWithDeps(componentName);\n componentsWithDeps.forEach((comp) => {\n if (!seenComponents.has(comp.name)) {\n seenComponents.add(comp.name);\n allComponents.push(comp);\n }\n });\n });\n\n // Generate safelist\n const safelist: string[] = [];\n\n // Add classes from getStyles() calls in user code\n [...getStylesProps.entries()].forEach(([propName, values]) => {\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n values.forEach((value) => {\n const cls = (variantGroup as Record<string, string>)[value];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n });\n }\n });\n\n // Add defaults from all components (including internal dependencies)\n allComponents.forEach((componentInfo) => {\n const userProps = componentProps.get(componentInfo.name) ?? new Map();\n\n // Add default classes (only for props not explicitly set by user)\n Object.entries(componentInfo.defaultProps).forEach(([propName, propValue]) => {\n // Skip if user set this prop explicitly\n if (userProps.has(propName)) {\n return;\n }\n\n // Try direct lookup first\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n const cls = (variantGroup as Record<string, string>)[propValue];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n }\n\n // Also check propToVariantKeys mapping (e.g., Text's variant -> fontFamily, fontSize, etc.)\n const variantKeys = getVariantKeysForProp(componentInfo, propName);\n if (variantKeys.length > 0) {\n variantKeys.forEach((variantKey) => {\n const mappedVariantGroup =\n variants[variantKey as keyof typeof variants] ?? autoVariantsCache[variantKey];\n if (mappedVariantGroup) {\n const cls = (mappedVariantGroup as Record<string, string>)[propValue];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n }\n });\n }\n });\n\n // Add hardcoded literals from getStyles() calls in component source\n Object.entries(componentInfo.getStylesLiterals).forEach(([propName, propValue]) => {\n // Strip indexed suffix (e.g., \"variantKey:1\" -> \"variantKey\")\n // This handles ternary expressions that generate multiple values per key\n const basePropName = propName.replace(/:\\d+$/, '');\n const variantGroup = variants[basePropName as keyof typeof variants];\n if (variantGroup) {\n const cls = (variantGroup as Record<string, string>)[propValue];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n }\n });\n\n // Add raw Tailwind classes from cx() calls in component source\n if (componentInfo.cxLiterals) {\n componentInfo.cxLiterals.forEach((cls) => safelist.push(cls));\n }\n\n // Add default-variant classes for props not explicitly set\n // The component uses \"uds-button-size-default-root\" at runtime when no size prop is specified\n // The CSS generator creates rules like: .uds-button-size-md-root, .uds-button-size-default-root { ... }\n // We need BOTH classes: the default (runtime) and the actual value (triggers CSS generation)\n if (componentInfo.propToVariantKeys) {\n // Get defaults from consumer config if provided\n const componentDefaults = options.variantDefaults?.[componentInfo.name] ?? {};\n\n Object.keys(componentInfo.propToVariantKeys).forEach((propName) => {\n // Skip if user set this prop explicitly\n if (userProps.has(propName)) {\n return;\n }\n\n // Get the default value from consumer's config\n const defaultValue = componentDefaults[propName];\n const variantKeys = getVariantKeysForProp(componentInfo, propName);\n\n variantKeys.forEach((variantKey) => {\n const variantGroup = autoVariantsCache[variantKey];\n if (variantGroup) {\n // Add the \"default\" class (used by component at runtime)\n if (variantGroup['default']) {\n safelist.push(variantGroup['default']);\n }\n // Add the actual value class (triggers CSS generation with the alias)\n if (defaultValue && variantGroup[defaultValue]) {\n safelist.push(variantGroup[defaultValue]);\n }\n }\n });\n });\n }\n\n // Add classes for props passed to internal components with literal values\n Object.entries(componentInfo.internalComponentProps).forEach(\n ([_internalCompName, propsRecord]) => {\n Object.entries(propsRecord).forEach(([propName, propValues]) => {\n if (propName === 'className') {\n propValues.forEach((propValue) => {\n propValue\n .split(/\\s+/)\n .filter(Boolean)\n .forEach((cls) => safelist.push(cls));\n });\n return;\n }\n\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n propValues.forEach((propValue) => {\n const cls = (variantGroup as Record<string, string>)[propValue];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n });\n }\n });\n },\n );\n\n // Add classes for explicitly used props\n [...userProps.entries()].forEach(([propName, usedValues]) => {\n if (propName === 'className') {\n [...usedValues].forEach((value) => {\n value\n .split(/\\s+/)\n .filter(Boolean)\n .forEach((cls: string) => safelist.push(cls));\n });\n return;\n }\n\n // First try direct lookup (for Box-style props like backgroundColor)\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n [...usedValues].forEach((value) => {\n const cls = (variantGroup as Record<string, string>)[value];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n });\n }\n\n // Check if this prop maps to variant keys in this component or its internal components\n // This handles cases like Avatar where size prop mapping is in internal AvatarIcon,\n // and Text where variant -> fontFamily, fontSize, fontWeight, lineHeight, etc.\n const componentsToCheck = [\n componentInfo,\n ...getComponentWithDeps(componentInfo.name).slice(1),\n ];\n componentsToCheck.forEach((comp) => {\n const variantKeys = getVariantKeysForProp(comp, propName);\n if (variantKeys.length > 0) {\n variantKeys.forEach((variantKey) => {\n const mappedVariantGroup = variants[variantKey as keyof typeof variants];\n if (mappedVariantGroup) {\n [...usedValues].forEach((value) => {\n const cls = (mappedVariantGroup as Record<string, string>)[value];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n });\n }\n });\n }\n });\n });\n });\n\n if (options.includeAllClassNamePrimitives) {\n safelist.push(...extractClassNamePrimitives(sourceFile));\n }\n\n // Deduplicate\n const finalSafelist = [...new Set(safelist)];\n\n stats.timeMs = Math.round(performance.now() - startTime);\n stats.classesGenerated = finalSafelist.length;\n\n return {\n safelist: finalSafelist,\n imports,\n components: [...seenComponents],\n stats,\n };\n};\n\n/**\n * Find JSX references for a component in the source file\n */\nconst findComponentReferences = (\n sourceFile: ReturnType<Project['createSourceFile']>,\n componentName: string,\n): JsxElementWithAttributes[] => {\n const references: JsxElementWithAttributes[] = [];\n const seenTags = new Set<string>();\n\n const collectMatchingTags = (localName: string): void => {\n sourceFile\n .getDescendants()\n .filter(\n (node): node is JsxElementWithAttributes =>\n Node.isJsxOpeningElement(node) || Node.isJsxSelfClosingElement(node),\n )\n .forEach((node) => {\n const tagName = node.getTagNameNode().getText();\n if (tagName === localName || tagName.startsWith(`${localName}.`)) {\n const key = `${tagName}:${node.getStart()}`;\n if (!seenTags.has(key)) {\n seenTags.add(key);\n references.push(node);\n }\n }\n });\n };\n\n sourceFile.getImportDeclarations().forEach((importDecl) => {\n const moduleSpec = getModuleSpecifierValue(importDecl);\n if (!isUdsComponentModule(moduleSpec)) {\n return;\n }\n\n importDecl.getNamedImports().forEach((namedImport) => {\n if (\n namedImport.getName() !== componentName ||\n isTypeOnlyNamedImport(importDecl, componentName)\n ) {\n return;\n }\n\n const localName = namedImport.getAliasNode()?.getText() ?? componentName;\n const identifier = namedImport.getFirstDescendantByKindOrThrow(ts.SyntaxKind.Identifier);\n\n findJsxReferences(identifier).forEach((reference) => {\n const key = `${reference.getTagNameNode().getText()}:${reference.getStart()}`;\n if (!seenTags.has(key)) {\n seenTags.add(key);\n references.push(reference);\n }\n });\n\n collectMatchingTags(localName);\n });\n });\n\n return references;\n};\n\n/**\n * Extract props from a JSX reference.\n */\nconst extractPropsFromReference = (\n reference: JsxElementWithAttributes,\n stats: PurgeStats,\n sourceFile: ReturnType<Project['createSourceFile']>,\n): Array<[string, string[]]> => {\n const props: Array<[string, string[]]> = [];\n const attributes = reference.getAttributes();\n\n attributes.forEach((attr) => {\n if (attr.asKind(SyntaxKind.JsxAttribute)) {\n const jsxAttr = attr.asKindOrThrow(SyntaxKind.JsxAttribute);\n const propName = jsxAttr.getNameNode().getText();\n const values: string[] = [];\n\n const initializer = jsxAttr.getInitializer();\n\n // Direct string literal: prop=\"value\"\n if (initializer && Node.isStringLiteral(initializer)) {\n values.push(initializer.getLiteralText());\n stats.expressionsResolved++;\n } else if (initializer && initializer.asKind(SyntaxKind.JsxExpression)) {\n // JSX expression: prop={expression}\n // Use extractStringLiterals to handle ternaries, nullish, OR, etc.\n const jsxExpr = initializer.asKindOrThrow(SyntaxKind.JsxExpression);\n const expression = jsxExpr.getExpression();\n if (expression) {\n const resolved = extractStringLiterals(expression);\n values.push(...resolved);\n if (resolved.length > 0) {\n stats.expressionsResolved++;\n }\n }\n }\n\n props.push([propName, values]);\n }\n\n if (attr.asKind(SyntaxKind.JsxSpreadAttribute)) {\n stats.spreadsTraced++;\n\n const spreadAttr = attr.asKindOrThrow(SyntaxKind.JsxSpreadAttribute);\n const expression = spreadAttr.getExpression();\n const spreadName = expression.getText();\n\n const resolvedSpreadProps = traceSpreadInFile(spreadName, sourceFile);\n\n resolvedSpreadProps.forEach(([propName, values]) => {\n if (values.length > 0) {\n props.push([propName, values]);\n }\n });\n }\n });\n\n return props;\n};\n\n/**\n * Trace spread props to their source within the same file.\n */\nconst traceSpreadInFile = (\n spreadName: string,\n sourceFile: ReturnType<Project['createSourceFile']>,\n): Array<[string, string[]]> => {\n const props: Array<[string, string[]]> = [];\n\n const varDecl = sourceFile.getVariableDeclaration(spreadName);\n if (!varDecl) {\n return props;\n }\n\n const initializer = varDecl.getInitializer();\n if (!initializer) {\n return props;\n }\n\n const objLiteral = initializer.asKind(SyntaxKind.ObjectLiteralExpression)\n ? initializer.asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n : initializer.asKind(SyntaxKind.AsExpression)\n ? initializer\n .asKindOrThrow(SyntaxKind.AsExpression)\n .getExpression()\n .asKind(SyntaxKind.ObjectLiteralExpression)\n ? initializer\n .asKindOrThrow(SyntaxKind.AsExpression)\n .getExpression()\n .asKindOrThrow(SyntaxKind.ObjectLiteralExpression)\n : null\n : null;\n\n if (!objLiteral) {\n return props;\n }\n\n objLiteral.getProperties().forEach((prop) => {\n if (prop.asKind(SyntaxKind.PropertyAssignment)) {\n const propAssign = prop.asKindOrThrow(SyntaxKind.PropertyAssignment);\n const propName = propAssign.getName();\n const propInit = propAssign.getInitializer();\n\n if (propInit) {\n const values = extractStringLiterals(propInit);\n if (values.length > 0) {\n props.push([propName, values]);\n }\n }\n }\n });\n\n return props;\n};\n\n/**\n * Extract props from getStyles() calls in user code.\n * This handles cases like:\n * const styles = getStyles({ backgroundColor: 'brand', spacing: '4' });\n */\nconst extractGetStylesCalls = (\n sourceFile: ReturnType<Project['createSourceFile']>,\n stats: PurgeStats,\n\n variants: Record<string, Record<string, string>>,\n): Map<string, Set<string>> => {\n const props = new Map<string, Set<string>>();\n\n const VALID_VARIANTS = new Set(Object.keys(variants));\n\n // Find all getStyles() call expressions\n const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);\n\n callExpressions.forEach((call) => {\n const expression = call.getExpression();\n if (expression.getText() !== 'getStyles') {\n return;\n }\n\n const args = call.getArguments();\n if (args.length === 0) {\n return;\n }\n\n const firstArg = args[0];\n if (!firstArg.asKind(SyntaxKind.ObjectLiteralExpression)) {\n return;\n }\n\n const objLiteral = firstArg.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);\n\n objLiteral.getProperties().forEach((prop) => {\n if (prop.asKind(SyntaxKind.PropertyAssignment)) {\n const propAssign = prop.asKindOrThrow(SyntaxKind.PropertyAssignment);\n const propName = propAssign.getName();\n const propInit = propAssign.getInitializer();\n\n if (propInit && VALID_VARIANTS.has(propName)) {\n const values = extractStringLiterals(propInit);\n if (values.length > 0) {\n const existing = props.get(propName) ?? new Set();\n values.forEach((v) => existing.add(v));\n props.set(propName, existing);\n stats.expressionsResolved++;\n }\n }\n } else if (prop.asKind(SyntaxKind.ShorthandPropertyAssignment)) {\n // Handle shorthand like { backgroundColor } where backgroundColor is a variable\n const shorthand = prop.asKindOrThrow(SyntaxKind.ShorthandPropertyAssignment);\n const propName = shorthand.getName();\n\n if (VALID_VARIANTS.has(propName)) {\n // Try to trace the variable\n const nameNode = shorthand.getNameNode();\n const values = extractStringLiterals(nameNode);\n if (values.length > 0) {\n const existing = props.get(propName) ?? new Set();\n values.forEach((v) => existing.add(v));\n props.set(propName, existing);\n stats.expressionsResolved++;\n }\n }\n }\n });\n });\n\n return props;\n};\n\nexport type { PurgeFromCodeOptions, PurgeFromCodeResult, VariantDefaults };\nexport { purgeFromCodeOptimized };\n"],"mappings":"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"}
1
+ {"version":3,"file":"purgeFromCode.js","names":[],"sources":["../../../src/purger/optimized/purgeFromCode.ts"],"sourcesContent":["import type { ImportDeclaration, ObjectLiteralExpression } from 'ts-morph';\nimport { Node, Project, SyntaxKind, ts } from 'ts-morph';\n\nimport { extractStringLiterals, findJsxReferences } from './ast';\nimport type { JsxElementWithAttributes, PurgeStats } from './types';\n\ninterface PurgeFromCodeResult {\n safelist: string[];\n imports: string[];\n components: string[];\n stats: PurgeStats;\n}\n\ntype RuntimeConfigValues = Record<string, string | number | boolean>;\n\n/**\n * Serialized component info from pre-generated data\n */\ninterface SerializedComponentInfo {\n name: string;\n defaultProps: Record<string, string>;\n getStylesLiterals: Record<string, string>;\n cxLiterals?: string[];\n internalComponents: string[];\n internalComponentProps: Record<string, Record<string, string[]>>;\n propToVariantKeys: Record<string, string[]>;\n runtimeConfigDefaultProps?: Record<string, string>;\n runtimeConfigGetStyles?: Record<string, string[]>;\n runtimeConfigInternalComponentProps?: Record<string, Record<string, string[]>>;\n}\n\n/**\n * Get component info with all its dependencies (using pre-generated data)\n */\nconst getComponentWithDeps = (componentName: string): SerializedComponentInfo[] => {\n const visited = new Set<string>();\n const result: SerializedComponentInfo[] = [];\n\n const collect = (name: string): void => {\n if (visited.has(name)) {\n return;\n }\n visited.add(name);\n\n const info = resolveComponentInfo(name);\n if (!info) {\n return;\n }\n\n result.push(info);\n\n // Recursively collect internal component dependencies\n info.internalComponents.forEach((depName) => collect(depName));\n };\n\n collect(componentName);\n return result;\n};\n\n/**\n * Optimized purge from code string.\n *\n * This is a standalone implementation that:\n * - Analyzes UDS component source files to get accurate default props\n * - Includes defaults from internally used components\n * - Only depends on variants from src/styles/variants.ts (source of truth)\n * - Uses ts-morph for AST analysis\n *\n * Key behaviors:\n * - Includes classes for component default props (analyzed from source)\n * - Includes defaults for internal component dependencies\n * - Includes classes for explicitly used prop values\n * - Resolves ternary/logical expressions to extract all possible values\n * - Traces spreads to const objects in the same file\n * - Does NOT fall back to type properties for unresolved spreads\n */\n/**\n * Variant defaults per component from consumer's config\n * e.g., { Button: { size: 'md', variant: 'primary' }, Avatar: { size: 'md' } }\n */\ntype VariantDefaults = Record<string, Record<string, string>>;\n\ninterface PurgeFromCodeOptions {\n colorModes?: ('dark' | 'light')[];\n /** Variant defaults from consumer's config - used to include default CSS when prop not specified */\n variantDefaults?: VariantDefaults;\n runtimeConfigValues?: RuntimeConfigValues;\n variants: Record<string, Record<string, string>>;\n autoVariants: Record<string, Record<string, string>>;\n componentData: Record<string, SerializedComponentInfo>;\n includeAllClassNamePrimitives?: boolean;\n filePath?: string;\n}\n\n/**\n * Auto-variants lookup (loaded at module init)\n */\nlet autoVariantsCache = null as unknown as Record<string, Record<string, string>>;\n\n/**\n * Pre-generated component data (loaded at module init)\n */\nlet componentCache = null as unknown as Record<string, SerializedComponentInfo>;\n\n/**\n * Map of normalized component name -> actual component cache key\n * Useful when internal components are imported without namespace separators\n * (e.g., MenuItemBase vs Menu.ItemBase).\n */\nlet componentNameLookup: Record<string, string> | null = null;\n\nconst buildComponentNameLookup = (\n data: Record<string, SerializedComponentInfo>,\n): Record<string, string> => {\n const lookup: Record<string, string> = {};\n\n Object.keys(data).forEach((key) => {\n const normalized = normalizeComponentName(key);\n // Keep the first match to avoid arbitrary overwrites on collisions\n if (!lookup[normalized]) {\n lookup[normalized] = key;\n }\n });\n\n return lookup;\n};\n\nconst resolveComponentInfo = (name: string): SerializedComponentInfo | undefined => {\n if (componentCache && componentCache[name]) {\n return componentCache[name];\n }\n\n const normalized = normalizeComponentName(name);\n const mappedName = componentNameLookup?.[normalized];\n if (mappedName && componentCache) {\n return componentCache[mappedName];\n }\n\n return undefined;\n};\n\nconst getModuleSpecifierValue = (importDecl: ImportDeclaration): string => {\n return (\n importDecl.getModuleSpecifierValue() ??\n importDecl\n .getModuleSpecifier()\n .getText()\n .replace(/^['\"]|['\"]$/g, '')\n );\n};\n\nconst isTypeOnlyNamedImport = (importDecl: ImportDeclaration, importName: string): boolean => {\n if (importDecl.isTypeOnly()) {\n return true;\n }\n\n return (\n importDecl\n .getNamedImports()\n .find((namedImport) => namedImport.getName() === importName)\n ?.isTypeOnly() ?? false\n );\n};\n\nconst isUdsComponentModule = (moduleSpecifier: string): boolean => {\n const cleaned = moduleSpecifier.replace(/^['\"]|['\"]$/g, '');\n return cleaned === '@yahoo/uds' || cleaned.startsWith('@yahoo/uds/');\n};\n\n/**\n * Normalize component name to match autoVariants keys (lower camel, no punctuation).\n */\nconst normalizeComponentName = (name: string): string => {\n const cleaned = name.replace(/\\W/g, '');\n return cleaned.charAt(0).toLowerCase() + cleaned.slice(1);\n};\n\n/**\n * Fallback: infer prop -> variant key mapping from autoVariants when the\n * generated component data misses it (e.g., helpers like buildAvatarRootClasses).\n */\nconst getAutoVariantKeysForProp = (componentName: string, propName: string): string[] => {\n if (!autoVariantsCache) {\n return [];\n }\n\n const segments = componentName.match(/[A-Z][a-z0-9]*/g) ?? [];\n const candidates = new Set<string>([normalizeComponentName(componentName)]);\n\n // Add progressively shorter prefixes (e.g., AvatarImage -> avatar, avatarimage)\n if (segments.length > 0) {\n Array.from({ length: segments.length }, (_, index) => index + 1).forEach((i) => {\n const partial = segments.slice(0, i).join('');\n candidates.add(normalizeComponentName(partial));\n });\n }\n\n const propLower = propName.toLowerCase();\n\n return Object.keys(autoVariantsCache).filter((key) => {\n const keyLower = key.toLowerCase();\n return Array.from(candidates).some(\n (candidate) => keyLower.startsWith(candidate) && keyLower.includes(propLower),\n );\n });\n};\n\nconst getVariantKeysForProp = (\n componentInfo: SerializedComponentInfo,\n propName: string,\n): string[] => {\n const keys = new Set(componentInfo.propToVariantKeys?.[propName] ?? []);\n\n getAutoVariantKeysForProp(componentInfo.name, propName).forEach((inferred) => keys.add(inferred));\n\n return [...keys];\n};\n\nconst addVariantGroupClasses = (\n variantGroup: Record<string, string> | undefined,\n safelist: string[],\n): void => {\n if (!variantGroup) {\n return;\n }\n\n Object.values(variantGroup).forEach((cls) => {\n safelist.push(cls.replaceAll('\\\\', ''));\n });\n};\n\nconst getRuntimeDefaultPropValues = (\n componentInfo: SerializedComponentInfo,\n propName: string,\n runtimeConfigValues?: RuntimeConfigValues,\n): string[] => {\n const selector = componentInfo.runtimeConfigDefaultProps?.[propName];\n if (!selector || !runtimeConfigValues) {\n return [];\n }\n\n const value = runtimeConfigValues[selector];\n return value === undefined ? [] : [String(value)];\n};\n\nconst getPropCandidateValues = (\n componentInfo: SerializedComponentInfo,\n propName: string,\n userProps: Map<string, Set<string>>,\n options: PurgeFromCodeOptions,\n): string[] => {\n const explicitValues = userProps.get(propName);\n if (explicitValues && explicitValues.size > 0) {\n return [...explicitValues];\n }\n\n const configuredDefault = options.variantDefaults?.[componentInfo.name]?.[propName];\n if (configuredDefault) {\n return [configuredDefault];\n }\n\n if (componentInfo.defaultProps[propName]) {\n return [componentInfo.defaultProps[propName]];\n }\n\n return getRuntimeDefaultPropValues(componentInfo, propName, options.runtimeConfigValues);\n};\n\nconst resolveRuntimeSelectorValues = (\n selectorTemplate: string,\n componentInfo: SerializedComponentInfo,\n userProps: Map<string, Set<string>>,\n options: PurgeFromCodeOptions,\n): string[] => {\n const runtimeConfigValues = options.runtimeConfigValues;\n if (!runtimeConfigValues) {\n return [];\n }\n\n const placeholders = [...selectorTemplate.matchAll(/\\$\\{(\\w+)\\}/g)].map((match) => match[1]);\n const selectors = placeholders.reduce<string[]>(\n (acc, propName) => {\n const propValues = getPropCandidateValues(componentInfo, propName, userProps, options);\n if (propValues.length === 0) {\n return [];\n }\n\n return acc.flatMap((selector) =>\n propValues.map((value) => selector.replaceAll('$' + '{' + propName + '}', value)),\n );\n },\n [selectorTemplate],\n );\n\n return selectors.flatMap((selector) => {\n const value = runtimeConfigValues[selector];\n return value === undefined ? [] : [String(value)];\n });\n};\n\nconst extractClassNamePrimitives = (\n sourceFile: ReturnType<Project['createSourceFile']>,\n): string[] => {\n const classes: string[] = [];\n\n // JSX className attributes\n sourceFile.getDescendantsOfKind(SyntaxKind.JsxAttribute).forEach((attr) => {\n if (attr.getNameNode().getText() !== 'className') {\n return;\n }\n\n const initializer = attr.getInitializer();\n if (!initializer) {\n return;\n }\n\n const values: string[] = [];\n\n if (Node.isStringLiteral(initializer)) {\n values.push(initializer.getLiteralText());\n } else if (Node.isJsxExpression(initializer)) {\n const expr = initializer.getExpression();\n if (expr) {\n values.push(...extractStringLiterals(expr));\n }\n }\n\n values.forEach((raw) => {\n classes.push(...raw.split(/\\s+/).filter(Boolean));\n });\n });\n\n // Plain object property assignments like const props = { className: '...' }\n sourceFile.getDescendantsOfKind(SyntaxKind.PropertyAssignment).forEach((prop) => {\n if (prop.getName() !== 'className') {\n return;\n }\n\n const initializer = prop.getInitializer();\n if (!initializer) {\n return;\n }\n\n const rawValues = extractStringLiterals(initializer);\n rawValues.forEach((raw) => {\n classes.push(...raw.split(/\\s+/).filter(Boolean));\n });\n });\n\n return classes;\n};\n\nconst purgeFromCodeOptimized = async (\n code: string,\n options: PurgeFromCodeOptions,\n): Promise<PurgeFromCodeResult> => {\n const { variants, autoVariants, componentData } = options;\n\n if (!autoVariantsCache) {\n autoVariantsCache = autoVariants;\n }\n\n if (!componentCache) {\n componentCache = componentData;\n componentNameLookup = buildComponentNameLookup(componentData);\n }\n\n const startTime = performance.now();\n\n const project = new Project({ useInMemoryFileSystem: true });\n const sourceFile = project.createSourceFile(options.filePath ?? 'input.tsx', code, {\n overwrite: true,\n });\n\n const stats: PurgeStats = {\n filesScanned: 1,\n timeMs: 0,\n classesGenerated: 0,\n spreadsTraced: 0,\n expressionsResolved: 0,\n };\n\n // Parse UDS imports\n const imports: string[] = [];\n sourceFile.getImportDeclarations().forEach((importDecl) => {\n const moduleSpec = getModuleSpecifierValue(importDecl);\n if (isUdsComponentModule(moduleSpec)) {\n importDecl.getNamedImports().forEach((namedImport) => {\n if (!namedImport.isTypeOnly() && !importDecl.isTypeOnly()) {\n imports.push(namedImport.getName());\n }\n });\n }\n });\n\n // Track all resolved prop values per component\n const componentProps = new Map<string, Map<string, Set<string>>>();\n const componentUnresolvedSpreadProps = new Map<string, Set<string>>();\n const referencedComponents = new Set<string>();\n\n // Extract props from getStyles() calls in user code\n const getStylesProps = extractGetStylesCalls(sourceFile, stats, variants);\n\n // Find all JSX elements that use UDS components\n imports.forEach((imp) => {\n const references = findComponentReferences(sourceFile, imp);\n\n references.forEach((reference) => {\n const tagName = reference.getTagNameNode().getText();\n const componentName = tagName || imp;\n\n referencedComponents.add(componentName);\n\n const propsMap = componentProps.get(componentName) ?? new Map<string, Set<string>>();\n const unresolvedSpreadProps = componentUnresolvedSpreadProps.get(componentName) ?? new Set();\n const props = extractPropsFromReference(reference, stats, sourceFile);\n\n props.forEach(({ propName, values, fromSpread }) => {\n if (values.length > 0) {\n const existing = propsMap.get(propName) ?? new Set();\n values.forEach((val) => existing.add(val));\n propsMap.set(propName, existing);\n return;\n }\n\n if (fromSpread) {\n unresolvedSpreadProps.add(propName);\n }\n });\n\n componentProps.set(componentName, propsMap);\n componentUnresolvedSpreadProps.set(componentName, unresolvedSpreadProps);\n });\n\n if (!componentProps.has(imp)) {\n componentProps.set(imp, new Map());\n }\n\n if (!componentUnresolvedSpreadProps.has(imp)) {\n componentUnresolvedSpreadProps.set(imp, new Set());\n }\n });\n\n // Collect all components (including dependencies)\n const allComponents: SerializedComponentInfo[] = [];\n const seenComponents = new Set<string>();\n\n const componentsToProcess = new Set<string>([...imports, ...referencedComponents]);\n\n componentsToProcess.forEach((componentName) => {\n const componentsWithDeps = getComponentWithDeps(componentName);\n componentsWithDeps.forEach((comp) => {\n if (!seenComponents.has(comp.name)) {\n seenComponents.add(comp.name);\n allComponents.push(comp);\n }\n });\n });\n\n // Generate safelist\n const safelist: string[] = [];\n\n // Add classes from getStyles() calls in user code\n [...getStylesProps.entries()].forEach(([propName, values]) => {\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n values.forEach((value) => {\n const cls = (variantGroup as Record<string, string>)[value];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n });\n }\n });\n\n // Add defaults from all components (including internal dependencies)\n allComponents.forEach((componentInfo) => {\n const userProps = componentProps.get(componentInfo.name) ?? new Map();\n const unresolvedSpreadProps =\n componentUnresolvedSpreadProps.get(componentInfo.name) ?? new Set();\n\n // Add default classes (only for props not explicitly set by user)\n Object.entries(componentInfo.defaultProps).forEach(([propName, propValue]) => {\n // Skip if user set this prop explicitly\n if (userProps.has(propName)) {\n return;\n }\n\n // Try direct lookup first\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n const cls = (variantGroup as Record<string, string>)[propValue];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n }\n\n // Also check propToVariantKeys mapping (e.g., Text's variant -> fontFamily, fontSize, etc.)\n const variantKeys = getVariantKeysForProp(componentInfo, propName);\n if (variantKeys.length > 0) {\n variantKeys.forEach((variantKey) => {\n const mappedVariantGroup =\n variants[variantKey as keyof typeof variants] ?? autoVariantsCache[variantKey];\n if (mappedVariantGroup) {\n const cls = (mappedVariantGroup as Record<string, string>)[propValue];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n }\n });\n }\n });\n\n // Add hardcoded literals from getStyles() calls in component source\n Object.entries(componentInfo.getStylesLiterals).forEach(([propName, propValue]) => {\n // Strip indexed suffix (e.g., \"variantKey:1\" -> \"variantKey\")\n // This handles ternary expressions that generate multiple values per key\n const basePropName = propName.replace(/:\\d+$/, '');\n const variantGroup = variants[basePropName as keyof typeof variants];\n if (variantGroup) {\n const cls = (variantGroup as Record<string, string>)[propValue];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n }\n });\n\n Object.entries(componentInfo.runtimeConfigGetStyles ?? {}).forEach(([propName, selectors]) => {\n const variantGroup =\n variants[propName as keyof typeof variants] ?? autoVariantsCache[propName];\n if (!variantGroup) {\n return;\n }\n\n selectors.forEach((selector) => {\n resolveRuntimeSelectorValues(selector, componentInfo, userProps, options).forEach(\n (value) => {\n const cls = (variantGroup as Record<string, string>)[value];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n },\n );\n });\n });\n\n // Add raw Tailwind classes from cx() calls in component source\n if (componentInfo.cxLiterals) {\n componentInfo.cxLiterals.forEach((cls) => safelist.push(cls));\n }\n\n // Add default-variant classes for props not explicitly set\n // The component uses \"uds-button-size-default-root\" at runtime when no size prop is specified\n // The CSS generator creates rules like: .uds-button-size-md-root, .uds-button-size-default-root { ... }\n // We need BOTH classes: the default (runtime) and the actual value (triggers CSS generation)\n if (componentInfo.propToVariantKeys) {\n // Get defaults from consumer config if provided\n const componentDefaults = options.variantDefaults?.[componentInfo.name] ?? {};\n\n Object.keys(componentInfo.propToVariantKeys).forEach((propName) => {\n // Skip if user set this prop explicitly\n if (userProps.has(propName)) {\n return;\n }\n\n // Get the default value from consumer's config\n const defaultValues = componentDefaults[propName]\n ? [componentDefaults[propName]]\n : getRuntimeDefaultPropValues(componentInfo, propName, options.runtimeConfigValues);\n const variantKeys = getVariantKeysForProp(componentInfo, propName);\n\n variantKeys.forEach((variantKey) => {\n const variantGroup = autoVariantsCache[variantKey];\n if (variantGroup) {\n // Add the \"default\" class (used by component at runtime)\n if (variantGroup['default']) {\n safelist.push(variantGroup['default']);\n }\n // Add the actual value class (triggers CSS generation with the alias)\n defaultValues.forEach((defaultValue) => {\n if (variantGroup[defaultValue]) {\n safelist.push(variantGroup[defaultValue]);\n }\n });\n }\n });\n });\n }\n\n // Add classes for props passed to internal components with literal values\n Object.entries(componentInfo.internalComponentProps).forEach(\n ([_internalCompName, propsRecord]) => {\n Object.entries(propsRecord).forEach(([propName, propValues]) => {\n if (propName === 'className') {\n propValues.forEach((propValue) => {\n propValue\n .split(/\\s+/)\n .filter(Boolean)\n .forEach((cls) => safelist.push(cls));\n });\n return;\n }\n\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n propValues.forEach((propValue) => {\n const cls = (variantGroup as Record<string, string>)[propValue];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n });\n }\n });\n },\n );\n\n Object.entries(componentInfo.runtimeConfigInternalComponentProps ?? {}).forEach(\n ([_internalCompName, propsRecord]) => {\n Object.entries(propsRecord).forEach(([propName, selectors]) => {\n const variantGroup = variants[propName as keyof typeof variants];\n if (!variantGroup) {\n return;\n }\n\n selectors.forEach((selector) => {\n resolveRuntimeSelectorValues(selector, componentInfo, userProps, options).forEach(\n (value) => {\n const cls = (variantGroup as Record<string, string>)[value];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n },\n );\n });\n });\n },\n );\n\n // Add classes for explicitly used props\n [...userProps.entries()].forEach(([propName, usedValues]) => {\n if (propName === 'className') {\n [...usedValues].forEach((value) => {\n value\n .split(/\\s+/)\n .filter(Boolean)\n .forEach((cls: string) => safelist.push(cls));\n });\n return;\n }\n\n // First try direct lookup (for Box-style props like backgroundColor)\n const variantGroup = variants[propName as keyof typeof variants];\n if (variantGroup) {\n [...usedValues].forEach((value) => {\n const cls = (variantGroup as Record<string, string>)[value];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n });\n }\n\n // Check if this prop maps to variant keys in this component or its internal components\n // This handles cases like Avatar where size prop mapping is in internal AvatarIcon,\n // and Text where variant -> fontFamily, fontSize, fontWeight, lineHeight, etc.\n const componentsToCheck = [\n componentInfo,\n ...getComponentWithDeps(componentInfo.name).slice(1),\n ];\n componentsToCheck.forEach((comp) => {\n const variantKeys = getVariantKeysForProp(comp, propName);\n if (variantKeys.length > 0) {\n variantKeys.forEach((variantKey) => {\n const mappedVariantGroup = variants[variantKey as keyof typeof variants];\n if (mappedVariantGroup) {\n [...usedValues].forEach((value) => {\n const cls = (mappedVariantGroup as Record<string, string>)[value];\n if (cls) {\n safelist.push(cls.replaceAll('\\\\', ''));\n }\n });\n }\n });\n }\n });\n });\n\n unresolvedSpreadProps.forEach((propName) => {\n addVariantGroupClasses(\n variants[propName as keyof typeof variants] ?? autoVariantsCache[propName],\n safelist,\n );\n\n const componentsToCheck = [\n componentInfo,\n ...getComponentWithDeps(componentInfo.name).slice(1),\n ];\n componentsToCheck.forEach((comp) => {\n const variantKeys = getVariantKeysForProp(comp, propName);\n variantKeys.forEach((variantKey) => {\n addVariantGroupClasses(\n variants[variantKey as keyof typeof variants] ?? autoVariantsCache[variantKey],\n safelist,\n );\n });\n });\n });\n });\n\n if (options.includeAllClassNamePrimitives) {\n safelist.push(...extractClassNamePrimitives(sourceFile));\n }\n\n // Deduplicate\n const finalSafelist = [...new Set(safelist)];\n\n stats.timeMs = Math.round(performance.now() - startTime);\n stats.classesGenerated = finalSafelist.length;\n\n return {\n safelist: finalSafelist,\n imports,\n components: [...seenComponents],\n stats,\n };\n};\n\n/**\n * Find JSX references for a component in the source file\n */\nconst findComponentReferences = (\n sourceFile: ReturnType<Project['createSourceFile']>,\n componentName: string,\n): JsxElementWithAttributes[] => {\n const references: JsxElementWithAttributes[] = [];\n const seenTags = new Set<string>();\n\n const collectMatchingTags = (localName: string): void => {\n sourceFile\n .getDescendants()\n .filter(\n (node): node is JsxElementWithAttributes =>\n Node.isJsxOpeningElement(node) || Node.isJsxSelfClosingElement(node),\n )\n .forEach((node) => {\n const tagName = node.getTagNameNode().getText();\n if (tagName === localName || tagName.startsWith(`${localName}.`)) {\n const key = `${tagName}:${node.getStart()}`;\n if (!seenTags.has(key)) {\n seenTags.add(key);\n references.push(node);\n }\n }\n });\n };\n\n sourceFile.getImportDeclarations().forEach((importDecl) => {\n const moduleSpec = getModuleSpecifierValue(importDecl);\n if (!isUdsComponentModule(moduleSpec)) {\n return;\n }\n\n importDecl.getNamedImports().forEach((namedImport) => {\n if (\n namedImport.getName() !== componentName ||\n isTypeOnlyNamedImport(importDecl, componentName)\n ) {\n return;\n }\n\n const localName = namedImport.getAliasNode()?.getText() ?? componentName;\n const identifier = namedImport.getFirstDescendantByKindOrThrow(ts.SyntaxKind.Identifier);\n\n findJsxReferences(identifier).forEach((reference) => {\n const key = `${reference.getTagNameNode().getText()}:${reference.getStart()}`;\n if (!seenTags.has(key)) {\n seenTags.add(key);\n references.push(reference);\n }\n });\n\n collectMatchingTags(localName);\n });\n });\n\n return references;\n};\n\n/**\n * Extract props from a JSX reference.\n */\nconst extractPropsFromReference = (\n reference: JsxElementWithAttributes,\n stats: PurgeStats,\n sourceFile: ReturnType<Project['createSourceFile']>,\n): Array<{ propName: string; values: string[]; fromSpread: boolean }> => {\n const props: Array<{ propName: string; values: string[]; fromSpread: boolean }> = [];\n const attributes = reference.getAttributes();\n\n attributes.forEach((attr) => {\n if (attr.asKind(SyntaxKind.JsxAttribute)) {\n const jsxAttr = attr.asKindOrThrow(SyntaxKind.JsxAttribute);\n const propName = jsxAttr.getNameNode().getText();\n const values: string[] = [];\n\n const initializer = jsxAttr.getInitializer();\n\n // Direct string literal: prop=\"value\"\n if (initializer && Node.isStringLiteral(initializer)) {\n values.push(initializer.getLiteralText());\n stats.expressionsResolved++;\n } else if (initializer && initializer.asKind(SyntaxKind.JsxExpression)) {\n // JSX expression: prop={expression}\n // Use extractStringLiterals to handle ternaries, nullish, OR, etc.\n const jsxExpr = initializer.asKindOrThrow(SyntaxKind.JsxExpression);\n const expression = jsxExpr.getExpression();\n if (expression) {\n const resolved = extractStringLiterals(expression);\n values.push(...resolved);\n if (resolved.length > 0) {\n stats.expressionsResolved++;\n }\n }\n }\n\n props.push({ propName, values, fromSpread: false });\n }\n\n if (attr.asKind(SyntaxKind.JsxSpreadAttribute)) {\n stats.spreadsTraced++;\n\n const spreadAttr = attr.asKindOrThrow(SyntaxKind.JsxSpreadAttribute);\n const expression = spreadAttr.getExpression();\n const spreadName = expression.getText();\n\n const resolvedSpreadProps = traceSpreadInFile(spreadName, sourceFile);\n\n resolvedSpreadProps.forEach(([propName, values]) => {\n props.push({ propName, values, fromSpread: true });\n });\n }\n });\n\n return props;\n};\n\n/**\n * Trace spread props to their source within the same file.\n */\nconst traceSpreadInFile = (\n spreadName: string,\n sourceFile: ReturnType<Project['createSourceFile']>,\n): Array<[string, string[]]> => {\n const props = new Map<string, Set<string>>();\n\n const varDecl = sourceFile\n .getDescendantsOfKind(SyntaxKind.VariableDeclaration)\n .find((declaration) => declaration.getName() === spreadName);\n if (!varDecl) {\n return [];\n }\n\n const initializer = varDecl.getInitializer();\n if (!initializer) {\n return [];\n }\n\n getSpreadObjectLiteralCandidates(initializer).forEach((objLiteral) => {\n objLiteral.getProperties().forEach((prop) => {\n if (!prop.asKind(SyntaxKind.PropertyAssignment)) {\n return;\n }\n\n const propAssign = prop.asKindOrThrow(SyntaxKind.PropertyAssignment);\n const propName = propAssign.getName();\n const propInit = propAssign.getInitializer();\n const values = propInit ? extractStringLiterals(propInit) : [];\n const existingValues = props.get(propName) ?? new Set<string>();\n\n values.forEach((value) => existingValues.add(value));\n props.set(propName, existingValues);\n });\n });\n\n return [...props.entries()].map(([propName, values]) => [propName, [...values]]);\n};\n\nconst getSpreadObjectLiteralCandidates = (node: Node): ObjectLiteralExpression[] => {\n if (Node.isObjectLiteralExpression(node)) {\n return [node];\n }\n\n if (Node.isParenthesizedExpression(node)) {\n return getSpreadObjectLiteralCandidates(node.getExpression());\n }\n\n if (Node.isAsExpression(node) || Node.isTypeAssertion(node) || Node.isSatisfiesExpression(node)) {\n return getSpreadObjectLiteralCandidates(node.getExpression());\n }\n\n if (Node.isConditionalExpression(node)) {\n return [\n ...getSpreadObjectLiteralCandidates(node.getWhenTrue()),\n ...getSpreadObjectLiteralCandidates(node.getWhenFalse()),\n ];\n }\n\n return [];\n};\n\n/**\n * Extract props from getStyles() calls in user code.\n * This handles cases like:\n * const styles = getStyles({ backgroundColor: 'brand', spacing: '4' });\n */\nconst extractGetStylesCalls = (\n sourceFile: ReturnType<Project['createSourceFile']>,\n stats: PurgeStats,\n\n variants: Record<string, Record<string, string>>,\n): Map<string, Set<string>> => {\n const props = new Map<string, Set<string>>();\n\n const VALID_VARIANTS = new Set(Object.keys(variants));\n\n // Find all getStyles() call expressions\n const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);\n\n callExpressions.forEach((call) => {\n const expression = call.getExpression();\n if (expression.getText() !== 'getStyles') {\n return;\n }\n\n const args = call.getArguments();\n if (args.length === 0) {\n return;\n }\n\n const firstArg = args[0];\n if (!firstArg.asKind(SyntaxKind.ObjectLiteralExpression)) {\n return;\n }\n\n const objLiteral = firstArg.asKindOrThrow(SyntaxKind.ObjectLiteralExpression);\n\n objLiteral.getProperties().forEach((prop) => {\n if (prop.asKind(SyntaxKind.PropertyAssignment)) {\n const propAssign = prop.asKindOrThrow(SyntaxKind.PropertyAssignment);\n const propName = propAssign.getName();\n const propInit = propAssign.getInitializer();\n\n if (propInit && VALID_VARIANTS.has(propName)) {\n const values = extractStringLiterals(propInit);\n if (values.length > 0) {\n const existing = props.get(propName) ?? new Set();\n values.forEach((v) => existing.add(v));\n props.set(propName, existing);\n stats.expressionsResolved++;\n }\n }\n } else if (prop.asKind(SyntaxKind.ShorthandPropertyAssignment)) {\n // Handle shorthand like { backgroundColor } where backgroundColor is a variable\n const shorthand = prop.asKindOrThrow(SyntaxKind.ShorthandPropertyAssignment);\n const propName = shorthand.getName();\n\n if (VALID_VARIANTS.has(propName)) {\n // Try to trace the variable\n const nameNode = shorthand.getNameNode();\n const values = extractStringLiterals(nameNode);\n if (values.length > 0) {\n const existing = props.get(propName) ?? new Set();\n values.forEach((v) => existing.add(v));\n props.set(propName, existing);\n stats.expressionsResolved++;\n }\n }\n }\n });\n });\n\n return props;\n};\n\nexport type { PurgeFromCodeOptions, PurgeFromCodeResult, RuntimeConfigValues, VariantDefaults };\nexport { purgeFromCodeOptimized };\n"],"mappings":";;;;;;;;;AAkCA,MAAM,wBAAwB,kBAAqD;CACjF,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,SAAoC,EAAE;CAE5C,MAAM,WAAW,SAAuB;AACtC,MAAI,QAAQ,IAAI,KAAK,CACnB;AAEF,UAAQ,IAAI,KAAK;EAEjB,MAAM,OAAO,qBAAqB,KAAK;AACvC,MAAI,CAAC,KACH;AAGF,SAAO,KAAK,KAAK;AAGjB,OAAK,mBAAmB,SAAS,YAAY,QAAQ,QAAQ,CAAC;;AAGhE,SAAQ,cAAc;AACtB,QAAO;;;;;AAyCT,IAAI,oBAAoB;;;;AAKxB,IAAI,iBAAiB;;;;;;AAOrB,IAAI,sBAAqD;AAEzD,MAAM,4BACJ,SAC2B;CAC3B,MAAM,SAAiC,EAAE;AAEzC,QAAO,KAAK,KAAK,CAAC,SAAS,QAAQ;EACjC,MAAM,aAAa,uBAAuB,IAAI;AAE9C,MAAI,CAAC,OAAO,YACV,QAAO,cAAc;GAEvB;AAEF,QAAO;;AAGT,MAAM,wBAAwB,SAAsD;AAClF,KAAI,kBAAkB,eAAe,MACnC,QAAO,eAAe;CAGxB,MAAM,aAAa,uBAAuB,KAAK;CAC/C,MAAM,aAAa,sBAAsB;AACzC,KAAI,cAAc,eAChB,QAAO,eAAe;;AAM1B,MAAM,2BAA2B,eAA0C;AACzE,QACE,WAAW,yBAAyB,IACpC,WACG,oBAAoB,CACpB,SAAS,CACT,QAAQ,gBAAgB,GAAG;;AAIlC,MAAM,yBAAyB,YAA+B,eAAgC;AAC5F,KAAI,WAAW,YAAY,CACzB,QAAO;AAGT,QACE,WACG,iBAAiB,CACjB,MAAM,gBAAgB,YAAY,SAAS,KAAK,WAAW,EAC1D,YAAY,IAAI;;AAIxB,MAAM,wBAAwB,oBAAqC;CACjE,MAAM,UAAU,gBAAgB,QAAQ,gBAAgB,GAAG;AAC3D,QAAO,YAAY,gBAAgB,QAAQ,WAAW,cAAc;;;;;AAMtE,MAAM,0BAA0B,SAAyB;CACvD,MAAM,UAAU,KAAK,QAAQ,OAAO,GAAG;AACvC,QAAO,QAAQ,OAAO,EAAE,CAAC,aAAa,GAAG,QAAQ,MAAM,EAAE;;;;;;AAO3D,MAAM,6BAA6B,eAAuB,aAA+B;AACvF,KAAI,CAAC,kBACH,QAAO,EAAE;CAGX,MAAM,WAAW,cAAc,MAAM,kBAAkB,IAAI,EAAE;CAC7D,MAAM,aAAa,IAAI,IAAY,CAAC,uBAAuB,cAAc,CAAC,CAAC;AAG3E,KAAI,SAAS,SAAS,EACpB,OAAM,KAAK,EAAE,QAAQ,SAAS,QAAQ,GAAG,GAAG,UAAU,QAAQ,EAAE,CAAC,SAAS,MAAM;EAC9E,MAAM,UAAU,SAAS,MAAM,GAAG,EAAE,CAAC,KAAK,GAAG;AAC7C,aAAW,IAAI,uBAAuB,QAAQ,CAAC;GAC/C;CAGJ,MAAM,YAAY,SAAS,aAAa;AAExC,QAAO,OAAO,KAAK,kBAAkB,CAAC,QAAQ,QAAQ;EACpD,MAAM,WAAW,IAAI,aAAa;AAClC,SAAO,MAAM,KAAK,WAAW,CAAC,MAC3B,cAAc,SAAS,WAAW,UAAU,IAAI,SAAS,SAAS,UAAU,CAC9E;GACD;;AAGJ,MAAM,yBACJ,eACA,aACa;CACb,MAAM,OAAO,IAAI,IAAI,cAAc,oBAAoB,aAAa,EAAE,CAAC;AAEvE,2BAA0B,cAAc,MAAM,SAAS,CAAC,SAAS,aAAa,KAAK,IAAI,SAAS,CAAC;AAEjG,QAAO,CAAC,GAAG,KAAK;;AAGlB,MAAM,0BACJ,cACA,aACS;AACT,KAAI,CAAC,aACH;AAGF,QAAO,OAAO,aAAa,CAAC,SAAS,QAAQ;AAC3C,WAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;GACvC;;AAGJ,MAAM,+BACJ,eACA,UACA,wBACa;CACb,MAAM,WAAW,cAAc,4BAA4B;AAC3D,KAAI,CAAC,YAAY,CAAC,oBAChB,QAAO,EAAE;CAGX,MAAM,QAAQ,oBAAoB;AAClC,QAAO,UAAU,SAAY,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC;;AAGnD,MAAM,0BACJ,eACA,UACA,WACA,YACa;CACb,MAAM,iBAAiB,UAAU,IAAI,SAAS;AAC9C,KAAI,kBAAkB,eAAe,OAAO,EAC1C,QAAO,CAAC,GAAG,eAAe;CAG5B,MAAM,oBAAoB,QAAQ,kBAAkB,cAAc,QAAQ;AAC1E,KAAI,kBACF,QAAO,CAAC,kBAAkB;AAG5B,KAAI,cAAc,aAAa,UAC7B,QAAO,CAAC,cAAc,aAAa,UAAU;AAG/C,QAAO,4BAA4B,eAAe,UAAU,QAAQ,oBAAoB;;AAG1F,MAAM,gCACJ,kBACA,eACA,WACA,YACa;CACb,MAAM,sBAAsB,QAAQ;AACpC,KAAI,CAAC,oBACH,QAAO,EAAE;AAkBX,QAfqB,CAAC,GAAG,iBAAiB,SAAS,eAAe,CAAC,CAAC,KAAK,UAAU,MAAM,GAAG,CAC7D,QAC5B,KAAK,aAAa;EACjB,MAAM,aAAa,uBAAuB,eAAe,UAAU,WAAW,QAAQ;AACtF,MAAI,WAAW,WAAW,EACxB,QAAO,EAAE;AAGX,SAAO,IAAI,SAAS,aAClB,WAAW,KAAK,UAAU,SAAS,WAAW,OAAY,WAAW,KAAK,MAAM,CAAC,CAClF;IAEH,CAAC,iBAAiB,CACnB,CAEgB,SAAS,aAAa;EACrC,MAAM,QAAQ,oBAAoB;AAClC,SAAO,UAAU,SAAY,EAAE,GAAG,CAAC,OAAO,MAAM,CAAC;GACjD;;AAGJ,MAAM,8BACJ,eACa;CACb,MAAM,UAAoB,EAAE;AAG5B,YAAW,qBAAqB,WAAW,aAAa,CAAC,SAAS,SAAS;AACzE,MAAI,KAAK,aAAa,CAAC,SAAS,KAAK,YACnC;EAGF,MAAM,cAAc,KAAK,gBAAgB;AACzC,MAAI,CAAC,YACH;EAGF,MAAM,SAAmB,EAAE;AAE3B,MAAI,KAAK,gBAAgB,YAAY,CACnC,QAAO,KAAK,YAAY,gBAAgB,CAAC;WAChC,KAAK,gBAAgB,YAAY,EAAE;GAC5C,MAAM,OAAO,YAAY,eAAe;AACxC,OAAI,KACF,QAAO,KAAK,GAAG,sBAAsB,KAAK,CAAC;;AAI/C,SAAO,SAAS,QAAQ;AACtB,WAAQ,KAAK,GAAG,IAAI,MAAM,MAAM,CAAC,OAAO,QAAQ,CAAC;IACjD;GACF;AAGF,YAAW,qBAAqB,WAAW,mBAAmB,CAAC,SAAS,SAAS;AAC/E,MAAI,KAAK,SAAS,KAAK,YACrB;EAGF,MAAM,cAAc,KAAK,gBAAgB;AACzC,MAAI,CAAC,YACH;AAIF,EADkB,sBAAsB,YAAY,CAC1C,SAAS,QAAQ;AACzB,WAAQ,KAAK,GAAG,IAAI,MAAM,MAAM,CAAC,OAAO,QAAQ,CAAC;IACjD;GACF;AAEF,QAAO;;AAGT,MAAM,yBAAyB,OAC7B,MACA,YACiC;CACjC,MAAM,EAAE,UAAU,cAAc,kBAAkB;AAElD,KAAI,CAAC,kBACH,qBAAoB;AAGtB,KAAI,CAAC,gBAAgB;AACnB,mBAAiB;AACjB,wBAAsB,yBAAyB,cAAc;;CAG/D,MAAM,YAAY,YAAY,KAAK;CAGnC,MAAM,aADU,IAAI,QAAQ,EAAE,uBAAuB,MAAM,CAAC,CACjC,iBAAiB,QAAQ,YAAY,aAAa,MAAM,EACjF,WAAW,MACZ,CAAC;CAEF,MAAM,QAAoB;EACxB,cAAc;EACd,QAAQ;EACR,kBAAkB;EAClB,eAAe;EACf,qBAAqB;EACtB;CAGD,MAAM,UAAoB,EAAE;AAC5B,YAAW,uBAAuB,CAAC,SAAS,eAAe;AAEzD,MAAI,qBADe,wBAAwB,WAAW,CAClB,CAClC,YAAW,iBAAiB,CAAC,SAAS,gBAAgB;AACpD,OAAI,CAAC,YAAY,YAAY,IAAI,CAAC,WAAW,YAAY,CACvD,SAAQ,KAAK,YAAY,SAAS,CAAC;IAErC;GAEJ;CAGF,MAAM,iCAAiB,IAAI,KAAuC;CAClE,MAAM,iDAAiC,IAAI,KAA0B;CACrE,MAAM,uCAAuB,IAAI,KAAa;CAG9C,MAAM,iBAAiB,sBAAsB,YAAY,OAAO,SAAS;AAGzE,SAAQ,SAAS,QAAQ;AAGvB,EAFmB,wBAAwB,YAAY,IAAI,CAEhD,SAAS,cAAc;GAEhC,MAAM,gBADU,UAAU,gBAAgB,CAAC,SAAS,IACnB;AAEjC,wBAAqB,IAAI,cAAc;GAEvC,MAAM,WAAW,eAAe,IAAI,cAAc,oBAAI,IAAI,KAA0B;GACpF,MAAM,wBAAwB,+BAA+B,IAAI,cAAc,oBAAI,IAAI,KAAK;AAG5F,GAFc,0BAA0B,WAAW,OAAO,WAAW,CAE/D,SAAS,EAAE,UAAU,QAAQ,iBAAiB;AAClD,QAAI,OAAO,SAAS,GAAG;KACrB,MAAM,WAAW,SAAS,IAAI,SAAS,oBAAI,IAAI,KAAK;AACpD,YAAO,SAAS,QAAQ,SAAS,IAAI,IAAI,CAAC;AAC1C,cAAS,IAAI,UAAU,SAAS;AAChC;;AAGF,QAAI,WACF,uBAAsB,IAAI,SAAS;KAErC;AAEF,kBAAe,IAAI,eAAe,SAAS;AAC3C,kCAA+B,IAAI,eAAe,sBAAsB;IACxE;AAEF,MAAI,CAAC,eAAe,IAAI,IAAI,CAC1B,gBAAe,IAAI,qBAAK,IAAI,KAAK,CAAC;AAGpC,MAAI,CAAC,+BAA+B,IAAI,IAAI,CAC1C,gCAA+B,IAAI,qBAAK,IAAI,KAAK,CAAC;GAEpD;CAGF,MAAM,gBAA2C,EAAE;CACnD,MAAM,iCAAiB,IAAI,KAAa;AAIxC,CAF4B,IAAI,IAAY,CAAC,GAAG,SAAS,GAAG,qBAAqB,CAAC,CAE9D,SAAS,kBAAkB;AAE7C,EAD2B,qBAAqB,cAAc,CAC3C,SAAS,SAAS;AACnC,OAAI,CAAC,eAAe,IAAI,KAAK,KAAK,EAAE;AAClC,mBAAe,IAAI,KAAK,KAAK;AAC7B,kBAAc,KAAK,KAAK;;IAE1B;GACF;CAGF,MAAM,WAAqB,EAAE;AAG7B,EAAC,GAAG,eAAe,SAAS,CAAC,CAAC,SAAS,CAAC,UAAU,YAAY;EAC5D,MAAM,eAAe,SAAS;AAC9B,MAAI,aACF,QAAO,SAAS,UAAU;GACxB,MAAM,MAAO,aAAwC;AACrD,OAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;IAEzC;GAEJ;AAGF,eAAc,SAAS,kBAAkB;EACvC,MAAM,YAAY,eAAe,IAAI,cAAc,KAAK,oBAAI,IAAI,KAAK;EACrE,MAAM,wBACJ,+BAA+B,IAAI,cAAc,KAAK,oBAAI,IAAI,KAAK;AAGrE,SAAO,QAAQ,cAAc,aAAa,CAAC,SAAS,CAAC,UAAU,eAAe;AAE5E,OAAI,UAAU,IAAI,SAAS,CACzB;GAIF,MAAM,eAAe,SAAS;AAC9B,OAAI,cAAc;IAChB,MAAM,MAAO,aAAwC;AACrD,QAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;;GAK3C,MAAM,cAAc,sBAAsB,eAAe,SAAS;AAClE,OAAI,YAAY,SAAS,EACvB,aAAY,SAAS,eAAe;IAClC,MAAM,qBACJ,SAAS,eAAwC,kBAAkB;AACrE,QAAI,oBAAoB;KACtB,MAAM,MAAO,mBAA8C;AAC3D,SAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;;KAG3C;IAEJ;AAGF,SAAO,QAAQ,cAAc,kBAAkB,CAAC,SAAS,CAAC,UAAU,eAAe;GAIjF,MAAM,eAAe,SADA,SAAS,QAAQ,SAAS,GAAG;AAElD,OAAI,cAAc;IAChB,MAAM,MAAO,aAAwC;AACrD,QAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;;IAG3C;AAEF,SAAO,QAAQ,cAAc,0BAA0B,EAAE,CAAC,CAAC,SAAS,CAAC,UAAU,eAAe;GAC5F,MAAM,eACJ,SAAS,aAAsC,kBAAkB;AACnE,OAAI,CAAC,aACH;AAGF,aAAU,SAAS,aAAa;AAC9B,iCAA6B,UAAU,eAAe,WAAW,QAAQ,CAAC,SACvE,UAAU;KACT,MAAM,MAAO,aAAwC;AACrD,SAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;MAG5C;KACD;IACF;AAGF,MAAI,cAAc,WAChB,eAAc,WAAW,SAAS,QAAQ,SAAS,KAAK,IAAI,CAAC;AAO/D,MAAI,cAAc,mBAAmB;GAEnC,MAAM,oBAAoB,QAAQ,kBAAkB,cAAc,SAAS,EAAE;AAE7E,UAAO,KAAK,cAAc,kBAAkB,CAAC,SAAS,aAAa;AAEjE,QAAI,UAAU,IAAI,SAAS,CACzB;IAIF,MAAM,gBAAgB,kBAAkB,YACpC,CAAC,kBAAkB,UAAU,GAC7B,4BAA4B,eAAe,UAAU,QAAQ,oBAAoB;AAGrF,IAFoB,sBAAsB,eAAe,SAAS,CAEtD,SAAS,eAAe;KAClC,MAAM,eAAe,kBAAkB;AACvC,SAAI,cAAc;AAEhB,UAAI,aAAa,WACf,UAAS,KAAK,aAAa,WAAW;AAGxC,oBAAc,SAAS,iBAAiB;AACtC,WAAI,aAAa,cACf,UAAS,KAAK,aAAa,cAAc;QAE3C;;MAEJ;KACF;;AAIJ,SAAO,QAAQ,cAAc,uBAAuB,CAAC,SAClD,CAAC,mBAAmB,iBAAiB;AACpC,UAAO,QAAQ,YAAY,CAAC,SAAS,CAAC,UAAU,gBAAgB;AAC9D,QAAI,aAAa,aAAa;AAC5B,gBAAW,SAAS,cAAc;AAChC,gBACG,MAAM,MAAM,CACZ,OAAO,QAAQ,CACf,SAAS,QAAQ,SAAS,KAAK,IAAI,CAAC;OACvC;AACF;;IAGF,MAAM,eAAe,SAAS;AAC9B,QAAI,aACF,YAAW,SAAS,cAAc;KAChC,MAAM,MAAO,aAAwC;AACrD,SAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;MAEzC;KAEJ;IAEL;AAED,SAAO,QAAQ,cAAc,uCAAuC,EAAE,CAAC,CAAC,SACrE,CAAC,mBAAmB,iBAAiB;AACpC,UAAO,QAAQ,YAAY,CAAC,SAAS,CAAC,UAAU,eAAe;IAC7D,MAAM,eAAe,SAAS;AAC9B,QAAI,CAAC,aACH;AAGF,cAAU,SAAS,aAAa;AAC9B,kCAA6B,UAAU,eAAe,WAAW,QAAQ,CAAC,SACvE,UAAU;MACT,MAAM,MAAO,aAAwC;AACrD,UAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;OAG5C;MACD;KACF;IAEL;AAGD,GAAC,GAAG,UAAU,SAAS,CAAC,CAAC,SAAS,CAAC,UAAU,gBAAgB;AAC3D,OAAI,aAAa,aAAa;AAC5B,KAAC,GAAG,WAAW,CAAC,SAAS,UAAU;AACjC,WACG,MAAM,MAAM,CACZ,OAAO,QAAQ,CACf,SAAS,QAAgB,SAAS,KAAK,IAAI,CAAC;MAC/C;AACF;;GAIF,MAAM,eAAe,SAAS;AAC9B,OAAI,aACF,EAAC,GAAG,WAAW,CAAC,SAAS,UAAU;IACjC,MAAM,MAAO,aAAwC;AACrD,QAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;KAEzC;AAUJ,GAJ0B,CACxB,eACA,GAAG,qBAAqB,cAAc,KAAK,CAAC,MAAM,EAAE,CACrD,CACiB,SAAS,SAAS;IAClC,MAAM,cAAc,sBAAsB,MAAM,SAAS;AACzD,QAAI,YAAY,SAAS,EACvB,aAAY,SAAS,eAAe;KAClC,MAAM,qBAAqB,SAAS;AACpC,SAAI,mBACF,EAAC,GAAG,WAAW,CAAC,SAAS,UAAU;MACjC,MAAM,MAAO,mBAA8C;AAC3D,UAAI,IACF,UAAS,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC;OAEzC;MAEJ;KAEJ;IACF;AAEF,wBAAsB,SAAS,aAAa;AAC1C,0BACE,SAAS,aAAsC,kBAAkB,WACjE,SACD;AAMD,GAJ0B,CACxB,eACA,GAAG,qBAAqB,cAAc,KAAK,CAAC,MAAM,EAAE,CACrD,CACiB,SAAS,SAAS;AAElC,IADoB,sBAAsB,MAAM,SAAS,CAC7C,SAAS,eAAe;AAClC,4BACE,SAAS,eAAwC,kBAAkB,aACnE,SACD;MACD;KACF;IACF;GACF;AAEF,KAAI,QAAQ,8BACV,UAAS,KAAK,GAAG,2BAA2B,WAAW,CAAC;CAI1D,MAAM,gBAAgB,CAAC,GAAG,IAAI,IAAI,SAAS,CAAC;AAE5C,OAAM,SAAS,KAAK,MAAM,YAAY,KAAK,GAAG,UAAU;AACxD,OAAM,mBAAmB,cAAc;AAEvC,QAAO;EACL,UAAU;EACV;EACA,YAAY,CAAC,GAAG,eAAe;EAC/B;EACD;;;;;AAMH,MAAM,2BACJ,YACA,kBAC+B;CAC/B,MAAM,aAAyC,EAAE;CACjD,MAAM,2BAAW,IAAI,KAAa;CAElC,MAAM,uBAAuB,cAA4B;AACvD,aACG,gBAAgB,CAChB,QACE,SACC,KAAK,oBAAoB,KAAK,IAAI,KAAK,wBAAwB,KAAK,CACvE,CACA,SAAS,SAAS;GACjB,MAAM,UAAU,KAAK,gBAAgB,CAAC,SAAS;AAC/C,OAAI,YAAY,aAAa,QAAQ,WAAW,GAAG,UAAU,GAAG,EAAE;IAChE,MAAM,MAAM,GAAG,QAAQ,GAAG,KAAK,UAAU;AACzC,QAAI,CAAC,SAAS,IAAI,IAAI,EAAE;AACtB,cAAS,IAAI,IAAI;AACjB,gBAAW,KAAK,KAAK;;;IAGzB;;AAGN,YAAW,uBAAuB,CAAC,SAAS,eAAe;AAEzD,MAAI,CAAC,qBADc,wBAAwB,WAAW,CACjB,CACnC;AAGF,aAAW,iBAAiB,CAAC,SAAS,gBAAgB;AACpD,OACE,YAAY,SAAS,KAAK,iBAC1B,sBAAsB,YAAY,cAAc,CAEhD;GAGF,MAAM,YAAY,YAAY,cAAc,EAAE,SAAS,IAAI;AAG3D,qBAFmB,YAAY,gCAAgC,GAAG,WAAW,WAAW,CAE3D,CAAC,SAAS,cAAc;IACnD,MAAM,MAAM,GAAG,UAAU,gBAAgB,CAAC,SAAS,CAAC,GAAG,UAAU,UAAU;AAC3E,QAAI,CAAC,SAAS,IAAI,IAAI,EAAE;AACtB,cAAS,IAAI,IAAI;AACjB,gBAAW,KAAK,UAAU;;KAE5B;AAEF,uBAAoB,UAAU;IAC9B;GACF;AAEF,QAAO;;;;;AAMT,MAAM,6BACJ,WACA,OACA,eACuE;CACvE,MAAM,QAA4E,EAAE;AAGpF,CAFmB,UAAU,eAAe,CAEjC,SAAS,SAAS;AAC3B,MAAI,KAAK,OAAO,WAAW,aAAa,EAAE;GACxC,MAAM,UAAU,KAAK,cAAc,WAAW,aAAa;GAC3D,MAAM,WAAW,QAAQ,aAAa,CAAC,SAAS;GAChD,MAAM,SAAmB,EAAE;GAE3B,MAAM,cAAc,QAAQ,gBAAgB;AAG5C,OAAI,eAAe,KAAK,gBAAgB,YAAY,EAAE;AACpD,WAAO,KAAK,YAAY,gBAAgB,CAAC;AACzC,UAAM;cACG,eAAe,YAAY,OAAO,WAAW,cAAc,EAAE;IAItE,MAAM,aADU,YAAY,cAAc,WAAW,cAAc,CACxC,eAAe;AAC1C,QAAI,YAAY;KACd,MAAM,WAAW,sBAAsB,WAAW;AAClD,YAAO,KAAK,GAAG,SAAS;AACxB,SAAI,SAAS,SAAS,EACpB,OAAM;;;AAKZ,SAAM,KAAK;IAAE;IAAU;IAAQ,YAAY;IAAO,CAAC;;AAGrD,MAAI,KAAK,OAAO,WAAW,mBAAmB,EAAE;AAC9C,SAAM;AAQN,GAF4B,kBAJT,KAAK,cAAc,WAAW,mBAAmB,CACtC,eAAe,CACf,SAAS,EAEmB,WAAW,CAEjD,SAAS,CAAC,UAAU,YAAY;AAClD,UAAM,KAAK;KAAE;KAAU;KAAQ,YAAY;KAAM,CAAC;KAClD;;GAEJ;AAEF,QAAO;;;;;AAMT,MAAM,qBACJ,YACA,eAC8B;CAC9B,MAAM,wBAAQ,IAAI,KAA0B;CAE5C,MAAM,UAAU,WACb,qBAAqB,WAAW,oBAAoB,CACpD,MAAM,gBAAgB,YAAY,SAAS,KAAK,WAAW;AAC9D,KAAI,CAAC,QACH,QAAO,EAAE;CAGX,MAAM,cAAc,QAAQ,gBAAgB;AAC5C,KAAI,CAAC,YACH,QAAO,EAAE;AAGX,kCAAiC,YAAY,CAAC,SAAS,eAAe;AACpE,aAAW,eAAe,CAAC,SAAS,SAAS;AAC3C,OAAI,CAAC,KAAK,OAAO,WAAW,mBAAmB,CAC7C;GAGF,MAAM,aAAa,KAAK,cAAc,WAAW,mBAAmB;GACpE,MAAM,WAAW,WAAW,SAAS;GACrC,MAAM,WAAW,WAAW,gBAAgB;GAC5C,MAAM,SAAS,WAAW,sBAAsB,SAAS,GAAG,EAAE;GAC9D,MAAM,iBAAiB,MAAM,IAAI,SAAS,oBAAI,IAAI,KAAa;AAE/D,UAAO,SAAS,UAAU,eAAe,IAAI,MAAM,CAAC;AACpD,SAAM,IAAI,UAAU,eAAe;IACnC;GACF;AAEF,QAAO,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,KAAK,CAAC,UAAU,YAAY,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,CAAC;;AAGlF,MAAM,oCAAoC,SAA0C;AAClF,KAAI,KAAK,0BAA0B,KAAK,CACtC,QAAO,CAAC,KAAK;AAGf,KAAI,KAAK,0BAA0B,KAAK,CACtC,QAAO,iCAAiC,KAAK,eAAe,CAAC;AAG/D,KAAI,KAAK,eAAe,KAAK,IAAI,KAAK,gBAAgB,KAAK,IAAI,KAAK,sBAAsB,KAAK,CAC7F,QAAO,iCAAiC,KAAK,eAAe,CAAC;AAG/D,KAAI,KAAK,wBAAwB,KAAK,CACpC,QAAO,CACL,GAAG,iCAAiC,KAAK,aAAa,CAAC,EACvD,GAAG,iCAAiC,KAAK,cAAc,CAAC,CACzD;AAGH,QAAO,EAAE;;;;;;;AAQX,MAAM,yBACJ,YACA,OAEA,aAC6B;CAC7B,MAAM,wBAAQ,IAAI,KAA0B;CAE5C,MAAM,iBAAiB,IAAI,IAAI,OAAO,KAAK,SAAS,CAAC;AAKrD,CAFwB,WAAW,qBAAqB,WAAW,eAAe,CAElE,SAAS,SAAS;AAEhC,MADmB,KAAK,eAAe,CACxB,SAAS,KAAK,YAC3B;EAGF,MAAM,OAAO,KAAK,cAAc;AAChC,MAAI,KAAK,WAAW,EAClB;EAGF,MAAM,WAAW,KAAK;AACtB,MAAI,CAAC,SAAS,OAAO,WAAW,wBAAwB,CACtD;AAKF,EAFmB,SAAS,cAAc,WAAW,wBAAwB,CAElE,eAAe,CAAC,SAAS,SAAS;AAC3C,OAAI,KAAK,OAAO,WAAW,mBAAmB,EAAE;IAC9C,MAAM,aAAa,KAAK,cAAc,WAAW,mBAAmB;IACpE,MAAM,WAAW,WAAW,SAAS;IACrC,MAAM,WAAW,WAAW,gBAAgB;AAE5C,QAAI,YAAY,eAAe,IAAI,SAAS,EAAE;KAC5C,MAAM,SAAS,sBAAsB,SAAS;AAC9C,SAAI,OAAO,SAAS,GAAG;MACrB,MAAM,WAAW,MAAM,IAAI,SAAS,oBAAI,IAAI,KAAK;AACjD,aAAO,SAAS,MAAM,SAAS,IAAI,EAAE,CAAC;AACtC,YAAM,IAAI,UAAU,SAAS;AAC7B,YAAM;;;cAGD,KAAK,OAAO,WAAW,4BAA4B,EAAE;IAE9D,MAAM,YAAY,KAAK,cAAc,WAAW,4BAA4B;IAC5E,MAAM,WAAW,UAAU,SAAS;AAEpC,QAAI,eAAe,IAAI,SAAS,EAAE;KAGhC,MAAM,SAAS,sBADE,UAAU,aAAa,CACM;AAC9C,SAAI,OAAO,SAAS,GAAG;MACrB,MAAM,WAAW,MAAM,IAAI,SAAS,oBAAI,IAAI,KAAK;AACjD,aAAO,SAAS,MAAM,SAAS,IAAI,EAAE,CAAC;AACtC,YAAM,IAAI,UAAU,SAAS;AAC7B,YAAM;;;;IAIZ;GACF;AAEF,QAAO"}
@@ -2,6 +2,7 @@
2
2
  const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
3
3
  const require_entryPoints = require('../../../utils/entryPoints.cjs');
4
4
  const require_index = require('../../../motion-tokens/dist/index.cjs');
5
+ const require_hookMetadata = require('../../../runtimeConfig/hookMetadata.cjs');
5
6
  let node_fs = require("node:fs");
6
7
  let node_path = require("node:path");
7
8
  node_path = require_runtime.__toESM(node_path);
@@ -67,6 +68,72 @@ const addPropToVariantKeyMapping = (propToVariantKeys, propName, variantKey) =>
67
68
  const existing = propToVariantKeys.get(propName) ?? [];
68
69
  if (!existing.includes(variantKey)) propToVariantKeys.set(propName, [...existing, variantKey]);
69
70
  };
71
+ const addRuntimeSelector = (target, key, selector) => {
72
+ const existing = target.get(key) ?? [];
73
+ if (!existing.includes(selector)) target.set(key, [...existing, selector]);
74
+ };
75
+ const getExpressionWithoutWrappers = (node) => {
76
+ if (ts_morph.Node.isParenthesizedExpression(node)) return getExpressionWithoutWrappers(node.getExpression());
77
+ if (ts_morph.Node.isAsExpression(node) || ts_morph.Node.isTypeAssertion(node) || ts_morph.Node.isSatisfiesExpression(node)) return getExpressionWithoutWrappers(node.getExpression());
78
+ return node;
79
+ };
80
+ const applyRuntimeSelectorIndex = (selector, indexKey, isIdentifierIndex = false) => {
81
+ if (selector.includes("${")) return selector;
82
+ return isIdentifierIndex ? selector + ".${" + indexKey + "}" : `${selector}.${indexKey}`;
83
+ };
84
+ const resolveRuntimeBindingFromExpression = (expr, runtimeBindings) => {
85
+ const normalized = getExpressionWithoutWrappers(expr);
86
+ if (ts_morph.Node.isIdentifier(normalized)) return runtimeBindings.get(normalized.getText()) ?? null;
87
+ if (ts_morph.Node.isElementAccessExpression(normalized)) {
88
+ const target = resolveRuntimeBindingFromExpression(normalized.getExpression(), runtimeBindings);
89
+ if (!target) return null;
90
+ const argumentExpression = normalized.getArgumentExpression();
91
+ if (!argumentExpression) return null;
92
+ const argument = getExpressionWithoutWrappers(argumentExpression);
93
+ if (ts_morph.Node.isStringLiteral(argument)) return { selector: applyRuntimeSelectorIndex(target.selector, argument.getLiteralValue()) };
94
+ if (ts_morph.Node.isIdentifier(argument)) return { selector: applyRuntimeSelectorIndex(target.selector, argument.getText(), true) };
95
+ }
96
+ if (ts_morph.Node.isPropertyAccessExpression(normalized)) {
97
+ const target = resolveRuntimeBindingFromExpression(normalized.getExpression(), runtimeBindings);
98
+ if (!target) return null;
99
+ return { selector: applyRuntimeSelectorIndex(target.selector, normalized.getName()) };
100
+ }
101
+ return null;
102
+ };
103
+ const collectRuntimeSelectorsFromExpression = (expr, runtimeBindings) => {
104
+ const normalized = getExpressionWithoutWrappers(expr);
105
+ const resolvedBinding = resolveRuntimeBindingFromExpression(normalized, runtimeBindings);
106
+ if (resolvedBinding) return [resolvedBinding.selector];
107
+ if (ts_morph.Node.isConditionalExpression(normalized)) return [...collectRuntimeSelectorsFromExpression(normalized.getWhenTrue(), runtimeBindings), ...collectRuntimeSelectorsFromExpression(normalized.getWhenFalse(), runtimeBindings)];
108
+ if (ts_morph.Node.isBinaryExpression(normalized)) return [...collectRuntimeSelectorsFromExpression(normalized.getLeft(), runtimeBindings), ...collectRuntimeSelectorsFromExpression(normalized.getRight(), runtimeBindings)];
109
+ return [];
110
+ };
111
+ const collectRuntimeConfigBindings = (sourceFile, runtimeBindings, runtimeConfigDefaultProps) => {
112
+ sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.VariableDeclaration).forEach((declaration) => {
113
+ const initializer = declaration.getInitializer();
114
+ if (!initializer) return;
115
+ const normalizedInitializer = getExpressionWithoutWrappers(initializer);
116
+ const nameNode = declaration.getNameNode();
117
+ if (ts_morph.Node.isObjectBindingPattern(nameNode) && ts_morph.Node.isCallExpression(normalizedInitializer)) {
118
+ const hookConfig = require_hookMetadata.getRuntimeHookConfig(normalizedInitializer.getExpression().getText());
119
+ if (!hookConfig) return;
120
+ Object.entries(hookConfig.defaultProps).forEach(([propName, selector]) => {
121
+ runtimeConfigDefaultProps.set(propName, selector);
122
+ });
123
+ nameNode.getElements().forEach((element) => {
124
+ const fieldName = element.getPropertyNameNode()?.getText() ?? element.getName();
125
+ const localName = element.getName();
126
+ const fieldConfig = hookConfig.fields[fieldName];
127
+ if (!fieldConfig) return;
128
+ runtimeBindings.set(localName, { selector: fieldConfig.bindingSelector });
129
+ });
130
+ return;
131
+ }
132
+ if (!ts_morph.Node.isIdentifier(nameNode)) return;
133
+ const resolvedBinding = resolveRuntimeBindingFromExpression(normalizedInitializer, runtimeBindings);
134
+ if (resolvedBinding) runtimeBindings.set(nameNode.getText(), resolvedBinding);
135
+ });
136
+ };
70
137
  const extractFallbackIdentifier = (initializer) => {
71
138
  if (!ts_morph.Node.isBinaryExpression(initializer)) return null;
72
139
  const operatorKind = initializer.getOperatorToken().getKind();
@@ -120,11 +187,16 @@ const analyzeComponent = (project, componentPath) => {
120
187
  const internalComponents = [];
121
188
  const internalComponentProps = /* @__PURE__ */ new Map();
122
189
  const propToVariantKeys = /* @__PURE__ */ new Map();
190
+ const runtimeConfigDefaultProps = /* @__PURE__ */ new Map();
191
+ const runtimeConfigGetStyles = /* @__PURE__ */ new Map();
192
+ const runtimeConfigInternalComponentProps = /* @__PURE__ */ new Map();
193
+ const runtimeBindings = /* @__PURE__ */ new Map();
123
194
  collectComponentDefaultsAndProps(sourceFile, defaultProps, componentPropNames);
124
- collectGetStylesMetadata(sourceFile, styleProps, getStylesLiterals, propToVariantKeys);
195
+ collectRuntimeConfigBindings(sourceFile, runtimeBindings, runtimeConfigDefaultProps);
196
+ collectGetStylesMetadata(sourceFile, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles);
125
197
  collectCxLiterals(sourceFile, cxLiterals);
126
198
  collectIntrinsicClassNameLiterals(sourceFile, cxLiterals);
127
- extractInternalComponents(sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentPropNames);
199
+ extractInternalComponents(sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentPropNames, runtimeBindings);
128
200
  return {
129
201
  name: componentName,
130
202
  filePath: componentPath,
@@ -135,6 +207,9 @@ const analyzeComponent = (project, componentPath) => {
135
207
  internalComponents,
136
208
  internalComponentProps,
137
209
  propToVariantKeys,
210
+ runtimeConfigDefaultProps,
211
+ runtimeConfigGetStyles,
212
+ runtimeConfigInternalComponentProps,
138
213
  motionVarPrefixes: extractMotionVarPrefixes(sourceFile)
139
214
  };
140
215
  };
@@ -175,20 +250,23 @@ const storeVariantLiteralValues = (variantKey, literalValues, getStylesLiterals)
175
250
  getStylesLiterals.set(literalKey, value);
176
251
  });
177
252
  };
178
- const handleGetStylesPropertyAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys) => {
253
+ const handleGetStylesPropertyAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles) => {
179
254
  const variantKey = prop.getName();
180
255
  addStyleProp(styleProps, variantKey);
181
256
  const initializer = prop.getInitializer();
182
257
  if (!initializer) return;
183
258
  if (ts_morph.Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
184
259
  if (ts_morph.Node.isIdentifier(initializer)) addPropToVariantKeyMapping(propToVariantKeys, initializer.getText(), variantKey);
260
+ collectRuntimeSelectorsFromExpression(initializer, runtimeBindings).forEach((selector) => {
261
+ addRuntimeSelector(runtimeConfigGetStyles, variantKey, selector);
262
+ });
185
263
  const fallbackIdentifier = extractFallbackIdentifier(initializer);
186
264
  if (fallbackIdentifier) addPropToVariantKeyMapping(propToVariantKeys, fallbackIdentifier, variantKey);
187
265
  if (ts_morph.Node.isConditionalExpression(initializer)) storeVariantLiteralValues(variantKey, [...extractConditionalStringLiterals(initializer.getWhenTrue()), ...extractConditionalStringLiterals(initializer.getWhenFalse())], getStylesLiterals);
188
266
  };
189
- const handleGetStylesObjectProperty = (prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile) => {
267
+ const handleGetStylesObjectProperty = (prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile, runtimeBindings, runtimeConfigGetStyles) => {
190
268
  if (ts_morph.Node.isPropertyAssignment(prop)) {
191
- handleGetStylesPropertyAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys);
269
+ handleGetStylesPropertyAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles);
192
270
  return;
193
271
  }
194
272
  if (ts_morph.Node.isShorthandPropertyAssignment(prop)) {
@@ -200,12 +278,12 @@ const handleGetStylesObjectProperty = (prop, styleProps, getStylesLiterals, prop
200
278
  if (objectLiteral) analyzeObjectForVariantMappings(objectLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
201
279
  }
202
280
  };
203
- const collectGetStylesMetadata = (sourceFile, styleProps, getStylesLiterals, propToVariantKeys) => {
281
+ const collectGetStylesMetadata = (sourceFile, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles) => {
204
282
  sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "getStyles").forEach((call) => {
205
283
  const args = call.getArguments();
206
284
  if (args.length === 0 || !ts_morph.Node.isObjectLiteralExpression(args[0])) return;
207
285
  args[0].getProperties().forEach((prop) => {
208
- handleGetStylesObjectProperty(prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
286
+ handleGetStylesObjectProperty(prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile, runtimeBindings, runtimeConfigGetStyles);
209
287
  });
210
288
  });
211
289
  };
@@ -241,9 +319,9 @@ const collectIntrinsicClassNameLiterals = (sourceFile, cxLiterals) => {
241
319
  * Extract UDS components used internally in the file and their prop values.
242
320
  * Also detects prop aliasing (e.g., columnGap={gap} means gap -> columnGap).
243
321
  */
244
- const extractInternalComponents = (sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps) => {
322
+ const extractInternalComponents = (sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings) => {
245
323
  collectImportedInternalComponents(sourceFile, internalComponents);
246
- collectInternalComponentUsages(sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps);
324
+ collectInternalComponentUsages(sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings);
247
325
  };
248
326
  const isInternalUdsModule = (moduleSpec) => {
249
327
  return (moduleSpec.startsWith("@yahoo/uds") || moduleSpec.startsWith("../") || moduleSpec.startsWith("./")) && (moduleSpec.includes("/components/") || moduleSpec === "@yahoo/uds");
@@ -294,12 +372,23 @@ const extractJsxAttributeLiteralValues = (attr, componentProps, propToVariantKey
294
372
  values: []
295
373
  };
296
374
  };
297
- const collectInternalComponentUsages = (sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps) => {
375
+ const collectInternalComponentUsages = (sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings) => {
298
376
  [...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(ts_morph.SyntaxKind.JsxOpeningElement)].forEach((element) => {
299
377
  const tagName = element.getTagNameNode().getText();
300
378
  if (!/^[A-Z]/.test(tagName)) return;
301
379
  pushUniqueComponentName(internalComponents, tagName);
302
380
  element.getAttributes().forEach((attr) => {
381
+ if (ts_morph.Node.isJsxAttribute(attr)) {
382
+ const initializer = attr.getInitializer();
383
+ const expression = initializer && ts_morph.Node.isJsxExpression(initializer) ? initializer.getExpression() : void 0;
384
+ const runtimeSelectors = expression ? collectRuntimeSelectorsFromExpression(expression, runtimeBindings) : [];
385
+ if (runtimeSelectors.length > 0) {
386
+ const runtimePropsMap = getOrCreateComponentPropsMap(runtimeConfigInternalComponentProps, tagName);
387
+ const runtimePropName = attr.getNameNode().getText();
388
+ const existingRuntimeSelectors = runtimePropsMap.get(runtimePropName) ?? [];
389
+ runtimePropsMap.set(runtimePropName, [...new Set([...existingRuntimeSelectors, ...runtimeSelectors])]);
390
+ }
391
+ }
303
392
  const extracted = extractJsxAttributeLiteralValues(attr, componentProps, propToVariantKeys);
304
393
  if (!extracted || extracted.values.length === 0) return;
305
394
  const componentPropsMap = getOrCreateComponentPropsMap(internalComponentProps, tagName);
@@ -1,6 +1,7 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Tailwind and Purger v0.0.0-development */
2
2
  import { getAllowedEntryFileGlobPatterns, stripAllowedEntryFileExtension } from "../../../utils/entryPoints.js";
3
3
  import { SPRING_MOTION_DEFAULTS } from "../../../motion-tokens/dist/index.js";
4
+ import { getRuntimeHookConfig } from "../../../runtimeConfig/hookMetadata.js";
4
5
  import { existsSync } from "node:fs";
5
6
  import path from "node:path";
6
7
  import fg from "fast-glob";
@@ -64,6 +65,72 @@ const addPropToVariantKeyMapping = (propToVariantKeys, propName, variantKey) =>
64
65
  const existing = propToVariantKeys.get(propName) ?? [];
65
66
  if (!existing.includes(variantKey)) propToVariantKeys.set(propName, [...existing, variantKey]);
66
67
  };
68
+ const addRuntimeSelector = (target, key, selector) => {
69
+ const existing = target.get(key) ?? [];
70
+ if (!existing.includes(selector)) target.set(key, [...existing, selector]);
71
+ };
72
+ const getExpressionWithoutWrappers = (node) => {
73
+ if (Node.isParenthesizedExpression(node)) return getExpressionWithoutWrappers(node.getExpression());
74
+ if (Node.isAsExpression(node) || Node.isTypeAssertion(node) || Node.isSatisfiesExpression(node)) return getExpressionWithoutWrappers(node.getExpression());
75
+ return node;
76
+ };
77
+ const applyRuntimeSelectorIndex = (selector, indexKey, isIdentifierIndex = false) => {
78
+ if (selector.includes("${")) return selector;
79
+ return isIdentifierIndex ? selector + ".${" + indexKey + "}" : `${selector}.${indexKey}`;
80
+ };
81
+ const resolveRuntimeBindingFromExpression = (expr, runtimeBindings) => {
82
+ const normalized = getExpressionWithoutWrappers(expr);
83
+ if (Node.isIdentifier(normalized)) return runtimeBindings.get(normalized.getText()) ?? null;
84
+ if (Node.isElementAccessExpression(normalized)) {
85
+ const target = resolveRuntimeBindingFromExpression(normalized.getExpression(), runtimeBindings);
86
+ if (!target) return null;
87
+ const argumentExpression = normalized.getArgumentExpression();
88
+ if (!argumentExpression) return null;
89
+ const argument = getExpressionWithoutWrappers(argumentExpression);
90
+ if (Node.isStringLiteral(argument)) return { selector: applyRuntimeSelectorIndex(target.selector, argument.getLiteralValue()) };
91
+ if (Node.isIdentifier(argument)) return { selector: applyRuntimeSelectorIndex(target.selector, argument.getText(), true) };
92
+ }
93
+ if (Node.isPropertyAccessExpression(normalized)) {
94
+ const target = resolveRuntimeBindingFromExpression(normalized.getExpression(), runtimeBindings);
95
+ if (!target) return null;
96
+ return { selector: applyRuntimeSelectorIndex(target.selector, normalized.getName()) };
97
+ }
98
+ return null;
99
+ };
100
+ const collectRuntimeSelectorsFromExpression = (expr, runtimeBindings) => {
101
+ const normalized = getExpressionWithoutWrappers(expr);
102
+ const resolvedBinding = resolveRuntimeBindingFromExpression(normalized, runtimeBindings);
103
+ if (resolvedBinding) return [resolvedBinding.selector];
104
+ if (Node.isConditionalExpression(normalized)) return [...collectRuntimeSelectorsFromExpression(normalized.getWhenTrue(), runtimeBindings), ...collectRuntimeSelectorsFromExpression(normalized.getWhenFalse(), runtimeBindings)];
105
+ if (Node.isBinaryExpression(normalized)) return [...collectRuntimeSelectorsFromExpression(normalized.getLeft(), runtimeBindings), ...collectRuntimeSelectorsFromExpression(normalized.getRight(), runtimeBindings)];
106
+ return [];
107
+ };
108
+ const collectRuntimeConfigBindings = (sourceFile, runtimeBindings, runtimeConfigDefaultProps) => {
109
+ sourceFile.getDescendantsOfKind(SyntaxKind.VariableDeclaration).forEach((declaration) => {
110
+ const initializer = declaration.getInitializer();
111
+ if (!initializer) return;
112
+ const normalizedInitializer = getExpressionWithoutWrappers(initializer);
113
+ const nameNode = declaration.getNameNode();
114
+ if (Node.isObjectBindingPattern(nameNode) && Node.isCallExpression(normalizedInitializer)) {
115
+ const hookConfig = getRuntimeHookConfig(normalizedInitializer.getExpression().getText());
116
+ if (!hookConfig) return;
117
+ Object.entries(hookConfig.defaultProps).forEach(([propName, selector]) => {
118
+ runtimeConfigDefaultProps.set(propName, selector);
119
+ });
120
+ nameNode.getElements().forEach((element) => {
121
+ const fieldName = element.getPropertyNameNode()?.getText() ?? element.getName();
122
+ const localName = element.getName();
123
+ const fieldConfig = hookConfig.fields[fieldName];
124
+ if (!fieldConfig) return;
125
+ runtimeBindings.set(localName, { selector: fieldConfig.bindingSelector });
126
+ });
127
+ return;
128
+ }
129
+ if (!Node.isIdentifier(nameNode)) return;
130
+ const resolvedBinding = resolveRuntimeBindingFromExpression(normalizedInitializer, runtimeBindings);
131
+ if (resolvedBinding) runtimeBindings.set(nameNode.getText(), resolvedBinding);
132
+ });
133
+ };
67
134
  const extractFallbackIdentifier = (initializer) => {
68
135
  if (!Node.isBinaryExpression(initializer)) return null;
69
136
  const operatorKind = initializer.getOperatorToken().getKind();
@@ -117,11 +184,16 @@ const analyzeComponent = (project, componentPath) => {
117
184
  const internalComponents = [];
118
185
  const internalComponentProps = /* @__PURE__ */ new Map();
119
186
  const propToVariantKeys = /* @__PURE__ */ new Map();
187
+ const runtimeConfigDefaultProps = /* @__PURE__ */ new Map();
188
+ const runtimeConfigGetStyles = /* @__PURE__ */ new Map();
189
+ const runtimeConfigInternalComponentProps = /* @__PURE__ */ new Map();
190
+ const runtimeBindings = /* @__PURE__ */ new Map();
120
191
  collectComponentDefaultsAndProps(sourceFile, defaultProps, componentPropNames);
121
- collectGetStylesMetadata(sourceFile, styleProps, getStylesLiterals, propToVariantKeys);
192
+ collectRuntimeConfigBindings(sourceFile, runtimeBindings, runtimeConfigDefaultProps);
193
+ collectGetStylesMetadata(sourceFile, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles);
122
194
  collectCxLiterals(sourceFile, cxLiterals);
123
195
  collectIntrinsicClassNameLiterals(sourceFile, cxLiterals);
124
- extractInternalComponents(sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentPropNames);
196
+ extractInternalComponents(sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentPropNames, runtimeBindings);
125
197
  return {
126
198
  name: componentName,
127
199
  filePath: componentPath,
@@ -132,6 +204,9 @@ const analyzeComponent = (project, componentPath) => {
132
204
  internalComponents,
133
205
  internalComponentProps,
134
206
  propToVariantKeys,
207
+ runtimeConfigDefaultProps,
208
+ runtimeConfigGetStyles,
209
+ runtimeConfigInternalComponentProps,
135
210
  motionVarPrefixes: extractMotionVarPrefixes(sourceFile)
136
211
  };
137
212
  };
@@ -172,20 +247,23 @@ const storeVariantLiteralValues = (variantKey, literalValues, getStylesLiterals)
172
247
  getStylesLiterals.set(literalKey, value);
173
248
  });
174
249
  };
175
- const handleGetStylesPropertyAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys) => {
250
+ const handleGetStylesPropertyAssignment = (prop, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles) => {
176
251
  const variantKey = prop.getName();
177
252
  addStyleProp(styleProps, variantKey);
178
253
  const initializer = prop.getInitializer();
179
254
  if (!initializer) return;
180
255
  if (Node.isStringLiteral(initializer)) getStylesLiterals.set(variantKey, initializer.getLiteralValue());
181
256
  if (Node.isIdentifier(initializer)) addPropToVariantKeyMapping(propToVariantKeys, initializer.getText(), variantKey);
257
+ collectRuntimeSelectorsFromExpression(initializer, runtimeBindings).forEach((selector) => {
258
+ addRuntimeSelector(runtimeConfigGetStyles, variantKey, selector);
259
+ });
182
260
  const fallbackIdentifier = extractFallbackIdentifier(initializer);
183
261
  if (fallbackIdentifier) addPropToVariantKeyMapping(propToVariantKeys, fallbackIdentifier, variantKey);
184
262
  if (Node.isConditionalExpression(initializer)) storeVariantLiteralValues(variantKey, [...extractConditionalStringLiterals(initializer.getWhenTrue()), ...extractConditionalStringLiterals(initializer.getWhenFalse())], getStylesLiterals);
185
263
  };
186
- const handleGetStylesObjectProperty = (prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile) => {
264
+ const handleGetStylesObjectProperty = (prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile, runtimeBindings, runtimeConfigGetStyles) => {
187
265
  if (Node.isPropertyAssignment(prop)) {
188
- handleGetStylesPropertyAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys);
266
+ handleGetStylesPropertyAssignment(prop, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles);
189
267
  return;
190
268
  }
191
269
  if (Node.isShorthandPropertyAssignment(prop)) {
@@ -197,12 +275,12 @@ const handleGetStylesObjectProperty = (prop, styleProps, getStylesLiterals, prop
197
275
  if (objectLiteral) analyzeObjectForVariantMappings(objectLiteral, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
198
276
  }
199
277
  };
200
- const collectGetStylesMetadata = (sourceFile, styleProps, getStylesLiterals, propToVariantKeys) => {
278
+ const collectGetStylesMetadata = (sourceFile, styleProps, getStylesLiterals, propToVariantKeys, runtimeBindings, runtimeConfigGetStyles) => {
201
279
  sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression).filter((call) => call.getExpression().getText() === "getStyles").forEach((call) => {
202
280
  const args = call.getArguments();
203
281
  if (args.length === 0 || !Node.isObjectLiteralExpression(args[0])) return;
204
282
  args[0].getProperties().forEach((prop) => {
205
- handleGetStylesObjectProperty(prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile);
283
+ handleGetStylesObjectProperty(prop, styleProps, getStylesLiterals, propToVariantKeys, sourceFile, runtimeBindings, runtimeConfigGetStyles);
206
284
  });
207
285
  });
208
286
  };
@@ -238,9 +316,9 @@ const collectIntrinsicClassNameLiterals = (sourceFile, cxLiterals) => {
238
316
  * Extract UDS components used internally in the file and their prop values.
239
317
  * Also detects prop aliasing (e.g., columnGap={gap} means gap -> columnGap).
240
318
  */
241
- const extractInternalComponents = (sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps) => {
319
+ const extractInternalComponents = (sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings) => {
242
320
  collectImportedInternalComponents(sourceFile, internalComponents);
243
- collectInternalComponentUsages(sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps);
321
+ collectInternalComponentUsages(sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings);
244
322
  };
245
323
  const isInternalUdsModule = (moduleSpec) => {
246
324
  return (moduleSpec.startsWith("@yahoo/uds") || moduleSpec.startsWith("../") || moduleSpec.startsWith("./")) && (moduleSpec.includes("/components/") || moduleSpec === "@yahoo/uds");
@@ -291,12 +369,23 @@ const extractJsxAttributeLiteralValues = (attr, componentProps, propToVariantKey
291
369
  values: []
292
370
  };
293
371
  };
294
- const collectInternalComponentUsages = (sourceFile, internalComponents, internalComponentProps, propToVariantKeys, componentProps) => {
372
+ const collectInternalComponentUsages = (sourceFile, internalComponents, internalComponentProps, runtimeConfigInternalComponentProps, propToVariantKeys, componentProps, runtimeBindings) => {
295
373
  [...sourceFile.getDescendantsOfKind(SyntaxKind.JsxSelfClosingElement), ...sourceFile.getDescendantsOfKind(SyntaxKind.JsxOpeningElement)].forEach((element) => {
296
374
  const tagName = element.getTagNameNode().getText();
297
375
  if (!/^[A-Z]/.test(tagName)) return;
298
376
  pushUniqueComponentName(internalComponents, tagName);
299
377
  element.getAttributes().forEach((attr) => {
378
+ if (Node.isJsxAttribute(attr)) {
379
+ const initializer = attr.getInitializer();
380
+ const expression = initializer && Node.isJsxExpression(initializer) ? initializer.getExpression() : void 0;
381
+ const runtimeSelectors = expression ? collectRuntimeSelectorsFromExpression(expression, runtimeBindings) : [];
382
+ if (runtimeSelectors.length > 0) {
383
+ const runtimePropsMap = getOrCreateComponentPropsMap(runtimeConfigInternalComponentProps, tagName);
384
+ const runtimePropName = attr.getNameNode().getText();
385
+ const existingRuntimeSelectors = runtimePropsMap.get(runtimePropName) ?? [];
386
+ runtimePropsMap.set(runtimePropName, [...new Set([...existingRuntimeSelectors, ...runtimeSelectors])]);
387
+ }
388
+ }
300
389
  const extracted = extractJsxAttributeLiteralValues(attr, componentProps, propToVariantKeys);
301
390
  if (!extracted || extracted.values.length === 0) return;
302
391
  const componentPropsMap = getOrCreateComponentPropsMap(internalComponentProps, tagName);