@yahoo/uds-mobile 2.24.0-beta.5 → 2.24.0-beta.7

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 (131) hide show
  1. package/README.md +6 -1
  2. package/dist/components/Avatar/AvatarIcon.cjs +2 -2
  3. package/dist/components/Avatar/AvatarIcon.js +2 -2
  4. package/dist/components/Avatar/AvatarIcon.js.map +1 -1
  5. package/dist/components/Avatar/AvatarImage.cjs +2 -2
  6. package/dist/components/Avatar/AvatarImage.js +2 -2
  7. package/dist/components/Avatar/AvatarImage.js.map +1 -1
  8. package/dist/components/Avatar/AvatarText.cjs +2 -2
  9. package/dist/components/Avatar/AvatarText.js +2 -2
  10. package/dist/components/Avatar/AvatarText.js.map +1 -1
  11. package/dist/components/Avatar/useAvatarFontScale.cjs +16 -0
  12. package/dist/components/Avatar/useAvatarFontScale.d.cts +7 -0
  13. package/dist/components/Avatar/useAvatarFontScale.d.cts.map +1 -0
  14. package/dist/components/Avatar/useAvatarFontScale.d.ts +7 -0
  15. package/dist/components/Avatar/useAvatarFontScale.d.ts.map +1 -0
  16. package/dist/components/Avatar/useAvatarFontScale.js +16 -0
  17. package/dist/components/Avatar/useAvatarFontScale.js.map +1 -0
  18. package/dist/components/Button/buttonTheme.cjs +10 -6
  19. package/dist/components/Button/buttonTheme.d.cts +10 -5
  20. package/dist/components/Button/buttonTheme.d.cts.map +1 -1
  21. package/dist/components/Button/buttonTheme.d.ts +10 -5
  22. package/dist/components/Button/buttonTheme.d.ts.map +1 -1
  23. package/dist/components/Button/buttonTheme.js +10 -6
  24. package/dist/components/Button/buttonTheme.js.map +1 -1
  25. package/dist/components/Button.cjs +17 -8
  26. package/dist/components/Button.js +17 -8
  27. package/dist/components/Button.js.map +1 -1
  28. package/dist/components/Checkbox.cjs +4 -2
  29. package/dist/components/Checkbox.js +4 -2
  30. package/dist/components/Checkbox.js.map +1 -1
  31. package/dist/components/Chip/ChipBase.cjs +22 -19
  32. package/dist/components/Chip/ChipBase.js +22 -19
  33. package/dist/components/Chip/ChipBase.js.map +1 -1
  34. package/dist/components/Icon.cjs +3 -2
  35. package/dist/components/Icon.d.cts.map +1 -1
  36. package/dist/components/Icon.d.ts.map +1 -1
  37. package/dist/components/Icon.js +3 -2
  38. package/dist/components/Icon.js.map +1 -1
  39. package/dist/components/Input.cjs +1 -1
  40. package/dist/components/Input.js +1 -1
  41. package/dist/components/Input.js.map +1 -1
  42. package/dist/components/Link.cjs +10 -1
  43. package/dist/components/Link.d.cts +6 -0
  44. package/dist/components/Link.d.cts.map +1 -1
  45. package/dist/components/Link.d.ts +6 -0
  46. package/dist/components/Link.d.ts.map +1 -1
  47. package/dist/components/Link.js +10 -1
  48. package/dist/components/Link.js.map +1 -1
  49. package/dist/components/Pagination/Pagination.cjs +18 -10
  50. package/dist/components/Pagination/Pagination.d.cts +2 -0
  51. package/dist/components/Pagination/Pagination.d.cts.map +1 -1
  52. package/dist/components/Pagination/Pagination.d.ts +2 -0
  53. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  54. package/dist/components/Pagination/Pagination.js +18 -10
  55. package/dist/components/Pagination/Pagination.js.map +1 -1
  56. package/dist/components/Pagination/PaginationEllipsis.cjs +8 -2
  57. package/dist/components/Pagination/PaginationEllipsis.d.cts.map +1 -1
  58. package/dist/components/Pagination/PaginationEllipsis.d.ts.map +1 -1
  59. package/dist/components/Pagination/PaginationEllipsis.js +9 -3
  60. package/dist/components/Pagination/PaginationEllipsis.js.map +1 -1
  61. package/dist/components/Pagination/PaginationItem.cjs +2 -1
  62. package/dist/components/Pagination/PaginationItem.js +2 -1
  63. package/dist/components/Pagination/PaginationItem.js.map +1 -1
  64. package/dist/components/Pagination/PaginationLink.cjs +2 -1
  65. package/dist/components/Pagination/PaginationLink.js +2 -1
  66. package/dist/components/Pagination/PaginationLink.js.map +1 -1
  67. package/dist/components/Pagination/PaginationNext.cjs +3 -1
  68. package/dist/components/Pagination/PaginationNext.js +3 -1
  69. package/dist/components/Pagination/PaginationNext.js.map +1 -1
  70. package/dist/components/Pagination/PaginationPrev.cjs +3 -1
  71. package/dist/components/Pagination/PaginationPrev.js +3 -1
  72. package/dist/components/Pagination/PaginationPrev.js.map +1 -1
  73. package/dist/components/Pagination/paginationContext.d.cts +2 -0
  74. package/dist/components/Pagination/paginationContext.d.cts.map +1 -1
  75. package/dist/components/Pagination/paginationContext.d.ts +2 -0
  76. package/dist/components/Pagination/paginationContext.d.ts.map +1 -1
  77. package/dist/components/Pagination/paginationContext.js.map +1 -1
  78. package/dist/components/Pagination/usePaginationControlStyles.cjs +8 -1
  79. package/dist/components/Pagination/usePaginationControlStyles.d.cts.map +1 -1
  80. package/dist/components/Pagination/usePaginationControlStyles.d.ts.map +1 -1
  81. package/dist/components/Pagination/usePaginationControlStyles.js +9 -2
  82. package/dist/components/Pagination/usePaginationControlStyles.js.map +1 -1
  83. package/dist/components/Radio/Radio.cjs +2 -1
  84. package/dist/components/Radio/Radio.js +2 -1
  85. package/dist/components/Radio/Radio.js.map +1 -1
  86. package/dist/components/Select/Select.cjs +16 -4
  87. package/dist/components/Select/Select.js +16 -4
  88. package/dist/components/Select/Select.js.map +1 -1
  89. package/dist/components/Select/SelectContent.cjs +31 -23
  90. package/dist/components/Select/SelectContent.d.cts.map +1 -1
  91. package/dist/components/Select/SelectContent.d.ts.map +1 -1
  92. package/dist/components/Select/SelectContent.js +32 -24
  93. package/dist/components/Select/SelectContent.js.map +1 -1
  94. package/dist/components/Select/SelectItem.cjs +6 -6
  95. package/dist/components/Select/SelectItem.js +6 -6
  96. package/dist/components/Select/SelectItem.js.map +1 -1
  97. package/dist/components/Select/SelectTrigger.cjs +1 -1
  98. package/dist/components/Select/SelectTrigger.js +1 -1
  99. package/dist/components/Select/SelectTrigger.js.map +1 -1
  100. package/dist/components/Switch.cjs +4 -2
  101. package/dist/components/Switch.js +4 -2
  102. package/dist/components/Switch.js.map +1 -1
  103. package/dist/components/Tabs/Tab.cjs +1 -1
  104. package/dist/components/Tabs/Tab.js +1 -1
  105. package/dist/components/Tabs/Tab.js.map +1 -1
  106. package/dist/fontScaling/androidNonlinearFontScaling.cjs +174 -0
  107. package/dist/fontScaling/androidNonlinearFontScaling.d.cts +7 -0
  108. package/dist/fontScaling/androidNonlinearFontScaling.d.cts.map +1 -0
  109. package/dist/fontScaling/androidNonlinearFontScaling.d.ts +7 -0
  110. package/dist/fontScaling/androidNonlinearFontScaling.d.ts.map +1 -0
  111. package/dist/fontScaling/androidNonlinearFontScaling.js +175 -0
  112. package/dist/fontScaling/androidNonlinearFontScaling.js.map +1 -0
  113. package/dist/fontScaling/constants.cjs +4 -3
  114. package/dist/fontScaling/constants.d.cts +4 -3
  115. package/dist/fontScaling/constants.d.cts.map +1 -1
  116. package/dist/fontScaling/constants.d.ts +4 -3
  117. package/dist/fontScaling/constants.d.ts.map +1 -1
  118. package/dist/fontScaling/constants.js +4 -3
  119. package/dist/fontScaling/constants.js.map +1 -1
  120. package/dist/fontScaling/types.d.cts +3 -2
  121. package/dist/fontScaling/types.d.cts.map +1 -1
  122. package/dist/fontScaling/types.d.ts +3 -2
  123. package/dist/fontScaling/types.d.ts.map +1 -1
  124. package/dist/fontScaling/useFontScale.cjs +13 -4
  125. package/dist/fontScaling/useFontScale.d.cts +8 -3
  126. package/dist/fontScaling/useFontScale.d.cts.map +1 -1
  127. package/dist/fontScaling/useFontScale.d.ts +8 -3
  128. package/dist/fontScaling/useFontScale.d.ts.map +1 -1
  129. package/dist/fontScaling/useFontScale.js +14 -5
  130. package/dist/fontScaling/useFontScale.js.map +1 -1
  131. package/package.json +1 -1
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
 
19
19
  `@yahoo/uds-mobile` brings UDS to React Native. It provides:
20
20
 
21
- - **Pre-built Components**: Avatar, Badge, Button, Checkbox, Chip, Divider, Icon, IconButton, Image, Input, InputHelpText, Link, Radio, RadioGroup, Switch, Tabs, Text, and layout primitives (Box, VStack, HStack, Screen)
21
+ - **Pre-built Components**: Avatar, Badge, Button, Checkbox, Chip, Divider, Icon, IconButton, Image, Input, InputHelpText, Link, Pagination, Radio, RadioGroup, Select, Switch, Tabs, Text, and layout primitives (Box, VStack, HStack, Screen)
22
22
  - **Theming**: Full light/dark mode support with automatic system preference detection
23
23
  - **Design Token Integration**: Colors, typography, spacing, and motion configs synced from UDS tokens
24
24
  - **Animations**: Smooth, physics-based animations using Reanimated with motion parity to web
