@yahoo/uds 3.142.0 → 3.143.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 (106) hide show
  1. package/dist/components/client/Popover/UDSPopoverConfigProvider.d.cts +1 -1
  2. package/dist/components/client/Popover/UDSPopoverConfigProvider.d.ts +1 -1
  3. package/dist/styles/styler.d.cts +3 -3
  4. package/dist/styles/styler.d.ts +3 -3
  5. package/dist/tailwind/dist/automated-config/dist/mapTextVariantFixtureToValue.js.map +1 -1
  6. package/dist/tailwind/dist/automated-config/dist/properties.js.map +1 -1
  7. package/dist/tailwind/dist/automated-config/dist/utils/assertUnreachable.js.map +1 -1
  8. package/dist/tailwind/dist/automated-config/dist/utils/generateDefaultClassName.js.map +1 -1
  9. package/dist/tailwind/dist/automated-config/dist/utils/generateSchemaKey.js.map +1 -1
  10. package/dist/tailwind/dist/automated-config/dist/utils/index.js.map +1 -1
  11. package/dist/tailwind/dist/automated-config/dist/utils/mapColorFixtureToValue.js.map +1 -1
  12. package/dist/tailwind/dist/cli/dist/lib/logger.js.map +1 -1
  13. package/dist/tailwind/dist/cli/dist/lib/print.js.map +1 -1
  14. package/dist/tailwind/dist/cli/dist/lib/spinner.js.map +1 -1
  15. package/dist/tailwind/dist/commands/css.helpers.js.map +1 -1
  16. package/dist/tailwind/dist/commands/css.js.map +1 -1
  17. package/dist/tailwind/dist/commands/generateComponentData.js.map +1 -1
  18. package/dist/tailwind/dist/commands/generatePurgeCSSData.js.map +1 -1
  19. package/dist/tailwind/dist/commands/purge.js.map +1 -1
  20. package/dist/tailwind/dist/css/generate.helpers.js.map +1 -1
  21. package/dist/tailwind/dist/css/generate.js.map +1 -1
  22. package/dist/tailwind/dist/css/nodeUtils.js.map +1 -1
  23. package/dist/tailwind/dist/css/perf.js.map +1 -1
  24. package/dist/tailwind/dist/css/postcss.helpers.js.map +1 -1
  25. package/dist/tailwind/dist/css/postcss.js.map +1 -1
  26. package/dist/tailwind/dist/css/purgeWorker.js.map +1 -1
  27. package/dist/tailwind/dist/css/runner.helpers.js.map +1 -1
  28. package/dist/tailwind/dist/css/runner.js.map +1 -1
  29. package/dist/tailwind/dist/css/utils.js.map +1 -1
  30. package/dist/tailwind/dist/css/workerPool.js.map +1 -1
  31. package/dist/tailwind/dist/css-tokens/dist/index.js.map +1 -1
  32. package/dist/tailwind/dist/fixtures/dist/index.cjs +0 -10
  33. package/dist/tailwind/dist/fixtures/dist/index.js +0 -10
  34. package/dist/tailwind/dist/fixtures/dist/index.js.map +1 -1
  35. package/dist/tailwind/dist/modes/dist/index.cjs +1 -0
  36. package/dist/tailwind/dist/modes/dist/index.js +1 -0
  37. package/dist/tailwind/dist/modes/dist/index.js.map +1 -1
  38. package/dist/tailwind/dist/plugin.js.map +1 -1
  39. package/dist/tailwind/dist/purger/legacy/purgeCSS.js.map +1 -1
  40. package/dist/tailwind/dist/purger/legacy/purgeFromCode.js.map +1 -1
  41. package/dist/tailwind/dist/purger/optimized/ast/expressions.js.map +1 -1
  42. package/dist/tailwind/dist/purger/optimized/purge.js.map +1 -1
  43. package/dist/tailwind/dist/purger/optimized/purgeFromCode.js.map +1 -1
  44. package/dist/tailwind/dist/purger/optimized/utils/componentAnalyzer.js.map +1 -1
  45. package/dist/tailwind/dist/purger/optimized/utils/files.js.map +1 -1
  46. package/dist/tailwind/dist/purger/optimized/utils/safelist.js.map +1 -1
  47. package/dist/tailwind/dist/runtimeConfig/hookMetadata.js.map +1 -1
  48. package/dist/tailwind/dist/tailwind/base/addColorModeVars.js.map +1 -1
  49. package/dist/tailwind/dist/tailwind/base/addColorModeVarsV2.js.map +1 -1
  50. package/dist/tailwind/dist/tailwind/base/addFontFaceDeclarations.js.map +1 -1
  51. package/dist/tailwind/dist/tailwind/base/addFontVars.js.map +1 -1
  52. package/dist/tailwind/dist/tailwind/base/addMotionVars.js.map +1 -1
  53. package/dist/tailwind/dist/tailwind/base/addScaleModeVars.js.map +1 -1
  54. package/dist/tailwind/dist/tailwind/components/getFocusRingStyles.js.map +1 -1
  55. package/dist/tailwind/dist/tailwind/components/getHitTargetStyles.js.map +1 -1
  56. package/dist/tailwind/dist/tailwind/components/getIconStyles.js.map +1 -1
  57. package/dist/tailwind/dist/tailwind/components/getInputStyles.js.map +1 -1
  58. package/dist/tailwind/dist/tailwind/components/getResponsiveTextStyles.js.map +1 -1
  59. package/dist/tailwind/dist/tailwind/plugins/a11y.js.map +1 -1
  60. package/dist/tailwind/dist/tailwind/plugins/blurBgFallback.js.map +1 -1
  61. package/dist/tailwind/dist/tailwind/plugins/borderRadius.js.map +1 -1
  62. package/dist/tailwind/dist/tailwind/plugins/borderWidth.js.map +1 -1
  63. package/dist/tailwind/dist/tailwind/plugins/breakpoints.js.map +1 -1
  64. package/dist/tailwind/dist/tailwind/plugins/colors.js.map +1 -1
  65. package/dist/tailwind/dist/tailwind/plugins/components.js.map +1 -1
  66. package/dist/tailwind/dist/tailwind/plugins/elevation.js.map +1 -1
  67. package/dist/tailwind/dist/tailwind/plugins/getTailwindAsUdsColors.js.map +1 -1
  68. package/dist/tailwind/dist/tailwind/plugins/icons.js.map +1 -1
  69. package/dist/tailwind/dist/tailwind/plugins/input.js.map +1 -1
  70. package/dist/tailwind/dist/tailwind/plugins/motion.js.map +1 -1
  71. package/dist/tailwind/dist/tailwind/plugins/nestedBorderRadius.js.map +1 -1
  72. package/dist/tailwind/dist/tailwind/plugins/scaleMode.js.map +1 -1
  73. package/dist/tailwind/dist/tailwind/plugins/shadows.js.map +1 -1
  74. package/dist/tailwind/dist/tailwind/plugins/sizing.js.map +1 -1
  75. package/dist/tailwind/dist/tailwind/plugins/typography.js.map +1 -1
  76. package/dist/tailwind/dist/tailwind/theme/getFontFamilyTheme.js.map +1 -1
  77. package/dist/tailwind/dist/tailwind/utils/addFontsPlugin.js.map +1 -1
  78. package/dist/tailwind/dist/tailwind/utils/composeTailwindPlugins.js.map +1 -1
  79. package/dist/tailwind/dist/tailwind/utils/getColorModeStyles.js.map +1 -1
  80. package/dist/tailwind/dist/tailwind/utils/getElevationStyles.js.map +1 -1
  81. package/dist/tailwind/dist/tailwind/utils/getFontFaceDeclarations.js.map +1 -1
  82. package/dist/tailwind/dist/tailwind/utils/getFontStyles.js.map +1 -1
  83. package/dist/tailwind/dist/tailwind/utils/getMotionStyles.js.map +1 -1
  84. package/dist/tailwind/dist/tailwind/utils/getNestedBorderRadiusUtilities.js.map +1 -1
  85. package/dist/tailwind/dist/tailwind/utils/getScaleModeStyles.js.map +1 -1
  86. package/dist/tailwind/dist/tailwind/utils/getShadowPresetValues.js.map +1 -1
  87. package/dist/tailwind/dist/tailwind/utils/getShadowStyles.js.map +1 -1
  88. package/dist/tailwind/dist/utils/assertUnreachable.js.map +1 -1
  89. package/dist/tailwind/dist/utils/entries.js.map +1 -1
  90. package/dist/tailwind/dist/utils/entryPoints.js.map +1 -1
  91. package/dist/tailwind/dist/utils/fromEntries.js.map +1 -1
  92. package/dist/tailwind/dist/utils/generatePurgeCSSData.js.map +1 -1
  93. package/dist/tailwind/dist/utils/mapValues.js.map +1 -1
  94. package/dist/tailwind/dist/utils/opacity.js.map +1 -1
  95. package/dist/tailwind/dist/utils/optimizeCSS.js.map +1 -1
  96. package/dist/tailwind/dist/utils/parseTokens.js.map +1 -1
  97. package/dist/tailwind/dist/utils/postcssPreserveVars.js.map +1 -1
  98. package/dist/tailwind/dist/utils/tsMorph.js.map +1 -1
  99. package/dist/uds/generated/componentData.cjs +1311 -1311
  100. package/dist/uds/generated/componentData.js +1311 -1311
  101. package/dist/uds/generated/tailwindPurge.cjs +3 -0
  102. package/dist/uds/generated/tailwindPurge.js +3 -0
  103. package/dist/uds/package.cjs +2 -2
  104. package/dist/uds/package.js +2 -2
  105. package/generated/componentData.json +1692 -1692
  106. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"getElevationStyles.js","names":[],"sources":["../../../src/tailwind/utils/getElevationStyles.ts"],"sourcesContent":["import type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport {\n BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX,\n BACKGROUND_BLUR_RADIUS_PREFIX,\n BACKGROUND_COLOR_PREFIX,\n} from '@yahoo/uds-css-tokens';\nimport type { CSSRuleObject } from 'tailwindcss/types/config';\n\nimport { entries } from '../../utils/entries';\nimport { fromEntries } from '../../utils/fromEntries';\nimport { shadowVariantToCSS } from './getShadowStyles';\n\nexport function getElevationStyles({ config }: { config: UniversalTokensConfig }) {\n const styles: CSSRuleObject = fromEntries([\n ...entries(config.elevation).map(([level]) => shadowVariantToCSS('drop', `elevation-${level}`)),\n ...entries(config.elevation).map(([level]) =>\n shadowVariantToCSS('inset', `elevation-${level}`),\n ),\n ]);\n\n entries(config.elevation).forEach(([level]) => {\n styles[`.bg-elevation-${level}`] = {\n // Fallback for browsers that don't support backdrop-filter\n // This will be the same value as `var(--${BACKGROUND_COLOR_PREFIX}-elevation-${level})` unless that color is NOT fully opaque.\n backgroundColor: `var(--${BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX}-elevation-${level})`,\n\n ['@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))']: {\n // Apply the actual background color when backdrop-filter is supported.\n backgroundColor: `var(--${BACKGROUND_COLOR_PREFIX}-elevation-${level})`,\n // NOTE: Order matters! The unprefixed version must come LAST.\n // Chrome treats these as equivalent properties and keeps the last one.\n WebkitBackdropFilter: `var(--${BACKGROUND_BLUR_RADIUS_PREFIX}-elevation-${level})`,\n backdropFilter: `var(--${BACKGROUND_BLUR_RADIUS_PREFIX}-elevation-${level})`,\n },\n };\n });\n\n // For users that prefer reduced transparency in their OS settings\n styles['@media (prefers-reduced-transparency)'] = entries(config.elevation).reduce<CSSRuleObject>(\n (acc, [level]) => {\n acc[`.bg-elevation-${level}`] = {\n backgroundColor: `var(--${BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX}-elevation-${level})`,\n WebkitBackdropFilter: 'none',\n backdropFilter: 'none',\n };\n return acc;\n },\n {},\n );\n\n return styles;\n}\n"],"mappings":";;;;;;AAYA,SAAgB,mBAAmB,EAAE,UAA6C;CAChF,MAAM,SAAwB,YAAY,CACxC,GAAG,QAAQ,OAAO,UAAU,CAAC,KAAK,CAAC,WAAW,mBAAmB,QAAQ,aAAa,QAAQ,CAAC,EAC/F,GAAG,QAAQ,OAAO,UAAU,CAAC,KAAK,CAAC,WACjC,mBAAmB,SAAS,aAAa,QAAQ,CAClD,CACF,CAAC;AAEF,SAAQ,OAAO,UAAU,CAAC,SAAS,CAAC,WAAW;AAC7C,SAAO,iBAAiB,WAAW;GAGjC,iBAAiB,SAAS,sCAAsC,aAAa,MAAM;IAElF,mFAAmF;IAElF,iBAAiB,SAAS,wBAAwB,aAAa,MAAM;IAGrE,sBAAsB,SAAS,8BAA8B,aAAa,MAAM;IAChF,gBAAgB,SAAS,8BAA8B,aAAa,MAAM;IAC3E;GACF;GACD;AAGF,QAAO,2CAA2C,QAAQ,OAAO,UAAU,CAAC,QACzE,KAAK,CAAC,WAAW;AAChB,MAAI,iBAAiB,WAAW;GAC9B,iBAAiB,SAAS,sCAAsC,aAAa,MAAM;GACnF,sBAAsB;GACtB,gBAAgB;GACjB;AACD,SAAO;IAET,EAAE,CACH;AAED,QAAO"}