@@ -505,6 +505,11 @@ See the [Accessibility and text scaling guide](https://uds.build/docs/mobile/acc
505
505
  default cap table, per-component overrides, custom-component hooks, known limits, and device test
506
506
  matrix.
507
507
 
508
+ When upgrading from manual scaling workarounds, remove app-level geometry multiplication only after
509
+ comparing the screen with UDS defaults; applying both can make controls oversized. App-owned
510
+ composite controls should use `useFontScale(cap, baseSize)`. As a temporary rollback,
511
+ `fontScaling={{ enabled: false }}` restores unrestricted native scaling.
512
+
508
513
  ## Fonts
509
514
 
510
515
  ### Font Handling
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("../../_virtual/_rolldown/runtime.cjs");
4
4
  const require_components_Box = require("../Box.cjs");
5
- const require_fontScaling_useFontScale = require("../../fontScaling/useFontScale.cjs");
6
5
  const require_fontScaling_useMaxFontSizeMultiplier = require("../../fontScaling/useMaxFontSizeMultiplier.cjs");
7
6
  const require_components_IconSlot = require("../IconSlot.cjs");
7
+ const require_components_Avatar_useAvatarFontScale = require("./useAvatarFontScale.cjs");
8
8
  const require_components_Avatar_utils = require("./utils.cjs");
9
9
  let react = require("react");
10
10
  let react_native = require("react-native");
@@ -13,11 +13,11 @@ let generated_styles = require("../../../generated/styles");
13
13
  //#region src/components/Avatar/AvatarIcon.tsx
14
14
  const AvatarIcon = (0, react.memo)(function AvatarIcon({ size = "md", variant = require_components_Avatar_utils.DEFAULT_AVATAR_VARIANT, icon, customSize, maxFontSizeMultiplier, style, accessibilityLabel, alt, ref, ...viewProps }) {
15
15
  const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
16
- const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier);
17
16
  generated_styles.avatarStyles.useVariants({
18
17
  size,
19
18
  icon: variant
20
19
  });
20
+ const fontScaleFactor = require_components_Avatar_useAvatarFontScale.useAvatarFontScale(resolvedMaxFontSizeMultiplier);
21
21
  const rootStyle = (0, react.useMemo)(() => [
22
22
  generated_styles.avatarStyles.root,
23
23
  avatarStaticStyles.root,
@@ -1,8 +1,8 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
2
  import { Box } from "../Box.js";
3
- import { useFontScale } from "../../fontScaling/useFontScale.js";
4
3
  import { useMaxFontSizeMultiplier } from "../../fontScaling/useMaxFontSizeMultiplier.js";
5
4
  import { IconSlot } from "../IconSlot.js";
5
+ import { useAvatarFontScale } from "./useAvatarFontScale.js";
6
6
  import { DEFAULT_AVATAR_VARIANT, getAvatarSizeStyle, getDefaultAvatarIcon } from "./utils.js";
7
7
  import { memo, useMemo } from "react";
8
8
  import { StyleSheet } from "react-native";
@@ -11,11 +11,11 @@ import { avatarStyles } from "../../../generated/styles";
11
11
  //#region src/components/Avatar/AvatarIcon.tsx
12
12
  const AvatarIcon = memo(function AvatarIcon({ size = "md", variant = DEFAULT_AVATAR_VARIANT, icon, customSize, maxFontSizeMultiplier, style, accessibilityLabel, alt, ref, ...viewProps }) {
13
13
  const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
14
- const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);
15
14
  avatarStyles.useVariants({
16
15
  size,
17
16
  icon: variant
18
17
  });
18
+ const fontScaleFactor = useAvatarFontScale(resolvedMaxFontSizeMultiplier);
19
19
  const rootStyle = useMemo(() => [
20
20
  avatarStyles.root,
21
21
  avatarStaticStyles.root,
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarIcon.js","names":[],"sources":["../../../src/components/Avatar/AvatarIcon.tsx"],"sourcesContent":["import { memo, useMemo } from 'react';\nimport { StyleSheet } from 'react-native';\n\nimport { avatarStyles } from '../../../generated/styles';\nimport { useFontScale } from '../../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { Box } from '../Box';\nimport { IconSlot } from '../IconSlot';\nimport type { AvatarIconProps } from './types';\nimport {\n DEFAULT_AVATAR_SIZE,\n DEFAULT_AVATAR_VARIANT,\n getAvatarSizeStyle,\n getDefaultAvatarIcon,\n} from './utils';\n\nconst AvatarIcon = memo(function AvatarIcon({\n size = DEFAULT_AVATAR_SIZE,\n variant = DEFAULT_AVATAR_VARIANT,\n icon,\n customSize,\n maxFontSizeMultiplier,\n style,\n accessibilityLabel,\n alt,\n ref,\n ...viewProps\n}: AvatarIconProps) {\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);\n avatarStyles.useVariants({ size, icon: variant });\n\n const rootStyle = useMemo(\n () => [\n avatarStyles.root,\n avatarStaticStyles.root,\n getAvatarSizeStyle(avatarStyles.root, customSize, fontScaleFactor),\n style,\n ],\n [avatarStyles.root, customSize, fontScaleFactor, style],\n );\n\n return (\n <Box\n ref={ref}\n accessibilityRole=\"image\"\n accessibilityLabel={accessibilityLabel ?? alt}\n {...viewProps}\n style={rootStyle}\n >\n <IconSlot\n icon={icon ?? getDefaultAvatarIcon(variant)}\n variant=\"fill\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={avatarStyles.icon}\n />\n </Box>\n );\n});\n\nAvatarIcon.displayName = 'AvatarIcon';\n\nconst avatarStaticStyles = StyleSheet.create({\n root: {\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n },\n});\n\nexport { AvatarIcon };\n"],"mappings":";;;;;;;;;;;AAgBA,MAAM,aAAa,KAAK,SAAS,WAAW,EAC1C,OAAA,MACA,UAAU,wBACV,MACA,YACA,uBACA,OACA,oBACA,KACA,KACA,GAAG,aACe;CAClB,MAAM,gCACJ,yBAAyB,WAAW,sBAAsB,IAAI;CAChE,MAAM,kBAAkB,aAAa,8BAA8B;CACnE,aAAa,YAAY;EAAE;EAAM,MAAM;EAAS,CAAC;CAEjD,MAAM,YAAY,cACV;EACJ,aAAa;EACb,mBAAmB;EACnB,mBAAmB,aAAa,MAAM,YAAY,gBAAgB;EAClE;EACD,EACD;EAAC,aAAa;EAAM;EAAY;EAAiB;EAAM,CACxD;CAED,OACE,oBAAC,KAAD;EACO;EACL,mBAAkB;EAClB,oBAAoB,sBAAsB;EAC1C,GAAI;EACJ,OAAO;YAEP,oBAAC,UAAD;GACE,MAAM,QAAQ,qBAAqB,QAAQ;GAC3C,SAAQ;GACR,uBAAuB;GACvB,OAAO,aAAa;GACpB,CAAA;EACE,CAAA;EAER;AAEF,WAAW,cAAc;AAEzB,MAAM,qBAAqB,WAAW,OAAO,EAC3C,MAAM;CACJ,YAAY;CACZ,gBAAgB;CAChB,UAAU;CACX,EACF,CAAC"}
1
+ {"version":3,"file":"AvatarIcon.js","names":[],"sources":["../../../src/components/Avatar/AvatarIcon.tsx"],"sourcesContent":["import { memo, useMemo } from 'react';\nimport { StyleSheet } from 'react-native';\n\nimport { avatarStyles } from '../../../generated/styles';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { Box } from '../Box';\nimport { IconSlot } from '../IconSlot';\nimport type { AvatarIconProps } from './types';\nimport { useAvatarFontScale } from './useAvatarFontScale';\nimport {\n DEFAULT_AVATAR_SIZE,\n DEFAULT_AVATAR_VARIANT,\n getAvatarSizeStyle,\n getDefaultAvatarIcon,\n} from './utils';\n\nconst AvatarIcon = memo(function AvatarIcon({\n size = DEFAULT_AVATAR_SIZE,\n variant = DEFAULT_AVATAR_VARIANT,\n icon,\n customSize,\n maxFontSizeMultiplier,\n style,\n accessibilityLabel,\n alt,\n ref,\n ...viewProps\n}: AvatarIconProps) {\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n avatarStyles.useVariants({ size, icon: variant });\n const fontScaleFactor = useAvatarFontScale(resolvedMaxFontSizeMultiplier);\n\n const rootStyle = useMemo(\n () => [\n avatarStyles.root,\n avatarStaticStyles.root,\n getAvatarSizeStyle(avatarStyles.root, customSize, fontScaleFactor),\n style,\n ],\n [avatarStyles.root, customSize, fontScaleFactor, style],\n );\n\n return (\n <Box\n ref={ref}\n accessibilityRole=\"image\"\n accessibilityLabel={accessibilityLabel ?? alt}\n {...viewProps}\n style={rootStyle}\n >\n <IconSlot\n icon={icon ?? getDefaultAvatarIcon(variant)}\n variant=\"fill\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={avatarStyles.icon}\n />\n </Box>\n );\n});\n\nAvatarIcon.displayName = 'AvatarIcon';\n\nconst avatarStaticStyles = StyleSheet.create({\n root: {\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n },\n});\n\nexport { AvatarIcon };\n"],"mappings":";;;;;;;;;;;AAgBA,MAAM,aAAa,KAAK,SAAS,WAAW,EAC1C,OAAA,MACA,UAAU,wBACV,MACA,YACA,uBACA,OACA,oBACA,KACA,KACA,GAAG,aACe;CAClB,MAAM,gCACJ,yBAAyB,WAAW,sBAAsB,IAAI;CAChE,aAAa,YAAY;EAAE;EAAM,MAAM;EAAS,CAAC;CACjD,MAAM,kBAAkB,mBAAmB,8BAA8B;CAEzE,MAAM,YAAY,cACV;EACJ,aAAa;EACb,mBAAmB;EACnB,mBAAmB,aAAa,MAAM,YAAY,gBAAgB;EAClE;EACD,EACD;EAAC,aAAa;EAAM;EAAY;EAAiB;EAAM,CACxD;CAED,OACE,oBAAC,KAAD;EACO;EACL,mBAAkB;EAClB,oBAAoB,sBAAsB;EAC1C,GAAI;EACJ,OAAO;YAEP,oBAAC,UAAD;GACE,MAAM,QAAQ,qBAAqB,QAAQ;GAC3C,SAAQ;GACR,uBAAuB;GACvB,OAAO,aAAa;GACpB,CAAA;EACE,CAAA;EAER;AAEF,WAAW,cAAc;AAEzB,MAAM,qBAAqB,WAAW,OAAO,EAC3C,MAAM;CACJ,YAAY;CACZ,gBAAgB;CAChB,UAAU;CACX,EACF,CAAC"}
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("../../_virtual/_rolldown/runtime.cjs");
4
4
  const require_components_Box = require("../Box.cjs");
5
- const require_fontScaling_useFontScale = require("../../fontScaling/useFontScale.cjs");
6
5
  const require_fontScaling_useMaxFontSizeMultiplier = require("../../fontScaling/useMaxFontSizeMultiplier.cjs");
6
+ const require_components_Avatar_useAvatarFontScale = require("./useAvatarFontScale.cjs");
7
7
  const require_components_Avatar_utils = require("./utils.cjs");
8
8
  const require_components_Avatar_AvatarIcon = require("./AvatarIcon.cjs");
9
9
  const require_components_Avatar_AvatarText = require("./AvatarText.cjs");
@@ -14,13 +14,13 @@ let generated_styles = require("../../../generated/styles");
14
14
  //#region src/components/Avatar/AvatarImage.tsx
15
15
  const AvatarImage = (0, react.memo)(function AvatarImage({ size = "md", variant = require_components_Avatar_utils.DEFAULT_AVATAR_VARIANT, src, alt, fallback, icon, abbreviationStrategy, customSize, maxFontSizeMultiplier, style, accessibilityLabel, ref, ...viewProps }) {
16
16
  const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
17
- const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier);
18
17
  const [imageError, setImageError] = (0, react.useState)(false);
19
18
  const shouldShowImage = Boolean(src) && !imageError;
20
19
  generated_styles.avatarStyles.useVariants({
21
20
  size,
22
21
  image: variant
23
22
  });
23
+ const fontScaleFactor = require_components_Avatar_useAvatarFontScale.useAvatarFontScale(resolvedMaxFontSizeMultiplier);
24
24
  const rootStyle = (0, react.useMemo)(() => [
25
25
  generated_styles.avatarStyles.root,
26
26
  avatarStaticStyles.root,
@@ -1,7 +1,7 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
2
  import { Box } from "../Box.js";
3
- import { useFontScale } from "../../fontScaling/useFontScale.js";
4
3
  import { useMaxFontSizeMultiplier } from "../../fontScaling/useMaxFontSizeMultiplier.js";
4
+ import { useAvatarFontScale } from "./useAvatarFontScale.js";
5
5
  import { DEFAULT_AVATAR_VARIANT, getAvatarSizeStyle } from "./utils.js";
6
6
  import { AvatarIcon } from "./AvatarIcon.js";
7
7
  import { AvatarText } from "./AvatarText.js";
@@ -12,13 +12,13 @@ import { avatarStyles } from "../../../generated/styles";
12
12
  //#region src/components/Avatar/AvatarImage.tsx
13
13
  const AvatarImage = memo(function AvatarImage({ size = "md", variant = DEFAULT_AVATAR_VARIANT, src, alt, fallback, icon, abbreviationStrategy, customSize, maxFontSizeMultiplier, style, accessibilityLabel, ref, ...viewProps }) {
14
14
  const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
15
- const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);
16
15
  const [imageError, setImageError] = useState(false);
17
16
  const shouldShowImage = Boolean(src) && !imageError;
18
17
  avatarStyles.useVariants({
19
18
  size,
20
19
  image: variant
21
20
  });
21
+ const fontScaleFactor = useAvatarFontScale(resolvedMaxFontSizeMultiplier);
22
22
  const rootStyle = useMemo(() => [
23
23
  avatarStyles.root,
24
24
  avatarStaticStyles.root,
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarImage.js","names":["RNImage"],"sources":["../../../src/components/Avatar/AvatarImage.tsx"],"sourcesContent":["import { memo, useMemo, useState } from 'react';\nimport { Image as RNImage, StyleSheet } from 'react-native';\n\nimport { avatarStyles } from '../../../generated/styles';\nimport { useFontScale } from '../../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { Box } from '../Box';\nimport { AvatarIcon } from './AvatarIcon';\nimport { AvatarText } from './AvatarText';\nimport type { AvatarImageProps } from './types';\nimport { DEFAULT_AVATAR_SIZE, DEFAULT_AVATAR_VARIANT, getAvatarSizeStyle } from './utils';\n\nconst AvatarImage = memo(function AvatarImage({\n size = DEFAULT_AVATAR_SIZE,\n variant = DEFAULT_AVATAR_VARIANT,\n src,\n alt,\n fallback,\n icon,\n abbreviationStrategy,\n customSize,\n maxFontSizeMultiplier,\n style,\n accessibilityLabel,\n ref,\n ...viewProps\n}: AvatarImageProps) {\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);\n const [imageError, setImageError] = useState(false);\n const shouldShowImage = Boolean(src) && !imageError;\n\n avatarStyles.useVariants({ size, image: variant });\n\n const rootStyle = useMemo(\n () => [\n avatarStyles.root,\n avatarStaticStyles.root,\n getAvatarSizeStyle(avatarStyles.root, customSize, fontScaleFactor),\n style,\n ],\n [avatarStyles.root, customSize, fontScaleFactor, style],\n );\n\n if (!shouldShowImage) {\n if (fallback || alt) {\n return (\n <AvatarText\n ref={ref}\n size={size}\n variant={variant}\n name={alt}\n initials={fallback}\n abbreviationStrategy={abbreviationStrategy}\n customSize={customSize}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n accessibilityLabel={accessibilityLabel ?? alt ?? fallback}\n style={style}\n {...viewProps}\n />\n );\n }\n\n return (\n <AvatarIcon\n ref={ref}\n size={size}\n variant={variant}\n icon={icon}\n customSize={customSize}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n accessibilityLabel={accessibilityLabel ?? alt}\n style={style}\n {...viewProps}\n />\n );\n }\n\n return (\n <Box\n ref={ref}\n accessibilityRole=\"image\"\n accessibilityLabel={accessibilityLabel ?? alt}\n {...viewProps}\n style={rootStyle}\n >\n <RNImage\n source={{ uri: src }}\n accessibilityLabel={alt}\n onError={() => setImageError(true)}\n style={avatarStaticStyles.image}\n />\n </Box>\n );\n});\n\nAvatarImage.displayName = 'AvatarImage';\n\nconst avatarStaticStyles = StyleSheet.create({\n root: {\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n },\n image: {\n height: '100%',\n width: '100%',\n },\n});\n\nexport { AvatarImage };\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,cAAc,KAAK,SAAS,YAAY,EAC5C,OAAA,MACA,UAAU,wBACV,KACA,KACA,UACA,MACA,sBACA,YACA,uBACA,OACA,oBACA,KACA,GAAG,aACgB;CACnB,MAAM,gCACJ,yBAAyB,WAAW,sBAAsB,IAAI;CAChE,MAAM,kBAAkB,aAAa,8BAA8B;CACnE,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM;CACnD,MAAM,kBAAkB,QAAQ,IAAI,IAAI,CAAC;CAEzC,aAAa,YAAY;EAAE;EAAM,OAAO;EAAS,CAAC;CAElD,MAAM,YAAY,cACV;EACJ,aAAa;EACb,mBAAmB;EACnB,mBAAmB,aAAa,MAAM,YAAY,gBAAgB;EAClE;EACD,EACD;EAAC,aAAa;EAAM;EAAY;EAAiB;EAAM,CACxD;CAED,IAAI,CAAC,iBAAiB;EACpB,IAAI,YAAY,KACd,OACE,oBAAC,YAAD;GACO;GACC;GACG;GACT,MAAM;GACN,UAAU;GACY;GACV;GACZ,uBAAuB;GACvB,oBAAoB,sBAAsB,OAAO;GAC1C;GACP,GAAI;GACJ,CAAA;EAIN,OACE,oBAAC,YAAD;GACO;GACC;GACG;GACH;GACM;GACZ,uBAAuB;GACvB,oBAAoB,sBAAsB;GACnC;GACP,GAAI;GACJ,CAAA;;CAIN,OACE,oBAAC,KAAD;EACO;EACL,mBAAkB;EAClB,oBAAoB,sBAAsB;EAC1C,GAAI;EACJ,OAAO;YAEP,oBAACA,OAAD;GACE,QAAQ,EAAE,KAAK,KAAK;GACpB,oBAAoB;GACpB,eAAe,cAAc,KAAK;GAClC,OAAO,mBAAmB;GAC1B,CAAA;EACE,CAAA;EAER;AAEF,YAAY,cAAc;AAE1B,MAAM,qBAAqB,WAAW,OAAO;CAC3C,MAAM;EACJ,YAAY;EACZ,gBAAgB;EAChB,UAAU;EACX;CACD,OAAO;EACL,QAAQ;EACR,OAAO;EACR;CACF,CAAC"}
1
+ {"version":3,"file":"AvatarImage.js","names":["RNImage"],"sources":["../../../src/components/Avatar/AvatarImage.tsx"],"sourcesContent":["import { memo, useMemo, useState } from 'react';\nimport { Image as RNImage, StyleSheet } from 'react-native';\n\nimport { avatarStyles } from '../../../generated/styles';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { Box } from '../Box';\nimport { AvatarIcon } from './AvatarIcon';\nimport { AvatarText } from './AvatarText';\nimport type { AvatarImageProps } from './types';\nimport { useAvatarFontScale } from './useAvatarFontScale';\nimport { DEFAULT_AVATAR_SIZE, DEFAULT_AVATAR_VARIANT, getAvatarSizeStyle } from './utils';\n\nconst AvatarImage = memo(function AvatarImage({\n size = DEFAULT_AVATAR_SIZE,\n variant = DEFAULT_AVATAR_VARIANT,\n src,\n alt,\n fallback,\n icon,\n abbreviationStrategy,\n customSize,\n maxFontSizeMultiplier,\n style,\n accessibilityLabel,\n ref,\n ...viewProps\n}: AvatarImageProps) {\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const [imageError, setImageError] = useState(false);\n const shouldShowImage = Boolean(src) && !imageError;\n\n avatarStyles.useVariants({ size, image: variant });\n const fontScaleFactor = useAvatarFontScale(resolvedMaxFontSizeMultiplier);\n\n const rootStyle = useMemo(\n () => [\n avatarStyles.root,\n avatarStaticStyles.root,\n getAvatarSizeStyle(avatarStyles.root, customSize, fontScaleFactor),\n style,\n ],\n [avatarStyles.root, customSize, fontScaleFactor, style],\n );\n\n if (!shouldShowImage) {\n if (fallback || alt) {\n return (\n <AvatarText\n ref={ref}\n size={size}\n variant={variant}\n name={alt}\n initials={fallback}\n abbreviationStrategy={abbreviationStrategy}\n customSize={customSize}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n accessibilityLabel={accessibilityLabel ?? alt ?? fallback}\n style={style}\n {...viewProps}\n />\n );\n }\n\n return (\n <AvatarIcon\n ref={ref}\n size={size}\n variant={variant}\n icon={icon}\n customSize={customSize}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n accessibilityLabel={accessibilityLabel ?? alt}\n style={style}\n {...viewProps}\n />\n );\n }\n\n return (\n <Box\n ref={ref}\n accessibilityRole=\"image\"\n accessibilityLabel={accessibilityLabel ?? alt}\n {...viewProps}\n style={rootStyle}\n >\n <RNImage\n source={{ uri: src }}\n accessibilityLabel={alt}\n onError={() => setImageError(true)}\n style={avatarStaticStyles.image}\n />\n </Box>\n );\n});\n\nAvatarImage.displayName = 'AvatarImage';\n\nconst avatarStaticStyles = StyleSheet.create({\n root: {\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n },\n image: {\n height: '100%',\n width: '100%',\n },\n});\n\nexport { AvatarImage };\n"],"mappings":";;;;;;;;;;;;AAYA,MAAM,cAAc,KAAK,SAAS,YAAY,EAC5C,OAAA,MACA,UAAU,wBACV,KACA,KACA,UACA,MACA,sBACA,YACA,uBACA,OACA,oBACA,KACA,GAAG,aACgB;CACnB,MAAM,gCACJ,yBAAyB,WAAW,sBAAsB,IAAI;CAChE,MAAM,CAAC,YAAY,iBAAiB,SAAS,MAAM;CACnD,MAAM,kBAAkB,QAAQ,IAAI,IAAI,CAAC;CAEzC,aAAa,YAAY;EAAE;EAAM,OAAO;EAAS,CAAC;CAClD,MAAM,kBAAkB,mBAAmB,8BAA8B;CAEzE,MAAM,YAAY,cACV;EACJ,aAAa;EACb,mBAAmB;EACnB,mBAAmB,aAAa,MAAM,YAAY,gBAAgB;EAClE;EACD,EACD;EAAC,aAAa;EAAM;EAAY;EAAiB;EAAM,CACxD;CAED,IAAI,CAAC,iBAAiB;EACpB,IAAI,YAAY,KACd,OACE,oBAAC,YAAD;GACO;GACC;GACG;GACT,MAAM;GACN,UAAU;GACY;GACV;GACZ,uBAAuB;GACvB,oBAAoB,sBAAsB,OAAO;GAC1C;GACP,GAAI;GACJ,CAAA;EAIN,OACE,oBAAC,YAAD;GACO;GACC;GACG;GACH;GACM;GACZ,uBAAuB;GACvB,oBAAoB,sBAAsB;GACnC;GACP,GAAI;GACJ,CAAA;;CAIN,OACE,oBAAC,KAAD;EACO;EACL,mBAAkB;EAClB,oBAAoB,sBAAsB;EAC1C,GAAI;EACJ,OAAO;YAEP,oBAACA,OAAD;GACE,QAAQ,EAAE,KAAK,KAAK;GACpB,oBAAoB;GACpB,eAAe,cAAc,KAAK;GAClC,OAAO,mBAAmB;GAC1B,CAAA;EACE,CAAA;EAER;AAEF,YAAY,cAAc;AAE1B,MAAM,qBAAqB,WAAW,OAAO;CAC3C,MAAM;EACJ,YAAY;EACZ,gBAAgB;EAChB,UAAU;EACX;CACD,OAAO;EACL,QAAQ;EACR,OAAO;EACR;CACF,CAAC"}
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("../../_virtual/_rolldown/runtime.cjs");
4
4
  const require_components_Box = require("../Box.cjs");
5
- const require_fontScaling_useFontScale = require("../../fontScaling/useFontScale.cjs");
6
5
  const require_fontScaling_useMaxFontSizeMultiplier = require("../../fontScaling/useMaxFontSizeMultiplier.cjs");
7
6
  const require_components_Text = require("../Text.cjs");
7
+ const require_components_Avatar_useAvatarFontScale = require("./useAvatarFontScale.cjs");
8
8
  const require_components_Avatar_utils = require("./utils.cjs");
9
9
  let react = require("react");
10
10
  let react_native = require("react-native");
@@ -13,11 +13,11 @@ let generated_styles = require("../../../generated/styles");
13
13
  //#region src/components/Avatar/AvatarText.tsx
14
14
  const AvatarText = (0, react.memo)(function AvatarText({ size = "md", variant = require_components_Avatar_utils.DEFAULT_AVATAR_VARIANT, name, initials, abbreviationStrategy, customSize, maxFontSizeMultiplier, style, accessibilityLabel, ref, ...viewProps }) {
15
15
  const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
16
- const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier);
17
16
  generated_styles.avatarStyles.useVariants({
18
17
  size,
19
18
  text: variant
20
19
  });
20
+ const fontScaleFactor = require_components_Avatar_useAvatarFontScale.useAvatarFontScale(resolvedMaxFontSizeMultiplier);
21
21
  const rootStyle = (0, react.useMemo)(() => [
22
22
  generated_styles.avatarStyles.root,
23
23
  avatarStaticStyles.root,
@@ -1,8 +1,8 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
2
  import { Box } from "../Box.js";
3
- import { useFontScale } from "../../fontScaling/useFontScale.js";
4
3
  import { useMaxFontSizeMultiplier } from "../../fontScaling/useMaxFontSizeMultiplier.js";
5
4
  import { Text as Text$1 } from "../Text.js";
5
+ import { useAvatarFontScale } from "./useAvatarFontScale.js";
6
6
  import { DEFAULT_AVATAR_VARIANT, generateAvatarAbbreviation, getAvatarSizeStyle } from "./utils.js";
7
7
  import { memo, useMemo } from "react";
8
8
  import { StyleSheet } from "react-native";
@@ -11,11 +11,11 @@ import { avatarStyles } from "../../../generated/styles";
11
11
  //#region src/components/Avatar/AvatarText.tsx
12
12
  const AvatarText = memo(function AvatarText({ size = "md", variant = DEFAULT_AVATAR_VARIANT, name, initials, abbreviationStrategy, customSize, maxFontSizeMultiplier, style, accessibilityLabel, ref, ...viewProps }) {
13
13
  const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
14
- const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);
15
14
  avatarStyles.useVariants({
16
15
  size,
17
16
  text: variant
18
17
  });
18
+ const fontScaleFactor = useAvatarFontScale(resolvedMaxFontSizeMultiplier);
19
19
  const rootStyle = useMemo(() => [
20
20
  avatarStyles.root,
21
21
  avatarStaticStyles.root,
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarText.js","names":["Text"],"sources":["../../../src/components/Avatar/AvatarText.tsx"],"sourcesContent":["import { memo, useMemo } from 'react';\nimport { StyleSheet } from 'react-native';\n\nimport { avatarStyles } from '../../../generated/styles';\nimport { useFontScale } from '../../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { Box } from '../Box';\nimport { Text } from '../Text';\nimport type { AvatarTextProps } from './types';\nimport {\n DEFAULT_AVATAR_SIZE,\n DEFAULT_AVATAR_VARIANT,\n generateAvatarAbbreviation,\n getAvatarSizeStyle,\n} from './utils';\n\nconst AvatarText = memo(function AvatarText({\n size = DEFAULT_AVATAR_SIZE,\n variant = DEFAULT_AVATAR_VARIANT,\n name,\n initials,\n abbreviationStrategy,\n customSize,\n maxFontSizeMultiplier,\n style,\n accessibilityLabel,\n ref,\n ...viewProps\n}: AvatarTextProps) {\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);\n avatarStyles.useVariants({ size, text: variant });\n\n const rootStyle = useMemo(\n () => [\n avatarStyles.root,\n avatarStaticStyles.root,\n getAvatarSizeStyle(avatarStyles.root, customSize, fontScaleFactor),\n style,\n ],\n [avatarStyles.root, customSize, fontScaleFactor, style],\n );\n\n return (\n <Box\n ref={ref}\n accessibilityRole=\"image\"\n accessibilityLabel={accessibilityLabel ?? name ?? initials}\n {...viewProps}\n style={rootStyle}\n >\n <Text\n color=\"inherit\"\n variant=\"inherit\"\n numberOfLines={1}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={avatarStyles.text}\n >\n {initials || generateAvatarAbbreviation(name, abbreviationStrategy)}\n </Text>\n </Box>\n );\n});\n\nAvatarText.displayName = 'AvatarText';\n\nconst avatarStaticStyles = StyleSheet.create({\n root: {\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n },\n});\n\nexport { AvatarText };\n"],"mappings":";;;;;;;;;;;AAgBA,MAAM,aAAa,KAAK,SAAS,WAAW,EAC1C,OAAA,MACA,UAAU,wBACV,MACA,UACA,sBACA,YACA,uBACA,OACA,oBACA,KACA,GAAG,aACe;CAClB,MAAM,gCACJ,yBAAyB,WAAW,sBAAsB,IAAI;CAChE,MAAM,kBAAkB,aAAa,8BAA8B;CACnE,aAAa,YAAY;EAAE;EAAM,MAAM;EAAS,CAAC;CAEjD,MAAM,YAAY,cACV;EACJ,aAAa;EACb,mBAAmB;EACnB,mBAAmB,aAAa,MAAM,YAAY,gBAAgB;EAClE;EACD,EACD;EAAC,aAAa;EAAM;EAAY;EAAiB;EAAM,CACxD;CAED,OACE,oBAAC,KAAD;EACO;EACL,mBAAkB;EAClB,oBAAoB,sBAAsB,QAAQ;EAClD,GAAI;EACJ,OAAO;YAEP,oBAACA,QAAD;GACE,OAAM;GACN,SAAQ;GACR,eAAe;GACf,uBAAuB;GACvB,OAAO,aAAa;aAEnB,YAAY,2BAA2B,MAAM,qBAAqB;GAC9D,CAAA;EACH,CAAA;EAER;AAEF,WAAW,cAAc;AAEzB,MAAM,qBAAqB,WAAW,OAAO,EAC3C,MAAM;CACJ,YAAY;CACZ,gBAAgB;CAChB,UAAU;CACX,EACF,CAAC"}
1
+ {"version":3,"file":"AvatarText.js","names":["Text"],"sources":["../../../src/components/Avatar/AvatarText.tsx"],"sourcesContent":["import { memo, useMemo } from 'react';\nimport { StyleSheet } from 'react-native';\n\nimport { avatarStyles } from '../../../generated/styles';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { Box } from '../Box';\nimport { Text } from '../Text';\nimport type { AvatarTextProps } from './types';\nimport { useAvatarFontScale } from './useAvatarFontScale';\nimport {\n DEFAULT_AVATAR_SIZE,\n DEFAULT_AVATAR_VARIANT,\n generateAvatarAbbreviation,\n getAvatarSizeStyle,\n} from './utils';\n\nconst AvatarText = memo(function AvatarText({\n size = DEFAULT_AVATAR_SIZE,\n variant = DEFAULT_AVATAR_VARIANT,\n name,\n initials,\n abbreviationStrategy,\n customSize,\n maxFontSizeMultiplier,\n style,\n accessibilityLabel,\n ref,\n ...viewProps\n}: AvatarTextProps) {\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n avatarStyles.useVariants({ size, text: variant });\n const fontScaleFactor = useAvatarFontScale(resolvedMaxFontSizeMultiplier);\n\n const rootStyle = useMemo(\n () => [\n avatarStyles.root,\n avatarStaticStyles.root,\n getAvatarSizeStyle(avatarStyles.root, customSize, fontScaleFactor),\n style,\n ],\n [avatarStyles.root, customSize, fontScaleFactor, style],\n );\n\n return (\n <Box\n ref={ref}\n accessibilityRole=\"image\"\n accessibilityLabel={accessibilityLabel ?? name ?? initials}\n {...viewProps}\n style={rootStyle}\n >\n <Text\n color=\"inherit\"\n variant=\"inherit\"\n numberOfLines={1}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={avatarStyles.text}\n >\n {initials || generateAvatarAbbreviation(name, abbreviationStrategy)}\n </Text>\n </Box>\n );\n});\n\nAvatarText.displayName = 'AvatarText';\n\nconst avatarStaticStyles = StyleSheet.create({\n root: {\n alignItems: 'center',\n justifyContent: 'center',\n overflow: 'hidden',\n },\n});\n\nexport { AvatarText };\n"],"mappings":";;;;;;;;;;;AAgBA,MAAM,aAAa,KAAK,SAAS,WAAW,EAC1C,OAAA,MACA,UAAU,wBACV,MACA,UACA,sBACA,YACA,uBACA,OACA,oBACA,KACA,GAAG,aACe;CAClB,MAAM,gCACJ,yBAAyB,WAAW,sBAAsB,IAAI;CAChE,aAAa,YAAY;EAAE;EAAM,MAAM;EAAS,CAAC;CACjD,MAAM,kBAAkB,mBAAmB,8BAA8B;CAEzE,MAAM,YAAY,cACV;EACJ,aAAa;EACb,mBAAmB;EACnB,mBAAmB,aAAa,MAAM,YAAY,gBAAgB;EAClE;EACD,EACD;EAAC,aAAa;EAAM;EAAY;EAAiB;EAAM,CACxD;CAED,OACE,oBAAC,KAAD;EACO;EACL,mBAAkB;EAClB,oBAAoB,sBAAsB,QAAQ;EAClD,GAAI;EACJ,OAAO;YAEP,oBAACA,QAAD;GACE,OAAM;GACN,SAAQ;GACR,eAAe;GACf,uBAAuB;GACvB,OAAO,aAAa;aAEnB,YAAY,2BAA2B,MAAM,qBAAqB;GAC9D,CAAA;EACH,CAAA;EAER;AAEF,WAAW,cAAc;AAEzB,MAAM,qBAAqB,WAAW,OAAO,EAC3C,MAAM;CACJ,YAAY;CACZ,gBAAgB;CAChB,UAAU;CACX,EACF,CAAC"}
@@ -0,0 +1,16 @@
1
+ /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ require("../../_virtual/_rolldown/runtime.cjs");
4
+ const require_fontScaling_useFontScale = require("../../fontScaling/useFontScale.cjs");
5
+ let generated_styles = require("../../../generated/styles");
6
+ //#region src/components/Avatar/useAvatarFontScale.ts
7
+ /** Keep every avatar content type on one size-aware scale that contains text and icons. */
8
+ function useAvatarFontScale(maxFontSizeMultiplier) {
9
+ const textStyle = generated_styles.avatarStyles.text;
10
+ const iconStyle = generated_styles.avatarStyles.icon;
11
+ const textScaleFactor = require_fontScaling_useFontScale.useFontScale(maxFontSizeMultiplier, (typeof textStyle.lineHeight === "number" ? textStyle.lineHeight : void 0) ?? (typeof textStyle.fontSize === "number" ? textStyle.fontSize : void 0));
12
+ const iconScaleFactor = require_fontScaling_useFontScale.useFontScale(maxFontSizeMultiplier, (typeof iconStyle.fontSize === "number" ? iconStyle.fontSize : void 0) ?? (typeof iconStyle.lineHeight === "number" ? iconStyle.lineHeight : void 0));
13
+ return Math.max(textScaleFactor, iconScaleFactor);
14
+ }
15
+ //#endregion
16
+ exports.useAvatarFontScale = useAvatarFontScale;
@@ -0,0 +1,7 @@
1
+
2
+ //#region src/components/Avatar/useAvatarFontScale.d.ts
3
+ /** Keep every avatar content type on one size-aware scale that contains text and icons. */
4
+ declare function useAvatarFontScale(maxFontSizeMultiplier: number): number;
5
+ //#endregion
6
+ export { useAvatarFontScale };
7
+ //# sourceMappingURL=useAvatarFontScale.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAvatarFontScale.d.cts","names":[],"sources":["../../../src/components/Avatar/useAvatarFontScale.ts"],"mappings":";;;iBAMS,kBAAA,CAAmB,qBAAA"}
@@ -0,0 +1,7 @@
1
+
2
+ //#region src/components/Avatar/useAvatarFontScale.d.ts
3
+ /** Keep every avatar content type on one size-aware scale that contains text and icons. */
4
+ declare function useAvatarFontScale(maxFontSizeMultiplier: number): number;
5
+ //#endregion
6
+ export { useAvatarFontScale };
7
+ //# sourceMappingURL=useAvatarFontScale.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAvatarFontScale.d.ts","names":[],"sources":["../../../src/components/Avatar/useAvatarFontScale.ts"],"mappings":";;;iBAMS,kBAAA,CAAmB,qBAAA"}
@@ -0,0 +1,16 @@
1
+ /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ import { useFontScale } from "../../fontScaling/useFontScale.js";
3
+ import { avatarStyles } from "../../../generated/styles";
4
+ //#region src/components/Avatar/useAvatarFontScale.ts
5
+ /** Keep every avatar content type on one size-aware scale that contains text and icons. */
6
+ function useAvatarFontScale(maxFontSizeMultiplier) {
7
+ const textStyle = avatarStyles.text;
8
+ const iconStyle = avatarStyles.icon;
9
+ const textScaleFactor = useFontScale(maxFontSizeMultiplier, (typeof textStyle.lineHeight === "number" ? textStyle.lineHeight : void 0) ?? (typeof textStyle.fontSize === "number" ? textStyle.fontSize : void 0));
10
+ const iconScaleFactor = useFontScale(maxFontSizeMultiplier, (typeof iconStyle.fontSize === "number" ? iconStyle.fontSize : void 0) ?? (typeof iconStyle.lineHeight === "number" ? iconStyle.lineHeight : void 0));
11
+ return Math.max(textScaleFactor, iconScaleFactor);
12
+ }
13
+ //#endregion
14
+ export { useAvatarFontScale };
15
+
16
+ //# sourceMappingURL=useAvatarFontScale.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAvatarFontScale.js","names":[],"sources":["../../../src/components/Avatar/useAvatarFontScale.ts"],"sourcesContent":["import type { TextStyle } from 'react-native';\n\nimport { avatarStyles } from '../../../generated/styles';\nimport { useFontScale } from '../../fontScaling/useFontScale';\n\n/** Keep every avatar content type on one size-aware scale that contains text and icons. */\nfunction useAvatarFontScale(maxFontSizeMultiplier: number): number {\n const textStyle = avatarStyles.text as TextStyle;\n const iconStyle = avatarStyles.icon as TextStyle;\n const textScaleFactor = useFontScale(\n maxFontSizeMultiplier,\n (typeof textStyle.lineHeight === 'number' ? textStyle.lineHeight : undefined) ??\n (typeof textStyle.fontSize === 'number' ? textStyle.fontSize : undefined),\n );\n const iconScaleFactor = useFontScale(\n maxFontSizeMultiplier,\n (typeof iconStyle.fontSize === 'number' ? iconStyle.fontSize : undefined) ??\n (typeof iconStyle.lineHeight === 'number' ? iconStyle.lineHeight : undefined),\n );\n\n return Math.max(textScaleFactor, iconScaleFactor);\n}\n\nexport { useAvatarFontScale };\n"],"mappings":";;;;;AAMA,SAAS,mBAAmB,uBAAuC;CACjE,MAAM,YAAY,aAAa;CAC/B,MAAM,YAAY,aAAa;CAC/B,MAAM,kBAAkB,aACtB,wBACC,OAAO,UAAU,eAAe,WAAW,UAAU,aAAa,KAAA,OAChE,OAAO,UAAU,aAAa,WAAW,UAAU,WAAW,KAAA,GAClE;CACD,MAAM,kBAAkB,aACtB,wBACC,OAAO,UAAU,aAAa,WAAW,UAAU,WAAW,KAAA,OAC5D,OAAO,UAAU,eAAe,WAAW,UAAU,aAAa,KAAA,GACtE;CAED,OAAO,KAAK,IAAI,iBAAiB,gBAAgB"}
@@ -47,10 +47,11 @@ function getSafeIconCell(fontSize) {
47
47
  /**
48
48
  * Safe native content metrics while retaining the token-derived target control height.
49
49
  *
50
- * `fontScaleFactor` (the capped OS font scale, >= 1) pre-scales container
51
- * metrics only. The returned `labelLineHeight`/`iconCellHeight` stay unscaled
52
- * because they go into Text/Icon styles, which native multiplies by the same
53
- * capped factor container math must mirror that, not double-apply it.
50
+ * `fontScaleFactor` pre-scales container metrics only. A single number keeps
51
+ * the legacy linear behavior; distinct label/icon factors let Android 14+
52
+ * geometry follow its size-dependent nonlinear font curve. The returned
53
+ * `labelLineHeight`/`iconCellHeight` stay unscaled because native Text applies
54
+ * the same cap.
54
55
  */
55
56
  function getButtonControlMetrics(theme, size, fontScaleFactor = 1) {
56
57
  const rootStyle = getLayerStyle(theme, buttonSizePath(size, "root"));
@@ -60,11 +61,14 @@ function getButtonControlMetrics(theme, size, fontScaleFactor = 1) {
60
61
  const iconSize = getIconSize(iconStyle);
61
62
  const fontSize = typeof textStyle.fontSize === "number" ? textStyle.fontSize : iconSize;
62
63
  const tokenLineHeight = typeof textStyle.lineHeight === "number" ? textStyle.lineHeight : fontSize;
63
- const targetContentHeight = Math.max(iconSize, tokenLineHeight) * fontScaleFactor;
64
+ const labelScaleFactor = typeof fontScaleFactor === "number" ? fontScaleFactor : fontScaleFactor.label;
65
+ const iconScaleFactor = typeof fontScaleFactor === "number" ? fontScaleFactor : fontScaleFactor.icon;
66
+ const iconCellScaleFactor = typeof fontScaleFactor === "number" ? fontScaleFactor : fontScaleFactor.iconCell ?? fontScaleFactor.icon;
67
+ const targetContentHeight = Math.max(iconSize * iconScaleFactor, tokenLineHeight * labelScaleFactor);
64
68
  const minHeight = Math.ceil(paddingVertical * 2 + targetContentHeight);
65
69
  const labelLineHeight = getSafeLabelLineHeight(textStyle, iconSize);
66
70
  const iconCellHeight = getSafeIconCell(iconSize);
67
- const safeContentHeight = Math.max(labelLineHeight, iconCellHeight) * fontScaleFactor;
71
+ const safeContentHeight = Math.max(labelLineHeight * labelScaleFactor, iconCellHeight * iconCellScaleFactor);
68
72
  return {
69
73
  minHeight,
70
74
  labelLineHeight,
@@ -11,12 +11,17 @@ declare function getSafeIconCell(fontSize: number): number;
11
11
  /**
12
12
  * Safe native content metrics while retaining the token-derived target control height.
13
13
  *
14
- * `fontScaleFactor` (the capped OS font scale, >= 1) pre-scales container
15
- * metrics only. The returned `labelLineHeight`/`iconCellHeight` stay unscaled
16
- * because they go into Text/Icon styles, which native multiplies by the same
17
- * capped factor container math must mirror that, not double-apply it.
14
+ * `fontScaleFactor` pre-scales container metrics only. A single number keeps
15
+ * the legacy linear behavior; distinct label/icon factors let Android 14+
16
+ * geometry follow its size-dependent nonlinear font curve. The returned
17
+ * `labelLineHeight`/`iconCellHeight` stay unscaled because native Text applies
18
+ * the same cap.
18
19
  */
19
- declare function getButtonControlMetrics(theme: ButtonTheme, size: ButtonSize, fontScaleFactor?: number): {
20
+ declare function getButtonControlMetrics(theme: ButtonTheme, size: ButtonSize, fontScaleFactor?: number | {
21
+ label: number;
22
+ icon: number;
23
+ iconCell?: number;
24
+ }): {
20
25
  minHeight: number;
21
26
  labelLineHeight: number;
22
27
  iconCellHeight: number;
@@ -1 +1 @@
1
- {"version":3,"file":"buttonTheme.d.cts","names":[],"sources":["../../../src/components/Button/buttonTheme.ts"],"mappings":";;;;;KAKK,WAAA;EAEH,UAAA,EAAY,MAAA;AAAA;;iBA4DE,eAAA,CAAgB,QAAA;;;AAAhC;;;;;AAwBA;iBAAgB,uBAAA,CACd,KAAA,EAAO,WAAA,EACP,IAAA,EAAM,UAAA,EACN,eAAA;EAEA,SAAA;EACA,eAAA;EACA,cAAA;EACA,eAAA;AAAA;;;;;;;iBA8Bc,2BAAA,CACd,KAAA,EAAO,WAAA,EACP,IAAA,EAAM,cAAA,EACN,eAAA;EAEA,SAAA;EACA,cAAA;EACA,eAAA;EACA,iBAAA;AAAA;;iBA4Bc,kBAAA,CAAmB,SAAA,EAAW,SAAA,EAAW,eAAA,WAA0B,SAAA"}
1
+ {"version":3,"file":"buttonTheme.d.cts","names":[],"sources":["../../../src/components/Button/buttonTheme.ts"],"mappings":";;;;;KAKK,WAAA;EAEH,UAAA,EAAY,MAAA;AAAA;;iBA4DE,eAAA,CAAgB,QAAA;;;AAAhC;;;;;AAyBA;;iBAAgB,uBAAA,CACd,KAAA,EAAO,WAAA,EACP,IAAA,EAAM,UAAA,EACN,eAAA;EAA4B,KAAA;EAAe,IAAA;EAAc,QAAA;AAAA;EAEzD,SAAA;EACA,eAAA;EACA,cAAA;EACA,eAAA;AAAA;;;;;;;iBA4Cc,2BAAA,CACd,KAAA,EAAO,WAAA,EACP,IAAA,EAAM,cAAA,EACN,eAAA;EAEA,SAAA;EACA,cAAA;EACA,eAAA;EACA,iBAAA;AAAA;;iBA4Bc,kBAAA,CAAmB,SAAA,EAAW,SAAA,EAAW,eAAA,WAA0B,SAAA"}
@@ -11,12 +11,17 @@ declare function getSafeIconCell(fontSize: number): number;
11
11
  /**
12
12
  * Safe native content metrics while retaining the token-derived target control height.
13
13
  *
14
- * `fontScaleFactor` (the capped OS font scale, >= 1) pre-scales container
15
- * metrics only. The returned `labelLineHeight`/`iconCellHeight` stay unscaled
16
- * because they go into Text/Icon styles, which native multiplies by the same
17
- * capped factor container math must mirror that, not double-apply it.
14
+ * `fontScaleFactor` pre-scales container metrics only. A single number keeps
15
+ * the legacy linear behavior; distinct label/icon factors let Android 14+
16
+ * geometry follow its size-dependent nonlinear font curve. The returned
17
+ * `labelLineHeight`/`iconCellHeight` stay unscaled because native Text applies
18
+ * the same cap.
18
19
  */
19
- declare function getButtonControlMetrics(theme: ButtonTheme, size: ButtonSize, fontScaleFactor?: number): {
20
+ declare function getButtonControlMetrics(theme: ButtonTheme, size: ButtonSize, fontScaleFactor?: number | {
21
+ label: number;
22
+ icon: number;
23
+ iconCell?: number;
24
+ }): {
20
25
  minHeight: number;
21
26
  labelLineHeight: number;
22
27
  iconCellHeight: number;
@@ -1 +1 @@
1
- {"version":3,"file":"buttonTheme.d.ts","names":[],"sources":["../../../src/components/Button/buttonTheme.ts"],"mappings":";;;;;KAKK,WAAA;EAEH,UAAA,EAAY,MAAA;AAAA;;iBA4DE,eAAA,CAAgB,QAAA;;;AAAhC;;;;;AAwBA;iBAAgB,uBAAA,CACd,KAAA,EAAO,WAAA,EACP,IAAA,EAAM,UAAA,EACN,eAAA;EAEA,SAAA;EACA,eAAA;EACA,cAAA;EACA,eAAA;AAAA;;;;;;;iBA8Bc,2BAAA,CACd,KAAA,EAAO,WAAA,EACP,IAAA,EAAM,cAAA,EACN,eAAA;EAEA,SAAA;EACA,cAAA;EACA,eAAA;EACA,iBAAA;AAAA;;iBA4Bc,kBAAA,CAAmB,SAAA,EAAW,SAAA,EAAW,eAAA,WAA0B,SAAA"}
1
+ {"version":3,"file":"buttonTheme.d.ts","names":[],"sources":["../../../src/components/Button/buttonTheme.ts"],"mappings":";;;;;KAKK,WAAA;EAEH,UAAA,EAAY,MAAA;AAAA;;iBA4DE,eAAA,CAAgB,QAAA;;;AAAhC;;;;;AAyBA;;iBAAgB,uBAAA,CACd,KAAA,EAAO,WAAA,EACP,IAAA,EAAM,UAAA,EACN,eAAA;EAA4B,KAAA;EAAe,IAAA;EAAc,QAAA;AAAA;EAEzD,SAAA;EACA,eAAA;EACA,cAAA;EACA,eAAA;AAAA;;;;;;;iBA4Cc,2BAAA,CACd,KAAA,EAAO,WAAA,EACP,IAAA,EAAM,cAAA,EACN,eAAA;EAEA,SAAA;EACA,cAAA;EACA,eAAA;EACA,iBAAA;AAAA;;iBA4Bc,kBAAA,CAAmB,SAAA,EAAW,SAAA,EAAW,eAAA,WAA0B,SAAA"}
@@ -46,10 +46,11 @@ function getSafeIconCell(fontSize) {
46
46
  /**
47
47
  * Safe native content metrics while retaining the token-derived target control height.
48
48
  *
49
- * `fontScaleFactor` (the capped OS font scale, >= 1) pre-scales container
50
- * metrics only. The returned `labelLineHeight`/`iconCellHeight` stay unscaled
51
- * because they go into Text/Icon styles, which native multiplies by the same
52
- * capped factor container math must mirror that, not double-apply it.
49
+ * `fontScaleFactor` pre-scales container metrics only. A single number keeps
50
+ * the legacy linear behavior; distinct label/icon factors let Android 14+
51
+ * geometry follow its size-dependent nonlinear font curve. The returned
52
+ * `labelLineHeight`/`iconCellHeight` stay unscaled because native Text applies
53
+ * the same cap.
53
54
  */
54
55
  function getButtonControlMetrics(theme, size, fontScaleFactor = 1) {
55
56
  const rootStyle = getLayerStyle(theme, buttonSizePath(size, "root"));
@@ -59,11 +60,14 @@ function getButtonControlMetrics(theme, size, fontScaleFactor = 1) {
59
60
  const iconSize = getIconSize(iconStyle);
60
61
  const fontSize = typeof textStyle.fontSize === "number" ? textStyle.fontSize : iconSize;
61
62
  const tokenLineHeight = typeof textStyle.lineHeight === "number" ? textStyle.lineHeight : fontSize;
62
- const targetContentHeight = Math.max(iconSize, tokenLineHeight) * fontScaleFactor;
63
+ const labelScaleFactor = typeof fontScaleFactor === "number" ? fontScaleFactor : fontScaleFactor.label;
64
+ const iconScaleFactor = typeof fontScaleFactor === "number" ? fontScaleFactor : fontScaleFactor.icon;
65
+ const iconCellScaleFactor = typeof fontScaleFactor === "number" ? fontScaleFactor : fontScaleFactor.iconCell ?? fontScaleFactor.icon;
66
+ const targetContentHeight = Math.max(iconSize * iconScaleFactor, tokenLineHeight * labelScaleFactor);
63
67
  const minHeight = Math.ceil(paddingVertical * 2 + targetContentHeight);
64
68
  const labelLineHeight = getSafeLabelLineHeight(textStyle, iconSize);
65
69
  const iconCellHeight = getSafeIconCell(iconSize);
66
- const safeContentHeight = Math.max(labelLineHeight, iconCellHeight) * fontScaleFactor;
70
+ const safeContentHeight = Math.max(labelLineHeight * labelScaleFactor, iconCellHeight * iconCellScaleFactor);
67
71
  return {
68
72
  minHeight,
69
73
  labelLineHeight,
@@ -1 +1 @@
1
- {"version":3,"file":"buttonTheme.js","names":[],"sources":["../../../src/components/Button/buttonTheme.ts"],"sourcesContent":["import type { ButtonSize, IconButtonSize } from '@yahoo/uds-types';\nimport type { TextStyle, ViewStyle } from 'react-native';\n\nimport { fontMetrics } from '../../../generated/fontMetrics';\n\ntype ButtonTheme = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n components: Record<string, any>;\n};\n\nconst SHARED_BUTTON_ICONBUTTON_SIZES = new Set<IconButtonSize>(['xs', 'sm', 'md', 'lg']);\n// Covers common native font boxes (roughly 1.2em) plus pixel-rounding headroom.\nconst UNKNOWN_FONT_LINE_HEIGHT_RATIO = 1.3;\n\nfunction buttonSizePath(size: ButtonSize, layer: 'root' | 'icon' | 'rootText'): string {\n return `button/size/${size}/${layer}/rest`;\n}\n\nfunction iconButtonSizePath(size: IconButtonSize, layer: 'root' | 'icon'): string {\n return `iconButton/size/${size}/${layer}/rest`;\n}\n\nfunction getLayerStyle(theme: ButtonTheme, path: string): ViewStyle | TextStyle {\n const style = theme.components[path];\n return style && typeof style === 'object' ? style : {};\n}\n\nfunction getIconSize(iconStyle: TextStyle): number {\n return (\n (typeof iconStyle.fontSize === 'number' ? iconStyle.fontSize : undefined) ??\n (typeof iconStyle.lineHeight === 'number' ? iconStyle.lineHeight : undefined) ??\n 16\n );\n}\n\nfunction getVerticalPadding(rootStyle: ViewStyle): number {\n return (\n (typeof rootStyle.paddingVertical === 'number' ? rootStyle.paddingVertical : undefined) ??\n (typeof rootStyle.padding === 'number' ? rootStyle.padding : undefined) ??\n 0\n );\n}\n\nfunction getMetricHeight(value: number, unitsPerEm: number, fontSize: number): number {\n return Math.ceil((Math.max(0, value) / unitsPerEm) * fontSize);\n}\n\nfunction getSafeLabelLineHeight(textStyle: TextStyle, fallbackFontSize: number): number {\n const fontSize = typeof textStyle.fontSize === 'number' ? textStyle.fontSize : fallbackFontSize;\n const tokenLineHeight =\n typeof textStyle.lineHeight === 'number' ? textStyle.lineHeight : fontSize;\n const metrics =\n typeof textStyle.fontFamily === 'string' ? fontMetrics[textStyle.fontFamily] : undefined;\n\n if (!metrics || metrics.unitsPerEm <= 0) {\n return Math.max(tokenLineHeight, Math.ceil(fontSize * UNKNOWN_FONT_LINE_HEIGHT_RATIO));\n }\n\n const metricsLineHeight =\n getMetricHeight(metrics.ascent, metrics.unitsPerEm, fontSize) +\n getMetricHeight(-metrics.descent, metrics.unitsPerEm, fontSize) +\n getMetricHeight(metrics.lineGap, metrics.unitsPerEm, fontSize);\n\n return Math.max(tokenLineHeight, metricsLineHeight);\n}\n\n/** Safe line box for the icon font's em square plus any bbox overflow. */\nexport function getSafeIconCell(fontSize: number): number {\n const metrics = fontMetrics['uds-icons'];\n if (!metrics || metrics.unitsPerEm <= 0) {\n return Math.ceil(fontSize * UNKNOWN_FONT_LINE_HEIGHT_RATIO);\n }\n\n const overflowAboveEm = Math.max(0, metrics.bbox.maxY - metrics.unitsPerEm);\n const overflowBelowEm = Math.max(0, -metrics.bbox.minY);\n\n return (\n Math.ceil(fontSize) +\n getMetricHeight(overflowAboveEm, metrics.unitsPerEm, fontSize) +\n getMetricHeight(overflowBelowEm, metrics.unitsPerEm, fontSize)\n );\n}\n\n/**\n * Safe native content metrics while retaining the token-derived target control height.\n *\n * `fontScaleFactor` (the capped OS font scale, >= 1) pre-scales container\n * metrics only. The returned `labelLineHeight`/`iconCellHeight` stay unscaled\n * because they go into Text/Icon styles, which native multiplies by the same\n * capped factor — container math must mirror that, not double-apply it.\n */\nexport function getButtonControlMetrics(\n theme: ButtonTheme,\n size: ButtonSize,\n fontScaleFactor = 1,\n): {\n minHeight: number;\n labelLineHeight: number;\n iconCellHeight: number;\n paddingVertical: number;\n} {\n const rootStyle = getLayerStyle(theme, buttonSizePath(size, 'root')) as ViewStyle;\n const iconStyle = getLayerStyle(theme, buttonSizePath(size, 'icon')) as TextStyle;\n const textStyle = getLayerStyle(theme, buttonSizePath(size, 'rootText')) as TextStyle;\n const paddingVertical = getVerticalPadding(rootStyle);\n const iconSize = getIconSize(iconStyle);\n const fontSize = typeof textStyle.fontSize === 'number' ? textStyle.fontSize : iconSize;\n const tokenLineHeight =\n typeof textStyle.lineHeight === 'number' ? textStyle.lineHeight : fontSize;\n const targetContentHeight = Math.max(iconSize, tokenLineHeight) * fontScaleFactor;\n const minHeight = Math.ceil(paddingVertical * 2 + targetContentHeight);\n const labelLineHeight = getSafeLabelLineHeight(textStyle, iconSize);\n const iconCellHeight = getSafeIconCell(iconSize);\n const safeContentHeight = Math.max(labelLineHeight, iconCellHeight) * fontScaleFactor;\n\n return {\n minHeight,\n labelLineHeight,\n iconCellHeight,\n paddingVertical: Math.max(0, (minHeight - safeContentHeight) / 2),\n };\n}\n\n/**\n * Safe icon cell within the token-derived control size; explicit token height (match-button-height opt-in) wins as the target.\n *\n * `fontScaleFactor` behaves as in {@link getButtonControlMetrics}; an explicit\n * token height stays fixed, with padding absorbing the scaled content.\n */\nexport function getIconButtonControlMetrics(\n theme: ButtonTheme,\n size: IconButtonSize,\n fontScaleFactor = 1,\n): {\n minHeight: number;\n iconCellHeight: number;\n paddingVertical: number;\n hasExplicitHeight: boolean;\n} {\n const rootStyle = getLayerStyle(theme, iconButtonSizePath(size, 'root')) as ViewStyle;\n const iconStyle = getLayerStyle(theme, iconButtonSizePath(size, 'icon')) as TextStyle;\n const iconSize = getIconSize(iconStyle);\n const tokenLineHeight =\n typeof iconStyle.lineHeight === 'number' ? iconStyle.lineHeight : iconSize;\n const paddingVertical = getVerticalPadding(rootStyle);\n const explicitHeight = typeof rootStyle.height === 'number' ? rootStyle.height : undefined;\n const hasExplicitHeight =\n SHARED_BUTTON_ICONBUTTON_SIZES.has(size) && explicitHeight !== undefined;\n const minHeight = hasExplicitHeight\n ? (explicitHeight as number)\n : Math.ceil(paddingVertical * 2 + Math.max(iconSize, tokenLineHeight) * fontScaleFactor);\n const iconCellHeight = getSafeIconCell(iconSize);\n\n return {\n minHeight,\n iconCellHeight,\n paddingVertical: Math.max(\n 0,\n (minHeight - Math.max(iconSize, iconCellHeight) * fontScaleFactor) / 2,\n ),\n hasExplicitHeight,\n };\n}\n\n/** Apply the metric-safe line height after the token typography styles. */\nexport function getButtonTextStyle(textStyle: TextStyle, labelLineHeight: number): TextStyle {\n return {\n ...textStyle,\n lineHeight: labelLineHeight,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"buttonTheme.js","names":[],"sources":["../../../src/components/Button/buttonTheme.ts"],"sourcesContent":["import type { ButtonSize, IconButtonSize } from '@yahoo/uds-types';\nimport type { TextStyle, ViewStyle } from 'react-native';\n\nimport { fontMetrics } from '../../../generated/fontMetrics';\n\ntype ButtonTheme = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n components: Record<string, any>;\n};\n\nconst SHARED_BUTTON_ICONBUTTON_SIZES = new Set<IconButtonSize>(['xs', 'sm', 'md', 'lg']);\n// Covers common native font boxes (roughly 1.2em) plus pixel-rounding headroom.\nconst UNKNOWN_FONT_LINE_HEIGHT_RATIO = 1.3;\n\nfunction buttonSizePath(size: ButtonSize, layer: 'root' | 'icon' | 'rootText'): string {\n return `button/size/${size}/${layer}/rest`;\n}\n\nfunction iconButtonSizePath(size: IconButtonSize, layer: 'root' | 'icon'): string {\n return `iconButton/size/${size}/${layer}/rest`;\n}\n\nfunction getLayerStyle(theme: ButtonTheme, path: string): ViewStyle | TextStyle {\n const style = theme.components[path];\n return style && typeof style === 'object' ? style : {};\n}\n\nfunction getIconSize(iconStyle: TextStyle): number {\n return (\n (typeof iconStyle.fontSize === 'number' ? iconStyle.fontSize : undefined) ??\n (typeof iconStyle.lineHeight === 'number' ? iconStyle.lineHeight : undefined) ??\n 16\n );\n}\n\nfunction getVerticalPadding(rootStyle: ViewStyle): number {\n return (\n (typeof rootStyle.paddingVertical === 'number' ? rootStyle.paddingVertical : undefined) ??\n (typeof rootStyle.padding === 'number' ? rootStyle.padding : undefined) ??\n 0\n );\n}\n\nfunction getMetricHeight(value: number, unitsPerEm: number, fontSize: number): number {\n return Math.ceil((Math.max(0, value) / unitsPerEm) * fontSize);\n}\n\nfunction getSafeLabelLineHeight(textStyle: TextStyle, fallbackFontSize: number): number {\n const fontSize = typeof textStyle.fontSize === 'number' ? textStyle.fontSize : fallbackFontSize;\n const tokenLineHeight =\n typeof textStyle.lineHeight === 'number' ? textStyle.lineHeight : fontSize;\n const metrics =\n typeof textStyle.fontFamily === 'string' ? fontMetrics[textStyle.fontFamily] : undefined;\n\n if (!metrics || metrics.unitsPerEm <= 0) {\n return Math.max(tokenLineHeight, Math.ceil(fontSize * UNKNOWN_FONT_LINE_HEIGHT_RATIO));\n }\n\n const metricsLineHeight =\n getMetricHeight(metrics.ascent, metrics.unitsPerEm, fontSize) +\n getMetricHeight(-metrics.descent, metrics.unitsPerEm, fontSize) +\n getMetricHeight(metrics.lineGap, metrics.unitsPerEm, fontSize);\n\n return Math.max(tokenLineHeight, metricsLineHeight);\n}\n\n/** Safe line box for the icon font's em square plus any bbox overflow. */\nexport function getSafeIconCell(fontSize: number): number {\n const metrics = fontMetrics['uds-icons'];\n if (!metrics || metrics.unitsPerEm <= 0) {\n return Math.ceil(fontSize * UNKNOWN_FONT_LINE_HEIGHT_RATIO);\n }\n\n const overflowAboveEm = Math.max(0, metrics.bbox.maxY - metrics.unitsPerEm);\n const overflowBelowEm = Math.max(0, -metrics.bbox.minY);\n\n return (\n Math.ceil(fontSize) +\n getMetricHeight(overflowAboveEm, metrics.unitsPerEm, fontSize) +\n getMetricHeight(overflowBelowEm, metrics.unitsPerEm, fontSize)\n );\n}\n\n/**\n * Safe native content metrics while retaining the token-derived target control height.\n *\n * `fontScaleFactor` pre-scales container metrics only. A single number keeps\n * the legacy linear behavior; distinct label/icon factors let Android 14+\n * geometry follow its size-dependent nonlinear font curve. The returned\n * `labelLineHeight`/`iconCellHeight` stay unscaled because native Text applies\n * the same cap.\n */\nexport function getButtonControlMetrics(\n theme: ButtonTheme,\n size: ButtonSize,\n fontScaleFactor: number | { label: number; icon: number; iconCell?: number } = 1,\n): {\n minHeight: number;\n labelLineHeight: number;\n iconCellHeight: number;\n paddingVertical: number;\n} {\n const rootStyle = getLayerStyle(theme, buttonSizePath(size, 'root')) as ViewStyle;\n const iconStyle = getLayerStyle(theme, buttonSizePath(size, 'icon')) as TextStyle;\n const textStyle = getLayerStyle(theme, buttonSizePath(size, 'rootText')) as TextStyle;\n const paddingVertical = getVerticalPadding(rootStyle);\n const iconSize = getIconSize(iconStyle);\n const fontSize = typeof textStyle.fontSize === 'number' ? textStyle.fontSize : iconSize;\n const tokenLineHeight =\n typeof textStyle.lineHeight === 'number' ? textStyle.lineHeight : fontSize;\n const labelScaleFactor =\n typeof fontScaleFactor === 'number' ? fontScaleFactor : fontScaleFactor.label;\n const iconScaleFactor =\n typeof fontScaleFactor === 'number' ? fontScaleFactor : fontScaleFactor.icon;\n const iconCellScaleFactor =\n typeof fontScaleFactor === 'number'\n ? fontScaleFactor\n : (fontScaleFactor.iconCell ?? fontScaleFactor.icon);\n const targetContentHeight = Math.max(\n iconSize * iconScaleFactor,\n tokenLineHeight * labelScaleFactor,\n );\n const minHeight = Math.ceil(paddingVertical * 2 + targetContentHeight);\n const labelLineHeight = getSafeLabelLineHeight(textStyle, iconSize);\n const iconCellHeight = getSafeIconCell(iconSize);\n const safeContentHeight = Math.max(\n labelLineHeight * labelScaleFactor,\n iconCellHeight * iconCellScaleFactor,\n );\n\n return {\n minHeight,\n labelLineHeight,\n iconCellHeight,\n paddingVertical: Math.max(0, (minHeight - safeContentHeight) / 2),\n };\n}\n\n/**\n * Safe icon cell within the token-derived control size; explicit token height (match-button-height opt-in) wins as the target.\n *\n * `fontScaleFactor` behaves as in {@link getButtonControlMetrics}; an explicit\n * token height stays fixed, with padding absorbing the scaled content.\n */\nexport function getIconButtonControlMetrics(\n theme: ButtonTheme,\n size: IconButtonSize,\n fontScaleFactor = 1,\n): {\n minHeight: number;\n iconCellHeight: number;\n paddingVertical: number;\n hasExplicitHeight: boolean;\n} {\n const rootStyle = getLayerStyle(theme, iconButtonSizePath(size, 'root')) as ViewStyle;\n const iconStyle = getLayerStyle(theme, iconButtonSizePath(size, 'icon')) as TextStyle;\n const iconSize = getIconSize(iconStyle);\n const tokenLineHeight =\n typeof iconStyle.lineHeight === 'number' ? iconStyle.lineHeight : iconSize;\n const paddingVertical = getVerticalPadding(rootStyle);\n const explicitHeight = typeof rootStyle.height === 'number' ? rootStyle.height : undefined;\n const hasExplicitHeight =\n SHARED_BUTTON_ICONBUTTON_SIZES.has(size) && explicitHeight !== undefined;\n const minHeight = hasExplicitHeight\n ? (explicitHeight as number)\n : Math.ceil(paddingVertical * 2 + Math.max(iconSize, tokenLineHeight) * fontScaleFactor);\n const iconCellHeight = getSafeIconCell(iconSize);\n\n return {\n minHeight,\n iconCellHeight,\n paddingVertical: Math.max(\n 0,\n (minHeight - Math.max(iconSize, iconCellHeight) * fontScaleFactor) / 2,\n ),\n hasExplicitHeight,\n };\n}\n\n/** Apply the metric-safe line height after the token typography styles. */\nexport function getButtonTextStyle(textStyle: TextStyle, labelLineHeight: number): TextStyle {\n return {\n ...textStyle,\n lineHeight: labelLineHeight,\n };\n}\n"],"mappings":"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"}
@@ -90,13 +90,9 @@ function AnimatedIconSlot({ children, visible, iconSize, iconCellHeight, gap })
90
90
  const Button = (0, react.memo)(function Button({ variant = "primary", size = "md", iconVariant = "outline", startIcon, endIcon, loading, disabled, width: _width, children, style, accessibilityLabel, accessibilityHint, disableEffects = false, maxFontSizeMultiplier, onPressIn, onPressOut, ref, ...props }) {
91
91
  const shouldAnimate = !disableEffects;
92
92
  const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
93
- const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier);
94
93
  const { theme } = (0, react_native_unistyles.useUnistyles)();
95
- const { minHeight, labelLineHeight, iconCellHeight, paddingVertical } = (0, react.useMemo)(() => require_components_Button_buttonTheme.getButtonControlMetrics(theme, size, fontScaleFactor), [
96
- theme,
97
- size,
98
- fontScaleFactor
99
- ]);
94
+ const baseMetrics = (0, react.useMemo)(() => require_components_Button_buttonTheme.getButtonControlMetrics(theme, size), [theme, size]);
95
+ const labelScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier, baseMetrics.labelLineHeight);
100
96
  const [pressed, setPressed] = (0, react.useState)(false);
101
97
  generated_styles.buttonStyles.useVariants({
102
98
  size,
@@ -106,6 +102,19 @@ const Button = (0, react.memo)(function Button({ variant = "primary", size = "md
106
102
  });
107
103
  const buttonGap = generated_styles.buttonStyles.root.gap;
108
104
  const iconSize = generated_styles.buttonStyles.icon.fontSize;
105
+ const iconScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier, iconSize);
106
+ const iconCellScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier, baseMetrics.iconCellHeight);
107
+ const { minHeight, labelLineHeight, iconCellHeight, paddingVertical } = (0, react.useMemo)(() => require_components_Button_buttonTheme.getButtonControlMetrics(theme, size, {
108
+ label: labelScaleFactor,
109
+ icon: iconScaleFactor,
110
+ iconCell: iconCellScaleFactor
111
+ }), [
112
+ theme,
113
+ size,
114
+ labelScaleFactor,
115
+ iconScaleFactor,
116
+ iconCellScaleFactor
117
+ ]);
109
118
  const animatedTheme = (0, react_native_unistyles_reanimated.useAnimatedTheme)();
110
119
  const scale = (0, react_native_reanimated.useSharedValue)(require_index.SCALE_EFFECTS.none);
111
120
  const handlePressIn = (0, react.useCallback)((event) => {
@@ -155,8 +164,8 @@ const Button = (0, react.memo)(function Button({ variant = "primary", size = "md
155
164
  const showStartIcon = !!startIcon && !loading;
156
165
  const showEndIcon = !!endIcon && !loading;
157
166
  const iconSizeToken = generated_styles.buttonStyles.icon.iconSizeToken ?? "sm";
158
- const scaledIconSize = Math.round(iconSize * fontScaleFactor);
159
- const scaledIconCellHeight = Math.ceil(iconCellHeight * fontScaleFactor);
167
+ const scaledIconSize = Math.round(iconSize * iconScaleFactor);
168
+ const scaledIconCellHeight = Math.ceil(iconCellHeight * iconCellScaleFactor);
160
169
  const startContent = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AnimatedIconSlot, {
161
170
  visible: showLoading || showStartIcon,
162
171
  iconSize: scaledIconSize,
@@ -87,13 +87,9 @@ function AnimatedIconSlot({ children, visible, iconSize, iconCellHeight, gap })
87
87
  const Button = memo(function Button({ variant = "primary", size = "md", iconVariant = "outline", startIcon, endIcon, loading, disabled, width: _width, children, style, accessibilityLabel, accessibilityHint, disableEffects = false, maxFontSizeMultiplier, onPressIn, onPressOut, ref, ...props }) {
88
88
  const shouldAnimate = !disableEffects;
89
89
  const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
90
- const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);
91
90
  const { theme } = useUnistyles();
92
- const { minHeight, labelLineHeight, iconCellHeight, paddingVertical } = useMemo(() => getButtonControlMetrics(theme, size, fontScaleFactor), [
93
- theme,
94
- size,
95
- fontScaleFactor
96
- ]);
91
+ const baseMetrics = useMemo(() => getButtonControlMetrics(theme, size), [theme, size]);
92
+ const labelScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier, baseMetrics.labelLineHeight);
97
93
  const [pressed, setPressed] = useState(false);
98
94
  buttonStyles.useVariants({
99
95
  size,
@@ -103,6 +99,19 @@ const Button = memo(function Button({ variant = "primary", size = "md", iconVari
103
99
  });
104
100
  const buttonGap = buttonStyles.root.gap;
105
101
  const iconSize = buttonStyles.icon.fontSize;
102
+ const iconScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier, iconSize);
103
+ const iconCellScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier, baseMetrics.iconCellHeight);
104
+ const { minHeight, labelLineHeight, iconCellHeight, paddingVertical } = useMemo(() => getButtonControlMetrics(theme, size, {
105
+ label: labelScaleFactor,
106
+ icon: iconScaleFactor,
107
+ iconCell: iconCellScaleFactor
108
+ }), [
109
+ theme,
110
+ size,
111
+ labelScaleFactor,
112
+ iconScaleFactor,
113
+ iconCellScaleFactor
114
+ ]);
106
115
  const animatedTheme = useAnimatedTheme();
107
116
  const scale = useSharedValue(SCALE_EFFECTS.none);
108
117
  const handlePressIn = useCallback((event) => {
@@ -152,8 +161,8 @@ const Button = memo(function Button({ variant = "primary", size = "md", iconVari
152
161
  const showStartIcon = !!startIcon && !loading;
153
162
  const showEndIcon = !!endIcon && !loading;
154
163
  const iconSizeToken = buttonStyles.icon.iconSizeToken ?? "sm";
155
- const scaledIconSize = Math.round(iconSize * fontScaleFactor);
156
- const scaledIconCellHeight = Math.ceil(iconCellHeight * fontScaleFactor);
164
+ const scaledIconSize = Math.round(iconSize * iconScaleFactor);
165
+ const scaledIconCellHeight = Math.ceil(iconCellHeight * iconCellScaleFactor);
157
166
  const startContent = /* @__PURE__ */ jsx(AnimatedIconSlot, {
158
167
  visible: showLoading || showStartIcon,
159
168
  iconSize: scaledIconSize,