1
+ {"version":3,"file":"getElevationStyles.js","names":[],"sources":["../../../src/tailwind/utils/getElevationStyles.ts"],"sourcesContent":["import type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport {\n BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX,\n BACKGROUND_BLUR_RADIUS_PREFIX,\n BACKGROUND_COLOR_PREFIX,\n} from '@yahoo/uds-css-tokens';\nimport type { CSSRuleObject } from 'tailwindcss/types/config';\n\nimport { entries } from '../../utils/entries';\nimport { fromEntries } from '../../utils/fromEntries';\nimport { shadowVariantToCSS } from './getShadowStyles';\n\nexport function getElevationStyles({ config }: { config: UniversalTokensConfig }) {\n const styles: CSSRuleObject = fromEntries([\n ...entries(config.elevation).map(([level]) => shadowVariantToCSS('drop', `elevation-${level}`)),\n ...entries(config.elevation).map(([level]) =>\n shadowVariantToCSS('inset', `elevation-${level}`),\n ),\n ]);\n\n entries(config.elevation).forEach(([level]) => {\n styles[`.bg-elevation-${level}`] = {\n // Fallback for browsers that don't support backdrop-filter\n // This will be the same value as `var(--${BACKGROUND_COLOR_PREFIX}-elevation-${level})` unless that color is NOT fully opaque.\n backgroundColor: `var(--${BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX}-elevation-${level})`,\n\n ['@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))']: {\n // Apply the actual background color when backdrop-filter is supported.\n backgroundColor: `var(--${BACKGROUND_COLOR_PREFIX}-elevation-${level})`,\n // NOTE: Order matters! The unprefixed version must come LAST.\n // Chrome treats these as equivalent properties and keeps the last one.\n WebkitBackdropFilter: `var(--${BACKGROUND_BLUR_RADIUS_PREFIX}-elevation-${level})`,\n backdropFilter: `var(--${BACKGROUND_BLUR_RADIUS_PREFIX}-elevation-${level})`,\n },\n };\n });\n\n // For users that prefer reduced transparency in their OS settings\n styles['@media (prefers-reduced-transparency)'] = entries(config.elevation).reduce<CSSRuleObject>(\n (acc, [level]) => {\n acc[`.bg-elevation-${level}`] = {\n backgroundColor: `var(--${BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX}-elevation-${level})`,\n WebkitBackdropFilter: 'none',\n backdropFilter: 'none',\n };\n return acc;\n },\n {},\n );\n\n return styles;\n}\n"],"mappings":";;;;;;AAYA,SAAgB,mBAAmB,EAAE,UAA6C;CAChF,MAAM,SAAwB,YAAY,CACxC,GAAG,QAAQ,OAAO,UAAU,CAAC,KAAK,CAAC,WAAW,mBAAmB,QAAQ,aAAa,QAAQ,CAAC,EAC/F,GAAG,QAAQ,OAAO,UAAU,CAAC,KAAK,CAAC,WACjC,mBAAmB,SAAS,aAAa,QAAQ,CAClD,CACF,CAAC;CAEF,QAAQ,OAAO,UAAU,CAAC,SAAS,CAAC,WAAW;EAC7C,OAAO,iBAAiB,WAAW;GAGjC,iBAAiB,SAAS,sCAAsC,aAAa,MAAM;IAElF,mFAAmF;IAElF,iBAAiB,SAAS,wBAAwB,aAAa,MAAM;IAGrE,sBAAsB,SAAS,8BAA8B,aAAa,MAAM;IAChF,gBAAgB,SAAS,8BAA8B,aAAa,MAAM;IAC3E;GACF;GACD;CAGF,OAAO,2CAA2C,QAAQ,OAAO,UAAU,CAAC,QACzE,KAAK,CAAC,WAAW;EAChB,IAAI,iBAAiB,WAAW;GAC9B,iBAAiB,SAAS,sCAAsC,aAAa,MAAM;GACnF,sBAAsB;GACtB,gBAAgB;GACjB;EACD,OAAO;IAET,EAAE,CACH;CAED,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"getFontFaceDeclarations.js","names":[],"sources":["../../../src/tailwind/utils/getFontFaceDeclarations.ts"],"sourcesContent":["import type { FontID } from '@yahoo/uds-fonts';\nimport { FONT_DECLARATIONS_MAP } from '@yahoo/uds-fonts';\n\n/**\n * Get all font face declarations for a given set of font IDs.\n */\nexport function getFontFaceDeclarations(fontIds: FontID[]) {\n return fontIds.flatMap((fontID) => {\n const { declarations, fontFamily, isVariableFont } = FONT_DECLARATIONS_MAP[fontID];\n return declarations.map((declaration) => {\n const src = isVariableFont\n ? `url('${declaration.src}') format(\"woff2 supports variations\"), url('${declaration.src}') format('woff2-variations')`\n : `url('${declaration.src}') format('woff2')`;\n\n return { fontFamily, fontDisplay: 'swap', ...declaration, src };\n });\n });\n}\n"],"mappings":";;;;;;AAMA,SAAgB,wBAAwB,SAAmB;AACzD,QAAO,QAAQ,SAAS,WAAW;EACjC,MAAM,EAAE,cAAc,YAAY,mBAAmB,sBAAsB;AAC3E,SAAO,aAAa,KAAK,gBAAgB;GACvC,MAAM,MAAM,iBACR,QAAQ,YAAY,IAAI,+CAA+C,YAAY,IAAI,iCACvF,QAAQ,YAAY,IAAI;AAE5B,UAAO;IAAE;IAAY,aAAa;IAAQ,GAAG;IAAa;IAAK;IAC/D;GACF"}
1
+ {"version":3,"file":"getFontFaceDeclarations.js","names":[],"sources":["../../../src/tailwind/utils/getFontFaceDeclarations.ts"],"sourcesContent":["import type { FontID } from '@yahoo/uds-fonts';\nimport { FONT_DECLARATIONS_MAP } from '@yahoo/uds-fonts';\n\n/**\n * Get all font face declarations for a given set of font IDs.\n */\nexport function getFontFaceDeclarations(fontIds: FontID[]) {\n return fontIds.flatMap((fontID) => {\n const { declarations, fontFamily, isVariableFont } = FONT_DECLARATIONS_MAP[fontID];\n return declarations.map((declaration) => {\n const src = isVariableFont\n ? `url('${declaration.src}') format(\"woff2 supports variations\"), url('${declaration.src}') format('woff2-variations')`\n : `url('${declaration.src}') format('woff2')`;\n\n return { fontFamily, fontDisplay: 'swap', ...declaration, src };\n });\n });\n}\n"],"mappings":";;;;;;AAMA,SAAgB,wBAAwB,SAAmB;CACzD,OAAO,QAAQ,SAAS,WAAW;EACjC,MAAM,EAAE,cAAc,YAAY,mBAAmB,sBAAsB;EAC3E,OAAO,aAAa,KAAK,gBAAgB;GACvC,MAAM,MAAM,iBACR,QAAQ,YAAY,IAAI,+CAA+C,YAAY,IAAI,iCACvF,QAAQ,YAAY,IAAI;GAE5B,OAAO;IAAE;IAAY,aAAa;IAAQ,GAAG;IAAa;IAAK;IAC/D;GACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"getFontStyles.js","names":[],"sources":["../../../src/tailwind/utils/getFontStyles.ts"],"sourcesContent":["import { FONT_FAMILY_PREFIX } from '@yahoo/uds-css-tokens';\nimport type { FontID } from '@yahoo/uds-fonts';\nimport { FONT_DECLARATIONS_MAP } from '@yahoo/uds-fonts';\nimport type { FontConfig } from '@yahoo/uds-types';\n\nimport { entries } from '../../utils/entries';\nimport { fromEntries } from '../../utils/fromEntries';\n\n/**\n * Tailwind does not automatically escape font names for you.\n * If you’re using a font that contains an invalid identifier, wrap it in quotes or escape the invalid characters.\n * @link https://tailwindcss.com/docs/font-family#customizing-your-theme:~:text=Tailwind%20does%20not%20automatically\n */\nfunction escapeFontFamilyName(fontFamily: string) {\n return `\"${fontFamily}\"`;\n}\n\n/**\n * Return CSS variables object based on font config.\n * i.e. { --font-xyz: '\"Font Family 1\", \"Font Family 2\", sans-serif' }\n *\n * @example\n * // 1. Use return value in style prop of an html element to assign font variables at runtime\n *\n * const fontVars = getFontStyles(fontConfig);\n * <body style={fontVars}> {...} </body>\n *\n * // 2. Generate CSS at build time in tailwind plugin via addBase.\n *\n * const fontVars = getFontStyles(fontConfig);\n * addBase(fontVars);\n *\n */\nexport function getFontStyles(fontConfig: Partial<FontConfig>) {\n return fromEntries(\n entries(fontConfig).map(([fontAlias, fontID]) => {\n const cssVar = `--${FONT_FAMILY_PREFIX}-${fontAlias}` as const;\n const font = FONT_DECLARATIONS_MAP[fontID as FontID];\n const value = [font.fontFamily, ...font.fallback].map(escapeFontFamilyName).join(', ');\n return [cssVar, value] as const;\n }),\n );\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAS,qBAAqB,YAAoB;AAChD,QAAO,IAAI,WAAW;;;;;;;;;;;;;;;;;;AAmBxB,SAAgB,cAAc,YAAiC;AAC7D,QAAO,YACL,QAAQ,WAAW,CAAC,KAAK,CAAC,WAAW,YAAY;EAC/C,MAAM,SAAS,KAAK,mBAAmB,GAAG;EAC1C,MAAM,OAAO,sBAAsB;AAEnC,SAAO,CAAC,QADM,CAAC,KAAK,YAAY,GAAG,KAAK,SAAS,CAAC,IAAI,qBAAqB,CAAC,KAAK,KAC5D,CAAC;GACtB,CACH"}
1
+ {"version":3,"file":"getFontStyles.js","names":[],"sources":["../../../src/tailwind/utils/getFontStyles.ts"],"sourcesContent":["import { FONT_FAMILY_PREFIX } from '@yahoo/uds-css-tokens';\nimport type { FontID } from '@yahoo/uds-fonts';\nimport { FONT_DECLARATIONS_MAP } from '@yahoo/uds-fonts';\nimport type { FontConfig } from '@yahoo/uds-types';\n\nimport { entries } from '../../utils/entries';\nimport { fromEntries } from '../../utils/fromEntries';\n\n/**\n * Tailwind does not automatically escape font names for you.\n * If you’re using a font that contains an invalid identifier, wrap it in quotes or escape the invalid characters.\n * @link https://tailwindcss.com/docs/font-family#customizing-your-theme:~:text=Tailwind%20does%20not%20automatically\n */\nfunction escapeFontFamilyName(fontFamily: string) {\n return `\"${fontFamily}\"`;\n}\n\n/**\n * Return CSS variables object based on font config.\n * i.e. { --font-xyz: '\"Font Family 1\", \"Font Family 2\", sans-serif' }\n *\n * @example\n * // 1. Use return value in style prop of an html element to assign font variables at runtime\n *\n * const fontVars = getFontStyles(fontConfig);\n * <body style={fontVars}> {...} </body>\n *\n * // 2. Generate CSS at build time in tailwind plugin via addBase.\n *\n * const fontVars = getFontStyles(fontConfig);\n * addBase(fontVars);\n *\n */\nexport function getFontStyles(fontConfig: Partial<FontConfig>) {\n return fromEntries(\n entries(fontConfig).map(([fontAlias, fontID]) => {\n const cssVar = `--${FONT_FAMILY_PREFIX}-${fontAlias}` as const;\n const font = FONT_DECLARATIONS_MAP[fontID as FontID];\n const value = [font.fontFamily, ...font.fallback].map(escapeFontFamilyName).join(', ');\n return [cssVar, value] as const;\n }),\n );\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAS,qBAAqB,YAAoB;CAChD,OAAO,IAAI,WAAW;;;;;;;;;;;;;;;;;;AAmBxB,SAAgB,cAAc,YAAiC;CAC7D,OAAO,YACL,QAAQ,WAAW,CAAC,KAAK,CAAC,WAAW,YAAY;EAC/C,MAAM,SAAS,KAAK,mBAAmB,GAAG;EAC1C,MAAM,OAAO,sBAAsB;EAEnC,OAAO,CAAC,QADM,CAAC,KAAK,YAAY,GAAG,KAAK,SAAS,CAAC,IAAI,qBAAqB,CAAC,KAAK,KAC5D,CAAC;GACtB,CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"getMotionStyles.js","names":[],"sources":["../../../src/tailwind/utils/getMotionStyles.ts"],"sourcesContent":["import { getMotionVar } from '@yahoo/uds-css-tokens';\nimport { motionSpringConfigOptions } from '@yahoo/uds-fixtures';\nimport type { MotionConfig, MotionCssVar } from '@yahoo/uds-types';\n\nimport { entries } from '../../utils/entries';\nimport { fromEntries } from '../../utils/fromEntries';\n\n/**\n * Return CSS variables object based on the motion config.\n * i.e. { --uds-motion-damped-1--damping: '20.585796264350424' }\n *\n * @example\n * // 1. Use return value in style prop of an html element to assign motion variables at runtime\n *\n * const motionVars = getMotionStyles(motionConfig);\n * <body style={motionVars}> {...} </body>\n *\n * // 2. Generate CSS at build time in tailwind plugin via addBase.\n *\n * const motionVars = getMotionStyles(motionConfig);\n * addBase(motionVars);\n *\n */\nexport function getMotionStyles(motionConfig: MotionConfig) {\n const motionEntries = entries(motionConfig).flatMap(([variant, speeds]) =>\n entries(speeds).flatMap(([speed, config]) => {\n return motionSpringConfigOptions.map((control) => {\n const cssVar = getMotionVar({ variant, speed, control });\n // Keep the unit wrapped in quotes to avoid tailwind from adding units (px/rem)\n return [cssVar, `${config[control]}`];\n });\n }),\n ) as [MotionCssVar, string][];\n\n return fromEntries(motionEntries);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,gBAAgB,cAA4B;AAW1D,QAAO,YAVe,QAAQ,aAAa,CAAC,SAAS,CAAC,SAAS,YAC7D,QAAQ,OAAO,CAAC,SAAS,CAAC,OAAO,YAAY;AAC3C,SAAO,0BAA0B,KAAK,YAAY;AAGhD,UAAO,CAFQ,aAAa;IAAE;IAAS;IAAO;IAAS,CAEzC,EAAE,GAAG,OAAO,WAAW;IACrC;GACF,CAG4B,CAAC"}
1
+ {"version":3,"file":"getMotionStyles.js","names":[],"sources":["../../../src/tailwind/utils/getMotionStyles.ts"],"sourcesContent":["import { getMotionVar } from '@yahoo/uds-css-tokens';\nimport { motionSpringConfigOptions } from '@yahoo/uds-fixtures';\nimport type { MotionConfig, MotionCssVar } from '@yahoo/uds-types';\n\nimport { entries } from '../../utils/entries';\nimport { fromEntries } from '../../utils/fromEntries';\n\n/**\n * Return CSS variables object based on the motion config.\n * i.e. { --uds-motion-damped-1--damping: '20.585796264350424' }\n *\n * @example\n * // 1. Use return value in style prop of an html element to assign motion variables at runtime\n *\n * const motionVars = getMotionStyles(motionConfig);\n * <body style={motionVars}> {...} </body>\n *\n * // 2. Generate CSS at build time in tailwind plugin via addBase.\n *\n * const motionVars = getMotionStyles(motionConfig);\n * addBase(motionVars);\n *\n */\nexport function getMotionStyles(motionConfig: MotionConfig) {\n const motionEntries = entries(motionConfig).flatMap(([variant, speeds]) =>\n entries(speeds).flatMap(([speed, config]) => {\n return motionSpringConfigOptions.map((control) => {\n const cssVar = getMotionVar({ variant, speed, control });\n // Keep the unit wrapped in quotes to avoid tailwind from adding units (px/rem)\n return [cssVar, `${config[control]}`];\n });\n }),\n ) as [MotionCssVar, string][];\n\n return fromEntries(motionEntries);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,gBAAgB,cAA4B;CAW1D,OAAO,YAVe,QAAQ,aAAa,CAAC,SAAS,CAAC,SAAS,YAC7D,QAAQ,OAAO,CAAC,SAAS,CAAC,OAAO,YAAY;EAC3C,OAAO,0BAA0B,KAAK,YAAY;GAGhD,OAAO,CAFQ,aAAa;IAAE;IAAS;IAAO;IAAS,CAEzC,EAAE,GAAG,OAAO,WAAW;IACrC;GACF,CAG4B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"getNestedBorderRadiusUtilities.js","names":[],"sources":["../../../src/tailwind/utils/getNestedBorderRadiusUtilities.ts"],"sourcesContent":["import type { CSSRuleObject } from 'tailwindcss/types/config';\n\n/******************************************************************************\n * Utility Generator\n ******************************************************************************/\n\n/**\n * Generates utility classNames that performs nested border radius calculation.\n * @link https://cloudfour.com/thinks/the-math-behind-nesting-rounded-corners\n * @link https://twitter.com/jh3yy/status/1711729473142018413\n *\n * @example\n * // Use with getStyles\n * <VStack\n * borderRadius=\"md\"\n * spacing=\"2\"\n * nestedBorderRadius={true}\n * >\n * <Item /> // Top corners rounded\n * <Item /> // No rounding\n * <Item /> // Bottom corners rounded\n * </VStack>\n */\nexport const getNestedBorderRadiusUtilities = (): CSSRuleObject => {\n const cssVar = {\n /*\n * Nested Border Radius Formula\n *\n * Purpose: Makes nested elements visually match their parent's curvature\n * while avoiding the \"snake belly\" effect (awkward gaps at edges).\n *\n * Formula: clamp(MIN, PREFERRED, MAX)\n *\n * - MIN: 50% of parent radius\n * Ensures nested elements always maintain some curvature relative to parent,\n * even when spacing is very large. Prevents dropping to 0px which looks abrupt.\n *\n * - PREFERRED: parent-radius - max(spacing, border-width)\n * The mathematically correct inner radius. Uses spacing when available,\n * falls back to border-width for the \"snake belly\" case (no gap).\n *\n * - MAX: 100% of parent radius (safety guard)\n * Prevents nested radius from exceeding parent (impossible geometry).\n * Note: This should never actually trigger since PREFERRED is always ≤ parent,\n * but kept as a defensive guard. Could use max(MIN, PREFERRED) instead.\n *\n * Examples:\n * parent=16px, spacing=4px → clamp(8px, 12px, 16px) = 12px ✓\n * parent=16px, spacing=24px → clamp(8px, -8px, 16px) = 8px ✓ (maintains 50%)\n * parent=16px, spacing=0px → clamp(8px, 15px, 16px) = 15px ✓ (uses border-width)\n * parent=4px, spacing=4px → clamp(2px, 0px, 4px) = 2px ✓ (maintains 50%)\n */\n '--uds-nested-radius':\n 'clamp(calc(var(--uds-nested-border-radius-size, 0px) * 0.5), calc(var(--uds-nested-border-radius-size, 0px) - max(var(--uds-nested-border-radius-spacing, 0px), var(--uds-nested-border-radius-width, 0px))), var(--uds-nested-border-radius-size, 0px))',\n };\n\n const firstStyles = {\n 'border-start-start-radius': 'var(--uds-nested-radius)',\n 'border-start-end-radius': 'var(--uds-nested-radius)',\n };\n\n const lastStyles = {\n 'border-end-start-radius': 'var(--uds-nested-radius)',\n 'border-end-end-radius': 'var(--uds-nested-radius)',\n };\n\n return {\n '.uds-nested-border-radius': {\n ...cssVar,\n '& > *:first-child': {\n ...firstStyles,\n },\n '& > *:last-child': {\n ...lastStyles,\n },\n },\n '.uds-nested-border-radius-first': {\n ...cssVar,\n '& > *:first-child': {\n ...firstStyles,\n },\n },\n '.uds-nested-border-radius-last': {\n ...cssVar,\n '& > *:last-child': {\n ...lastStyles,\n },\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,uCAAsD;CACjE,MAAM,SAAS,EA4Bb,uBACE,4PACH;CAED,MAAM,cAAc;EAClB,6BAA6B;EAC7B,2BAA2B;EAC5B;CAED,MAAM,aAAa;EACjB,2BAA2B;EAC3B,yBAAyB;EAC1B;AAED,QAAO;EACL,6BAA6B;GAC3B,GAAG;GACH,qBAAqB,EACnB,GAAG,aACJ;GACD,oBAAoB,EAClB,GAAG,YACJ;GACF;EACD,mCAAmC;GACjC,GAAG;GACH,qBAAqB,EACnB,GAAG,aACJ;GACF;EACD,kCAAkC;GAChC,GAAG;GACH,oBAAoB,EAClB,GAAG,YACJ;GACF;EACF"}
1
+ {"version":3,"file":"getNestedBorderRadiusUtilities.js","names":[],"sources":["../../../src/tailwind/utils/getNestedBorderRadiusUtilities.ts"],"sourcesContent":["import type { CSSRuleObject } from 'tailwindcss/types/config';\n\n/******************************************************************************\n * Utility Generator\n ******************************************************************************/\n\n/**\n * Generates utility classNames that performs nested border radius calculation.\n * @link https://cloudfour.com/thinks/the-math-behind-nesting-rounded-corners\n * @link https://twitter.com/jh3yy/status/1711729473142018413\n *\n * @example\n * // Use with getStyles\n * <VStack\n * borderRadius=\"md\"\n * spacing=\"2\"\n * nestedBorderRadius={true}\n * >\n * <Item /> // Top corners rounded\n * <Item /> // No rounding\n * <Item /> // Bottom corners rounded\n * </VStack>\n */\nexport const getNestedBorderRadiusUtilities = (): CSSRuleObject => {\n const cssVar = {\n /*\n * Nested Border Radius Formula\n *\n * Purpose: Makes nested elements visually match their parent's curvature\n * while avoiding the \"snake belly\" effect (awkward gaps at edges).\n *\n * Formula: clamp(MIN, PREFERRED, MAX)\n *\n * - MIN: 50% of parent radius\n * Ensures nested elements always maintain some curvature relative to parent,\n * even when spacing is very large. Prevents dropping to 0px which looks abrupt.\n *\n * - PREFERRED: parent-radius - max(spacing, border-width)\n * The mathematically correct inner radius. Uses spacing when available,\n * falls back to border-width for the \"snake belly\" case (no gap).\n *\n * - MAX: 100% of parent radius (safety guard)\n * Prevents nested radius from exceeding parent (impossible geometry).\n * Note: This should never actually trigger since PREFERRED is always ≤ parent,\n * but kept as a defensive guard. Could use max(MIN, PREFERRED) instead.\n *\n * Examples:\n * parent=16px, spacing=4px → clamp(8px, 12px, 16px) = 12px ✓\n * parent=16px, spacing=24px → clamp(8px, -8px, 16px) = 8px ✓ (maintains 50%)\n * parent=16px, spacing=0px → clamp(8px, 15px, 16px) = 15px ✓ (uses border-width)\n * parent=4px, spacing=4px → clamp(2px, 0px, 4px) = 2px ✓ (maintains 50%)\n */\n '--uds-nested-radius':\n 'clamp(calc(var(--uds-nested-border-radius-size, 0px) * 0.5), calc(var(--uds-nested-border-radius-size, 0px) - max(var(--uds-nested-border-radius-spacing, 0px), var(--uds-nested-border-radius-width, 0px))), var(--uds-nested-border-radius-size, 0px))',\n };\n\n const firstStyles = {\n 'border-start-start-radius': 'var(--uds-nested-radius)',\n 'border-start-end-radius': 'var(--uds-nested-radius)',\n };\n\n const lastStyles = {\n 'border-end-start-radius': 'var(--uds-nested-radius)',\n 'border-end-end-radius': 'var(--uds-nested-radius)',\n };\n\n return {\n '.uds-nested-border-radius': {\n ...cssVar,\n '& > *:first-child': {\n ...firstStyles,\n },\n '& > *:last-child': {\n ...lastStyles,\n },\n },\n '.uds-nested-border-radius-first': {\n ...cssVar,\n '& > *:first-child': {\n ...firstStyles,\n },\n },\n '.uds-nested-border-radius-last': {\n ...cssVar,\n '& > *:last-child': {\n ...lastStyles,\n },\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAa,uCAAsD;CACjE,MAAM,SAAS,EA4Bb,uBACE,4PACH;CAED,MAAM,cAAc;EAClB,6BAA6B;EAC7B,2BAA2B;EAC5B;CAED,MAAM,aAAa;EACjB,2BAA2B;EAC3B,yBAAyB;EAC1B;CAED,OAAO;EACL,6BAA6B;GAC3B,GAAG;GACH,qBAAqB,EACnB,GAAG,aACJ;GACD,oBAAoB,EAClB,GAAG,YACJ;GACF;EACD,mCAAmC;GACjC,GAAG;GACH,qBAAqB,EACnB,GAAG,aACJ;GACF;EACD,kCAAkC;GAChC,GAAG;GACH,oBAAoB,EAClB,GAAG,YACJ;GACF;EACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"getScaleModeStyles.js","names":[],"sources":["../../../src/tailwind/utils/getScaleModeStyles.ts"],"sourcesContent":["import type { ScaleMode } from '@yahoo/uds-types';\n\nimport type { WebTokens } from '../../utils/parseTokens';\n\nfunction getStylesForScaleMode(config: WebTokens['scaleMode'][ScaleMode]) {\n return {\n ...config.borderRadius._vars,\n ...config.borderWidth._vars,\n ...config.avatarSizes._vars,\n ...config.iconSizes._vars,\n };\n}\n\nexport function getScaleModeStyles(tokens: WebTokens) {\n return {\n xSmall: getStylesForScaleMode(tokens.scaleMode.xSmall),\n small: getStylesForScaleMode(tokens.scaleMode.small),\n medium: getStylesForScaleMode(tokens.scaleMode.medium),\n large: getStylesForScaleMode(tokens.scaleMode.large),\n xLarge: getStylesForScaleMode(tokens.scaleMode.xLarge),\n xxLarge: getStylesForScaleMode(tokens.scaleMode.xxLarge),\n xxxLarge: getStylesForScaleMode(tokens.scaleMode.xxxLarge),\n };\n}\n"],"mappings":";;AAIA,SAAS,sBAAsB,QAA2C;AACxE,QAAO;EACL,GAAG,OAAO,aAAa;EACvB,GAAG,OAAO,YAAY;EACtB,GAAG,OAAO,YAAY;EACtB,GAAG,OAAO,UAAU;EACrB;;AAGH,SAAgB,mBAAmB,QAAmB;AACpD,QAAO;EACL,QAAQ,sBAAsB,OAAO,UAAU,OAAO;EACtD,OAAO,sBAAsB,OAAO,UAAU,MAAM;EACpD,QAAQ,sBAAsB,OAAO,UAAU,OAAO;EACtD,OAAO,sBAAsB,OAAO,UAAU,MAAM;EACpD,QAAQ,sBAAsB,OAAO,UAAU,OAAO;EACtD,SAAS,sBAAsB,OAAO,UAAU,QAAQ;EACxD,UAAU,sBAAsB,OAAO,UAAU,SAAS;EAC3D"}
1
+ {"version":3,"file":"getScaleModeStyles.js","names":[],"sources":["../../../src/tailwind/utils/getScaleModeStyles.ts"],"sourcesContent":["import type { ScaleMode } from '@yahoo/uds-types';\n\nimport type { WebTokens } from '../../utils/parseTokens';\n\nfunction getStylesForScaleMode(config: WebTokens['scaleMode'][ScaleMode]) {\n return {\n ...config.borderRadius._vars,\n ...config.borderWidth._vars,\n ...config.avatarSizes._vars,\n ...config.iconSizes._vars,\n };\n}\n\nexport function getScaleModeStyles(tokens: WebTokens) {\n return {\n xSmall: getStylesForScaleMode(tokens.scaleMode.xSmall),\n small: getStylesForScaleMode(tokens.scaleMode.small),\n medium: getStylesForScaleMode(tokens.scaleMode.medium),\n large: getStylesForScaleMode(tokens.scaleMode.large),\n xLarge: getStylesForScaleMode(tokens.scaleMode.xLarge),\n xxLarge: getStylesForScaleMode(tokens.scaleMode.xxLarge),\n xxxLarge: getStylesForScaleMode(tokens.scaleMode.xxxLarge),\n };\n}\n"],"mappings":";;AAIA,SAAS,sBAAsB,QAA2C;CACxE,OAAO;EACL,GAAG,OAAO,aAAa;EACvB,GAAG,OAAO,YAAY;EACtB,GAAG,OAAO,YAAY;EACtB,GAAG,OAAO,UAAU;EACrB;;AAGH,SAAgB,mBAAmB,QAAmB;CACpD,OAAO;EACL,QAAQ,sBAAsB,OAAO,UAAU,OAAO;EACtD,OAAO,sBAAsB,OAAO,UAAU,MAAM;EACpD,QAAQ,sBAAsB,OAAO,UAAU,OAAO;EACtD,OAAO,sBAAsB,OAAO,UAAU,MAAM;EACpD,QAAQ,sBAAsB,OAAO,UAAU,OAAO;EACtD,SAAS,sBAAsB,OAAO,UAAU,QAAQ;EACxD,UAAU,sBAAsB,OAAO,UAAU,SAAS;EAC3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"getShadowPresetValues.js","names":[],"sources":["../../../src/tailwind/utils/getShadowPresetValues.ts"],"sourcesContent":["import type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport { getShadowLayerValue } from '@yahoo/uds-css-tokens';\nimport type { ShadowType } from '@yahoo/uds-types';\n\nimport { entries } from '../../utils/entries';\n// Import directly from source to avoid circular dependency:\n// getShadowPresetValues -> @yahoo/uds/tokens -> automation -> getShadowPresetValues\n\n/**\n * Generate shadow values from the shadow config presets.\n * Each size can have multiple shadow presets that are combined into a single box-shadow.\n *\n * For regular shadows:\n * - Uses the outer shadow configuration from the shadow config\n * - Uses CSS variables with the --uds-shadow-* prefix for shadow properties\n * - The first shadow uses default variable names, subsequent shadows are numbered (e.g. --uds-shadow-2-*)\n * - Shadow colors are scoped to the element, allowing for instance-specific colors\n *\n * For inset shadows:\n * - Uses the inner shadow configuration from the shadow config\n * - Uses CSS variables with the --uds-inset-shadow-* prefix for shadow properties\n * - Adds the 'inset' keyword to each shadow value\n * - Shadow colors are scoped to the element, allowing for instance-specific colors\n *\n * This approach ensures that both regular and inset shadows use the correct CSS variables\n * set by the shadow utilities, while allowing for instance-specific color customization.\n * The separation of variable namespaces allows both shadow types to be used together on the same element.\n *\n * When both shadow and inset-shadow utilities are used together on an element,\n * they combine to create a box-shadow with both outer and inner shadows.\n *\n * @returns A record of shadow values by size (xs, sm, md, etc.)\n */\nfunction getShadowPresetValues({\n config,\n shadowType,\n}: {\n config: UniversalTokensConfig;\n shadowType: ShadowType;\n}) {\n const presets = config?.shadow?.[shadowType];\n\n // Bail fast if no presets\n if (!presets) {\n return {};\n }\n\n const result: Record<string, string> = {};\n\n // Process shadows\n entries(presets).forEach(([key, presetArray]) => {\n // Special case for none - always use transparent shadow to avoid breaking combined box-shadows\n if (key === 'none') {\n result[`--uds-${shadowType}-shadow-${key}`] = '0 0 transparent';\n return;\n }\n\n const shadowValues = presetArray.map((preset, index) =>\n getShadowLayerValue({ preset, prefix: index > 0 ? `${index + 1}` : undefined, shadowType }),\n );\n\n // Join the shadow values with the appropriate separator\n // For inset shadows, we ensure each shadow has the 'inset' keyword\n result[`--uds-${shadowType}-shadow-${key}`] = `${shadowValues.join(', ')}`;\n });\n\n return result;\n}\n\nexport { getShadowPresetValues };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAS,sBAAsB,EAC7B,QACA,cAIC;CACD,MAAM,UAAU,QAAQ,SAAS;AAGjC,KAAI,CAAC,QACH,QAAO,EAAE;CAGX,MAAM,SAAiC,EAAE;AAGzC,SAAQ,QAAQ,CAAC,SAAS,CAAC,KAAK,iBAAiB;AAE/C,MAAI,QAAQ,QAAQ;AAClB,UAAO,SAAS,WAAW,UAAU,SAAS;AAC9C;;EAGF,MAAM,eAAe,YAAY,KAAK,QAAQ,UAC5C,oBAAoB;GAAE;GAAQ,QAAQ,QAAQ,IAAI,GAAG,QAAQ,MAAM,KAAA;GAAW;GAAY,CAAC,CAC5F;AAID,SAAO,SAAS,WAAW,UAAU,SAAS,GAAG,aAAa,KAAK,KAAK;GACxE;AAEF,QAAO"}
1
+ {"version":3,"file":"getShadowPresetValues.js","names":[],"sources":["../../../src/tailwind/utils/getShadowPresetValues.ts"],"sourcesContent":["import type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport { getShadowLayerValue } from '@yahoo/uds-css-tokens';\nimport type { ShadowType } from '@yahoo/uds-types';\n\nimport { entries } from '../../utils/entries';\n// Import directly from source to avoid circular dependency:\n// getShadowPresetValues -> @yahoo/uds/tokens -> automation -> getShadowPresetValues\n\n/**\n * Generate shadow values from the shadow config presets.\n * Each size can have multiple shadow presets that are combined into a single box-shadow.\n *\n * For regular shadows:\n * - Uses the outer shadow configuration from the shadow config\n * - Uses CSS variables with the --uds-shadow-* prefix for shadow properties\n * - The first shadow uses default variable names, subsequent shadows are numbered (e.g. --uds-shadow-2-*)\n * - Shadow colors are scoped to the element, allowing for instance-specific colors\n *\n * For inset shadows:\n * - Uses the inner shadow configuration from the shadow config\n * - Uses CSS variables with the --uds-inset-shadow-* prefix for shadow properties\n * - Adds the 'inset' keyword to each shadow value\n * - Shadow colors are scoped to the element, allowing for instance-specific colors\n *\n * This approach ensures that both regular and inset shadows use the correct CSS variables\n * set by the shadow utilities, while allowing for instance-specific color customization.\n * The separation of variable namespaces allows both shadow types to be used together on the same element.\n *\n * When both shadow and inset-shadow utilities are used together on an element,\n * they combine to create a box-shadow with both outer and inner shadows.\n *\n * @returns A record of shadow values by size (xs, sm, md, etc.)\n */\nfunction getShadowPresetValues({\n config,\n shadowType,\n}: {\n config: UniversalTokensConfig;\n shadowType: ShadowType;\n}) {\n const presets = config?.shadow?.[shadowType];\n\n // Bail fast if no presets\n if (!presets) {\n return {};\n }\n\n const result: Record<string, string> = {};\n\n // Process shadows\n entries(presets).forEach(([key, presetArray]) => {\n // Special case for none - always use transparent shadow to avoid breaking combined box-shadows\n if (key === 'none') {\n result[`--uds-${shadowType}-shadow-${key}`] = '0 0 transparent';\n return;\n }\n\n const shadowValues = presetArray.map((preset, index) =>\n getShadowLayerValue({ preset, prefix: index > 0 ? `${index + 1}` : undefined, shadowType }),\n );\n\n // Join the shadow values with the appropriate separator\n // For inset shadows, we ensure each shadow has the 'inset' keyword\n result[`--uds-${shadowType}-shadow-${key}`] = `${shadowValues.join(', ')}`;\n });\n\n return result;\n}\n\nexport { getShadowPresetValues };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAS,sBAAsB,EAC7B,QACA,cAIC;CACD,MAAM,UAAU,QAAQ,SAAS;CAGjC,IAAI,CAAC,SACH,OAAO,EAAE;CAGX,MAAM,SAAiC,EAAE;CAGzC,QAAQ,QAAQ,CAAC,SAAS,CAAC,KAAK,iBAAiB;EAE/C,IAAI,QAAQ,QAAQ;GAClB,OAAO,SAAS,WAAW,UAAU,SAAS;GAC9C;;EAGF,MAAM,eAAe,YAAY,KAAK,QAAQ,UAC5C,oBAAoB;GAAE;GAAQ,QAAQ,QAAQ,IAAI,GAAG,QAAQ,MAAM,KAAA;GAAW;GAAY,CAAC,CAC5F;EAID,OAAO,SAAS,WAAW,UAAU,SAAS,GAAG,aAAa,KAAK,KAAK;GACxE;CAEF,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"getShadowStyles.js","names":[],"sources":["../../../src/tailwind/utils/getShadowStyles.ts"],"sourcesContent":["import type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport { DROP_SHADOW_PREFIX, UDS_PREFIX } from '@yahoo/uds-css-tokens';\nimport type { ElevationAlias, ShadowType, ShadowVariant } from '@yahoo/uds-types';\n\nimport { entries } from '../../utils/entries';\nimport { fromEntries } from '../../utils/fromEntries';\n\nconst shadowVariantToCSS = (\n shadowType: ShadowType,\n shadowVariant: ShadowVariant | ElevationAlias,\n) => {\n return [\n `.uds-${shadowType}-shadow-${shadowVariant}`,\n {\n [`--${UDS_PREFIX}-${shadowType}-shadow`]: `var(--${UDS_PREFIX}-${shadowType}-shadow-${shadowVariant})`,\n boxShadow: `var(--${DROP_SHADOW_PREFIX}, 0 0 transparent), var(--${UDS_PREFIX}-inset-shadow, 0 0 transparent), var(--tw-ring-offset-shadow, 0 0 transparent), var(--tw-ring-shadow, 0 0 transparent), var(--tw-shadow, 0 0 transparent)`,\n },\n ] as const;\n};\n\nfunction getShadowStyles({\n config,\n shadowType,\n}: {\n config: UniversalTokensConfig;\n shadowType: ShadowType;\n}) {\n const shadowTypeConfig = config.shadow[shadowType];\n\n const tuple = entries(shadowTypeConfig).map(([shadowVariant]) =>\n shadowVariantToCSS(shadowType, shadowVariant),\n );\n\n return fromEntries(tuple);\n}\n\nexport { getShadowStyles, shadowVariantToCSS };\n"],"mappings":";;;;;AAOA,MAAM,sBACJ,YACA,kBACG;AACH,QAAO,CACL,QAAQ,WAAW,UAAU,iBAC7B;GACG,SAAmB,WAAW,WAAW,aAAuB,WAAW,UAAU,cAAc;EACpG,WAAW,SAAS,mBAAmB;EACxC,CACF;;AAGH,SAAS,gBAAgB,EACvB,QACA,cAIC;CACD,MAAM,mBAAmB,OAAO,OAAO;AAMvC,QAAO,YAJO,QAAQ,iBAAiB,CAAC,KAAK,CAAC,mBAC5C,mBAAmB,YAAY,cAAc,CAGvB,CAAC"}
1
+ {"version":3,"file":"getShadowStyles.js","names":[],"sources":["../../../src/tailwind/utils/getShadowStyles.ts"],"sourcesContent":["import type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport { DROP_SHADOW_PREFIX, UDS_PREFIX } from '@yahoo/uds-css-tokens';\nimport type { ElevationAlias, ShadowType, ShadowVariant } from '@yahoo/uds-types';\n\nimport { entries } from '../../utils/entries';\nimport { fromEntries } from '../../utils/fromEntries';\n\nconst shadowVariantToCSS = (\n shadowType: ShadowType,\n shadowVariant: ShadowVariant | ElevationAlias,\n) => {\n return [\n `.uds-${shadowType}-shadow-${shadowVariant}`,\n {\n [`--${UDS_PREFIX}-${shadowType}-shadow`]: `var(--${UDS_PREFIX}-${shadowType}-shadow-${shadowVariant})`,\n boxShadow: `var(--${DROP_SHADOW_PREFIX}, 0 0 transparent), var(--${UDS_PREFIX}-inset-shadow, 0 0 transparent), var(--tw-ring-offset-shadow, 0 0 transparent), var(--tw-ring-shadow, 0 0 transparent), var(--tw-shadow, 0 0 transparent)`,\n },\n ] as const;\n};\n\nfunction getShadowStyles({\n config,\n shadowType,\n}: {\n config: UniversalTokensConfig;\n shadowType: ShadowType;\n}) {\n const shadowTypeConfig = config.shadow[shadowType];\n\n const tuple = entries(shadowTypeConfig).map(([shadowVariant]) =>\n shadowVariantToCSS(shadowType, shadowVariant),\n );\n\n return fromEntries(tuple);\n}\n\nexport { getShadowStyles, shadowVariantToCSS };\n"],"mappings":";;;;;AAOA,MAAM,sBACJ,YACA,kBACG;CACH,OAAO,CACL,QAAQ,WAAW,UAAU,iBAC7B;GACG,SAAmB,WAAW,WAAW,aAAuB,WAAW,UAAU,cAAc;EACpG,WAAW,SAAS,mBAAmB;EACxC,CACF;;AAGH,SAAS,gBAAgB,EACvB,QACA,cAIC;CACD,MAAM,mBAAmB,OAAO,OAAO;CAMvC,OAAO,YAJO,QAAQ,iBAAiB,CAAC,KAAK,CAAC,mBAC5C,mBAAmB,YAAY,cAAc,CAGvB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"assertUnreachable.js","names":[],"sources":["../../src/utils/assertUnreachable.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst assertUnreachable = (x: never): never => {\n throw new Error(\"Didn't expect to get here\");\n};\n\nexport { assertUnreachable };\n"],"mappings":";;AACA,MAAM,qBAAqB,MAAoB;AAC7C,OAAM,IAAI,MAAM,4BAA4B"}
1
+ {"version":3,"file":"assertUnreachable.js","names":[],"sources":["../../src/utils/assertUnreachable.ts"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst assertUnreachable = (x: never): never => {\n throw new Error(\"Didn't expect to get here\");\n};\n\nexport { assertUnreachable };\n"],"mappings":";;AACA,MAAM,qBAAqB,MAAoB;CAC7C,MAAM,IAAI,MAAM,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"entries.js","names":[],"sources":["../../src/utils/entries.ts"],"sourcesContent":["export function entries<T>(item: T) {\n return Object.entries(item as Record<string, unknown>) as [\n Extract<keyof T, string>,\n T[keyof T],\n ][];\n}\n"],"mappings":";;AAAA,SAAgB,QAAW,MAAS;AAClC,QAAO,OAAO,QAAQ,KAAgC"}
1
+ {"version":3,"file":"entries.js","names":[],"sources":["../../src/utils/entries.ts"],"sourcesContent":["export function entries<T>(item: T) {\n return Object.entries(item as Record<string, unknown>) as [\n Extract<keyof T, string>,\n T[keyof T],\n ][];\n}\n"],"mappings":";;AAAA,SAAgB,QAAW,MAAS;CAClC,OAAO,OAAO,QAAQ,KAAgC"}
@@ -1 +1 @@
1
- {"version":3,"file":"entryPoints.js","names":[],"sources":["../../src/utils/entryPoints.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\ntype EntryValue = string | string[];\n\nconst ALLOWED_ENTRY_FILE_EXTENSIONS = ['.tsx'] as const;\n\nconst DEFAULT_ENTRY = './src';\n\ntype ResolvedEntryPath = {\n originalPath: string;\n absolutePath: string;\n kind: 'directory' | 'file';\n watchDirectory: string;\n fileName?: string;\n};\n\nconst getAllowedEntryFileGlobPatterns = (prefix = '**/*'): string[] =>\n ALLOWED_ENTRY_FILE_EXTENSIONS.map((extension) => `${prefix}${extension}`);\n\nconst hasAllowedEntryFileExtension = (entryPath: string): boolean =>\n ALLOWED_ENTRY_FILE_EXTENSIONS.includes(\n path.extname(entryPath) as (typeof ALLOWED_ENTRY_FILE_EXTENSIONS)[number],\n );\n\nconst stripAllowedEntryFileExtension = (entryPath: string): string => {\n const extension = ALLOWED_ENTRY_FILE_EXTENSIONS.find((candidate) =>\n entryPath.endsWith(candidate),\n );\n\n return extension ? entryPath.slice(0, -extension.length) : entryPath;\n};\n\nconst formatAllowedEntryFileExtensions = (): string => ALLOWED_ENTRY_FILE_EXTENSIONS.join(', ');\n\nconst createUnsupportedEntryExtensionError = (entryPath: string): Error =>\n new Error(\n `Unsupported entry file extension for ${entryPath}. File entries must use one of: ${formatAllowedEntryFileExtensions()}.`,\n );\n\nconst createMissingEntryPathError = (entryPath: string): Error =>\n new Error(`Entry path not found: ${entryPath}.`);\n\nconst isExistingDirectory = (entryPath: string): boolean => {\n if (!fs.existsSync(entryPath)) {\n return false;\n }\n\n return fs.statSync(entryPath).isDirectory();\n};\n\nconst toAbsoluteEntryPath = (entryPath: string, workspaceDir: string): string =>\n path.isAbsolute(entryPath) ? entryPath : path.join(workspaceDir, entryPath);\n\nconst resolveEntryPath = (entryPath: string, workspaceDir: string): ResolvedEntryPath => {\n const absolutePath = toAbsoluteEntryPath(entryPath, workspaceDir);\n\n if (fs.existsSync(absolutePath)) {\n const stats = fs.statSync(absolutePath);\n\n if (stats.isDirectory()) {\n return {\n originalPath: entryPath,\n absolutePath,\n kind: 'directory',\n watchDirectory: absolutePath,\n };\n }\n\n if (stats.isFile()) {\n if (!hasAllowedEntryFileExtension(absolutePath)) {\n throw createUnsupportedEntryExtensionError(entryPath);\n }\n\n return {\n originalPath: entryPath,\n absolutePath,\n kind: 'file',\n watchDirectory: path.dirname(absolutePath),\n fileName: path.basename(absolutePath),\n };\n }\n }\n\n if (\n path.extname(entryPath) &&\n isExistingDirectory(path.dirname(absolutePath)) &&\n !hasAllowedEntryFileExtension(entryPath)\n ) {\n throw createUnsupportedEntryExtensionError(entryPath);\n }\n\n throw createMissingEntryPathError(entryPath);\n};\n\nconst normalizeEntryPaths = (\n entry: EntryValue | undefined,\n defaultEntry = DEFAULT_ENTRY,\n): string[] => {\n const values = Array.isArray(entry) ? entry : [entry];\n const normalized = values.filter(\n (value): value is string => typeof value === 'string' && value.trim().length > 0,\n );\n\n return normalized.length > 0 ? [...new Set(normalized)] : [defaultEntry];\n};\n\nconst formatEntryValue = (entry: EntryValue): string =>\n Array.isArray(entry) ? `[${entry.map((value) => `'${value}'`).join(', ')}]` : `'${entry}'`;\n\nconst resolveEntryPaths = (\n entry: EntryValue | undefined,\n workspaceDir: string,\n defaultEntry = DEFAULT_ENTRY,\n): ResolvedEntryPath[] =>\n normalizeEntryPaths(entry, defaultEntry).map((entryPath) =>\n resolveEntryPath(entryPath, workspaceDir),\n );\n\nexport {\n ALLOWED_ENTRY_FILE_EXTENSIONS,\n DEFAULT_ENTRY,\n formatEntryValue,\n getAllowedEntryFileGlobPatterns,\n hasAllowedEntryFileExtension,\n normalizeEntryPaths,\n resolveEntryPaths,\n stripAllowedEntryFileExtension,\n};\nexport type { EntryValue, ResolvedEntryPath };\n"],"mappings":";;;;AAKA,MAAM,gCAAgC,CAAC,OAAO;AAE9C,MAAM,gBAAgB;AAUtB,MAAM,mCAAmC,SAAS,WAChD,8BAA8B,KAAK,cAAc,GAAG,SAAS,YAAY;AAE3E,MAAM,gCAAgC,cACpC,8BAA8B,SAC5B,KAAK,QAAQ,UAAU,CACxB;AAEH,MAAM,kCAAkC,cAA8B;CACpE,MAAM,YAAY,8BAA8B,MAAM,cACpD,UAAU,SAAS,UAAU,CAC9B;AAED,QAAO,YAAY,UAAU,MAAM,GAAG,CAAC,UAAU,OAAO,GAAG;;AAG7D,MAAM,yCAAiD,8BAA8B,KAAK,KAAK;AAE/F,MAAM,wCAAwC,8BAC5C,IAAI,MACF,wCAAwC,UAAU,kCAAkC,kCAAkC,CAAC,GACxH;AAEH,MAAM,+BAA+B,8BACnC,IAAI,MAAM,yBAAyB,UAAU,GAAG;AAElD,MAAM,uBAAuB,cAA+B;AAC1D,KAAI,CAAC,GAAG,WAAW,UAAU,CAC3B,QAAO;AAGT,QAAO,GAAG,SAAS,UAAU,CAAC,aAAa;;AAG7C,MAAM,uBAAuB,WAAmB,iBAC9C,KAAK,WAAW,UAAU,GAAG,YAAY,KAAK,KAAK,cAAc,UAAU;AAE7E,MAAM,oBAAoB,WAAmB,iBAA4C;CACvF,MAAM,eAAe,oBAAoB,WAAW,aAAa;AAEjE,KAAI,GAAG,WAAW,aAAa,EAAE;EAC/B,MAAM,QAAQ,GAAG,SAAS,aAAa;AAEvC,MAAI,MAAM,aAAa,CACrB,QAAO;GACL,cAAc;GACd;GACA,MAAM;GACN,gBAAgB;GACjB;AAGH,MAAI,MAAM,QAAQ,EAAE;AAClB,OAAI,CAAC,6BAA6B,aAAa,CAC7C,OAAM,qCAAqC,UAAU;AAGvD,UAAO;IACL,cAAc;IACd;IACA,MAAM;IACN,gBAAgB,KAAK,QAAQ,aAAa;IAC1C,UAAU,KAAK,SAAS,aAAa;IACtC;;;AAIL,KACE,KAAK,QAAQ,UAAU,IACvB,oBAAoB,KAAK,QAAQ,aAAa,CAAC,IAC/C,CAAC,6BAA6B,UAAU,CAExC,OAAM,qCAAqC,UAAU;AAGvD,OAAM,4BAA4B,UAAU;;AAG9C,MAAM,uBACJ,OACA,eAAe,kBACF;CAEb,MAAM,cADS,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM,EAC3B,QACvB,UAA2B,OAAO,UAAU,YAAY,MAAM,MAAM,CAAC,SAAS,EAChF;AAED,QAAO,WAAW,SAAS,IAAI,CAAC,GAAG,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,aAAa;;AAG1E,MAAM,oBAAoB,UACxB,MAAM,QAAQ,MAAM,GAAG,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,IAAI,MAAM;AAE1F,MAAM,qBACJ,OACA,cACA,eAAe,kBAEf,oBAAoB,OAAO,aAAa,CAAC,KAAK,cAC5C,iBAAiB,WAAW,aAAa,CAC1C"}
1
+ {"version":3,"file":"entryPoints.js","names":[],"sources":["../../src/utils/entryPoints.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\ntype EntryValue = string | string[];\n\nconst ALLOWED_ENTRY_FILE_EXTENSIONS = ['.tsx'] as const;\n\nconst DEFAULT_ENTRY = './src';\n\ntype ResolvedEntryPath = {\n originalPath: string;\n absolutePath: string;\n kind: 'directory' | 'file';\n watchDirectory: string;\n fileName?: string;\n};\n\nconst getAllowedEntryFileGlobPatterns = (prefix = '**/*'): string[] =>\n ALLOWED_ENTRY_FILE_EXTENSIONS.map((extension) => `${prefix}${extension}`);\n\nconst hasAllowedEntryFileExtension = (entryPath: string): boolean =>\n ALLOWED_ENTRY_FILE_EXTENSIONS.includes(\n path.extname(entryPath) as (typeof ALLOWED_ENTRY_FILE_EXTENSIONS)[number],\n );\n\nconst stripAllowedEntryFileExtension = (entryPath: string): string => {\n const extension = ALLOWED_ENTRY_FILE_EXTENSIONS.find((candidate) =>\n entryPath.endsWith(candidate),\n );\n\n return extension ? entryPath.slice(0, -extension.length) : entryPath;\n};\n\nconst formatAllowedEntryFileExtensions = (): string => ALLOWED_ENTRY_FILE_EXTENSIONS.join(', ');\n\nconst createUnsupportedEntryExtensionError = (entryPath: string): Error =>\n new Error(\n `Unsupported entry file extension for ${entryPath}. File entries must use one of: ${formatAllowedEntryFileExtensions()}.`,\n );\n\nconst createMissingEntryPathError = (entryPath: string): Error =>\n new Error(`Entry path not found: ${entryPath}.`);\n\nconst isExistingDirectory = (entryPath: string): boolean => {\n if (!fs.existsSync(entryPath)) {\n return false;\n }\n\n return fs.statSync(entryPath).isDirectory();\n};\n\nconst toAbsoluteEntryPath = (entryPath: string, workspaceDir: string): string =>\n path.isAbsolute(entryPath) ? entryPath : path.join(workspaceDir, entryPath);\n\nconst resolveEntryPath = (entryPath: string, workspaceDir: string): ResolvedEntryPath => {\n const absolutePath = toAbsoluteEntryPath(entryPath, workspaceDir);\n\n if (fs.existsSync(absolutePath)) {\n const stats = fs.statSync(absolutePath);\n\n if (stats.isDirectory()) {\n return {\n originalPath: entryPath,\n absolutePath,\n kind: 'directory',\n watchDirectory: absolutePath,\n };\n }\n\n if (stats.isFile()) {\n if (!hasAllowedEntryFileExtension(absolutePath)) {\n throw createUnsupportedEntryExtensionError(entryPath);\n }\n\n return {\n originalPath: entryPath,\n absolutePath,\n kind: 'file',\n watchDirectory: path.dirname(absolutePath),\n fileName: path.basename(absolutePath),\n };\n }\n }\n\n if (\n path.extname(entryPath) &&\n isExistingDirectory(path.dirname(absolutePath)) &&\n !hasAllowedEntryFileExtension(entryPath)\n ) {\n throw createUnsupportedEntryExtensionError(entryPath);\n }\n\n throw createMissingEntryPathError(entryPath);\n};\n\nconst normalizeEntryPaths = (\n entry: EntryValue | undefined,\n defaultEntry = DEFAULT_ENTRY,\n): string[] => {\n const values = Array.isArray(entry) ? entry : [entry];\n const normalized = values.filter(\n (value): value is string => typeof value === 'string' && value.trim().length > 0,\n );\n\n return normalized.length > 0 ? [...new Set(normalized)] : [defaultEntry];\n};\n\nconst formatEntryValue = (entry: EntryValue): string =>\n Array.isArray(entry) ? `[${entry.map((value) => `'${value}'`).join(', ')}]` : `'${entry}'`;\n\nconst resolveEntryPaths = (\n entry: EntryValue | undefined,\n workspaceDir: string,\n defaultEntry = DEFAULT_ENTRY,\n): ResolvedEntryPath[] =>\n normalizeEntryPaths(entry, defaultEntry).map((entryPath) =>\n resolveEntryPath(entryPath, workspaceDir),\n );\n\nexport {\n ALLOWED_ENTRY_FILE_EXTENSIONS,\n DEFAULT_ENTRY,\n formatEntryValue,\n getAllowedEntryFileGlobPatterns,\n hasAllowedEntryFileExtension,\n normalizeEntryPaths,\n resolveEntryPaths,\n stripAllowedEntryFileExtension,\n};\nexport type { EntryValue, ResolvedEntryPath };\n"],"mappings":";;;;AAKA,MAAM,gCAAgC,CAAC,OAAO;AAE9C,MAAM,gBAAgB;AAUtB,MAAM,mCAAmC,SAAS,WAChD,8BAA8B,KAAK,cAAc,GAAG,SAAS,YAAY;AAE3E,MAAM,gCAAgC,cACpC,8BAA8B,SAC5B,KAAK,QAAQ,UAAU,CACxB;AAEH,MAAM,kCAAkC,cAA8B;CACpE,MAAM,YAAY,8BAA8B,MAAM,cACpD,UAAU,SAAS,UAAU,CAC9B;CAED,OAAO,YAAY,UAAU,MAAM,GAAG,CAAC,UAAU,OAAO,GAAG;;AAG7D,MAAM,yCAAiD,8BAA8B,KAAK,KAAK;AAE/F,MAAM,wCAAwC,8BAC5C,IAAI,MACF,wCAAwC,UAAU,kCAAkC,kCAAkC,CAAC,GACxH;AAEH,MAAM,+BAA+B,8BACnC,IAAI,MAAM,yBAAyB,UAAU,GAAG;AAElD,MAAM,uBAAuB,cAA+B;CAC1D,IAAI,CAAC,GAAG,WAAW,UAAU,EAC3B,OAAO;CAGT,OAAO,GAAG,SAAS,UAAU,CAAC,aAAa;;AAG7C,MAAM,uBAAuB,WAAmB,iBAC9C,KAAK,WAAW,UAAU,GAAG,YAAY,KAAK,KAAK,cAAc,UAAU;AAE7E,MAAM,oBAAoB,WAAmB,iBAA4C;CACvF,MAAM,eAAe,oBAAoB,WAAW,aAAa;CAEjE,IAAI,GAAG,WAAW,aAAa,EAAE;EAC/B,MAAM,QAAQ,GAAG,SAAS,aAAa;EAEvC,IAAI,MAAM,aAAa,EACrB,OAAO;GACL,cAAc;GACd;GACA,MAAM;GACN,gBAAgB;GACjB;EAGH,IAAI,MAAM,QAAQ,EAAE;GAClB,IAAI,CAAC,6BAA6B,aAAa,EAC7C,MAAM,qCAAqC,UAAU;GAGvD,OAAO;IACL,cAAc;IACd;IACA,MAAM;IACN,gBAAgB,KAAK,QAAQ,aAAa;IAC1C,UAAU,KAAK,SAAS,aAAa;IACtC;;;CAIL,IACE,KAAK,QAAQ,UAAU,IACvB,oBAAoB,KAAK,QAAQ,aAAa,CAAC,IAC/C,CAAC,6BAA6B,UAAU,EAExC,MAAM,qCAAqC,UAAU;CAGvD,MAAM,4BAA4B,UAAU;;AAG9C,MAAM,uBACJ,OACA,eAAe,kBACF;CAEb,MAAM,cADS,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM,EAC3B,QACvB,UAA2B,OAAO,UAAU,YAAY,MAAM,MAAM,CAAC,SAAS,EAChF;CAED,OAAO,WAAW,SAAS,IAAI,CAAC,GAAG,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,aAAa;;AAG1E,MAAM,oBAAoB,UACxB,MAAM,QAAQ,MAAM,GAAG,IAAI,MAAM,KAAK,UAAU,IAAI,MAAM,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,IAAI,MAAM;AAE1F,MAAM,qBACJ,OACA,cACA,eAAe,kBAEf,oBAAoB,OAAO,aAAa,CAAC,KAAK,cAC5C,iBAAiB,WAAW,aAAa,CAC1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"fromEntries.js","names":[],"sources":["../../src/utils/fromEntries.ts"],"sourcesContent":["/**\n * Converts an array of key-value pair entries into an object.\n *\n * This function takes an array of `[key, value]` pairs and converts it into an object\n * where each key is associated with its corresponding value. The generic types `T` and `K`\n * represent the types of the keys and values, respectively. The keys are constrained to\n * be strings.\n */\nexport function fromEntries<T extends string, K>(item: [T, K][] | (readonly [T, K])[]) {\n return Object.fromEntries(item) as Record<T, K>;\n}\n"],"mappings":";;;;;;;;;;AAQA,SAAgB,YAAiC,MAAsC;AACrF,QAAO,OAAO,YAAY,KAAK"}
1
+ {"version":3,"file":"fromEntries.js","names":[],"sources":["../../src/utils/fromEntries.ts"],"sourcesContent":["/**\n * Converts an array of key-value pair entries into an object.\n *\n * This function takes an array of `[key, value]` pairs and converts it into an object\n * where each key is associated with its corresponding value. The generic types `T` and `K`\n * represent the types of the keys and values, respectively. The keys are constrained to\n * be strings.\n */\nexport function fromEntries<T extends string, K>(item: [T, K][] | (readonly [T, K])[]) {\n return Object.fromEntries(item) as Record<T, K>;\n}\n"],"mappings":";;;;;;;;;;AAQA,SAAgB,YAAiC,MAAsC;CACrF,OAAO,OAAO,YAAY,KAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"generatePurgeCSSData.js","names":[],"sources":["../../src/utils/generatePurgeCSSData.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { autoVariants } from '@yahoo/uds-automated-config/autoVariants';\nimport { print, red } from '@yahoo/uds-cli/lib';\nimport { defaultTokensConfig } from '@yahoo/uds-config';\nimport type { AcceptedPlugin } from 'postcss';\nimport postcss from 'postcss';\nimport tailwindcss from 'tailwindcss';\nimport type { Project } from 'ts-morph';\nimport { SyntaxKind } from 'ts-morph';\n\nimport { tailwindPlugin } from '../tailwind/tailwindPlugin';\nimport {\n findReferencesAsJsxElements,\n getReactFunctionDeclaration,\n getUsedPropsInReference,\n} from './tsMorph';\n\ntype ComponentsList = string[];\ntype ComponentToVariants = { [key: string]: PropToUsedOptions[] };\ntype VariantsList = string[];\ntype ComponentDependencies = { [key: string]: string[] };\ntype ComponentToTwClasses = { [key: string]: string };\ntype ExportToFilePath = { [key: string]: string };\ntype AllProps = Array<[string, string[]]>;\ntype PropToUsedOptions = [string, string[]];\n\nconst NO_FILE: string = 'noFile';\n\n/**\n * Returns a list of exported Components from UDS\n * both stable and experimental\n */\nconst getExportedComponents = (\n UDS: Record<string, any>,\n UDS_EXPERIMENTAL: Record<string, any>,\n): ComponentsList => {\n const udsStableExports = Object.keys(UDS);\n const udsExperimentalExports = Object.keys(UDS_EXPERIMENTAL);\n const allExports = udsStableExports.concat(udsExperimentalExports);\n const keys = allExports.filter((key) => {\n const regexStartsWithCapitalLetter = new RegExp('^[A-Z].[^_]');\n const hasUnderscore = key.includes('_');\n const startsWithCapitalLetter = regexStartsWithCapitalLetter.test(key);\n return !hasUnderscore && startsWithCapitalLetter;\n });\n return keys;\n};\n\n/**\n * Some UDS components are built using other UDS components,\n * we need to know those dependencies so generate the correct\n */\nconst getComponentsDependencies = (\n project: Project,\n componentsList: ComponentsList,\n exportsToFilePath: ExportToFilePath,\n): ComponentDependencies => {\n const componentsListSet = new Set(componentsList);\n // the components a component from UDS depends on\n const componentUDSDependencies: { [k: string]: string[] } = {};\n componentsList.forEach((component) => {\n componentUDSDependencies[component] = getComponentUdsDependencies(\n project,\n componentsListSet,\n component,\n exportsToFilePath,\n );\n });\n return componentUDSDependencies;\n};\n\n/**\n * We need to make sure that components from UDS that use other components\n * from UDS also gets included\n */\nconst getComponentUdsDependencies = (\n project: Project,\n componentsList: Set<string>,\n componentName: string,\n exportsToFilePath: ExportToFilePath,\n): string[] => {\n const sourceFile = project.getSourceFileOrThrow(exportsToFilePath[componentName]);\n\n const deps = sourceFile\n .getImportDeclarations()\n .map((declaration) => {\n return declaration.getNamedImports().map((namedImport) => namedImport.getName());\n })\n .flat()\n .filter((namedImport) => componentsList.has(namedImport));\n\n return deps;\n};\n\nconst getComponentsProps = (\n project: Project,\n list: ComponentsList,\n variants: Record<string, Record<string, string>>,\n variantsList: VariantsList,\n exportsToFilePath: ExportToFilePath,\n): ComponentToVariants => {\n const map: ComponentToVariants = {};\n\n list.forEach((componentName) => {\n const list = getInitializedAndReferencedProps(\n project,\n componentName,\n variants,\n variantsList,\n exportsToFilePath,\n );\n map[componentName] = list;\n });\n\n return map;\n};\n\n/**\n * Converts the variants object used in CVA to\n */\nconst convertVariantsIntoTailwindClass = (\n variants: Record<string, Record<string, string>>,\n): VariantsList => {\n const variantsList = Object.keys(variants) as Array<keyof typeof variants>;\n\n return variantsList;\n};\n\n/**\n * Get the params with default values,\n * required and the ones used in references\n */\nconst getInitializedAndReferencedProps = (\n project: Project,\n componentName: string,\n variants: Record<string, Record<string, string>>,\n variantsList: VariantsList,\n exportsToFilePath: ExportToFilePath,\n): AllProps => {\n const sourceFile = project.getSourceFileOrThrow(exportsToFilePath[componentName] ?? NO_FILE);\n\n const functionDeclarations = sourceFile.getFunctions();\n const variableDeclarations = sourceFile.getVariableDeclarations();\n const node = [...functionDeclarations, ...variableDeclarations].filter(\n (declaration) => declaration.getName() === componentName,\n )[0];\n\n const functionDeclaration = getReactFunctionDeclaration(node);\n\n if (!functionDeclaration) {\n print(red(`No function declaration found for ${componentName}`));\n }\n\n const parameterDeclaration = functionDeclaration?.getParameters();\n\n if (!parameterDeclaration || parameterDeclaration.length === 0) {\n print(red(`No parameter declaration found for ${componentName}`));\n return [];\n }\n\n // the first parameter in all react components is the props\n if (!parameterDeclaration[0].getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0]) {\n return [];\n }\n\n const componentIdentifier = node.getFirstDescendantByKindOrThrow(SyntaxKind.Identifier);\n const references = findReferencesAsJsxElements(componentIdentifier);\n\n const propsWithDefaultValues = parameterDeclaration[0]\n .getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0]\n .getElements()\n .filter((el) => !!el.getInitializer())\n .map((el) => {\n const stringLiteral = el.getDescendantsOfKind(SyntaxKind.StringLiteral)[0];\n const propName = el.getName();\n const values: string[] = [];\n if (stringLiteral) {\n values.push(stringLiteral.getLiteralText());\n }\n\n return [propName, values] as [string, string[]];\n })\n .filter(([propName]) => variantsList.includes(propName));\n\n const propsUsedInReferences = references\n .map((r) => getUsedPropsInReference(r, variants))\n .flat()\n .filter(([propName]) => variantsList.includes(propName));\n\n const mapPropToUsedOptions = new Map<string, Set<string>>();\n\n propsWithDefaultValues.concat(propsUsedInReferences).forEach(([propName, propValues]) => {\n // This means that an expression has been used\n // so we need to add all possible options for that prop\n if (propValues.length === 0) {\n propValues = Object.keys(variants[propName as keyof typeof variants]);\n }\n\n const options: Set<string> = mapPropToUsedOptions.get(propName) ?? new Set();\n propValues.forEach((val) => options.add(val));\n mapPropToUsedOptions.set(propName, options);\n });\n\n const res: Array<[string, string[]]> = Array.from(mapPropToUsedOptions).map(\n ([propName, options]) => [propName, Array.from(options)],\n );\n\n return res;\n};\n\n/**\n * Gets the Tailwind CSS classes used in a component\n */\nconst getTwClassesInComponent = async (\n componentsList: ComponentsList,\n exportsToFilePath: ExportToFilePath,\n): Promise<ComponentToTwClasses> => {\n const CSS_DATA = `\n @tailwind components;\n @tailwind utilities;\n `;\n\n const res: ComponentToTwClasses = {};\n\n const promises = componentsList.map((component) => {\n const plugin = tailwindcss({\n content: [exportsToFilePath[component]],\n plugins: [tailwindPlugin({ config: defaultTokensConfig })],\n });\n return postcss([plugin as AcceptedPlugin]).process(CSS_DATA, {\n from: 'app.css',\n to: './dist/app.css',\n });\n });\n\n const resolvedPromises = await Promise.all(promises);\n\n resolvedPromises.forEach((result, i) => {\n const currentComponent = componentsList[i];\n const classes = result.root.nodes\n .map((node) => {\n if ((node as any).selector) {\n return (node as any).selector.replace('.', '');\n }\n\n return [];\n })\n .join(' ')\n // replace multiple spaces with one space\n .replace(/\\s+/g, ' ');\n res[currentComponent] = classes;\n });\n\n return res;\n};\n\n/**\n * Goes through the list of all exports from UDS (stable and experimental)\n * and return a map of each exports and the source file path where its declared\n */\nconst getExportsToFilePath = (project: Project): ExportToFilePath => {\n const stableComponentsMainFile = project.getSourceFileOrThrow('./src/components/index.ts');\n const experimentalComponentsMainFile = project.getSourceFileOrThrow(\n './src/components/experimental/index.ts',\n );\n const exportToFilePath: ExportToFilePath = {};\n for (const [name, declarations] of stableComponentsMainFile.getExportedDeclarations()) {\n exportToFilePath[name] = declarations.map((d) => d.getSourceFile().getFilePath())[0];\n }\n for (const [name, declarations] of experimentalComponentsMainFile.getExportedDeclarations()) {\n exportToFilePath[name] = declarations.map((d) => d.getSourceFile().getFilePath())[0];\n }\n\n return exportToFilePath;\n};\n\n/**\n * Adds auto-generated variants to the Tailwind CSS classes of components.\n *\n * This function extracts component names from auto variants keys, groups class names by component,\n * updates component classes using auto-generated variant classes, and propagates base classes to subcomponents.\n *\n * @param componentToTwClasses - A map of component names to their current Tailwind CSS classes.\n * @returns Updated map with auto variants added to the component classes.\n */\nconst addAutoVariantsToComponentClasses = (\n componentToTwClasses: ComponentToTwClasses,\n): ComponentToTwClasses => {\n // Extract component names from auto variants keys\n // Example: \"checkboxSizeRoot\" -> \"Checkbox\"\n const componentNameRegex = /^([a-z]+)[A-Z]/;\n const componentNameMap: Record<string, string[]> = {};\n\n // Create a case-insensitive lookup map from component names in componentToTwClasses\n const componentNameLookup = new Map<string, string>();\n Object.keys(componentToTwClasses).forEach((actualName) => {\n componentNameLookup.set(actualName.toLowerCase(), actualName);\n });\n\n // Group class names by component\n Object.keys(autoVariants).forEach((key) => {\n const match = key.match(componentNameRegex);\n if (match && match[1]) {\n const extractedName = match[1].charAt(0).toUpperCase() + match[1].slice(1);\n // Use case-insensitive lookup to find the actual component name\n const actualComponentName =\n componentNameLookup.get(extractedName.toLowerCase()) || extractedName;\n\n if (!componentNameMap[actualComponentName]) {\n componentNameMap[actualComponentName] = [];\n }\n\n // Get all class names for this variant\n Object.values(autoVariants[key as keyof typeof autoVariants]).forEach((className) => {\n componentNameMap[actualComponentName].push(className);\n });\n }\n });\n\n // Add or update component classes\n Object.entries(componentNameMap).forEach(([componentName, classes]) => {\n const existingClasses = componentToTwClasses[componentName] || '';\n componentToTwClasses[componentName] = `${existingClasses} ${classes.join(' ')}`.trim();\n });\n\n // add a step to also add the classes to sub components (example, AvatarText, AvatarIcon, ...)\n const components = Object.keys(componentNameMap);\n Object.keys(componentToTwClasses).forEach((key) => {\n components.forEach((comp) => {\n const compName = comp.charAt(0).toUpperCase() + comp.slice(1);\n if (key.startsWith(compName) && key !== compName) {\n const baseClasses = componentToTwClasses[compName] || '';\n if (baseClasses) {\n componentToTwClasses[key] = `${componentToTwClasses[key]} ${baseClasses}`.trim();\n }\n }\n });\n });\n return componentToTwClasses;\n};\n\nexport {\n addAutoVariantsToComponentClasses,\n convertVariantsIntoTailwindClass,\n getComponentsDependencies,\n getComponentsProps,\n getComponentUdsDependencies,\n getExportedComponents,\n getExportsToFilePath,\n getInitializedAndReferencedProps,\n getTwClassesInComponent,\n NO_FILE,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"generatePurgeCSSData.js","names":[],"sources":["../../src/utils/generatePurgeCSSData.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { autoVariants } from '@yahoo/uds-automated-config/autoVariants';\nimport { print, red } from '@yahoo/uds-cli/lib';\nimport { defaultTokensConfig } from '@yahoo/uds-config';\nimport type { AcceptedPlugin } from 'postcss';\nimport postcss from 'postcss';\nimport tailwindcss from 'tailwindcss';\nimport type { Project } from 'ts-morph';\nimport { SyntaxKind } from 'ts-morph';\n\nimport { tailwindPlugin } from '../tailwind/tailwindPlugin';\nimport {\n findReferencesAsJsxElements,\n getReactFunctionDeclaration,\n getUsedPropsInReference,\n} from './tsMorph';\n\ntype ComponentsList = string[];\ntype ComponentToVariants = { [key: string]: PropToUsedOptions[] };\ntype VariantsList = string[];\ntype ComponentDependencies = { [key: string]: string[] };\ntype ComponentToTwClasses = { [key: string]: string };\ntype ExportToFilePath = { [key: string]: string };\ntype AllProps = Array<[string, string[]]>;\ntype PropToUsedOptions = [string, string[]];\n\nconst NO_FILE: string = 'noFile';\n\n/**\n * Returns a list of exported Components from UDS\n * both stable and experimental\n */\nconst getExportedComponents = (\n UDS: Record<string, any>,\n UDS_EXPERIMENTAL: Record<string, any>,\n): ComponentsList => {\n const udsStableExports = Object.keys(UDS);\n const udsExperimentalExports = Object.keys(UDS_EXPERIMENTAL);\n const allExports = udsStableExports.concat(udsExperimentalExports);\n const keys = allExports.filter((key) => {\n const regexStartsWithCapitalLetter = new RegExp('^[A-Z].[^_]');\n const hasUnderscore = key.includes('_');\n const startsWithCapitalLetter = regexStartsWithCapitalLetter.test(key);\n return !hasUnderscore && startsWithCapitalLetter;\n });\n return keys;\n};\n\n/**\n * Some UDS components are built using other UDS components,\n * we need to know those dependencies so generate the correct\n */\nconst getComponentsDependencies = (\n project: Project,\n componentsList: ComponentsList,\n exportsToFilePath: ExportToFilePath,\n): ComponentDependencies => {\n const componentsListSet = new Set(componentsList);\n // the components a component from UDS depends on\n const componentUDSDependencies: { [k: string]: string[] } = {};\n componentsList.forEach((component) => {\n componentUDSDependencies[component] = getComponentUdsDependencies(\n project,\n componentsListSet,\n component,\n exportsToFilePath,\n );\n });\n return componentUDSDependencies;\n};\n\n/**\n * We need to make sure that components from UDS that use other components\n * from UDS also gets included\n */\nconst getComponentUdsDependencies = (\n project: Project,\n componentsList: Set<string>,\n componentName: string,\n exportsToFilePath: ExportToFilePath,\n): string[] => {\n const sourceFile = project.getSourceFileOrThrow(exportsToFilePath[componentName]);\n\n const deps = sourceFile\n .getImportDeclarations()\n .map((declaration) => {\n return declaration.getNamedImports().map((namedImport) => namedImport.getName());\n })\n .flat()\n .filter((namedImport) => componentsList.has(namedImport));\n\n return deps;\n};\n\nconst getComponentsProps = (\n project: Project,\n list: ComponentsList,\n variants: Record<string, Record<string, string>>,\n variantsList: VariantsList,\n exportsToFilePath: ExportToFilePath,\n): ComponentToVariants => {\n const map: ComponentToVariants = {};\n\n list.forEach((componentName) => {\n const list = getInitializedAndReferencedProps(\n project,\n componentName,\n variants,\n variantsList,\n exportsToFilePath,\n );\n map[componentName] = list;\n });\n\n return map;\n};\n\n/**\n * Converts the variants object used in CVA to\n */\nconst convertVariantsIntoTailwindClass = (\n variants: Record<string, Record<string, string>>,\n): VariantsList => {\n const variantsList = Object.keys(variants) as Array<keyof typeof variants>;\n\n return variantsList;\n};\n\n/**\n * Get the params with default values,\n * required and the ones used in references\n */\nconst getInitializedAndReferencedProps = (\n project: Project,\n componentName: string,\n variants: Record<string, Record<string, string>>,\n variantsList: VariantsList,\n exportsToFilePath: ExportToFilePath,\n): AllProps => {\n const sourceFile = project.getSourceFileOrThrow(exportsToFilePath[componentName] ?? NO_FILE);\n\n const functionDeclarations = sourceFile.getFunctions();\n const variableDeclarations = sourceFile.getVariableDeclarations();\n const node = [...functionDeclarations, ...variableDeclarations].filter(\n (declaration) => declaration.getName() === componentName,\n )[0];\n\n const functionDeclaration = getReactFunctionDeclaration(node);\n\n if (!functionDeclaration) {\n print(red(`No function declaration found for ${componentName}`));\n }\n\n const parameterDeclaration = functionDeclaration?.getParameters();\n\n if (!parameterDeclaration || parameterDeclaration.length === 0) {\n print(red(`No parameter declaration found for ${componentName}`));\n return [];\n }\n\n // the first parameter in all react components is the props\n if (!parameterDeclaration[0].getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0]) {\n return [];\n }\n\n const componentIdentifier = node.getFirstDescendantByKindOrThrow(SyntaxKind.Identifier);\n const references = findReferencesAsJsxElements(componentIdentifier);\n\n const propsWithDefaultValues = parameterDeclaration[0]\n .getChildrenOfKind(SyntaxKind.ObjectBindingPattern)[0]\n .getElements()\n .filter((el) => !!el.getInitializer())\n .map((el) => {\n const stringLiteral = el.getDescendantsOfKind(SyntaxKind.StringLiteral)[0];\n const propName = el.getName();\n const values: string[] = [];\n if (stringLiteral) {\n values.push(stringLiteral.getLiteralText());\n }\n\n return [propName, values] as [string, string[]];\n })\n .filter(([propName]) => variantsList.includes(propName));\n\n const propsUsedInReferences = references\n .map((r) => getUsedPropsInReference(r, variants))\n .flat()\n .filter(([propName]) => variantsList.includes(propName));\n\n const mapPropToUsedOptions = new Map<string, Set<string>>();\n\n propsWithDefaultValues.concat(propsUsedInReferences).forEach(([propName, propValues]) => {\n // This means that an expression has been used\n // so we need to add all possible options for that prop\n if (propValues.length === 0) {\n propValues = Object.keys(variants[propName as keyof typeof variants]);\n }\n\n const options: Set<string> = mapPropToUsedOptions.get(propName) ?? new Set();\n propValues.forEach((val) => options.add(val));\n mapPropToUsedOptions.set(propName, options);\n });\n\n const res: Array<[string, string[]]> = Array.from(mapPropToUsedOptions).map(\n ([propName, options]) => [propName, Array.from(options)],\n );\n\n return res;\n};\n\n/**\n * Gets the Tailwind CSS classes used in a component\n */\nconst getTwClassesInComponent = async (\n componentsList: ComponentsList,\n exportsToFilePath: ExportToFilePath,\n): Promise<ComponentToTwClasses> => {\n const CSS_DATA = `\n @tailwind components;\n @tailwind utilities;\n `;\n\n const res: ComponentToTwClasses = {};\n\n const promises = componentsList.map((component) => {\n const plugin = tailwindcss({\n content: [exportsToFilePath[component]],\n plugins: [tailwindPlugin({ config: defaultTokensConfig })],\n });\n return postcss([plugin as AcceptedPlugin]).process(CSS_DATA, {\n from: 'app.css',\n to: './dist/app.css',\n });\n });\n\n const resolvedPromises = await Promise.all(promises);\n\n resolvedPromises.forEach((result, i) => {\n const currentComponent = componentsList[i];\n const classes = result.root.nodes\n .map((node) => {\n if ((node as any).selector) {\n return (node as any).selector.replace('.', '');\n }\n\n return [];\n })\n .join(' ')\n // replace multiple spaces with one space\n .replace(/\\s+/g, ' ');\n res[currentComponent] = classes;\n });\n\n return res;\n};\n\n/**\n * Goes through the list of all exports from UDS (stable and experimental)\n * and return a map of each exports and the source file path where its declared\n */\nconst getExportsToFilePath = (project: Project): ExportToFilePath => {\n const stableComponentsMainFile = project.getSourceFileOrThrow('./src/components/index.ts');\n const experimentalComponentsMainFile = project.getSourceFileOrThrow(\n './src/components/experimental/index.ts',\n );\n const exportToFilePath: ExportToFilePath = {};\n for (const [name, declarations] of stableComponentsMainFile.getExportedDeclarations()) {\n exportToFilePath[name] = declarations.map((d) => d.getSourceFile().getFilePath())[0];\n }\n for (const [name, declarations] of experimentalComponentsMainFile.getExportedDeclarations()) {\n exportToFilePath[name] = declarations.map((d) => d.getSourceFile().getFilePath())[0];\n }\n\n return exportToFilePath;\n};\n\n/**\n * Adds auto-generated variants to the Tailwind CSS classes of components.\n *\n * This function extracts component names from auto variants keys, groups class names by component,\n * updates component classes using auto-generated variant classes, and propagates base classes to subcomponents.\n *\n * @param componentToTwClasses - A map of component names to their current Tailwind CSS classes.\n * @returns Updated map with auto variants added to the component classes.\n */\nconst addAutoVariantsToComponentClasses = (\n componentToTwClasses: ComponentToTwClasses,\n): ComponentToTwClasses => {\n // Extract component names from auto variants keys\n // Example: \"checkboxSizeRoot\" -> \"Checkbox\"\n const componentNameRegex = /^([a-z]+)[A-Z]/;\n const componentNameMap: Record<string, string[]> = {};\n\n // Create a case-insensitive lookup map from component names in componentToTwClasses\n const componentNameLookup = new Map<string, string>();\n Object.keys(componentToTwClasses).forEach((actualName) => {\n componentNameLookup.set(actualName.toLowerCase(), actualName);\n });\n\n // Group class names by component\n Object.keys(autoVariants).forEach((key) => {\n const match = key.match(componentNameRegex);\n if (match && match[1]) {\n const extractedName = match[1].charAt(0).toUpperCase() + match[1].slice(1);\n // Use case-insensitive lookup to find the actual component name\n const actualComponentName =\n componentNameLookup.get(extractedName.toLowerCase()) || extractedName;\n\n if (!componentNameMap[actualComponentName]) {\n componentNameMap[actualComponentName] = [];\n }\n\n // Get all class names for this variant\n Object.values(autoVariants[key as keyof typeof autoVariants]).forEach((className) => {\n componentNameMap[actualComponentName].push(className);\n });\n }\n });\n\n // Add or update component classes\n Object.entries(componentNameMap).forEach(([componentName, classes]) => {\n const existingClasses = componentToTwClasses[componentName] || '';\n componentToTwClasses[componentName] = `${existingClasses} ${classes.join(' ')}`.trim();\n });\n\n // add a step to also add the classes to sub components (example, AvatarText, AvatarIcon, ...)\n const components = Object.keys(componentNameMap);\n Object.keys(componentToTwClasses).forEach((key) => {\n components.forEach((comp) => {\n const compName = comp.charAt(0).toUpperCase() + comp.slice(1);\n if (key.startsWith(compName) && key !== compName) {\n const baseClasses = componentToTwClasses[compName] || '';\n if (baseClasses) {\n componentToTwClasses[key] = `${componentToTwClasses[key]} ${baseClasses}`.trim();\n }\n }\n });\n });\n return componentToTwClasses;\n};\n\nexport {\n addAutoVariantsToComponentClasses,\n convertVariantsIntoTailwindClass,\n getComponentsDependencies,\n getComponentsProps,\n getComponentUdsDependencies,\n getExportedComponents,\n getExportsToFilePath,\n getInitializedAndReferencedProps,\n getTwClassesInComponent,\n NO_FILE,\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"mapValues.js","names":[],"sources":["../../src/utils/mapValues.ts"],"sourcesContent":["type AnyObject = Record<string, unknown>;\n\nexport function mapValues<\n T extends AnyObject,\n K extends (value: T[keyof T], key: keyof T, i: number) => unknown,\n>(obj: T, callbackFn: K) {\n return Object.keys(obj).reduce(\n (acc, key: keyof T, i) => {\n acc[key] = callbackFn(obj[key], key, i) as ReturnType<typeof callbackFn>;\n return acc;\n },\n\n {} as { [key in keyof T]: ReturnType<K> },\n );\n}\n"],"mappings":";;AAEA,SAAgB,UAGd,KAAQ,YAAe;AACvB,QAAO,OAAO,KAAK,IAAI,CAAC,QACrB,KAAK,KAAc,MAAM;AACxB,MAAI,OAAO,WAAW,IAAI,MAAM,KAAK,EAAE;AACvC,SAAO;IAGT,EAAE,CACH"}
1
+ {"version":3,"file":"mapValues.js","names":[],"sources":["../../src/utils/mapValues.ts"],"sourcesContent":["type AnyObject = Record<string, unknown>;\n\nexport function mapValues<\n T extends AnyObject,\n K extends (value: T[keyof T], key: keyof T, i: number) => unknown,\n>(obj: T, callbackFn: K) {\n return Object.keys(obj).reduce(\n (acc, key: keyof T, i) => {\n acc[key] = callbackFn(obj[key], key, i) as ReturnType<typeof callbackFn>;\n return acc;\n },\n\n {} as { [key in keyof T]: ReturnType<K> },\n );\n}\n"],"mappings":";;AAEA,SAAgB,UAGd,KAAQ,YAAe;CACvB,OAAO,OAAO,KAAK,IAAI,CAAC,QACrB,KAAK,KAAc,MAAM;EACxB,IAAI,OAAO,WAAW,IAAI,MAAM,KAAK,EAAE;EACvC,OAAO;IAGT,EAAE,CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"opacity.js","names":[],"sources":["../../src/utils/opacity.ts"],"sourcesContent":["import type { OpacityStep } from '@yahoo/uds-types';\nimport { clamp } from 'lodash';\n\n/**\n * Converts a number or string to a valid OpacityStep.\n *\n * Converts a number or string to a valid OpacityStep by:\n * - Parsing the value as an integer\n * - Clamping between 0 and 100\n * - Returning as a string in the format expected by OpacityStep\n *\n * @param opacity - The opacity value (number or string)\n * @returns A valid OpacityStep string clamped between 0-100\n * @throws {Error} If opacity is undefined, null, or cannot be parsed as a number\n */\nexport function parseOpacityStep(opacity: number | string | undefined): OpacityStep {\n if (opacity === undefined || opacity === null) {\n throw new Error(`Invalid opacity value: ${opacity}`);\n }\n\n const parsed = typeof opacity === 'number' ? opacity : parseInt(opacity, 10);\n\n if (isNaN(parsed)) {\n throw new Error(`Invalid opacity value: cannot parse \"${opacity}\" as a number`);\n }\n\n return clamp(parsed, 0, 100).toString() as OpacityStep;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAgB,iBAAiB,SAAmD;AAClF,KAAI,YAAY,KAAA,KAAa,YAAY,KACvC,OAAM,IAAI,MAAM,0BAA0B,UAAU;CAGtD,MAAM,SAAS,OAAO,YAAY,WAAW,UAAU,SAAS,SAAS,GAAG;AAE5E,KAAI,MAAM,OAAO,CACf,OAAM,IAAI,MAAM,wCAAwC,QAAQ,eAAe;AAGjF,QAAO,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU"}
1
+ {"version":3,"file":"opacity.js","names":[],"sources":["../../src/utils/opacity.ts"],"sourcesContent":["import type { OpacityStep } from '@yahoo/uds-types';\nimport { clamp } from 'lodash';\n\n/**\n * Converts a number or string to a valid OpacityStep.\n *\n * Converts a number or string to a valid OpacityStep by:\n * - Parsing the value as an integer\n * - Clamping between 0 and 100\n * - Returning as a string in the format expected by OpacityStep\n *\n * @param opacity - The opacity value (number or string)\n * @returns A valid OpacityStep string clamped between 0-100\n * @throws {Error} If opacity is undefined, null, or cannot be parsed as a number\n */\nexport function parseOpacityStep(opacity: number | string | undefined): OpacityStep {\n if (opacity === undefined || opacity === null) {\n throw new Error(`Invalid opacity value: ${opacity}`);\n }\n\n const parsed = typeof opacity === 'number' ? opacity : parseInt(opacity, 10);\n\n if (isNaN(parsed)) {\n throw new Error(`Invalid opacity value: cannot parse \"${opacity}\" as a number`);\n }\n\n return clamp(parsed, 0, 100).toString() as OpacityStep;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAgB,iBAAiB,SAAmD;CAClF,IAAI,YAAY,KAAA,KAAa,YAAY,MACvC,MAAM,IAAI,MAAM,0BAA0B,UAAU;CAGtD,MAAM,SAAS,OAAO,YAAY,WAAW,UAAU,SAAS,SAAS,GAAG;CAE5E,IAAI,MAAM,OAAO,EACf,MAAM,IAAI,MAAM,wCAAwC,QAAQ,eAAe;CAGjF,OAAO,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU"}
@@ -1 +1 @@
1
- {"version":3,"file":"optimizeCSS.js","names":[],"sources":["../../src/utils/optimizeCSS.ts"],"sourcesContent":["import { gzipSync } from 'node:zlib';\n\nimport type { AtRule, Declaration, Plugin, Root, Rule } from 'postcss';\nimport postcss from 'postcss';\n\n/**\n * Check if a selector is a \"meaningful\" selector (class, ID, attribute, or pseudo-class)\n * as opposed to just element/type selectors (like `code, kbd, pre` in preflight).\n * Meaningful selectors indicate the font is actually used by components, not just base reset.\n */\nfunction isMeaningfulSelector(selector: string): boolean {\n // Split compound selectors\n const parts = selector.split(',').map((s) => s.trim());\n\n for (const part of parts) {\n // Check if any part of the selector has class, ID, attribute, or custom pseudo-class\n // This indicates actual usage by components, not just preflight/reset\n if (\n part.includes('.') || // class selector\n part.includes('#') || // ID selector\n part.includes('[') || // attribute selector\n part.includes(':not(') || // complex pseudo-class\n part.includes(':where(') ||\n part.includes(':is(') ||\n part.includes(':has(')\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * PostCSS plugin to remove @font-face declarations for font families that are not used\n * anywhere in the CSS (excluding preflight/reset styles that only use element selectors).\n */\nfunction removeUnusedFontFaces(): Plugin {\n return {\n postcssPlugin: 'remove-unused-font-faces',\n Once(root: Root) {\n // Track font variables and whether they're used in meaningful selectors\n // Key: variable name (without --uds-font- prefix), Value: { used: boolean, meaningful: boolean }\n const fontVarUsage = new Map<string, { used: boolean; meaningful: boolean }>();\n\n // First pass: collect all font-family references from the CSS (excluding @font-face)\n const usedFontFamilies = new Set<string>();\n\n root.walkDecls('font-family', (decl) => {\n // Skip font-family declarations inside @font-face\n if (decl.parent?.type === 'atrule' && (decl.parent as AtRule).name === 'font-face') {\n return;\n }\n\n // Get the selector for this rule\n const rule = decl.parent as Rule;\n const selector = rule?.selector || '';\n const meaningful = isMeaningfulSelector(selector);\n\n // Parse font-family value to extract font names\n // Handles: \"Font Name\", 'Font Name', Font-Name, var(--uds-font-xxx)\n const value = decl.value;\n\n // Check for CSS variables that reference fonts\n const varMatches = value.matchAll(/var\\(--uds-font-([^),]+)\\)/g);\n for (const match of varMatches) {\n const varName = match[1];\n const existing = fontVarUsage.get(varName) || { used: false, meaningful: false };\n fontVarUsage.set(varName, {\n used: true,\n meaningful: existing.meaningful || meaningful,\n });\n }\n\n // Extract font family names (quoted or unquoted) - only if in meaningful selector\n if (meaningful) {\n const fontNames = value\n .split(',')\n .map((font) => font.trim())\n .map((font) => {\n // Remove quotes\n if (\n (font.startsWith('\"') && font.endsWith('\"')) ||\n (font.startsWith(\"'\") && font.endsWith(\"'\"))\n ) {\n return font.slice(1, -1);\n }\n // Skip var() references and generic families\n if (\n font.startsWith('var(') ||\n [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-monospace',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-rounded',\n ].includes(font.toLowerCase())\n ) {\n return null;\n }\n return font;\n })\n .filter(Boolean) as string[];\n\n fontNames.forEach((name) => usedFontFamilies.add(name));\n }\n });\n\n // Collect all font variable definitions for resolving nested references\n const fontVarDefinitions = new Map<string, string>();\n root.walkDecls((decl) => {\n if (\n decl.prop.startsWith('--uds-font-') &&\n !decl.prop.includes('size') &&\n !decl.prop.includes('weight') &&\n !decl.prop.includes('slant') &&\n !decl.prop.includes('width')\n ) {\n const varName = decl.prop.replace('--uds-font-', '');\n fontVarDefinitions.set(varName, decl.value);\n }\n });\n\n // Helper to resolve a variable value to actual font names (handles nested var() references)\n const resolveToFontNames = (value: string, visited = new Set<string>()): string[] => {\n const fontNames: string[] = [];\n\n // Check for nested var() references\n const varMatch = value.match(/var\\(--uds-font-([^),]+)\\)/);\n if (varMatch) {\n const nestedVarName = varMatch[1];\n // Prevent infinite loops\n if (!visited.has(nestedVarName)) {\n visited.add(nestedVarName);\n const nestedValue = fontVarDefinitions.get(nestedVarName);\n if (nestedValue) {\n // Mark the nested variable as used if parent is used\n const nestedUsage = fontVarUsage.get(nestedVarName);\n if (nestedUsage) {\n // Propagate meaningful status up the chain\n const parentUsage = fontVarUsage.get(\n value.replace(/var\\(--uds-font-([^),]+)\\).*/, '$1'),\n );\n if (parentUsage?.meaningful) {\n nestedUsage.meaningful = true;\n }\n }\n fontNames.push(...resolveToFontNames(nestedValue, visited));\n }\n }\n }\n\n // Extract actual font names from the value\n value\n .split(',')\n .map((font) => font.trim())\n .forEach((font) => {\n // Skip var() references (handled above)\n if (font.startsWith('var(')) {\n return;\n }\n\n // Remove quotes\n if (\n (font.startsWith('\"') && font.endsWith('\"')) ||\n (font.startsWith(\"'\") && font.endsWith(\"'\"))\n ) {\n font = font.slice(1, -1);\n }\n\n // Skip generic families\n if (\n [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-monospace',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-rounded',\n ].includes(font.toLowerCase())\n ) {\n return;\n }\n\n if (font) {\n fontNames.push(font);\n }\n });\n\n return fontNames;\n };\n\n // Process font variable definitions and resolve nested references\n for (const [varName, value] of fontVarDefinitions) {\n const usage = fontVarUsage.get(varName);\n\n // Only include fonts from this variable if it's used in a meaningful selector\n if (usage?.used && usage?.meaningful) {\n const fontNames = resolveToFontNames(value);\n fontNames.forEach((name) => usedFontFamilies.add(name));\n }\n }\n\n // Second pass: remove unused @font-face rules and track which fonts are kept\n const keptFonts = new Set<string>();\n root.walkAtRules('font-face', (atRule) => {\n let fontFamily: string | null = null;\n\n atRule.walkDecls('font-family', (decl) => {\n fontFamily = decl.value.replace(/[\"']/g, '').trim();\n });\n\n if (fontFamily && !usedFontFamilies.has(fontFamily)) {\n atRule.remove();\n } else if (fontFamily) {\n keptFonts.add(fontFamily);\n }\n });\n\n // Third pass: update CSS variable definitions to remove fonts that were not kept\n // This ensures variables like --uds-font-mono don't reference fonts we didn't load\n root.walkDecls((decl) => {\n if (\n decl.prop.startsWith('--uds-font-') &&\n !decl.prop.includes('size') &&\n !decl.prop.includes('weight') &&\n !decl.prop.includes('slant') &&\n !decl.prop.includes('width')\n ) {\n // Parse the font stack and filter out fonts that weren't kept\n const fonts = decl.value.split(',').map((f) => f.trim());\n const filteredFonts = fonts.filter((font) => {\n // Keep var() references\n if (font.startsWith('var(')) {\n return true;\n }\n\n // Extract font name (remove quotes)\n let fontName = font;\n if (\n (font.startsWith('\"') && font.endsWith('\"')) ||\n (font.startsWith(\"'\") && font.endsWith(\"'\"))\n ) {\n fontName = font.slice(1, -1);\n }\n\n // Keep generic font families\n if (\n [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-monospace',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-rounded',\n ].includes(fontName.toLowerCase())\n ) {\n return true;\n }\n\n // Keep fonts that have @font-face declarations\n return keptFonts.has(fontName);\n });\n\n // Update the declaration if fonts were removed\n if (filteredFonts.length < fonts.length && filteredFonts.length > 0) {\n decl.value = filteredFonts.join(', ');\n }\n }\n });\n },\n };\n}\n\nremoveUnusedFontFaces.postcss = true;\n\n/**\n * PostCSS plugin to remove redundant .uds-color-mode-light rules.\n * Light mode is the default (set on :root), so the explicit class is unnecessary.\n */\nfunction removeRedundantLightModePlugin(): Plugin {\n return {\n postcssPlugin: 'remove-redundant-light-mode',\n Once(root: Root) {\n root.walkRules((rule) => {\n // Match .uds-color-mode-light selector (exact match or as part of selector list)\n const selectors = rule.selector.split(',').map((s) => s.trim());\n const filteredSelectors = selectors.filter((s) => {\n // Remove selectors that are exactly .uds-color-mode-light\n // or .uds-color-mode-light with just :root/:where/:is wrappers\n const normalized = s.replace(/\\s+/g, ' ').trim();\n return (\n normalized !== '.uds-color-mode-light' &&\n normalized !== ':root .uds-color-mode-light' &&\n normalized !== ':where(.uds-color-mode-light)' &&\n normalized !== ':is(.uds-color-mode-light)'\n );\n });\n\n if (filteredSelectors.length === 0) {\n // All selectors were light mode - remove the entire rule\n rule.remove();\n } else if (filteredSelectors.length < selectors.length) {\n // Some selectors were light mode - update the selector\n rule.selector = filteredSelectors.join(', ');\n }\n });\n },\n };\n}\n\nremoveRedundantLightModePlugin.postcss = true;\n\n/**\n * PostCSS plugin to remove empty CSS rules (rules with no declarations).\n * Also aggregates duplicate selectors.\n */\nfunction removeEmptyRulesPlugin(): Plugin {\n return {\n postcssPlugin: 'remove-empty-rules',\n Once(root: Root) {\n // Remove empty rules\n root.walkRules((rule) => {\n // Check if rule has any declarations (not just comments or empty)\n const hasDeclarations = rule.nodes?.some(\n (node) => node.type === 'decl' || (node.type === 'rule' && node.nodes?.length > 0),\n );\n\n if (!hasDeclarations) {\n rule.remove();\n }\n });\n\n // Remove empty at-rules (like empty @media blocks)\n root.walkAtRules((atRule) => {\n if (atRule.name !== 'font-face' && atRule.name !== 'keyframes') {\n const hasContent = atRule.nodes?.some((node) => {\n if (node.type === 'rule') {\n return node.nodes?.some((n) => n.type === 'decl');\n }\n if (node.type === 'decl') {\n return true;\n }\n return false;\n });\n\n if (!hasContent && atRule.nodes?.length === 0) {\n atRule.remove();\n }\n }\n });\n },\n };\n}\n\nremoveEmptyRulesPlugin.postcss = true;\n\n/**\n * PostCSS plugin to aggregate rules with identical selectors.\n */\nfunction aggregateDuplicateSelectorsPlugin(): Plugin {\n return {\n postcssPlugin: 'aggregate-duplicate-selectors',\n Once(root: Root) {\n // Map of selector -> first rule with that selector\n const selectorMap = new Map<string, Rule>();\n\n // Collect rules to process (only top-level rules, not nested)\n const rulesToProcess: Rule[] = [];\n root.walkRules((rule) => {\n // Only process top-level rules (direct children of root or at-rules)\n if (rule.parent?.type === 'root' || rule.parent?.type === 'atrule') {\n rulesToProcess.push(rule);\n }\n });\n\n for (const rule of rulesToProcess) {\n const selector = rule.selector;\n const parent = rule.parent;\n\n // Create a unique key including the parent context\n const parentKey =\n parent?.type === 'atrule'\n ? `@${(parent as AtRule).name}:${(parent as AtRule).params}`\n : 'root';\n const key = `${parentKey}|${selector}`;\n\n if (selectorMap.has(key)) {\n const existingRule = selectorMap.get(key)!;\n\n // Move all declarations from current rule to existing rule\n rule.walkDecls((decl) => {\n // Check if the declaration already exists\n const existingDecl = existingRule.nodes?.find(\n (node): node is Declaration => node.type === 'decl' && node.prop === decl.prop,\n );\n\n if (existingDecl) {\n // Replace with new value\n existingDecl.value = decl.value;\n } else {\n // Append the declaration\n existingRule.append(decl.clone());\n }\n });\n\n // Remove the duplicate rule\n rule.remove();\n } else {\n selectorMap.set(key, rule);\n }\n }\n },\n };\n}\n\naggregateDuplicateSelectorsPlugin.postcss = true;\n\n/**\n * Validates CSS syntax and returns any errors found.\n */\nfunction validateCSS(css: string): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n try {\n // Parse the CSS to check for syntax errors\n const result = postcss.parse(css);\n\n // Check for common issues\n result.walkRules((rule) => {\n // Check for empty selectors\n if (!rule.selector.trim()) {\n errors.push(`Empty selector found at line ${rule.source?.start?.line}`);\n }\n\n // Check for malformed selectors\n try {\n // Basic selector validation - this catches obvious syntax errors\n if (rule.selector.includes('{{') || rule.selector.includes('}}')) {\n errors.push(`Malformed selector \"${rule.selector}\" at line ${rule.source?.start?.line}`);\n }\n } catch {\n errors.push(`Invalid selector \"${rule.selector}\" at line ${rule.source?.start?.line}`);\n }\n });\n\n // Check for unclosed blocks (postcss.parse will throw for these)\n result.walkDecls((decl) => {\n // Check for missing values\n if (!decl.value.trim()) {\n errors.push(`Empty value for property \"${decl.prop}\" at line ${decl.source?.start?.line}`);\n }\n });\n\n return { valid: errors.length === 0, errors };\n } catch (error) {\n if (error instanceof Error) {\n errors.push(`CSS Parse Error: ${error.message}`);\n } else {\n errors.push('Unknown CSS parse error');\n }\n return { valid: false, errors };\n }\n}\n\n/**\n * Reference data extracted from CSS for deduplication\n */\ninterface CSSReferenceData {\n /** Font-face fingerprints (font-family + src + weight + style) */\n fontFaces: Set<string>;\n /** Keyframes fingerprints (name + content) */\n keyframes: Set<string>;\n /** Regular rule fingerprints (selector + declarations) */\n rules: Set<string>;\n}\n\n/**\n * Create a fingerprint for a @font-face rule\n */\nfunction getFontFaceFingerprint(atRule: AtRule): string {\n let fontFamily = '';\n let src = '';\n let fontWeight = 'normal';\n let fontStyle = 'normal';\n\n atRule.walkDecls((decl) => {\n if (decl.prop === 'font-family') {\n fontFamily = decl.value.replace(/[\"']/g, '').trim();\n } else if (decl.prop === 'src') {\n src = decl.value;\n } else if (decl.prop === 'font-weight') {\n fontWeight = decl.value;\n } else if (decl.prop === 'font-style') {\n fontStyle = decl.value;\n }\n });\n\n return JSON.stringify({ fontFamily, src, fontWeight, fontStyle });\n}\n\n/**\n * Create a fingerprint for a @keyframes rule\n */\nfunction getKeyframesFingerprint(atRule: AtRule): string {\n // Use name + normalized content as fingerprint\n const name = atRule.params;\n const content = atRule.toString().replace(/\\s+/g, ' ').trim();\n return JSON.stringify({ name, content });\n}\n\n/**\n * Normalize a selector by removing scope prefix and whitespace\n */\nfunction normalizeSelector(selector: string, scopeClass?: string): string {\n let normalized = selector.trim();\n if (scopeClass) {\n // Remove scope prefix patterns like \".scope \" or \".scope.\"\n const escapedScope = scopeClass.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n normalized = normalized\n .replace(new RegExp(`${escapedScope}\\\\s+`, 'g'), '')\n .replace(new RegExp(`${escapedScope}\\\\.`, 'g'), '.')\n .replace(new RegExp(`${escapedScope}`, 'g'), '');\n }\n return normalized.replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Create a fingerprint for a CSS rule (selector + declarations)\n */\nfunction getRuleFingerprint(rule: Rule, scopeClass?: string): string {\n const selector = normalizeSelector(rule.selector, scopeClass);\n const declarations: string[] = [];\n\n rule.walkDecls((decl) => {\n declarations.push(`${decl.prop}:${decl.value}`);\n });\n\n // Sort declarations for consistent comparison\n declarations.sort();\n return JSON.stringify({ selector, declarations });\n}\n\n/**\n * Extract reference data from CSS for deduplication\n */\nfunction extractCSSReferenceData(css: string, scopeClass?: string): CSSReferenceData {\n const data: CSSReferenceData = {\n fontFaces: new Set(),\n keyframes: new Set(),\n rules: new Set(),\n };\n\n try {\n const root = postcss.parse(css);\n\n root.walkAtRules((atRule) => {\n if (atRule.name === 'font-face') {\n data.fontFaces.add(getFontFaceFingerprint(atRule));\n } else if (atRule.name === 'keyframes' || atRule.name === '-webkit-keyframes') {\n data.keyframes.add(getKeyframesFingerprint(atRule));\n }\n });\n\n root.walkRules((rule) => {\n // Skip rules inside @font-face or @keyframes\n if (rule.parent?.type === 'atrule') {\n const parentName = (rule.parent as AtRule).name;\n if (\n parentName === 'font-face' ||\n parentName === 'keyframes' ||\n parentName === '-webkit-keyframes'\n ) {\n return;\n }\n }\n data.rules.add(getRuleFingerprint(rule, scopeClass));\n });\n } catch {\n // If parsing fails, return empty data\n }\n\n return data;\n}\n\n/**\n * PostCSS plugin to remove CSS that exists in reference CSS\n * Handles @font-face, @keyframes, and regular rule deduplication\n */\nfunction removeDuplicateCss(referenceData: CSSReferenceData, scopeClass?: string): Plugin {\n return {\n postcssPlugin: 'remove-duplicate-css',\n Once(root: Root) {\n const toRemove: (AtRule | Rule)[] = [];\n\n root.walkAtRules((atRule) => {\n if (atRule.name === 'font-face') {\n const fingerprint = getFontFaceFingerprint(atRule);\n if (referenceData.fontFaces.has(fingerprint)) {\n toRemove.push(atRule);\n }\n } else if (atRule.name === 'keyframes' || atRule.name === '-webkit-keyframes') {\n const fingerprint = getKeyframesFingerprint(atRule);\n if (referenceData.keyframes.has(fingerprint)) {\n toRemove.push(atRule);\n }\n }\n });\n\n root.walkRules((rule) => {\n // Skip rules inside @font-face or @keyframes\n if (rule.parent?.type === 'atrule') {\n const parentName = (rule.parent as AtRule).name;\n if (\n parentName === 'font-face' ||\n parentName === 'keyframes' ||\n parentName === '-webkit-keyframes'\n ) {\n return;\n }\n }\n\n const fingerprint = getRuleFingerprint(rule, scopeClass);\n if (referenceData.rules.has(fingerprint)) {\n toRemove.push(rule);\n }\n });\n\n // Remove duplicates\n for (const node of toRemove) {\n node.remove();\n }\n },\n };\n}\n\n/**\n * Options for CSS optimization\n */\ninterface OptimizeCSSOptions {\n /** Remove unused @font-face declarations (default: true) */\n removeUnusedFonts?: boolean;\n /** Remove empty CSS rules (default: true) */\n removeEmptyRules?: boolean;\n /** Aggregate duplicate selectors (default: true) */\n aggregateDuplicateSelectors?: boolean;\n /** Reference CSS to deduplicate against (for scoped CSS) */\n referenceCss?: string;\n /** Scope class used in this CSS (for normalizing selectors during deduplication) */\n scopeClass?: string;\n}\n\n/**\n * Optimizes CSS by:\n * 1. Removing unused @font-face declarations\n * 2. Removing empty rules\n * 3. Aggregating duplicate selectors\n *\n * Returns the optimized CSS and validation results.\n */\nasync function optimizeCSS(\n css: string,\n options?: OptimizeCSSOptions,\n): Promise<{\n css: string;\n validation: { valid: boolean; errors: string[] };\n stats: {\n originalSize: number;\n originalSizeGzip: number;\n optimizedSize: number;\n fontFacesRemoved: number;\n emptyRulesRemoved: number;\n };\n}> {\n const originalSize = Buffer.byteLength(css, 'utf8');\n const originalSizeGzip = gzipSync(css).length;\n\n // Count font-faces before\n const fontFacesBefore = (css.match(/@font-face/g) || []).length;\n\n // Count rules before (rough estimate)\n const rulesBefore = (css.match(/\\{[^}]*\\}/g) || []).length;\n\n // Build list of plugins based on options (all enabled by default)\n const plugins: postcss.AcceptedPlugin[] = [];\n\n if (options?.removeUnusedFonts !== false) {\n plugins.push(removeUnusedFontFaces());\n }\n\n // Remove redundant .uds-color-mode-light rules (light is default on :root)\n plugins.push(removeRedundantLightModePlugin());\n\n // If reference CSS is provided, deduplicate all matching CSS (font-faces, keyframes, rules)\n if (options?.referenceCss) {\n const referenceData = extractCSSReferenceData(options.referenceCss);\n if (\n referenceData.fontFaces.size > 0 ||\n referenceData.keyframes.size > 0 ||\n referenceData.rules.size > 0\n ) {\n plugins.push(removeDuplicateCss(referenceData, options.scopeClass));\n }\n }\n\n if (options?.removeEmptyRules !== false) {\n plugins.push(removeEmptyRulesPlugin());\n }\n\n if (options?.aggregateDuplicateSelectors !== false) {\n plugins.push(aggregateDuplicateSelectorsPlugin());\n }\n\n // Apply optimizations\n const result =\n plugins.length > 0 ? await postcss(plugins).process(css, { from: undefined }) : { css };\n\n const optimizedCSS = result.css;\n const optimizedSize = Buffer.byteLength(optimizedCSS, 'utf8');\n\n // Count font-faces after\n const fontFacesAfter = (optimizedCSS.match(/@font-face/g) || []).length;\n\n // Count rules after\n const rulesAfter = (optimizedCSS.match(/\\{[^}]*\\}/g) || []).length;\n\n // Validate the result\n const validation = validateCSS(optimizedCSS);\n\n return {\n css: optimizedCSS,\n validation,\n stats: {\n originalSize,\n originalSizeGzip,\n optimizedSize,\n fontFacesRemoved: fontFacesBefore - fontFacesAfter,\n emptyRulesRemoved: Math.max(0, rulesBefore - rulesAfter),\n },\n };\n}\n\nexport {\n aggregateDuplicateSelectorsPlugin as aggregateDuplicateSelectors,\n optimizeCSS,\n type OptimizeCSSOptions,\n removeEmptyRulesPlugin as removeEmptyRules,\n removeUnusedFontFaces,\n validateCSS,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"optimizeCSS.js","names":[],"sources":["../../src/utils/optimizeCSS.ts"],"sourcesContent":["import { gzipSync } from 'node:zlib';\n\nimport type { AtRule, Declaration, Plugin, Root, Rule } from 'postcss';\nimport postcss from 'postcss';\n\n/**\n * Check if a selector is a \"meaningful\" selector (class, ID, attribute, or pseudo-class)\n * as opposed to just element/type selectors (like `code, kbd, pre` in preflight).\n * Meaningful selectors indicate the font is actually used by components, not just base reset.\n */\nfunction isMeaningfulSelector(selector: string): boolean {\n // Split compound selectors\n const parts = selector.split(',').map((s) => s.trim());\n\n for (const part of parts) {\n // Check if any part of the selector has class, ID, attribute, or custom pseudo-class\n // This indicates actual usage by components, not just preflight/reset\n if (\n part.includes('.') || // class selector\n part.includes('#') || // ID selector\n part.includes('[') || // attribute selector\n part.includes(':not(') || // complex pseudo-class\n part.includes(':where(') ||\n part.includes(':is(') ||\n part.includes(':has(')\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * PostCSS plugin to remove @font-face declarations for font families that are not used\n * anywhere in the CSS (excluding preflight/reset styles that only use element selectors).\n */\nfunction removeUnusedFontFaces(): Plugin {\n return {\n postcssPlugin: 'remove-unused-font-faces',\n Once(root: Root) {\n // Track font variables and whether they're used in meaningful selectors\n // Key: variable name (without --uds-font- prefix), Value: { used: boolean, meaningful: boolean }\n const fontVarUsage = new Map<string, { used: boolean; meaningful: boolean }>();\n\n // First pass: collect all font-family references from the CSS (excluding @font-face)\n const usedFontFamilies = new Set<string>();\n\n root.walkDecls('font-family', (decl) => {\n // Skip font-family declarations inside @font-face\n if (decl.parent?.type === 'atrule' && (decl.parent as AtRule).name === 'font-face') {\n return;\n }\n\n // Get the selector for this rule\n const rule = decl.parent as Rule;\n const selector = rule?.selector || '';\n const meaningful = isMeaningfulSelector(selector);\n\n // Parse font-family value to extract font names\n // Handles: \"Font Name\", 'Font Name', Font-Name, var(--uds-font-xxx)\n const value = decl.value;\n\n // Check for CSS variables that reference fonts\n const varMatches = value.matchAll(/var\\(--uds-font-([^),]+)\\)/g);\n for (const match of varMatches) {\n const varName = match[1];\n const existing = fontVarUsage.get(varName) || { used: false, meaningful: false };\n fontVarUsage.set(varName, {\n used: true,\n meaningful: existing.meaningful || meaningful,\n });\n }\n\n // Extract font family names (quoted or unquoted) - only if in meaningful selector\n if (meaningful) {\n const fontNames = value\n .split(',')\n .map((font) => font.trim())\n .map((font) => {\n // Remove quotes\n if (\n (font.startsWith('\"') && font.endsWith('\"')) ||\n (font.startsWith(\"'\") && font.endsWith(\"'\"))\n ) {\n return font.slice(1, -1);\n }\n // Skip var() references and generic families\n if (\n font.startsWith('var(') ||\n [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-monospace',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-rounded',\n ].includes(font.toLowerCase())\n ) {\n return null;\n }\n return font;\n })\n .filter(Boolean) as string[];\n\n fontNames.forEach((name) => usedFontFamilies.add(name));\n }\n });\n\n // Collect all font variable definitions for resolving nested references\n const fontVarDefinitions = new Map<string, string>();\n root.walkDecls((decl) => {\n if (\n decl.prop.startsWith('--uds-font-') &&\n !decl.prop.includes('size') &&\n !decl.prop.includes('weight') &&\n !decl.prop.includes('slant') &&\n !decl.prop.includes('width')\n ) {\n const varName = decl.prop.replace('--uds-font-', '');\n fontVarDefinitions.set(varName, decl.value);\n }\n });\n\n // Helper to resolve a variable value to actual font names (handles nested var() references)\n const resolveToFontNames = (value: string, visited = new Set<string>()): string[] => {\n const fontNames: string[] = [];\n\n // Check for nested var() references\n const varMatch = value.match(/var\\(--uds-font-([^),]+)\\)/);\n if (varMatch) {\n const nestedVarName = varMatch[1];\n // Prevent infinite loops\n if (!visited.has(nestedVarName)) {\n visited.add(nestedVarName);\n const nestedValue = fontVarDefinitions.get(nestedVarName);\n if (nestedValue) {\n // Mark the nested variable as used if parent is used\n const nestedUsage = fontVarUsage.get(nestedVarName);\n if (nestedUsage) {\n // Propagate meaningful status up the chain\n const parentUsage = fontVarUsage.get(\n value.replace(/var\\(--uds-font-([^),]+)\\).*/, '$1'),\n );\n if (parentUsage?.meaningful) {\n nestedUsage.meaningful = true;\n }\n }\n fontNames.push(...resolveToFontNames(nestedValue, visited));\n }\n }\n }\n\n // Extract actual font names from the value\n value\n .split(',')\n .map((font) => font.trim())\n .forEach((font) => {\n // Skip var() references (handled above)\n if (font.startsWith('var(')) {\n return;\n }\n\n // Remove quotes\n if (\n (font.startsWith('\"') && font.endsWith('\"')) ||\n (font.startsWith(\"'\") && font.endsWith(\"'\"))\n ) {\n font = font.slice(1, -1);\n }\n\n // Skip generic families\n if (\n [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-monospace',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-rounded',\n ].includes(font.toLowerCase())\n ) {\n return;\n }\n\n if (font) {\n fontNames.push(font);\n }\n });\n\n return fontNames;\n };\n\n // Process font variable definitions and resolve nested references\n for (const [varName, value] of fontVarDefinitions) {\n const usage = fontVarUsage.get(varName);\n\n // Only include fonts from this variable if it's used in a meaningful selector\n if (usage?.used && usage?.meaningful) {\n const fontNames = resolveToFontNames(value);\n fontNames.forEach((name) => usedFontFamilies.add(name));\n }\n }\n\n // Second pass: remove unused @font-face rules and track which fonts are kept\n const keptFonts = new Set<string>();\n root.walkAtRules('font-face', (atRule) => {\n let fontFamily: string | null = null;\n\n atRule.walkDecls('font-family', (decl) => {\n fontFamily = decl.value.replace(/[\"']/g, '').trim();\n });\n\n if (fontFamily && !usedFontFamilies.has(fontFamily)) {\n atRule.remove();\n } else if (fontFamily) {\n keptFonts.add(fontFamily);\n }\n });\n\n // Third pass: update CSS variable definitions to remove fonts that were not kept\n // This ensures variables like --uds-font-mono don't reference fonts we didn't load\n root.walkDecls((decl) => {\n if (\n decl.prop.startsWith('--uds-font-') &&\n !decl.prop.includes('size') &&\n !decl.prop.includes('weight') &&\n !decl.prop.includes('slant') &&\n !decl.prop.includes('width')\n ) {\n // Parse the font stack and filter out fonts that weren't kept\n const fonts = decl.value.split(',').map((f) => f.trim());\n const filteredFonts = fonts.filter((font) => {\n // Keep var() references\n if (font.startsWith('var(')) {\n return true;\n }\n\n // Extract font name (remove quotes)\n let fontName = font;\n if (\n (font.startsWith('\"') && font.endsWith('\"')) ||\n (font.startsWith(\"'\") && font.endsWith(\"'\"))\n ) {\n fontName = font.slice(1, -1);\n }\n\n // Keep generic font families\n if (\n [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-monospace',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-rounded',\n ].includes(fontName.toLowerCase())\n ) {\n return true;\n }\n\n // Keep fonts that have @font-face declarations\n return keptFonts.has(fontName);\n });\n\n // Update the declaration if fonts were removed\n if (filteredFonts.length < fonts.length && filteredFonts.length > 0) {\n decl.value = filteredFonts.join(', ');\n }\n }\n });\n },\n };\n}\n\nremoveUnusedFontFaces.postcss = true;\n\n/**\n * PostCSS plugin to remove redundant .uds-color-mode-light rules.\n * Light mode is the default (set on :root), so the explicit class is unnecessary.\n */\nfunction removeRedundantLightModePlugin(): Plugin {\n return {\n postcssPlugin: 'remove-redundant-light-mode',\n Once(root: Root) {\n root.walkRules((rule) => {\n // Match .uds-color-mode-light selector (exact match or as part of selector list)\n const selectors = rule.selector.split(',').map((s) => s.trim());\n const filteredSelectors = selectors.filter((s) => {\n // Remove selectors that are exactly .uds-color-mode-light\n // or .uds-color-mode-light with just :root/:where/:is wrappers\n const normalized = s.replace(/\\s+/g, ' ').trim();\n return (\n normalized !== '.uds-color-mode-light' &&\n normalized !== ':root .uds-color-mode-light' &&\n normalized !== ':where(.uds-color-mode-light)' &&\n normalized !== ':is(.uds-color-mode-light)'\n );\n });\n\n if (filteredSelectors.length === 0) {\n // All selectors were light mode - remove the entire rule\n rule.remove();\n } else if (filteredSelectors.length < selectors.length) {\n // Some selectors were light mode - update the selector\n rule.selector = filteredSelectors.join(', ');\n }\n });\n },\n };\n}\n\nremoveRedundantLightModePlugin.postcss = true;\n\n/**\n * PostCSS plugin to remove empty CSS rules (rules with no declarations).\n * Also aggregates duplicate selectors.\n */\nfunction removeEmptyRulesPlugin(): Plugin {\n return {\n postcssPlugin: 'remove-empty-rules',\n Once(root: Root) {\n // Remove empty rules\n root.walkRules((rule) => {\n // Check if rule has any declarations (not just comments or empty)\n const hasDeclarations = rule.nodes?.some(\n (node) => node.type === 'decl' || (node.type === 'rule' && node.nodes?.length > 0),\n );\n\n if (!hasDeclarations) {\n rule.remove();\n }\n });\n\n // Remove empty at-rules (like empty @media blocks)\n root.walkAtRules((atRule) => {\n if (atRule.name !== 'font-face' && atRule.name !== 'keyframes') {\n const hasContent = atRule.nodes?.some((node) => {\n if (node.type === 'rule') {\n return node.nodes?.some((n) => n.type === 'decl');\n }\n if (node.type === 'decl') {\n return true;\n }\n return false;\n });\n\n if (!hasContent && atRule.nodes?.length === 0) {\n atRule.remove();\n }\n }\n });\n },\n };\n}\n\nremoveEmptyRulesPlugin.postcss = true;\n\n/**\n * PostCSS plugin to aggregate rules with identical selectors.\n */\nfunction aggregateDuplicateSelectorsPlugin(): Plugin {\n return {\n postcssPlugin: 'aggregate-duplicate-selectors',\n Once(root: Root) {\n // Map of selector -> first rule with that selector\n const selectorMap = new Map<string, Rule>();\n\n // Collect rules to process (only top-level rules, not nested)\n const rulesToProcess: Rule[] = [];\n root.walkRules((rule) => {\n // Only process top-level rules (direct children of root or at-rules)\n if (rule.parent?.type === 'root' || rule.parent?.type === 'atrule') {\n rulesToProcess.push(rule);\n }\n });\n\n for (const rule of rulesToProcess) {\n const selector = rule.selector;\n const parent = rule.parent;\n\n // Create a unique key including the parent context\n const parentKey =\n parent?.type === 'atrule'\n ? `@${(parent as AtRule).name}:${(parent as AtRule).params}`\n : 'root';\n const key = `${parentKey}|${selector}`;\n\n if (selectorMap.has(key)) {\n const existingRule = selectorMap.get(key)!;\n\n // Move all declarations from current rule to existing rule\n rule.walkDecls((decl) => {\n // Check if the declaration already exists\n const existingDecl = existingRule.nodes?.find(\n (node): node is Declaration => node.type === 'decl' && node.prop === decl.prop,\n );\n\n if (existingDecl) {\n // Replace with new value\n existingDecl.value = decl.value;\n } else {\n // Append the declaration\n existingRule.append(decl.clone());\n }\n });\n\n // Remove the duplicate rule\n rule.remove();\n } else {\n selectorMap.set(key, rule);\n }\n }\n },\n };\n}\n\naggregateDuplicateSelectorsPlugin.postcss = true;\n\n/**\n * Validates CSS syntax and returns any errors found.\n */\nfunction validateCSS(css: string): { valid: boolean; errors: string[] } {\n const errors: string[] = [];\n\n try {\n // Parse the CSS to check for syntax errors\n const result = postcss.parse(css);\n\n // Check for common issues\n result.walkRules((rule) => {\n // Check for empty selectors\n if (!rule.selector.trim()) {\n errors.push(`Empty selector found at line ${rule.source?.start?.line}`);\n }\n\n // Check for malformed selectors\n try {\n // Basic selector validation - this catches obvious syntax errors\n if (rule.selector.includes('{{') || rule.selector.includes('}}')) {\n errors.push(`Malformed selector \"${rule.selector}\" at line ${rule.source?.start?.line}`);\n }\n } catch {\n errors.push(`Invalid selector \"${rule.selector}\" at line ${rule.source?.start?.line}`);\n }\n });\n\n // Check for unclosed blocks (postcss.parse will throw for these)\n result.walkDecls((decl) => {\n // Check for missing values\n if (!decl.value.trim()) {\n errors.push(`Empty value for property \"${decl.prop}\" at line ${decl.source?.start?.line}`);\n }\n });\n\n return { valid: errors.length === 0, errors };\n } catch (error) {\n if (error instanceof Error) {\n errors.push(`CSS Parse Error: ${error.message}`);\n } else {\n errors.push('Unknown CSS parse error');\n }\n return { valid: false, errors };\n }\n}\n\n/**\n * Reference data extracted from CSS for deduplication\n */\ninterface CSSReferenceData {\n /** Font-face fingerprints (font-family + src + weight + style) */\n fontFaces: Set<string>;\n /** Keyframes fingerprints (name + content) */\n keyframes: Set<string>;\n /** Regular rule fingerprints (selector + declarations) */\n rules: Set<string>;\n}\n\n/**\n * Create a fingerprint for a @font-face rule\n */\nfunction getFontFaceFingerprint(atRule: AtRule): string {\n let fontFamily = '';\n let src = '';\n let fontWeight = 'normal';\n let fontStyle = 'normal';\n\n atRule.walkDecls((decl) => {\n if (decl.prop === 'font-family') {\n fontFamily = decl.value.replace(/[\"']/g, '').trim();\n } else if (decl.prop === 'src') {\n src = decl.value;\n } else if (decl.prop === 'font-weight') {\n fontWeight = decl.value;\n } else if (decl.prop === 'font-style') {\n fontStyle = decl.value;\n }\n });\n\n return JSON.stringify({ fontFamily, src, fontWeight, fontStyle });\n}\n\n/**\n * Create a fingerprint for a @keyframes rule\n */\nfunction getKeyframesFingerprint(atRule: AtRule): string {\n // Use name + normalized content as fingerprint\n const name = atRule.params;\n const content = atRule.toString().replace(/\\s+/g, ' ').trim();\n return JSON.stringify({ name, content });\n}\n\n/**\n * Normalize a selector by removing scope prefix and whitespace\n */\nfunction normalizeSelector(selector: string, scopeClass?: string): string {\n let normalized = selector.trim();\n if (scopeClass) {\n // Remove scope prefix patterns like \".scope \" or \".scope.\"\n const escapedScope = scopeClass.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n normalized = normalized\n .replace(new RegExp(`${escapedScope}\\\\s+`, 'g'), '')\n .replace(new RegExp(`${escapedScope}\\\\.`, 'g'), '.')\n .replace(new RegExp(`${escapedScope}`, 'g'), '');\n }\n return normalized.replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Create a fingerprint for a CSS rule (selector + declarations)\n */\nfunction getRuleFingerprint(rule: Rule, scopeClass?: string): string {\n const selector = normalizeSelector(rule.selector, scopeClass);\n const declarations: string[] = [];\n\n rule.walkDecls((decl) => {\n declarations.push(`${decl.prop}:${decl.value}`);\n });\n\n // Sort declarations for consistent comparison\n declarations.sort();\n return JSON.stringify({ selector, declarations });\n}\n\n/**\n * Extract reference data from CSS for deduplication\n */\nfunction extractCSSReferenceData(css: string, scopeClass?: string): CSSReferenceData {\n const data: CSSReferenceData = {\n fontFaces: new Set(),\n keyframes: new Set(),\n rules: new Set(),\n };\n\n try {\n const root = postcss.parse(css);\n\n root.walkAtRules((atRule) => {\n if (atRule.name === 'font-face') {\n data.fontFaces.add(getFontFaceFingerprint(atRule));\n } else if (atRule.name === 'keyframes' || atRule.name === '-webkit-keyframes') {\n data.keyframes.add(getKeyframesFingerprint(atRule));\n }\n });\n\n root.walkRules((rule) => {\n // Skip rules inside @font-face or @keyframes\n if (rule.parent?.type === 'atrule') {\n const parentName = (rule.parent as AtRule).name;\n if (\n parentName === 'font-face' ||\n parentName === 'keyframes' ||\n parentName === '-webkit-keyframes'\n ) {\n return;\n }\n }\n data.rules.add(getRuleFingerprint(rule, scopeClass));\n });\n } catch {\n // If parsing fails, return empty data\n }\n\n return data;\n}\n\n/**\n * PostCSS plugin to remove CSS that exists in reference CSS\n * Handles @font-face, @keyframes, and regular rule deduplication\n */\nfunction removeDuplicateCss(referenceData: CSSReferenceData, scopeClass?: string): Plugin {\n return {\n postcssPlugin: 'remove-duplicate-css',\n Once(root: Root) {\n const toRemove: (AtRule | Rule)[] = [];\n\n root.walkAtRules((atRule) => {\n if (atRule.name === 'font-face') {\n const fingerprint = getFontFaceFingerprint(atRule);\n if (referenceData.fontFaces.has(fingerprint)) {\n toRemove.push(atRule);\n }\n } else if (atRule.name === 'keyframes' || atRule.name === '-webkit-keyframes') {\n const fingerprint = getKeyframesFingerprint(atRule);\n if (referenceData.keyframes.has(fingerprint)) {\n toRemove.push(atRule);\n }\n }\n });\n\n root.walkRules((rule) => {\n // Skip rules inside @font-face or @keyframes\n if (rule.parent?.type === 'atrule') {\n const parentName = (rule.parent as AtRule).name;\n if (\n parentName === 'font-face' ||\n parentName === 'keyframes' ||\n parentName === '-webkit-keyframes'\n ) {\n return;\n }\n }\n\n const fingerprint = getRuleFingerprint(rule, scopeClass);\n if (referenceData.rules.has(fingerprint)) {\n toRemove.push(rule);\n }\n });\n\n // Remove duplicates\n for (const node of toRemove) {\n node.remove();\n }\n },\n };\n}\n\n/**\n * Options for CSS optimization\n */\ninterface OptimizeCSSOptions {\n /** Remove unused @font-face declarations (default: true) */\n removeUnusedFonts?: boolean;\n /** Remove empty CSS rules (default: true) */\n removeEmptyRules?: boolean;\n /** Aggregate duplicate selectors (default: true) */\n aggregateDuplicateSelectors?: boolean;\n /** Reference CSS to deduplicate against (for scoped CSS) */\n referenceCss?: string;\n /** Scope class used in this CSS (for normalizing selectors during deduplication) */\n scopeClass?: string;\n}\n\n/**\n * Optimizes CSS by:\n * 1. Removing unused @font-face declarations\n * 2. Removing empty rules\n * 3. Aggregating duplicate selectors\n *\n * Returns the optimized CSS and validation results.\n */\nasync function optimizeCSS(\n css: string,\n options?: OptimizeCSSOptions,\n): Promise<{\n css: string;\n validation: { valid: boolean; errors: string[] };\n stats: {\n originalSize: number;\n originalSizeGzip: number;\n optimizedSize: number;\n fontFacesRemoved: number;\n emptyRulesRemoved: number;\n };\n}> {\n const originalSize = Buffer.byteLength(css, 'utf8');\n const originalSizeGzip = gzipSync(css).length;\n\n // Count font-faces before\n const fontFacesBefore = (css.match(/@font-face/g) || []).length;\n\n // Count rules before (rough estimate)\n const rulesBefore = (css.match(/\\{[^}]*\\}/g) || []).length;\n\n // Build list of plugins based on options (all enabled by default)\n const plugins: postcss.AcceptedPlugin[] = [];\n\n if (options?.removeUnusedFonts !== false) {\n plugins.push(removeUnusedFontFaces());\n }\n\n // Remove redundant .uds-color-mode-light rules (light is default on :root)\n plugins.push(removeRedundantLightModePlugin());\n\n // If reference CSS is provided, deduplicate all matching CSS (font-faces, keyframes, rules)\n if (options?.referenceCss) {\n const referenceData = extractCSSReferenceData(options.referenceCss);\n if (\n referenceData.fontFaces.size > 0 ||\n referenceData.keyframes.size > 0 ||\n referenceData.rules.size > 0\n ) {\n plugins.push(removeDuplicateCss(referenceData, options.scopeClass));\n }\n }\n\n if (options?.removeEmptyRules !== false) {\n plugins.push(removeEmptyRulesPlugin());\n }\n\n if (options?.aggregateDuplicateSelectors !== false) {\n plugins.push(aggregateDuplicateSelectorsPlugin());\n }\n\n // Apply optimizations\n const result =\n plugins.length > 0 ? await postcss(plugins).process(css, { from: undefined }) : { css };\n\n const optimizedCSS = result.css;\n const optimizedSize = Buffer.byteLength(optimizedCSS, 'utf8');\n\n // Count font-faces after\n const fontFacesAfter = (optimizedCSS.match(/@font-face/g) || []).length;\n\n // Count rules after\n const rulesAfter = (optimizedCSS.match(/\\{[^}]*\\}/g) || []).length;\n\n // Validate the result\n const validation = validateCSS(optimizedCSS);\n\n return {\n css: optimizedCSS,\n validation,\n stats: {\n originalSize,\n originalSizeGzip,\n optimizedSize,\n fontFacesRemoved: fontFacesBefore - fontFacesAfter,\n emptyRulesRemoved: Math.max(0, rulesBefore - rulesAfter),\n },\n };\n}\n\nexport {\n aggregateDuplicateSelectorsPlugin as aggregateDuplicateSelectors,\n optimizeCSS,\n type OptimizeCSSOptions,\n removeEmptyRulesPlugin as removeEmptyRules,\n removeUnusedFontFaces,\n validateCSS,\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"parseTokens.js","names":[],"sources":["../../src/utils/parseTokens.ts"],"sourcesContent":["import type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport {\n AVATAR_SIZE_PREFIX,\n BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX,\n BACKGROUND_BLUR_RADIUS_PREFIX,\n BACKGROUND_COLOR_PREFIX,\n BORDER_RADIUS_PREFIX,\n BORDER_WIDTH_PREFIX,\n DROP_SHADOW_PREFIX,\n getShadowLayerValue,\n ICON_SIZE_PREFIX,\n INSET_SHADOW_PREFIX,\n LINE_COLOR_PREFIX,\n OUTLINE_PREFIX,\n SPECTRUM_COLOR_PREFIX,\n UDS_PREFIX,\n} from '@yahoo/uds-css-tokens';\nimport { alwaysPalette } from '@yahoo/uds-palette';\nimport type {\n ColorMode,\n ColorsConfig,\n ElevationLevel,\n ElevationPreset,\n FocusRingColor,\n FocusRingConfig,\n Hue,\n HueStep,\n OpacityStep,\n PaletteConfig,\n PaletteType,\n ScaleMode,\n} from '@yahoo/uds-types';\n\nimport { entries } from './entries';\nimport { mapValues } from './mapValues';\nimport { parseOpacityStep } from './opacity';\n\n/** Converts a SpectrumValueEntry to a space-separated RGB string for CSS variables. */\nfunction spectrumValueToRgbString(value: { rgb: { r: number; g: number; b: number } }): string {\n const { r, g, b } = value.rgb;\n return `${r} ${g} ${b}`;\n}\n\nfunction shouldIncludeOpacity(opacity: OpacityStep | undefined): boolean {\n if (!opacity) {\n return false;\n }\n\n const parsedOpacity = parseInt(opacity, 10);\n return !isNaN(parsedOpacity) && parsedOpacity !== 100;\n}\n\ntype ColorModeElevationPresets = Partial<Record<ElevationLevel, ElevationPreset>>;\n\nfunction resolveFocusRingColor(color: FocusRingColor): string {\n switch (color.type) {\n case 'spectrum':\n return `rgb(var(--${SPECTRUM_COLOR_PREFIX}-${color.value.hue}-${color.value.step}))`;\n case 'line':\n return `rgb(var(--${LINE_COLOR_PREFIX}-${color.value}))`;\n case 'always':\n return alwaysPalette[color.value as keyof typeof alwaysPalette];\n default:\n return `rgb(var(--${SPECTRUM_COLOR_PREFIX}-gray-15))`;\n }\n}\n\nfunction transformColors(\n colors: ColorsConfig,\n elevationPresets: ColorModeElevationPresets,\n focusRingConfig?: FocusRingConfig,\n) {\n const { palette, spectrum } = colors;\n const rootVars: Record<string, string> = {};\n const tailwindConfig = {\n spectrum: {} as Record<Hue, Record<HueStep, string>>,\n palette: {} as {\n [key in PaletteType]: Record<keyof PaletteConfig[key], string>;\n },\n };\n\n for (const [hue, hueSteps] of entries(spectrum)) {\n for (const [hueStep, value] of entries(hueSteps)) {\n const name = `${hue}-${hueStep}`;\n const varKey = `--${SPECTRUM_COLOR_PREFIX}-${name}`;\n if (!tailwindConfig.spectrum[hue]) {\n tailwindConfig.spectrum[hue] = {} as Record<HueStep, string>;\n }\n tailwindConfig.spectrum[hue][hueStep] = `rgb(var(${varKey}))`;\n rootVars[varKey] = spectrumValueToRgbString(value);\n }\n }\n\n entries(palette).forEach(([paletteType, paletteConfig]) => {\n for (const [paletteKey, { hue, step, opacity }] of Object.entries(paletteConfig)) {\n if (!(paletteType in tailwindConfig.palette)) {\n // @ts-expect-error we fill this object later\n tailwindConfig.palette[paletteType] = {};\n }\n const name = `--${UDS_PREFIX}-${paletteType}-color-${paletteKey}`;\n rootVars[name] = `var(--${SPECTRUM_COLOR_PREFIX}-${hue}-${step})`;\n const opacityValue = opacity !== undefined ? parseOpacityStep(opacity) : undefined;\n // @ts-expect-error this is fine\n tailwindConfig.palette[paletteType][paletteKey] = shouldIncludeOpacity(opacityValue)\n ? `rgb(var(${name}) / ${opacityValue}%)`\n : `rgb(var(${name}))`;\n }\n });\n\n // Elevation levels\n entries(elevationPresets).forEach(([level, elevationPreset]) => {\n if (elevationPreset) {\n entries(elevationPreset).forEach(([key]) => {\n // background color\n if (key === 'finalBackgroundValue') {\n const { r, g, b, a } = elevationPreset[key];\n const alpha = parseInt(a) / 100;\n const name = `--${BACKGROUND_COLOR_PREFIX}-elevation-${level}`;\n rootVars[name] = `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n // border color\n if (key === 'borderColor') {\n const name = `--${LINE_COLOR_PREFIX}-elevation-${level}`;\n\n switch (elevationPreset[key].type) {\n case 'always':\n rootVars[name] = alwaysPalette[elevationPreset[key].value];\n break;\n case 'spectrum':\n rootVars[name] =\n `rgb(var(--${SPECTRUM_COLOR_PREFIX}-${elevationPreset[key].value.hue}-${elevationPreset[key].value.step}))`;\n break;\n case 'line':\n rootVars[name] = `rgb(var(--${LINE_COLOR_PREFIX}-${elevationPreset[key].value}))`;\n break;\n }\n }\n\n // border width\n if (key === 'borderWidth') {\n const name = `--${BORDER_WIDTH_PREFIX}-elevation-${level}`;\n rootVars[name] = `var(--${BORDER_WIDTH_PREFIX}-${elevationPreset[key]})`;\n }\n\n // drop shadow\n if (key === 'dropShadow') {\n const name = `--${DROP_SHADOW_PREFIX}-elevation-${level}`;\n const configValue = elevationPreset[key];\n\n rootVars[name] = Array.isArray(configValue)\n ? configValue\n .map((preset, index) =>\n getShadowLayerValue({\n preset,\n prefix: index > 0 ? `${index + 1}` : undefined,\n shadowType: 'drop',\n }),\n )\n .join(', ')\n : `var(--${DROP_SHADOW_PREFIX}-${elevationPreset[key]})`;\n }\n\n // inset shadow\n if (key === 'insetShadow') {\n const name = `--${INSET_SHADOW_PREFIX}-elevation-${level}`;\n const configValue = elevationPreset[key];\n\n rootVars[name] = Array.isArray(configValue)\n ? configValue\n .map((preset, index) =>\n getShadowLayerValue({\n preset,\n prefix: index > 0 ? `${index + 1}` : undefined,\n shadowType: 'inset',\n }),\n )\n .join(', ')\n : `var(--${INSET_SHADOW_PREFIX}-${elevationPreset[key]})`;\n }\n\n // background blur radius\n if (key === 'backgroundBlurRadius') {\n const name = `--${BACKGROUND_BLUR_RADIUS_PREFIX}-elevation-${level}`;\n rootVars[name] = `blur(${elevationPreset[key]}px)`;\n }\n\n // background blur fallback value\n if (key === 'fallbackBlurredBackgroundValue') {\n const { r, g, b } = elevationPreset[key];\n const name = `--${BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX}-elevation-${level}`;\n rootVars[name] = `rgb(${r}, ${g}, ${b})`;\n }\n });\n }\n });\n\n rootVars[`--${OUTLINE_PREFIX}-offset`] = focusRingConfig ? `${focusRingConfig.offset}px` : '2px';\n rootVars[`--${OUTLINE_PREFIX}-width`] = focusRingConfig ? `${focusRingConfig.width}px` : '2px';\n rootVars[`--${OUTLINE_PREFIX}-style`] = 'solid';\n rootVars[`--${OUTLINE_PREFIX}-color`] = focusRingConfig\n ? resolveFocusRingColor(focusRingConfig.color)\n : `rgb(var(--${SPECTRUM_COLOR_PREFIX}-gray-15))`;\n\n return {\n _vars: rootVars,\n _raw: colors,\n tailwindConfig,\n };\n}\n\nfunction transformNumericToPx<T extends Record<string, number>>(prefix: string, config: T) {\n if (!config) {\n return {\n _vars: {} as Record<string, string>,\n _raw: {} as Record<string, number>,\n tailwindConfig: {} as Record<string, string>,\n };\n }\n const rootVars: Record<string, string> = {};\n const tailwindConfig = {} as Record<string, string>;\n for (const [variant, value] of entries(config)) {\n const rootVarKey = `--${prefix}-${variant}`;\n const rootVarValue = `${value}px`;\n rootVars[rootVarKey] = rootVarValue;\n tailwindConfig[variant] = `var(${rootVarKey})`;\n }\n return {\n _vars: rootVars,\n _raw: config,\n tailwindConfig,\n };\n}\n\ntype WebTokens = Omit<UniversalTokensConfig, 'colorMode' | 'scaleMode' | 'fontFamily'> & {\n colorMode: Record<ColorMode, ReturnType<typeof transformColors>>;\n scaleMode: Record<\n ScaleMode,\n {\n borderRadius: ReturnType<typeof transformNumericToPx>;\n borderWidth: ReturnType<typeof transformNumericToPx>;\n avatarSizes: ReturnType<typeof transformNumericToPx>;\n iconSizes: ReturnType<typeof transformNumericToPx>;\n }\n >;\n};\n\nfunction getElevationPresetsForColorMode(\n colorMode: ColorMode,\n config: UniversalTokensConfig,\n): ColorModeElevationPresets {\n if (!config.elevation) {\n return {};\n }\n\n const result: ColorModeElevationPresets = {};\n\n entries(config.elevation).forEach(([level, levelPreset]) => {\n result[level] = levelPreset[colorMode];\n });\n\n return result;\n}\n\nexport function parseTokens(config: UniversalTokensConfig): WebTokens {\n const { colorMode, scaleMode } = config;\n\n return {\n ...config,\n colorMode: {\n light: transformColors(\n colorMode.light,\n getElevationPresetsForColorMode('light', config),\n config.focusRing?.light,\n ),\n dark: transformColors(\n colorMode.dark,\n getElevationPresetsForColorMode('dark', config),\n config.focusRing?.dark,\n ),\n },\n scaleMode: mapValues(scaleMode, ({ borderRadius, borderWidth, avatarSizes, iconSizes }) => {\n return {\n borderRadius: transformNumericToPx(BORDER_RADIUS_PREFIX, borderRadius),\n borderWidth: transformNumericToPx(BORDER_WIDTH_PREFIX, borderWidth),\n avatarSizes: transformNumericToPx(AVATAR_SIZE_PREFIX, avatarSizes),\n iconSizes: transformNumericToPx(ICON_SIZE_PREFIX, iconSizes),\n };\n }),\n };\n}\n\nexport { type WebTokens };\n"],"mappings":"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"}
1
+ {"version":3,"file":"parseTokens.js","names":[],"sources":["../../src/utils/parseTokens.ts"],"sourcesContent":["import type { UniversalTokensConfig } from '@yahoo/uds-config';\nimport {\n AVATAR_SIZE_PREFIX,\n BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX,\n BACKGROUND_BLUR_RADIUS_PREFIX,\n BACKGROUND_COLOR_PREFIX,\n BORDER_RADIUS_PREFIX,\n BORDER_WIDTH_PREFIX,\n DROP_SHADOW_PREFIX,\n getShadowLayerValue,\n ICON_SIZE_PREFIX,\n INSET_SHADOW_PREFIX,\n LINE_COLOR_PREFIX,\n OUTLINE_PREFIX,\n SPECTRUM_COLOR_PREFIX,\n UDS_PREFIX,\n} from '@yahoo/uds-css-tokens';\nimport { alwaysPalette } from '@yahoo/uds-palette';\nimport type {\n ColorMode,\n ColorsConfig,\n ElevationLevel,\n ElevationPreset,\n FocusRingColor,\n FocusRingConfig,\n Hue,\n HueStep,\n OpacityStep,\n PaletteConfig,\n PaletteType,\n ScaleMode,\n} from '@yahoo/uds-types';\n\nimport { entries } from './entries';\nimport { mapValues } from './mapValues';\nimport { parseOpacityStep } from './opacity';\n\n/** Converts a SpectrumValueEntry to a space-separated RGB string for CSS variables. */\nfunction spectrumValueToRgbString(value: { rgb: { r: number; g: number; b: number } }): string {\n const { r, g, b } = value.rgb;\n return `${r} ${g} ${b}`;\n}\n\nfunction shouldIncludeOpacity(opacity: OpacityStep | undefined): boolean {\n if (!opacity) {\n return false;\n }\n\n const parsedOpacity = parseInt(opacity, 10);\n return !isNaN(parsedOpacity) && parsedOpacity !== 100;\n}\n\ntype ColorModeElevationPresets = Partial<Record<ElevationLevel, ElevationPreset>>;\n\nfunction resolveFocusRingColor(color: FocusRingColor): string {\n switch (color.type) {\n case 'spectrum':\n return `rgb(var(--${SPECTRUM_COLOR_PREFIX}-${color.value.hue}-${color.value.step}))`;\n case 'line':\n return `rgb(var(--${LINE_COLOR_PREFIX}-${color.value}))`;\n case 'always':\n return alwaysPalette[color.value as keyof typeof alwaysPalette];\n default:\n return `rgb(var(--${SPECTRUM_COLOR_PREFIX}-gray-15))`;\n }\n}\n\nfunction transformColors(\n colors: ColorsConfig,\n elevationPresets: ColorModeElevationPresets,\n focusRingConfig?: FocusRingConfig,\n) {\n const { palette, spectrum } = colors;\n const rootVars: Record<string, string> = {};\n const tailwindConfig = {\n spectrum: {} as Record<Hue, Record<HueStep, string>>,\n palette: {} as {\n [key in PaletteType]: Record<keyof PaletteConfig[key], string>;\n },\n };\n\n for (const [hue, hueSteps] of entries(spectrum)) {\n for (const [hueStep, value] of entries(hueSteps)) {\n const name = `${hue}-${hueStep}`;\n const varKey = `--${SPECTRUM_COLOR_PREFIX}-${name}`;\n if (!tailwindConfig.spectrum[hue]) {\n tailwindConfig.spectrum[hue] = {} as Record<HueStep, string>;\n }\n tailwindConfig.spectrum[hue][hueStep] = `rgb(var(${varKey}))`;\n rootVars[varKey] = spectrumValueToRgbString(value);\n }\n }\n\n entries(palette).forEach(([paletteType, paletteConfig]) => {\n for (const [paletteKey, { hue, step, opacity }] of Object.entries(paletteConfig)) {\n if (!(paletteType in tailwindConfig.palette)) {\n // @ts-expect-error we fill this object later\n tailwindConfig.palette[paletteType] = {};\n }\n const name = `--${UDS_PREFIX}-${paletteType}-color-${paletteKey}`;\n rootVars[name] = `var(--${SPECTRUM_COLOR_PREFIX}-${hue}-${step})`;\n const opacityValue = opacity !== undefined ? parseOpacityStep(opacity) : undefined;\n // @ts-expect-error this is fine\n tailwindConfig.palette[paletteType][paletteKey] = shouldIncludeOpacity(opacityValue)\n ? `rgb(var(${name}) / ${opacityValue}%)`\n : `rgb(var(${name}))`;\n }\n });\n\n // Elevation levels\n entries(elevationPresets).forEach(([level, elevationPreset]) => {\n if (elevationPreset) {\n entries(elevationPreset).forEach(([key]) => {\n // background color\n if (key === 'finalBackgroundValue') {\n const { r, g, b, a } = elevationPreset[key];\n const alpha = parseInt(a) / 100;\n const name = `--${BACKGROUND_COLOR_PREFIX}-elevation-${level}`;\n rootVars[name] = `rgba(${r}, ${g}, ${b}, ${alpha})`;\n }\n\n // border color\n if (key === 'borderColor') {\n const name = `--${LINE_COLOR_PREFIX}-elevation-${level}`;\n\n switch (elevationPreset[key].type) {\n case 'always':\n rootVars[name] = alwaysPalette[elevationPreset[key].value];\n break;\n case 'spectrum':\n rootVars[name] =\n `rgb(var(--${SPECTRUM_COLOR_PREFIX}-${elevationPreset[key].value.hue}-${elevationPreset[key].value.step}))`;\n break;\n case 'line':\n rootVars[name] = `rgb(var(--${LINE_COLOR_PREFIX}-${elevationPreset[key].value}))`;\n break;\n }\n }\n\n // border width\n if (key === 'borderWidth') {\n const name = `--${BORDER_WIDTH_PREFIX}-elevation-${level}`;\n rootVars[name] = `var(--${BORDER_WIDTH_PREFIX}-${elevationPreset[key]})`;\n }\n\n // drop shadow\n if (key === 'dropShadow') {\n const name = `--${DROP_SHADOW_PREFIX}-elevation-${level}`;\n const configValue = elevationPreset[key];\n\n rootVars[name] = Array.isArray(configValue)\n ? configValue\n .map((preset, index) =>\n getShadowLayerValue({\n preset,\n prefix: index > 0 ? `${index + 1}` : undefined,\n shadowType: 'drop',\n }),\n )\n .join(', ')\n : `var(--${DROP_SHADOW_PREFIX}-${elevationPreset[key]})`;\n }\n\n // inset shadow\n if (key === 'insetShadow') {\n const name = `--${INSET_SHADOW_PREFIX}-elevation-${level}`;\n const configValue = elevationPreset[key];\n\n rootVars[name] = Array.isArray(configValue)\n ? configValue\n .map((preset, index) =>\n getShadowLayerValue({\n preset,\n prefix: index > 0 ? `${index + 1}` : undefined,\n shadowType: 'inset',\n }),\n )\n .join(', ')\n : `var(--${INSET_SHADOW_PREFIX}-${elevationPreset[key]})`;\n }\n\n // background blur radius\n if (key === 'backgroundBlurRadius') {\n const name = `--${BACKGROUND_BLUR_RADIUS_PREFIX}-elevation-${level}`;\n rootVars[name] = `blur(${elevationPreset[key]}px)`;\n }\n\n // background blur fallback value\n if (key === 'fallbackBlurredBackgroundValue') {\n const { r, g, b } = elevationPreset[key];\n const name = `--${BACKGROUND_BLUR_FALLBACK_COLOR_PREFIX}-elevation-${level}`;\n rootVars[name] = `rgb(${r}, ${g}, ${b})`;\n }\n });\n }\n });\n\n rootVars[`--${OUTLINE_PREFIX}-offset`] = focusRingConfig ? `${focusRingConfig.offset}px` : '2px';\n rootVars[`--${OUTLINE_PREFIX}-width`] = focusRingConfig ? `${focusRingConfig.width}px` : '2px';\n rootVars[`--${OUTLINE_PREFIX}-style`] = 'solid';\n rootVars[`--${OUTLINE_PREFIX}-color`] = focusRingConfig\n ? resolveFocusRingColor(focusRingConfig.color)\n : `rgb(var(--${SPECTRUM_COLOR_PREFIX}-gray-15))`;\n\n return {\n _vars: rootVars,\n _raw: colors,\n tailwindConfig,\n };\n}\n\nfunction transformNumericToPx<T extends Record<string, number>>(prefix: string, config: T) {\n if (!config) {\n return {\n _vars: {} as Record<string, string>,\n _raw: {} as Record<string, number>,\n tailwindConfig: {} as Record<string, string>,\n };\n }\n const rootVars: Record<string, string> = {};\n const tailwindConfig = {} as Record<string, string>;\n for (const [variant, value] of entries(config)) {\n const rootVarKey = `--${prefix}-${variant}`;\n const rootVarValue = `${value}px`;\n rootVars[rootVarKey] = rootVarValue;\n tailwindConfig[variant] = `var(${rootVarKey})`;\n }\n return {\n _vars: rootVars,\n _raw: config,\n tailwindConfig,\n };\n}\n\ntype WebTokens = Omit<UniversalTokensConfig, 'colorMode' | 'scaleMode' | 'fontFamily'> & {\n colorMode: Record<ColorMode, ReturnType<typeof transformColors>>;\n scaleMode: Record<\n ScaleMode,\n {\n borderRadius: ReturnType<typeof transformNumericToPx>;\n borderWidth: ReturnType<typeof transformNumericToPx>;\n avatarSizes: ReturnType<typeof transformNumericToPx>;\n iconSizes: ReturnType<typeof transformNumericToPx>;\n }\n >;\n};\n\nfunction getElevationPresetsForColorMode(\n colorMode: ColorMode,\n config: UniversalTokensConfig,\n): ColorModeElevationPresets {\n if (!config.elevation) {\n return {};\n }\n\n const result: ColorModeElevationPresets = {};\n\n entries(config.elevation).forEach(([level, levelPreset]) => {\n result[level] = levelPreset[colorMode];\n });\n\n return result;\n}\n\nexport function parseTokens(config: UniversalTokensConfig): WebTokens {\n const { colorMode, scaleMode } = config;\n\n return {\n ...config,\n colorMode: {\n light: transformColors(\n colorMode.light,\n getElevationPresetsForColorMode('light', config),\n config.focusRing?.light,\n ),\n dark: transformColors(\n colorMode.dark,\n getElevationPresetsForColorMode('dark', config),\n config.focusRing?.dark,\n ),\n },\n scaleMode: mapValues(scaleMode, ({ borderRadius, borderWidth, avatarSizes, iconSizes }) => {\n return {\n borderRadius: transformNumericToPx(BORDER_RADIUS_PREFIX, borderRadius),\n borderWidth: transformNumericToPx(BORDER_WIDTH_PREFIX, borderWidth),\n avatarSizes: transformNumericToPx(AVATAR_SIZE_PREFIX, avatarSizes),\n iconSizes: transformNumericToPx(ICON_SIZE_PREFIX, iconSizes),\n };\n }),\n };\n}\n\nexport { type WebTokens };\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"postcssPreserveVars.js","names":[],"sources":["../../src/utils/postcssPreserveVars.ts"],"sourcesContent":["import type { Plugin } from 'postcss';\n\ninterface PreserveVarsOptions {\n /** Variable name patterns to preserve (regex or string prefix) */\n preserve?: (string | RegExp)[];\n}\n\nconst PRESERVE_SELECTOR = '._uds-preserve-vars';\n\n/**\n * PostCSS plugin to preserve CSS variables from being pruned.\n *\n * Runs BEFORE postcss-prune-var to inject fake usages for preserved variables,\n * preventing them from being removed.\n *\n * @example\n * ```ts\n * postcss([\n * preserveVars({ preserve: ['--uds-motion-'] }),\n * pruneVar(),\n * preserveVarsCleanup(),\n * ])\n * ```\n */\nfunction preserveVars(options: PreserveVarsOptions = {}): Plugin {\n const { preserve = [] } = options;\n\n return {\n postcssPlugin: 'postcss-preserve-vars',\n Once(root) {\n if (preserve.length === 0) {\n return;\n }\n\n // Collect all CSS variable declarations\n const declaredVars = new Set<string>();\n\n root.walkDecls((decl) => {\n if (decl.prop.startsWith('--')) {\n declaredVars.add(decl.prop);\n }\n });\n\n // Find variables that match preserve patterns\n const varsToPreserve: string[] = [];\n\n for (const varName of declaredVars) {\n for (const pattern of preserve) {\n const matches =\n pattern instanceof RegExp ? pattern.test(varName) : varName.startsWith(pattern);\n\n if (matches) {\n varsToPreserve.push(varName);\n break;\n }\n }\n }\n\n if (varsToPreserve.length === 0) {\n return;\n }\n\n // Add a temporary rule that \"uses\" all preserved variables\n // This prevents postcss-prune-var from removing them\n const varUsages = varsToPreserve.map((v) => `var(${v})`).join(' ');\n\n root.append({\n selector: PRESERVE_SELECTOR,\n nodes: [{ prop: 'content', value: `\"${varUsages}\"` }],\n });\n },\n };\n}\n\npreserveVars.postcss = true;\n\n/**\n * PostCSS plugin to remove the temporary preserve rule after pruning.\n * Run this AFTER postcss-prune-var.\n */\nfunction preserveVarsCleanup(): Plugin {\n return {\n postcssPlugin: 'postcss-preserve-vars-cleanup',\n Once(root) {\n root.walkRules((rule) => {\n if (rule.selector === PRESERVE_SELECTOR) {\n rule.remove();\n }\n });\n },\n };\n}\n\npreserveVarsCleanup.postcss = true;\n\nexport { preserveVars, preserveVarsCleanup };\nexport type { PreserveVarsOptions };\n"],"mappings":";;AAOA,MAAM,oBAAoB;;;;;;;;;;;;;;;;AAiB1B,SAAS,aAAa,UAA+B,EAAE,EAAU;CAC/D,MAAM,EAAE,WAAW,EAAE,KAAK;AAE1B,QAAO;EACL,eAAe;EACf,KAAK,MAAM;AACT,OAAI,SAAS,WAAW,EACtB;GAIF,MAAM,+BAAe,IAAI,KAAa;AAEtC,QAAK,WAAW,SAAS;AACvB,QAAI,KAAK,KAAK,WAAW,KAAK,CAC5B,cAAa,IAAI,KAAK,KAAK;KAE7B;GAGF,MAAM,iBAA2B,EAAE;AAEnC,QAAK,MAAM,WAAW,aACpB,MAAK,MAAM,WAAW,SAIpB,KAFE,mBAAmB,SAAS,QAAQ,KAAK,QAAQ,GAAG,QAAQ,WAAW,QAAQ,EAEpE;AACX,mBAAe,KAAK,QAAQ;AAC5B;;AAKN,OAAI,eAAe,WAAW,EAC5B;GAKF,MAAM,YAAY,eAAe,KAAK,MAAM,OAAO,EAAE,GAAG,CAAC,KAAK,IAAI;AAElE,QAAK,OAAO;IACV,UAAU;IACV,OAAO,CAAC;KAAE,MAAM;KAAW,OAAO,IAAI,UAAU;KAAI,CAAC;IACtD,CAAC;;EAEL;;AAGH,aAAa,UAAU;;;;;AAMvB,SAAS,sBAA8B;AACrC,QAAO;EACL,eAAe;EACf,KAAK,MAAM;AACT,QAAK,WAAW,SAAS;AACvB,QAAI,KAAK,aAAa,kBACpB,MAAK,QAAQ;KAEf;;EAEL;;AAGH,oBAAoB,UAAU"}
1
+ {"version":3,"file":"postcssPreserveVars.js","names":[],"sources":["../../src/utils/postcssPreserveVars.ts"],"sourcesContent":["import type { Plugin } from 'postcss';\n\ninterface PreserveVarsOptions {\n /** Variable name patterns to preserve (regex or string prefix) */\n preserve?: (string | RegExp)[];\n}\n\nconst PRESERVE_SELECTOR = '._uds-preserve-vars';\n\n/**\n * PostCSS plugin to preserve CSS variables from being pruned.\n *\n * Runs BEFORE postcss-prune-var to inject fake usages for preserved variables,\n * preventing them from being removed.\n *\n * @example\n * ```ts\n * postcss([\n * preserveVars({ preserve: ['--uds-motion-'] }),\n * pruneVar(),\n * preserveVarsCleanup(),\n * ])\n * ```\n */\nfunction preserveVars(options: PreserveVarsOptions = {}): Plugin {\n const { preserve = [] } = options;\n\n return {\n postcssPlugin: 'postcss-preserve-vars',\n Once(root) {\n if (preserve.length === 0) {\n return;\n }\n\n // Collect all CSS variable declarations\n const declaredVars = new Set<string>();\n\n root.walkDecls((decl) => {\n if (decl.prop.startsWith('--')) {\n declaredVars.add(decl.prop);\n }\n });\n\n // Find variables that match preserve patterns\n const varsToPreserve: string[] = [];\n\n for (const varName of declaredVars) {\n for (const pattern of preserve) {\n const matches =\n pattern instanceof RegExp ? pattern.test(varName) : varName.startsWith(pattern);\n\n if (matches) {\n varsToPreserve.push(varName);\n break;\n }\n }\n }\n\n if (varsToPreserve.length === 0) {\n return;\n }\n\n // Add a temporary rule that \"uses\" all preserved variables\n // This prevents postcss-prune-var from removing them\n const varUsages = varsToPreserve.map((v) => `var(${v})`).join(' ');\n\n root.append({\n selector: PRESERVE_SELECTOR,\n nodes: [{ prop: 'content', value: `\"${varUsages}\"` }],\n });\n },\n };\n}\n\npreserveVars.postcss = true;\n\n/**\n * PostCSS plugin to remove the temporary preserve rule after pruning.\n * Run this AFTER postcss-prune-var.\n */\nfunction preserveVarsCleanup(): Plugin {\n return {\n postcssPlugin: 'postcss-preserve-vars-cleanup',\n Once(root) {\n root.walkRules((rule) => {\n if (rule.selector === PRESERVE_SELECTOR) {\n rule.remove();\n }\n });\n },\n };\n}\n\npreserveVarsCleanup.postcss = true;\n\nexport { preserveVars, preserveVarsCleanup };\nexport type { PreserveVarsOptions };\n"],"mappings":";;AAOA,MAAM,oBAAoB;;;;;;;;;;;;;;;;AAiB1B,SAAS,aAAa,UAA+B,EAAE,EAAU;CAC/D,MAAM,EAAE,WAAW,EAAE,KAAK;CAE1B,OAAO;EACL,eAAe;EACf,KAAK,MAAM;GACT,IAAI,SAAS,WAAW,GACtB;GAIF,MAAM,+BAAe,IAAI,KAAa;GAEtC,KAAK,WAAW,SAAS;IACvB,IAAI,KAAK,KAAK,WAAW,KAAK,EAC5B,aAAa,IAAI,KAAK,KAAK;KAE7B;GAGF,MAAM,iBAA2B,EAAE;GAEnC,KAAK,MAAM,WAAW,cACpB,KAAK,MAAM,WAAW,UAIpB,IAFE,mBAAmB,SAAS,QAAQ,KAAK,QAAQ,GAAG,QAAQ,WAAW,QAAQ,EAEpE;IACX,eAAe,KAAK,QAAQ;IAC5B;;GAKN,IAAI,eAAe,WAAW,GAC5B;GAKF,MAAM,YAAY,eAAe,KAAK,MAAM,OAAO,EAAE,GAAG,CAAC,KAAK,IAAI;GAElE,KAAK,OAAO;IACV,UAAU;IACV,OAAO,CAAC;KAAE,MAAM;KAAW,OAAO,IAAI,UAAU;KAAI,CAAC;IACtD,CAAC;;EAEL;;AAGH,aAAa,UAAU;;;;;AAMvB,SAAS,sBAA8B;CACrC,OAAO;EACL,eAAe;EACf,KAAK,MAAM;GACT,KAAK,WAAW,SAAS;IACvB,IAAI,KAAK,aAAa,mBACpB,KAAK,QAAQ;KAEf;;EAEL;;AAGH,oBAAoB,UAAU"}