@yahoo/uds-mobile 2.23.3 → 2.24.0-beta.10

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 (298) hide show
  1. package/README.md +41 -13
  2. package/dist/bin/automated-config/dist/generated/generatedConfigs.mjs +92 -46
  3. package/dist/components/Avatar/AvatarIcon.cjs +8 -2
  4. package/dist/components/Avatar/AvatarIcon.d.cts.map +1 -1
  5. package/dist/components/Avatar/AvatarIcon.d.ts.map +1 -1
  6. package/dist/components/Avatar/AvatarIcon.js +9 -3
  7. package/dist/components/Avatar/AvatarIcon.js.map +1 -1
  8. package/dist/components/Avatar/AvatarImage.cjs +9 -2
  9. package/dist/components/Avatar/AvatarImage.d.cts.map +1 -1
  10. package/dist/components/Avatar/AvatarImage.d.ts.map +1 -1
  11. package/dist/components/Avatar/AvatarImage.js +10 -3
  12. package/dist/components/Avatar/AvatarImage.js.map +1 -1
  13. package/dist/components/Avatar/AvatarText.cjs +8 -2
  14. package/dist/components/Avatar/AvatarText.d.cts.map +1 -1
  15. package/dist/components/Avatar/AvatarText.d.ts.map +1 -1
  16. package/dist/components/Avatar/AvatarText.js +9 -3
  17. package/dist/components/Avatar/AvatarText.js.map +1 -1
  18. package/dist/components/Avatar/types.d.cts +7 -3
  19. package/dist/components/Avatar/types.d.cts.map +1 -1
  20. package/dist/components/Avatar/types.d.ts +7 -3
  21. package/dist/components/Avatar/types.d.ts.map +1 -1
  22. package/dist/components/Avatar/useAvatarFontScale.cjs +16 -0
  23. package/dist/components/Avatar/useAvatarFontScale.d.cts +7 -0
  24. package/dist/components/Avatar/useAvatarFontScale.d.cts.map +1 -0
  25. package/dist/components/Avatar/useAvatarFontScale.d.ts +7 -0
  26. package/dist/components/Avatar/useAvatarFontScale.d.ts.map +1 -0
  27. package/dist/components/Avatar/useAvatarFontScale.js +16 -0
  28. package/dist/components/Avatar/useAvatarFontScale.js.map +1 -0
  29. package/dist/components/Avatar/utils.cjs +9 -6
  30. package/dist/components/Avatar/utils.d.cts +2 -2
  31. package/dist/components/Avatar/utils.d.cts.map +1 -1
  32. package/dist/components/Avatar/utils.d.ts +2 -2
  33. package/dist/components/Avatar/utils.d.ts.map +1 -1
  34. package/dist/components/Avatar/utils.js +9 -6
  35. package/dist/components/Avatar/utils.js.map +1 -1
  36. package/dist/components/BottomSheet/BottomSheet.cjs +1 -1
  37. package/dist/components/BottomSheet/BottomSheet.js +1 -1
  38. package/dist/components/Button/buttonTheme.cjs +31 -9
  39. package/dist/components/Button/buttonTheme.d.cts +24 -5
  40. package/dist/components/Button/buttonTheme.d.cts.map +1 -1
  41. package/dist/components/Button/buttonTheme.d.ts +24 -5
  42. package/dist/components/Button/buttonTheme.d.ts.map +1 -1
  43. package/dist/components/Button/buttonTheme.js +31 -10
  44. package/dist/components/Button/buttonTheme.js.map +1 -1
  45. package/dist/components/Button.cjs +35 -8
  46. package/dist/components/Button.d.cts +7 -0
  47. package/dist/components/Button.d.cts.map +1 -1
  48. package/dist/components/Button.d.ts +7 -0
  49. package/dist/components/Button.d.ts.map +1 -1
  50. package/dist/components/Button.js +35 -8
  51. package/dist/components/Button.js.map +1 -1
  52. package/dist/components/Checkbox.cjs +42 -9
  53. package/dist/components/Checkbox.d.cts +7 -0
  54. package/dist/components/Checkbox.d.cts.map +1 -1
  55. package/dist/components/Checkbox.d.ts +7 -0
  56. package/dist/components/Checkbox.d.ts.map +1 -1
  57. package/dist/components/Checkbox.js +42 -9
  58. package/dist/components/Checkbox.js.map +1 -1
  59. package/dist/components/Chip/ChipBase.cjs +31 -14
  60. package/dist/components/Chip/ChipBase.d.cts.map +1 -1
  61. package/dist/components/Chip/ChipBase.d.ts.map +1 -1
  62. package/dist/components/Chip/ChipBase.js +31 -14
  63. package/dist/components/Chip/ChipBase.js.map +1 -1
  64. package/dist/components/Chip/ChipDismissible.cjs +3 -1
  65. package/dist/components/Chip/ChipDismissible.js +3 -1
  66. package/dist/components/Chip/ChipDismissible.js.map +1 -1
  67. package/dist/components/Chip/types.d.cts +7 -0
  68. package/dist/components/Chip/types.d.cts.map +1 -1
  69. package/dist/components/Chip/types.d.ts +7 -0
  70. package/dist/components/Chip/types.d.ts.map +1 -1
  71. package/dist/components/Icon.cjs +24 -5
  72. package/dist/components/Icon.d.cts +11 -2
  73. package/dist/components/Icon.d.cts.map +1 -1
  74. package/dist/components/Icon.d.ts +11 -2
  75. package/dist/components/Icon.d.ts.map +1 -1
  76. package/dist/components/Icon.js +24 -5
  77. package/dist/components/Icon.js.map +1 -1
  78. package/dist/components/IconButton.cjs +17 -6
  79. package/dist/components/IconButton.d.cts +6 -0
  80. package/dist/components/IconButton.d.cts.map +1 -1
  81. package/dist/components/IconButton.d.ts +6 -0
  82. package/dist/components/IconButton.d.ts.map +1 -1
  83. package/dist/components/IconButton.js +18 -7
  84. package/dist/components/IconButton.js.map +1 -1
  85. package/dist/components/Input.cjs +56 -18
  86. package/dist/components/Input.d.cts +5 -0
  87. package/dist/components/Input.d.cts.map +1 -1
  88. package/dist/components/Input.d.ts +5 -0
  89. package/dist/components/Input.d.ts.map +1 -1
  90. package/dist/components/Input.js +56 -18
  91. package/dist/components/Input.js.map +1 -1
  92. package/dist/components/InputHelpText.cjs +7 -1
  93. package/dist/components/InputHelpText.d.cts +2 -0
  94. package/dist/components/InputHelpText.d.cts.map +1 -1
  95. package/dist/components/InputHelpText.d.ts +2 -0
  96. package/dist/components/InputHelpText.d.ts.map +1 -1
  97. package/dist/components/InputHelpText.js +7 -1
  98. package/dist/components/InputHelpText.js.map +1 -1
  99. package/dist/components/Link.cjs +13 -1
  100. package/dist/components/Link.d.cts +7 -0
  101. package/dist/components/Link.d.cts.map +1 -1
  102. package/dist/components/Link.d.ts +7 -0
  103. package/dist/components/Link.d.ts.map +1 -1
  104. package/dist/components/Link.js +13 -1
  105. package/dist/components/Link.js.map +1 -1
  106. package/dist/components/Pagination/Pagination.cjs +18 -10
  107. package/dist/components/Pagination/Pagination.d.cts +2 -0
  108. package/dist/components/Pagination/Pagination.d.cts.map +1 -1
  109. package/dist/components/Pagination/Pagination.d.ts +2 -0
  110. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  111. package/dist/components/Pagination/Pagination.js +18 -10
  112. package/dist/components/Pagination/Pagination.js.map +1 -1
  113. package/dist/components/Pagination/PaginationEllipsis.cjs +8 -2
  114. package/dist/components/Pagination/PaginationEllipsis.d.cts.map +1 -1
  115. package/dist/components/Pagination/PaginationEllipsis.d.ts.map +1 -1
  116. package/dist/components/Pagination/PaginationEllipsis.js +9 -3
  117. package/dist/components/Pagination/PaginationEllipsis.js.map +1 -1
  118. package/dist/components/Pagination/PaginationItem.cjs +2 -1
  119. package/dist/components/Pagination/PaginationItem.js +2 -1
  120. package/dist/components/Pagination/PaginationItem.js.map +1 -1
  121. package/dist/components/Pagination/PaginationLink.cjs +2 -1
  122. package/dist/components/Pagination/PaginationLink.js +2 -1
  123. package/dist/components/Pagination/PaginationLink.js.map +1 -1
  124. package/dist/components/Pagination/PaginationNext.cjs +3 -1
  125. package/dist/components/Pagination/PaginationNext.js +3 -1
  126. package/dist/components/Pagination/PaginationNext.js.map +1 -1
  127. package/dist/components/Pagination/PaginationPrev.cjs +3 -1
  128. package/dist/components/Pagination/PaginationPrev.js +3 -1
  129. package/dist/components/Pagination/PaginationPrev.js.map +1 -1
  130. package/dist/components/Pagination/paginationContext.d.cts +2 -0
  131. package/dist/components/Pagination/paginationContext.d.cts.map +1 -1
  132. package/dist/components/Pagination/paginationContext.d.ts +2 -0
  133. package/dist/components/Pagination/paginationContext.d.ts.map +1 -1
  134. package/dist/components/Pagination/paginationContext.js.map +1 -1
  135. package/dist/components/Pagination/usePaginationControlStyles.cjs +8 -1
  136. package/dist/components/Pagination/usePaginationControlStyles.d.cts.map +1 -1
  137. package/dist/components/Pagination/usePaginationControlStyles.d.ts.map +1 -1
  138. package/dist/components/Pagination/usePaginationControlStyles.js +9 -2
  139. package/dist/components/Pagination/usePaginationControlStyles.js.map +1 -1
  140. package/dist/components/Radio/Radio.cjs +30 -11
  141. package/dist/components/Radio/Radio.d.cts +7 -0
  142. package/dist/components/Radio/Radio.d.cts.map +1 -1
  143. package/dist/components/Radio/Radio.d.ts +7 -0
  144. package/dist/components/Radio/Radio.d.ts.map +1 -1
  145. package/dist/components/Radio/Radio.js +30 -11
  146. package/dist/components/Radio/Radio.js.map +1 -1
  147. package/dist/components/Select/Select.cjs +29 -6
  148. package/dist/components/Select/Select.d.cts +2 -0
  149. package/dist/components/Select/Select.d.cts.map +1 -1
  150. package/dist/components/Select/Select.d.ts +2 -0
  151. package/dist/components/Select/Select.d.ts.map +1 -1
  152. package/dist/components/Select/Select.js +29 -6
  153. package/dist/components/Select/Select.js.map +1 -1
  154. package/dist/components/Select/SelectContent.cjs +31 -23
  155. package/dist/components/Select/SelectContent.d.cts.map +1 -1
  156. package/dist/components/Select/SelectContent.d.ts.map +1 -1
  157. package/dist/components/Select/SelectContent.js +32 -24
  158. package/dist/components/Select/SelectContent.js.map +1 -1
  159. package/dist/components/Select/SelectItem.cjs +25 -15
  160. package/dist/components/Select/SelectItem.d.cts.map +1 -1
  161. package/dist/components/Select/SelectItem.d.ts.map +1 -1
  162. package/dist/components/Select/SelectItem.js +25 -15
  163. package/dist/components/Select/SelectItem.js.map +1 -1
  164. package/dist/components/Select/SelectTrigger.cjs +27 -13
  165. package/dist/components/Select/SelectTrigger.d.cts.map +1 -1
  166. package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
  167. package/dist/components/Select/SelectTrigger.js +27 -13
  168. package/dist/components/Select/SelectTrigger.js.map +1 -1
  169. package/dist/components/Select/types.d.cts +2 -0
  170. package/dist/components/Select/types.d.cts.map +1 -1
  171. package/dist/components/Select/types.d.ts +2 -0
  172. package/dist/components/Select/types.d.ts.map +1 -1
  173. package/dist/components/Switch.cjs +48 -8
  174. package/dist/components/Switch.d.cts +7 -0
  175. package/dist/components/Switch.d.cts.map +1 -1
  176. package/dist/components/Switch.d.ts +7 -0
  177. package/dist/components/Switch.d.ts.map +1 -1
  178. package/dist/components/Switch.js +48 -8
  179. package/dist/components/Switch.js.map +1 -1
  180. package/dist/components/Tabs/Tab.cjs +17 -3
  181. package/dist/components/Tabs/Tab.d.cts.map +1 -1
  182. package/dist/components/Tabs/Tab.d.ts.map +1 -1
  183. package/dist/components/Tabs/Tab.js +17 -3
  184. package/dist/components/Tabs/Tab.js.map +1 -1
  185. package/dist/components/Tabs/Tabs.cjs +8 -3
  186. package/dist/components/Tabs/Tabs.d.cts +9 -1
  187. package/dist/components/Tabs/Tabs.d.cts.map +1 -1
  188. package/dist/components/Tabs/Tabs.d.ts +9 -1
  189. package/dist/components/Tabs/Tabs.d.ts.map +1 -1
  190. package/dist/components/Tabs/Tabs.js +8 -3
  191. package/dist/components/Tabs/Tabs.js.map +1 -1
  192. package/dist/components/Tabs/tabsContexts.d.cts +2 -0
  193. package/dist/components/Tabs/tabsContexts.d.cts.map +1 -1
  194. package/dist/components/Tabs/tabsContexts.d.ts +2 -0
  195. package/dist/components/Tabs/tabsContexts.d.ts.map +1 -1
  196. package/dist/components/Tabs/tabsContexts.js.map +1 -1
  197. package/dist/components/Text.cjs +9 -1
  198. package/dist/components/Text.d.cts +11 -2
  199. package/dist/components/Text.d.cts.map +1 -1
  200. package/dist/components/Text.d.ts +11 -2
  201. package/dist/components/Text.d.ts.map +1 -1
  202. package/dist/components/Text.js +9 -1
  203. package/dist/components/Text.js.map +1 -1
  204. package/dist/components/UDSProvider.cjs +6 -2
  205. package/dist/components/UDSProvider.d.cts +9 -0
  206. package/dist/components/UDSProvider.d.cts.map +1 -1
  207. package/dist/components/UDSProvider.d.ts +9 -0
  208. package/dist/components/UDSProvider.d.ts.map +1 -1
  209. package/dist/components/UDSProvider.js +6 -2
  210. package/dist/components/UDSProvider.js.map +1 -1
  211. package/dist/components/internal/Overlay/index.cjs +1 -1
  212. package/dist/components/internal/Overlay/index.js +1 -1
  213. package/dist/fontScaling/FontScalingContext.cjs +67 -0
  214. package/dist/fontScaling/FontScalingContext.d.cts +53 -0
  215. package/dist/fontScaling/FontScalingContext.d.cts.map +1 -0
  216. package/dist/fontScaling/FontScalingContext.d.ts +53 -0
  217. package/dist/fontScaling/FontScalingContext.d.ts.map +1 -0
  218. package/dist/fontScaling/FontScalingContext.js +63 -0
  219. package/dist/fontScaling/FontScalingContext.js.map +1 -0
  220. package/dist/fontScaling/androidNonlinearFontScaling.cjs +250 -0
  221. package/dist/fontScaling/androidNonlinearFontScaling.d.cts +7 -0
  222. package/dist/fontScaling/androidNonlinearFontScaling.d.cts.map +1 -0
  223. package/dist/fontScaling/androidNonlinearFontScaling.d.ts +7 -0
  224. package/dist/fontScaling/androidNonlinearFontScaling.d.ts.map +1 -0
  225. package/dist/fontScaling/androidNonlinearFontScaling.js +251 -0
  226. package/dist/fontScaling/androidNonlinearFontScaling.js.map +1 -0
  227. package/dist/fontScaling/constants.cjs +106 -0
  228. package/dist/fontScaling/constants.d.cts +60 -0
  229. package/dist/fontScaling/constants.d.cts.map +1 -0
  230. package/dist/fontScaling/constants.d.ts +60 -0
  231. package/dist/fontScaling/constants.d.ts.map +1 -0
  232. package/dist/fontScaling/constants.js +103 -0
  233. package/dist/fontScaling/constants.js.map +1 -0
  234. package/dist/fontScaling/index.cjs +14 -0
  235. package/dist/fontScaling/index.d.cts +8 -0
  236. package/dist/fontScaling/index.d.ts +8 -0
  237. package/dist/fontScaling/index.js +6 -0
  238. package/dist/fontScaling/resolveMaxFontSizeMultiplier.cjs +37 -0
  239. package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.cts +35 -0
  240. package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.cts.map +1 -0
  241. package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.ts +35 -0
  242. package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.ts.map +1 -0
  243. package/dist/fontScaling/resolveMaxFontSizeMultiplier.js +38 -0
  244. package/dist/fontScaling/resolveMaxFontSizeMultiplier.js.map +1 -0
  245. package/dist/fontScaling/types.cjs +1 -0
  246. package/dist/fontScaling/types.d.cts +54 -0
  247. package/dist/fontScaling/types.d.cts.map +1 -0
  248. package/dist/fontScaling/types.d.ts +54 -0
  249. package/dist/fontScaling/types.d.ts.map +1 -0
  250. package/dist/fontScaling/types.js +1 -0
  251. package/dist/fontScaling/useFontScale.cjs +58 -0
  252. package/dist/fontScaling/useFontScale.d.cts +12 -0
  253. package/dist/fontScaling/useFontScale.d.cts.map +1 -0
  254. package/dist/fontScaling/useFontScale.d.ts +12 -0
  255. package/dist/fontScaling/useFontScale.d.ts.map +1 -0
  256. package/dist/fontScaling/useFontScale.js +57 -0
  257. package/dist/fontScaling/useFontScale.js.map +1 -0
  258. package/dist/fontScaling/useMaxFontSizeMultiplier.cjs +24 -0
  259. package/dist/fontScaling/useMaxFontSizeMultiplier.d.cts +16 -0
  260. package/dist/fontScaling/useMaxFontSizeMultiplier.d.cts.map +1 -0
  261. package/dist/fontScaling/useMaxFontSizeMultiplier.d.ts +16 -0
  262. package/dist/fontScaling/useMaxFontSizeMultiplier.d.ts.map +1 -0
  263. package/dist/fontScaling/useMaxFontSizeMultiplier.js +24 -0
  264. package/dist/fontScaling/useMaxFontSizeMultiplier.js.map +1 -0
  265. package/dist/jest/mocks/react-native.cjs +19 -4
  266. package/dist/jest/mocks/react-native.d.cts +8 -5
  267. package/dist/jest/mocks/react-native.d.cts.map +1 -1
  268. package/dist/jest/mocks/react-native.d.ts +8 -5
  269. package/dist/jest/mocks/react-native.d.ts.map +1 -1
  270. package/dist/jest/mocks/react-native.js +18 -5
  271. package/dist/jest/mocks/react-native.js.map +1 -1
  272. package/dist/jest/mocks/styles.cjs +28 -1
  273. package/dist/jest/mocks/styles.d.cts.map +1 -1
  274. package/dist/jest/mocks/styles.d.ts.map +1 -1
  275. package/dist/jest/mocks/styles.js +28 -1
  276. package/dist/jest/mocks/styles.js.map +1 -1
  277. package/dist/jest/setup.cjs +4 -0
  278. package/dist/jest/setup.d.cts.map +1 -1
  279. package/dist/jest/setup.d.ts.map +1 -1
  280. package/dist/jest/setup.js +4 -0
  281. package/dist/jest/setup.js.map +1 -1
  282. package/dist/mobile/generated/fontMetrics.cjs +530 -530
  283. package/dist/mobile/generated/fontMetrics.js +530 -530
  284. package/dist/mobile/generated/fontMetrics.js.map +1 -1
  285. package/dist/portal.cjs +8 -2
  286. package/dist/portal.d.cts.map +1 -1
  287. package/dist/portal.d.ts.map +1 -1
  288. package/dist/portal.js +8 -2
  289. package/dist/portal.js.map +1 -1
  290. package/dist/types/dist/index.d.cts.map +1 -1
  291. package/dist/types/dist/index.d.ts.map +1 -1
  292. package/fonts/index.cjs +214 -214
  293. package/fonts/index.mjs +214 -214
  294. package/fonts/uds-icons.ttf +0 -0
  295. package/generated/fontMetrics.ts +530 -530
  296. package/generated/styles.d.ts +5 -28
  297. package/generated/unistyles.d.ts +0 -27
  298. package/package.json +11 -1
@@ -15,6 +15,13 @@ interface SwitchProps extends Omit<ViewProps, 'style'>, UniversalSwitchProps<Ico
15
15
  disabled?: boolean;
16
16
  /** Whether the switch is required (shows asterisk with label) */
17
17
  required?: boolean;
18
+ /**
19
+ * Caps how far the track, handle, and label grow with the OS text-size
20
+ * setting; all scale by the same factor. Set null to remove the cap;
21
+ * override app-wide via UDSFontScalingProvider.
22
+ * @default 2
23
+ */
24
+ maxFontSizeMultiplier?: number | null;
18
25
  /** Accessibility hint describing what happens when activated */
19
26
  accessibilityHint?: AccessibilityProps['accessibilityHint'];
20
27
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.d.ts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAsBU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;EAQN,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;cA2ClC,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
1
+ {"version":3,"file":"Switch.d.ts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAyBU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;;;;;;EAaN,qBAAA;EAfiC;EAiBjC,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;;;;;;;cAsClC,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
@@ -1,4 +1,7 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ import { useComponentFontScale } from "../fontScaling/useFontScale.js";
3
+ import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
4
+ import { getSafeIconCell } from "./Button/buttonTheme.js";
2
5
  import { IconSlot } from "./IconSlot.js";
3
6
  import { FormLabel } from "./FormLabel.js";
4
7
  import { memo, useCallback, useEffect, useMemo, useState } from "react";
@@ -9,10 +12,6 @@ import { StyleSheet as StyleSheet$1, useUnistyles } from "react-native-unistyles
9
12
  import Animated, { useAnimatedStyle, useDerivedValue, withTiming } from "react-native-reanimated";
10
13
  import { useAnimatedVariantColor } from "react-native-unistyles/reanimated";
11
14
  //#region src/components/Switch.tsx
12
- const HANDLE_TRAVEL = {
13
- md: 20,
14
- sm: 12
15
- };
16
15
  const ANIMATION_DURATION = 120;
17
16
  /**
18
17
  * **Switch component for toggling options**
@@ -47,13 +46,14 @@ const ANIMATION_DURATION = 120;
47
46
  * @see {@link Checkbox} for forms with submit actions
48
47
  * @see {@link Radio} for single-select options
49
48
  */
50
- const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onChange, label, labelPosition = "start", size = "md", onIcon, offIcon, disabled = false, required, accessibilityHint, reduceMotion = false, ref, ...viewProps }) {
49
+ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onChange, label, labelPosition = "start", size = "md", onIcon, offIcon, disabled = false, required, maxFontSizeMultiplier, accessibilityHint, reduceMotion = false, ref, ...viewProps }) {
51
50
  const isControlled = isOnProp !== void 0;
52
51
  const [internalIsOn, setInternalIsOn] = useState(defaultIsOn);
53
52
  const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);
54
53
  const isOn = isControlled ? isOnProp : internalIsOn;
55
54
  const activeVariant = isOn ? "on" : "off";
56
55
  const { theme } = useUnistyles();
56
+ const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
57
57
  useEffect(() => {
58
58
  const checkReducedMotion = async () => {
59
59
  setPrefersReducedMotion(await AccessibilityInfo.isReduceMotionEnabled());
@@ -64,7 +64,6 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
64
64
  }, []);
65
65
  const animationDuration = reduceMotion || prefersReducedMotion ? 0 : ANIMATION_DURATION;
66
66
  const progress = useDerivedValue(() => withTiming(isOn ? 1 : 0, { duration: animationDuration }), [isOn, animationDuration]);
67
- const travelDistance = HANDLE_TRAVEL[size] * (I18nManager.isRTL ? -1 : 1);
68
67
  const handlePress = useCallback(() => {
69
68
  if (disabled) return;
70
69
  const newValue = !isOn;
@@ -80,6 +79,15 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
80
79
  size,
81
80
  variant: activeVariant
82
81
  }) ?? switchStyles;
82
+ const labelBaseSize = resolvedSwitchStyles.text.lineHeight ?? resolvedSwitchStyles.text.fontSize;
83
+ const fontScaleFactor = useComponentFontScale(resolvedMaxFontSizeMultiplier, typeof labelBaseSize === "number" ? labelBaseSize : void 0);
84
+ const handleIconSize = resolvedSwitchStyles.handleIcon.fontSize;
85
+ const handleIconScaleFactor = useComponentFontScale(resolvedMaxFontSizeMultiplier, typeof handleIconSize === "number" ? handleIconSize : void 0);
86
+ const scaledHandleIconSize = typeof handleIconSize === "number" ? Math.round(handleIconSize * handleIconScaleFactor) : void 0;
87
+ const scaledTrackWidth = Math.round(resolvedSwitchStyles.switch.width * fontScaleFactor);
88
+ const scaledTrackPadding = Math.round(resolvedSwitchStyles.switch.padding * fontScaleFactor);
89
+ const scaledHandleWidth = Math.round(resolvedSwitchStyles.handle.width * fontScaleFactor);
90
+ const travelDistance = Math.max(0, scaledTrackWidth - scaledHandleWidth - scaledTrackPadding * 2) * (I18nManager.isRTL ? -1 : 1);
83
91
  const variantLayerStyles = useMemo(() => {
84
92
  const components = theme.components;
85
93
  const getLayerStyle = (layer) => components[`switch/variant/default/active/${activeVariant}/${layer}/rest`];
@@ -100,24 +108,37 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
100
108
  return { transform: [{ translateX: progress.value * travelDistance }] };
101
109
  });
102
110
  const rootStyle = useMemo(() => [resolvedSwitchStyles.root, switchStaticStyles.root({ disabled })], [resolvedSwitchStyles.root, disabled]);
111
+ const scaleDimensions = useCallback((style) => {
112
+ if (!style || fontScaleFactor === 1) return;
113
+ const { width, height, padding } = style;
114
+ return typeof width === "number" && typeof height === "number" ? {
115
+ width: Math.round(width * fontScaleFactor),
116
+ height: Math.round(height * fontScaleFactor),
117
+ ...typeof padding === "number" && { padding: Math.round(padding * fontScaleFactor) }
118
+ } : void 0;
119
+ }, [fontScaleFactor]);
103
120
  const trackStyle = useMemo(() => [
104
121
  resolvedSwitchStyles.switch,
105
122
  switchStaticStyles.track,
106
123
  variantLayerStyles.switch,
124
+ scaleDimensions(resolvedSwitchStyles.switch),
107
125
  Platform.OS !== "web" && animatedTrackStyle
108
126
  ], [
109
127
  resolvedSwitchStyles.switch,
110
128
  variantLayerStyles.switch,
129
+ scaleDimensions,
111
130
  animatedTrackStyle
112
131
  ]);
113
132
  const handleStyle = useMemo(() => [
114
133
  resolvedSwitchStyles.handle,
115
134
  switchStaticStyles.handle,
116
135
  variantLayerStyles.handle,
136
+ scaleDimensions(resolvedSwitchStyles.handle),
117
137
  animatedHandleStyle
118
138
  ], [
119
139
  resolvedSwitchStyles.handle,
120
140
  variantLayerStyles.handle,
141
+ scaleDimensions,
121
142
  animatedHandleStyle
122
143
  ]);
123
144
  const accessibilityLabel = typeof label === "string" ? label : void 0;
@@ -128,6 +149,7 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
128
149
  label,
129
150
  required,
130
151
  showRequiredAsterisk: required,
152
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
131
153
  style: [resolvedSwitchStyles.text, variantLayerStyles.text]
132
154
  });
133
155
  const a11yValue = useMemo(() => ({ text: isOn ? "On" : "Off" }), [isOn]);
@@ -158,14 +180,32 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
158
180
  children: /* @__PURE__ */ jsx(IconSlot, {
159
181
  icon: onIcon,
160
182
  variant: "fill",
161
- style: [resolvedSwitchStyles.handleIcon, variantLayerStyles.handleIcon]
183
+ dangerouslySetSize: scaledHandleIconSize,
184
+ allowFontScaling: false,
185
+ style: [
186
+ resolvedSwitchStyles.handleIcon,
187
+ variantLayerStyles.handleIcon,
188
+ scaledHandleIconSize === void 0 ? void 0 : {
189
+ fontSize: scaledHandleIconSize,
190
+ lineHeight: getSafeIconCell(scaledHandleIconSize)
191
+ }
192
+ ]
162
193
  })
163
194
  }), offIcon && !isOn && /* @__PURE__ */ jsx(Animated.View, {
164
195
  style: switchStaticStyles.iconContainer,
165
196
  children: /* @__PURE__ */ jsx(IconSlot, {
166
197
  icon: offIcon,
167
198
  variant: "fill",
168
- style: [resolvedSwitchStyles.handleIcon, variantLayerStyles.handleIcon]
199
+ dangerouslySetSize: scaledHandleIconSize,
200
+ allowFontScaling: false,
201
+ style: [
202
+ resolvedSwitchStyles.handleIcon,
203
+ variantLayerStyles.handleIcon,
204
+ scaledHandleIconSize === void 0 ? void 0 : {
205
+ fontSize: scaledHandleIconSize,
206
+ lineHeight: getSafeIconCell(scaledHandleIconSize)
207
+ }
208
+ ]
169
209
  })
170
210
  })]
171
211
  })
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.js","names":["StyleSheet"],"sources":["../../src/components/Switch.tsx"],"sourcesContent":["import type { SwitchSize, UniversalSwitchProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type {\n AccessibilityProps,\n StyleProp,\n TextStyle,\n View,\n ViewProps,\n ViewStyle,\n} from 'react-native';\nimport { AccessibilityInfo, I18nManager, Platform, Pressable } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withTiming } from 'react-native-reanimated';\n// eslint-disable-next-line uds/no-use-unistyles -- switch variant layers need concrete web styles\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\nimport { useAnimatedVariantColor } from 'react-native-unistyles/reanimated';\n\nimport { switchStyles } from '../../generated/styles';\nimport { FormLabel } from './FormLabel';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\n\ninterface SwitchProps extends Omit<ViewProps, 'style'>, UniversalSwitchProps<IconSlotType> {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Callback when the switch value changes */\n onChange?: (value: boolean) => void;\n /** Whether the switch is disabled */\n disabled?: boolean;\n /** Whether the switch is required (shows asterisk with label) */\n required?: boolean;\n /** Accessibility hint describing what happens when activated */\n accessibilityHint?: AccessibilityProps['accessibilityHint'];\n}\n\nconst HANDLE_TRAVEL: Record<SwitchSize, number> = {\n md: 20,\n sm: 12,\n};\n\nconst ANIMATION_DURATION = 120;\n\n/**\n * **Switch component for toggling options**\n *\n * @description\n * A switch (also called a toggle) is a binary on/off input control.\n * It allows users to pick between two clearly opposite choices.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Switch } from '@yahoo/uds-mobile/Switch';\n *\n * <Switch label=\"Notifications\" />\n * <Switch isOn={enabled} onChange={setEnabled} label=\"Dark mode\" />\n * <Switch onIcon=\"Check\" offIcon=\"Cross\" label=\"Sync\" />\n * ```\n *\n * @usage\n * - Settings: For toggling preferences on/off\n * - Feature flags: For enabling/disabling features\n * - Immediate effect toggles (no submit button needed)\n *\n * @accessibility\n * - Sets `accessibilityRole=\"switch\"` automatically\n * - Announces on/off state to screen readers\n * - Respects system reduce motion preference\n * - Supports `reduceMotion` prop to disable animations\n *\n * @see {@link Checkbox} for forms with submit actions\n * @see {@link Radio} for single-select options\n */\nconst Switch = memo(function Switch({\n isOn: isOnProp,\n defaultIsOn = false,\n onChange,\n label,\n labelPosition = 'start',\n size = 'md',\n onIcon,\n offIcon,\n disabled = false,\n required,\n accessibilityHint,\n reduceMotion = false,\n ref,\n ...viewProps\n}: SwitchProps) {\n const isControlled = isOnProp !== undefined;\n const [internalIsOn, setInternalIsOn] = useState(defaultIsOn);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const isOn = isControlled ? isOnProp : internalIsOn;\n const activeVariant = isOn ? 'on' : 'off';\n const { theme } = useUnistyles();\n\n // Check system reduced motion preference\n useEffect(() => {\n const checkReducedMotion = async () => {\n const isReduceMotionEnabled = await AccessibilityInfo.isReduceMotionEnabled();\n setPrefersReducedMotion(isReduceMotionEnabled);\n };\n checkReducedMotion();\n\n const subscription = AccessibilityInfo.addEventListener(\n 'reduceMotionChanged',\n setPrefersReducedMotion,\n );\n return () => subscription.remove();\n }, []);\n\n const shouldReduceMotion = reduceMotion || prefersReducedMotion;\n const animationDuration = shouldReduceMotion ? 0 : ANIMATION_DURATION;\n\n const progress = useDerivedValue(\n () => withTiming(isOn ? 1 : 0, { duration: animationDuration }),\n [isOn, animationDuration],\n );\n\n // RTL mirrors the track layout but not transforms, so travel flips sign\n const travelDistance = HANDLE_TRAVEL[size] * (I18nManager.isRTL ? -1 : 1);\n\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n const newValue = !isOn;\n\n if (!isControlled) {\n setInternalIsOn(newValue);\n }\n\n onChange?.(newValue);\n }, [disabled, isOn, isControlled, onChange]);\n\n // On web, useVariants returns the resolved style object instead of mutating\n // switchStyles in place.\n const variantSwitchStyles = switchStyles.useVariants({\n size,\n variant: activeVariant,\n }) as unknown as typeof switchStyles | undefined;\n const resolvedSwitchStyles = variantSwitchStyles ?? switchStyles;\n\n const variantLayerStyles = useMemo(() => {\n const components = theme.components as unknown as Record<string, Record<string, unknown>>;\n const getLayerStyle = <TStyle,>(layer: string) =>\n components[`switch/variant/default/active/${activeVariant}/${layer}/rest`] as\n | TStyle\n | undefined;\n\n return {\n handle: getLayerStyle<ViewStyle>('handle'),\n handleIcon: getLayerStyle<TextStyle>('handleIcon'),\n switch: getLayerStyle<ViewStyle>('switch'),\n text: getLayerStyle<TextStyle>('rootText'),\n };\n }, [activeVariant, theme]);\n\n // Get animated track color from design tokens (changes when variant changes)\n const trackBackgroundColor = useAnimatedVariantColor(\n resolvedSwitchStyles.switch,\n 'backgroundColor',\n );\n\n const animatedTrackStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n backgroundColor: withTiming(trackBackgroundColor.value, { duration: animationDuration }),\n };\n });\n\n const animatedHandleStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n transform: [{ translateX: progress.value * travelDistance }],\n };\n });\n\n const rootStyle: StyleProp<ViewStyle> = useMemo(\n () => [resolvedSwitchStyles.root, switchStaticStyles.root({ disabled })],\n [resolvedSwitchStyles.root, disabled],\n );\n\n const trackStyle: StyleProp<ViewStyle> = useMemo(\n () => [\n resolvedSwitchStyles.switch,\n switchStaticStyles.track,\n variantLayerStyles.switch,\n // On web, the animated variant color hook currently resolves to Unistyles'\n // black fallback, so the concrete variant layer provides the track color.\n Platform.OS !== 'web' && animatedTrackStyle,\n ],\n [resolvedSwitchStyles.switch, variantLayerStyles.switch, animatedTrackStyle],\n );\n\n const handleStyle: StyleProp<ViewStyle> = useMemo(\n () => [\n resolvedSwitchStyles.handle,\n switchStaticStyles.handle,\n variantLayerStyles.handle,\n animatedHandleStyle,\n ],\n [resolvedSwitchStyles.handle, variantLayerStyles.handle, animatedHandleStyle],\n );\n\n const accessibilityLabel = typeof label === 'string' ? label : undefined;\n const resolvedAccessibilityHint = accessibilityHint ?? 'Double tap to toggle';\n\n const labelContent = label && (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n style={[resolvedSwitchStyles.text, variantLayerStyles.text]}\n />\n );\n\n const a11yValue = useMemo(() => ({ text: isOn ? 'On' : 'Off' }), [isOn]);\n\n return (\n <Pressable\n ref={ref}\n onPress={handlePress}\n disabled={disabled}\n accessible\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: isOn, disabled }}\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={resolvedAccessibilityHint}\n accessibilityValue={a11yValue}\n {...viewProps}\n style={rootStyle}\n >\n {labelPosition === 'start' && labelContent}\n\n <Animated.View style={trackStyle} importantForAccessibility=\"no-hide-descendants\">\n <Animated.View style={handleStyle}>\n {onIcon && isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot\n icon={onIcon}\n variant=\"fill\"\n style={[resolvedSwitchStyles.handleIcon, variantLayerStyles.handleIcon]}\n />\n </Animated.View>\n )}\n {offIcon && !isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot\n icon={offIcon}\n variant=\"fill\"\n style={[resolvedSwitchStyles.handleIcon, variantLayerStyles.handleIcon]}\n />\n </Animated.View>\n )}\n </Animated.View>\n </Animated.View>\n\n {labelPosition === 'end' && labelContent}\n </Pressable>\n );\n});\n\nSwitch.displayName = 'Switch';\n\nconst switchStaticStyles = StyleSheet.create((theme) => ({\n handle: {\n borderRadius: theme.borderRadius.full,\n alignItems: 'center',\n justifyContent: 'center',\n },\n iconContainer: {\n position: 'absolute',\n alignItems: 'center',\n justifyContent: 'center',\n },\n track: {\n justifyContent: 'center',\n borderRadius: theme.borderRadius.full,\n },\n root: ({ disabled }: { disabled: boolean }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n alignSelf: 'flex-start',\n opacity: disabled ? 0.5 : 1,\n }),\n}));\n\nexport { Switch, type SwitchProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"Switch.js","names":["StyleSheet"],"sources":["../../src/components/Switch.tsx"],"sourcesContent":["import type { UniversalSwitchProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type {\n AccessibilityProps,\n StyleProp,\n TextStyle,\n View,\n ViewProps,\n ViewStyle,\n} from 'react-native';\nimport { AccessibilityInfo, I18nManager, Platform, Pressable } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withTiming } from 'react-native-reanimated';\n// eslint-disable-next-line uds/no-use-unistyles -- switch variant layers need concrete web styles\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\nimport { useAnimatedVariantColor } from 'react-native-unistyles/reanimated';\n\nimport { switchStyles } from '../../generated/styles';\nimport { useComponentFontScale } from '../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\nimport { getSafeIconCell } from './Button/buttonTheme';\nimport { FormLabel } from './FormLabel';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\n\ninterface SwitchProps extends Omit<ViewProps, 'style'>, UniversalSwitchProps<IconSlotType> {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Callback when the switch value changes */\n onChange?: (value: boolean) => void;\n /** Whether the switch is disabled */\n disabled?: boolean;\n /** Whether the switch is required (shows asterisk with label) */\n required?: boolean;\n /**\n * Caps how far the track, handle, and label grow with the OS text-size\n * setting; all scale by the same factor. Set null to remove the cap;\n * override app-wide via UDSFontScalingProvider.\n * @default 2\n */\n maxFontSizeMultiplier?: number | null;\n /** Accessibility hint describing what happens when activated */\n accessibilityHint?: AccessibilityProps['accessibilityHint'];\n}\n\nconst ANIMATION_DURATION = 120;\n\n/**\n * **Switch component for toggling options**\n *\n * @description\n * A switch (also called a toggle) is a binary on/off input control.\n * It allows users to pick between two clearly opposite choices.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Switch } from '@yahoo/uds-mobile/Switch';\n *\n * <Switch label=\"Notifications\" />\n * <Switch isOn={enabled} onChange={setEnabled} label=\"Dark mode\" />\n * <Switch onIcon=\"Check\" offIcon=\"Cross\" label=\"Sync\" />\n * ```\n *\n * @usage\n * - Settings: For toggling preferences on/off\n * - Feature flags: For enabling/disabling features\n * - Immediate effect toggles (no submit button needed)\n *\n * @accessibility\n * - Sets `accessibilityRole=\"switch\"` automatically\n * - Announces on/off state to screen readers\n * - Respects system reduce motion preference\n * - Supports `reduceMotion` prop to disable animations\n *\n * @see {@link Checkbox} for forms with submit actions\n * @see {@link Radio} for single-select options\n */\nconst Switch = memo(function Switch({\n isOn: isOnProp,\n defaultIsOn = false,\n onChange,\n label,\n labelPosition = 'start',\n size = 'md',\n onIcon,\n offIcon,\n disabled = false,\n required,\n maxFontSizeMultiplier,\n accessibilityHint,\n reduceMotion = false,\n ref,\n ...viewProps\n}: SwitchProps) {\n const isControlled = isOnProp !== undefined;\n const [internalIsOn, setInternalIsOn] = useState(defaultIsOn);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const isOn = isControlled ? isOnProp : internalIsOn;\n const activeVariant = isOn ? 'on' : 'off';\n const { theme } = useUnistyles();\n\n // One resolved cap governs track, handle, travel, and label. Android may\n // resolve different nonlinear factors for the label and handle glyph.\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier('control', maxFontSizeMultiplier);\n // Check system reduced motion preference\n useEffect(() => {\n const checkReducedMotion = async () => {\n const isReduceMotionEnabled = await AccessibilityInfo.isReduceMotionEnabled();\n setPrefersReducedMotion(isReduceMotionEnabled);\n };\n checkReducedMotion();\n\n const subscription = AccessibilityInfo.addEventListener(\n 'reduceMotionChanged',\n setPrefersReducedMotion,\n );\n return () => subscription.remove();\n }, []);\n\n const shouldReduceMotion = reduceMotion || prefersReducedMotion;\n const animationDuration = shouldReduceMotion ? 0 : ANIMATION_DURATION;\n\n const progress = useDerivedValue(\n () => withTiming(isOn ? 1 : 0, { duration: animationDuration }),\n [isOn, animationDuration],\n );\n\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n const newValue = !isOn;\n\n if (!isControlled) {\n setInternalIsOn(newValue);\n }\n\n onChange?.(newValue);\n }, [disabled, isOn, isControlled, onChange]);\n\n // On web, useVariants returns the resolved style object instead of mutating\n // switchStyles in place.\n const variantSwitchStyles = switchStyles.useVariants({\n size,\n variant: activeVariant,\n }) as unknown as typeof switchStyles | undefined;\n const resolvedSwitchStyles = variantSwitchStyles ?? switchStyles;\n const labelBaseSize = resolvedSwitchStyles.text.lineHeight ?? resolvedSwitchStyles.text.fontSize;\n const fontScaleFactor = useComponentFontScale(\n resolvedMaxFontSizeMultiplier,\n typeof labelBaseSize === 'number' ? labelBaseSize : undefined,\n );\n // Size the handle glyph from the configured size layer and the same factor\n // Android would apply to a native glyph of this size.\n const handleIconSize = resolvedSwitchStyles.handleIcon.fontSize;\n const handleIconScaleFactor = useComponentFontScale(\n resolvedMaxFontSizeMultiplier,\n typeof handleIconSize === 'number' ? handleIconSize : undefined,\n );\n const scaledHandleIconSize =\n typeof handleIconSize === 'number'\n ? Math.round(handleIconSize * handleIconScaleFactor)\n : undefined;\n\n // Derive travel from the same rounded metrics used to render the control.\n // Scaling the token travel independently can differ by a pixel at fractional\n // font scales, leaving unequal insets at opposite ends of the track.\n const scaledTrackWidth = Math.round(resolvedSwitchStyles.switch.width * fontScaleFactor);\n const scaledTrackPadding = Math.round(resolvedSwitchStyles.switch.padding * fontScaleFactor);\n const scaledHandleWidth = Math.round(resolvedSwitchStyles.handle.width * fontScaleFactor);\n const scaledHandleTravel = Math.max(\n 0,\n scaledTrackWidth - scaledHandleWidth - scaledTrackPadding * 2,\n );\n // RTL mirrors the track layout but not transforms, so travel flips sign.\n const travelDistance = scaledHandleTravel * (I18nManager.isRTL ? -1 : 1);\n\n const variantLayerStyles = useMemo(() => {\n const components = theme.components as unknown as Record<string, Record<string, unknown>>;\n const getLayerStyle = <TStyle,>(layer: string) =>\n components[`switch/variant/default/active/${activeVariant}/${layer}/rest`] as\n TStyle | undefined;\n\n return {\n handle: getLayerStyle<ViewStyle>('handle'),\n handleIcon: getLayerStyle<TextStyle>('handleIcon'),\n switch: getLayerStyle<ViewStyle>('switch'),\n text: getLayerStyle<TextStyle>('rootText'),\n };\n }, [activeVariant, theme]);\n\n // Get animated track color from design tokens (changes when variant changes)\n const trackBackgroundColor = useAnimatedVariantColor(\n resolvedSwitchStyles.switch,\n 'backgroundColor',\n );\n\n const animatedTrackStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n backgroundColor: withTiming(trackBackgroundColor.value, { duration: animationDuration }),\n };\n });\n\n const animatedHandleStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n transform: [{ translateX: progress.value * travelDistance }],\n };\n });\n\n const rootStyle: StyleProp<ViewStyle> = useMemo(\n () => [resolvedSwitchStyles.root, switchStaticStyles.root({ disabled })],\n [resolvedSwitchStyles.root, disabled],\n );\n\n // Track and handle grow by the capped factor so the handle (and its icon)\n // stays contained. Scale the track's inset too so the derived travel lands\n // the handle at the same distance from either end.\n const scaleDimensions = useCallback(\n (style: ViewStyle | undefined): ViewStyle | undefined => {\n if (!style || fontScaleFactor === 1) {\n return undefined;\n }\n const { width, height, padding } = style;\n return typeof width === 'number' && typeof height === 'number'\n ? {\n width: Math.round(width * fontScaleFactor),\n height: Math.round(height * fontScaleFactor),\n ...(typeof padding === 'number' && {\n padding: Math.round(padding * fontScaleFactor),\n }),\n }\n : undefined;\n },\n [fontScaleFactor],\n );\n\n const trackStyle: StyleProp<ViewStyle> = useMemo(\n () => [\n resolvedSwitchStyles.switch,\n switchStaticStyles.track,\n variantLayerStyles.switch,\n scaleDimensions(resolvedSwitchStyles.switch as ViewStyle),\n // On web, the animated variant color hook currently resolves to Unistyles'\n // black fallback, so the concrete variant layer provides the track color.\n Platform.OS !== 'web' && animatedTrackStyle,\n ],\n [resolvedSwitchStyles.switch, variantLayerStyles.switch, scaleDimensions, animatedTrackStyle],\n );\n\n const handleStyle: StyleProp<ViewStyle> = useMemo(\n () => [\n resolvedSwitchStyles.handle,\n switchStaticStyles.handle,\n variantLayerStyles.handle,\n scaleDimensions(resolvedSwitchStyles.handle as ViewStyle),\n animatedHandleStyle,\n ],\n [resolvedSwitchStyles.handle, variantLayerStyles.handle, scaleDimensions, animatedHandleStyle],\n );\n\n const accessibilityLabel = typeof label === 'string' ? label : undefined;\n const resolvedAccessibilityHint = accessibilityHint ?? 'Double tap to toggle';\n\n const labelContent = label && (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={[resolvedSwitchStyles.text, variantLayerStyles.text]}\n />\n );\n\n const a11yValue = useMemo(() => ({ text: isOn ? 'On' : 'Off' }), [isOn]);\n\n return (\n <Pressable\n ref={ref}\n onPress={handlePress}\n disabled={disabled}\n accessible\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: isOn, disabled }}\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={resolvedAccessibilityHint}\n accessibilityValue={a11yValue}\n {...viewProps}\n style={rootStyle}\n >\n {labelPosition === 'start' && labelContent}\n\n <Animated.View style={trackStyle} importantForAccessibility=\"no-hide-descendants\">\n <Animated.View style={handleStyle}>\n {onIcon && isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot\n icon={onIcon}\n variant=\"fill\"\n dangerouslySetSize={scaledHandleIconSize}\n allowFontScaling={false}\n style={[\n resolvedSwitchStyles.handleIcon,\n variantLayerStyles.handleIcon,\n scaledHandleIconSize === undefined\n ? undefined\n : {\n fontSize: scaledHandleIconSize,\n lineHeight: getSafeIconCell(scaledHandleIconSize),\n },\n ]}\n />\n </Animated.View>\n )}\n {offIcon && !isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot\n icon={offIcon}\n variant=\"fill\"\n dangerouslySetSize={scaledHandleIconSize}\n allowFontScaling={false}\n style={[\n resolvedSwitchStyles.handleIcon,\n variantLayerStyles.handleIcon,\n scaledHandleIconSize === undefined\n ? undefined\n : {\n fontSize: scaledHandleIconSize,\n lineHeight: getSafeIconCell(scaledHandleIconSize),\n },\n ]}\n />\n </Animated.View>\n )}\n </Animated.View>\n </Animated.View>\n\n {labelPosition === 'end' && labelContent}\n </Pressable>\n );\n});\n\nSwitch.displayName = 'Switch';\n\nconst switchStaticStyles = StyleSheet.create((theme) => ({\n handle: {\n borderRadius: theme.borderRadius.full,\n alignItems: 'center',\n justifyContent: 'center',\n },\n iconContainer: {\n position: 'absolute',\n alignItems: 'center',\n justifyContent: 'center',\n },\n track: {\n justifyContent: 'center',\n borderRadius: theme.borderRadius.full,\n },\n root: ({ disabled }: { disabled: boolean }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n alignSelf: 'flex-start',\n opacity: disabled ? 0.5 : 1,\n }),\n}));\n\nexport { Switch, type SwitchProps };\n"],"mappings":"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"}
@@ -1,6 +1,9 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("../../_virtual/_rolldown/runtime.cjs");
4
+ const require_fontScaling_FontScalingContext = require("../../fontScaling/FontScalingContext.cjs");
5
+ const require_fontScaling_useFontScale = require("../../fontScaling/useFontScale.cjs");
6
+ const require_fontScaling_useMaxFontSizeMultiplier = require("../../fontScaling/useMaxFontSizeMultiplier.cjs");
4
7
  const require_components_IconSlot = require("../IconSlot.cjs");
5
8
  const require_components_Pressable = require("../Pressable.cjs");
6
9
  const require_components_Tabs_tabsContexts = require("./tabsContexts.cjs");
@@ -19,12 +22,16 @@ const CLEAR_SELECTION_CHROME = {
19
22
  elevation: 0,
20
23
  boxShadow: []
21
24
  };
22
- function TabLabel({ style, children }) {
25
+ function TabLabel({ style, maxFontSizeMultiplier, children }) {
23
26
  if (typeof children === "string" || typeof children === "number") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
24
27
  style,
28
+ maxFontSizeMultiplier,
29
+ children
30
+ });
31
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_fontScaling_FontScalingContext.ResolvedControlFontScalingProvider, {
32
+ maxFontSizeMultiplier,
25
33
  children
26
34
  });
27
- return children;
28
35
  }
29
36
  /**
30
37
  * **⚙️ Tab**
@@ -38,10 +45,11 @@ function TabLabel({ style, children }) {
38
45
  const Tab = (0, react.memo)(function Tab({ value, children, startIcon, endIcon, disabled, style, ...pressableRest }) {
39
46
  const generatedId = (0, react.useId)();
40
47
  const uid = value ?? `uds-tab-${generatedId}`;
41
- const { variant: visualVariant, reduceMotion } = require_components_Tabs_tabsContexts.useTabsVisualContext();
48
+ const { variant: visualVariant, reduceMotion, maxFontSizeMultiplier } = require_components_Tabs_tabsContexts.useTabsVisualContext();
42
49
  const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } = require_components_Tabs_tabsContexts.useTabSelectionContext();
43
50
  const { theme } = (0, react_native_unistyles.useUnistyles)();
44
51
  const [pressed, setPressed] = (0, react.useState)(false);
52
+ const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
45
53
  const selected = !disabled && selectedId === uid;
46
54
  const active = selected ? "on" : "off";
47
55
  const interaction = pressed ? "pressed" : "rest";
@@ -67,6 +75,7 @@ const Tab = (0, react.memo)(function Tab({ value, children, startIcon, endIcon,
67
75
  active,
68
76
  interaction
69
77
  ]);
78
+ const fontScaleFactor = require_fontScaling_useFontScale.useComponentFontScale(resolvedMaxFontSizeMultiplier, (typeof textStyle.lineHeight === "number" ? textStyle.lineHeight : void 0) ?? (typeof textStyle.fontSize === "number" ? textStyle.fontSize : void 0));
70
79
  const iconStyle = (0, react.useMemo)(() => require_components_Tabs_tabTheme.getMergedTabLayerStyle(theme, visualVariant, active, "icon", interaction), [
71
80
  theme,
72
81
  visualVariant,
@@ -102,6 +111,7 @@ const Tab = (0, react.memo)(function Tab({ value, children, startIcon, endIcon,
102
111
  zIndex: 1,
103
112
  position: "relative"
104
113
  };
114
+ if (fontScaleFactor !== 1 && typeof base.height === "number") base.height = Math.round(base.height * fontScaleFactor);
105
115
  if (selected && !reduceMotion) return {
106
116
  ...base,
107
117
  ...CLEAR_SELECTION_CHROME
@@ -109,6 +119,7 @@ const Tab = (0, react.memo)(function Tab({ value, children, startIcon, endIcon,
109
119
  return base;
110
120
  }, [
111
121
  rootBase,
122
+ fontScaleFactor,
112
123
  selected,
113
124
  reduceMotion
114
125
  ]);
@@ -140,16 +151,19 @@ const Tab = (0, react.memo)(function Tab({ value, children, startIcon, endIcon,
140
151
  startIcon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_IconSlot.IconSlot, {
141
152
  icon: startIcon,
142
153
  size: "sm",
154
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
143
155
  style: iconStyle,
144
156
  ...iconColor !== void 0 ? { color: iconColor } : {}
145
157
  }) : null,
146
158
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TabLabel, {
147
159
  style: textStyle,
160
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
148
161
  children
149
162
  }),
150
163
  endIcon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_IconSlot.IconSlot, {
151
164
  icon: endIcon,
152
165
  size: "sm",
166
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
153
167
  style: iconStyle,
154
168
  ...iconColor !== void 0 ? { color: iconColor } : {}
155
169
  }) : null,
@@ -1 +1 @@
1
- {"version":3,"file":"Tab.d.cts","names":[],"sources":["../../../src/components/Tabs/Tab.tsx"],"mappings":";;;;;;;UAiBU,QAAA,SAEN,IAAA,CAAK,cAAA,kDACL,IAAA,CAAK,iBAAA;EACP,QAAA,EAAU,iBAAA;EACV,SAAA,GAAY,YAAA;EACZ,OAAA,GAAU,YAAA;EACV,KAAA,GAAQ,SAAA;AAAA;;;;;;;;;;cA4BJ,GAAA,EAAG,OAAA,CAAA,oBAAA,CAAA,QAAA"}
1
+ {"version":3,"file":"Tab.d.cts","names":[],"sources":["../../../src/components/Tabs/Tab.tsx"],"mappings":";;;;;;;UAoBU,QAAA,SAEN,IAAA,CAAK,cAAA,kDACL,IAAA,CAAK,iBAAA;EACP,QAAA,EAAU,iBAAA;EACV,SAAA,GAAY,YAAA;EACZ,OAAA,GAAU,YAAA;EACV,KAAA,GAAQ,SAAA;AAAA;;;;;;;;;;cA4CJ,GAAA,EAAG,OAAA,CAAA,oBAAA,CAAA,QAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tab.d.ts","names":[],"sources":["../../../src/components/Tabs/Tab.tsx"],"mappings":";;;;;;;UAiBU,QAAA,SAEN,IAAA,CAAK,cAAA,kDACL,IAAA,CAAK,iBAAA;EACP,QAAA,EAAU,iBAAA;EACV,SAAA,GAAY,YAAA;EACZ,OAAA,GAAU,YAAA;EACV,KAAA,GAAQ,SAAA;AAAA;;;;;;;;;;cA4BJ,GAAA,EAAG,OAAA,CAAA,oBAAA,CAAA,QAAA"}
1
+ {"version":3,"file":"Tab.d.ts","names":[],"sources":["../../../src/components/Tabs/Tab.tsx"],"mappings":";;;;;;;UAoBU,QAAA,SAEN,IAAA,CAAK,cAAA,kDACL,IAAA,CAAK,iBAAA;EACP,QAAA,EAAU,iBAAA;EACV,SAAA,GAAY,YAAA;EACZ,OAAA,GAAU,YAAA;EACV,KAAA,GAAQ,SAAA;AAAA;;;;;;;;;;cA4CJ,GAAA,EAAG,OAAA,CAAA,oBAAA,CAAA,QAAA"}
@@ -1,4 +1,7 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ import { ResolvedControlFontScalingProvider } from "../../fontScaling/FontScalingContext.js";
3
+ import { useComponentFontScale } from "../../fontScaling/useFontScale.js";
4
+ import { useMaxFontSizeMultiplier } from "../../fontScaling/useMaxFontSizeMultiplier.js";
2
5
  import { IconSlot } from "../IconSlot.js";
3
6
  import { Pressable as Pressable$1 } from "../Pressable.js";
4
7
  import { useTabSelectionContext, useTabsVisualContext } from "./tabsContexts.js";
@@ -17,12 +20,16 @@ const CLEAR_SELECTION_CHROME = {
17
20
  elevation: 0,
18
21
  boxShadow: []
19
22
  };
20
- function TabLabel({ style, children }) {
23
+ function TabLabel({ style, maxFontSizeMultiplier, children }) {
21
24
  if (typeof children === "string" || typeof children === "number") return /* @__PURE__ */ jsx(Text, {
22
25
  style,
26
+ maxFontSizeMultiplier,
27
+ children
28
+ });
29
+ return /* @__PURE__ */ jsx(ResolvedControlFontScalingProvider, {
30
+ maxFontSizeMultiplier,
23
31
  children
24
32
  });
25
- return children;
26
33
  }
27
34
  /**
28
35
  * **⚙️ Tab**
@@ -36,10 +43,11 @@ function TabLabel({ style, children }) {
36
43
  const Tab = memo(function Tab({ value, children, startIcon, endIcon, disabled, style, ...pressableRest }) {
37
44
  const generatedId = useId();
38
45
  const uid = value ?? `uds-tab-${generatedId}`;
39
- const { variant: visualVariant, reduceMotion } = useTabsVisualContext();
46
+ const { variant: visualVariant, reduceMotion, maxFontSizeMultiplier } = useTabsVisualContext();
40
47
  const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } = useTabSelectionContext();
41
48
  const { theme } = useUnistyles();
42
49
  const [pressed, setPressed] = useState(false);
50
+ const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
43
51
  const selected = !disabled && selectedId === uid;
44
52
  const active = selected ? "on" : "off";
45
53
  const interaction = pressed ? "pressed" : "rest";
@@ -65,6 +73,7 @@ const Tab = memo(function Tab({ value, children, startIcon, endIcon, disabled, s
65
73
  active,
66
74
  interaction
67
75
  ]);
76
+ const fontScaleFactor = useComponentFontScale(resolvedMaxFontSizeMultiplier, (typeof textStyle.lineHeight === "number" ? textStyle.lineHeight : void 0) ?? (typeof textStyle.fontSize === "number" ? textStyle.fontSize : void 0));
68
77
  const iconStyle = useMemo(() => getMergedTabLayerStyle(theme, visualVariant, active, "icon", interaction), [
69
78
  theme,
70
79
  visualVariant,
@@ -100,6 +109,7 @@ const Tab = memo(function Tab({ value, children, startIcon, endIcon, disabled, s
100
109
  zIndex: 1,
101
110
  position: "relative"
102
111
  };
112
+ if (fontScaleFactor !== 1 && typeof base.height === "number") base.height = Math.round(base.height * fontScaleFactor);
103
113
  if (selected && !reduceMotion) return {
104
114
  ...base,
105
115
  ...CLEAR_SELECTION_CHROME
@@ -107,6 +117,7 @@ const Tab = memo(function Tab({ value, children, startIcon, endIcon, disabled, s
107
117
  return base;
108
118
  }, [
109
119
  rootBase,
120
+ fontScaleFactor,
110
121
  selected,
111
122
  reduceMotion
112
123
  ]);
@@ -138,16 +149,19 @@ const Tab = memo(function Tab({ value, children, startIcon, endIcon, disabled, s
138
149
  startIcon ? /* @__PURE__ */ jsx(IconSlot, {
139
150
  icon: startIcon,
140
151
  size: "sm",
152
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
141
153
  style: iconStyle,
142
154
  ...iconColor !== void 0 ? { color: iconColor } : {}
143
155
  }) : null,
144
156
  /* @__PURE__ */ jsx(TabLabel, {
145
157
  style: textStyle,
158
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
146
159
  children
147
160
  }),
148
161
  endIcon ? /* @__PURE__ */ jsx(IconSlot, {
149
162
  icon: endIcon,
150
163
  size: "sm",
164
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
151
165
  style: iconStyle,
152
166
  ...iconColor !== void 0 ? { color: iconColor } : {}
153
167
  }) : null,
@@ -1 +1 @@
1
- {"version":3,"file":"Tab.js","names":["RNText","Pressable"],"sources":["../../../src/components/Tabs/Tab.tsx"],"sourcesContent":["import type { UniversalTabProps } from '@yahoo/uds-types';\nimport type { ReactElement, ReactNode } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { LayoutChangeEvent, PressableProps, TextStyle, ViewStyle } from 'react-native';\nimport { Text as RNText, View } from 'react-native';\n// eslint-disable-next-line uds/no-use-unistyles -- theme.components path lookups for tab layers\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport type { IconSlotType } from '../IconSlot';\nimport { IconSlot } from '../IconSlot';\nimport { Pressable } from '../Pressable';\nimport { useTabSelectionContext, useTabsVisualContext } from './tabsContexts';\nimport { getMergedTabLayerStyle, getTabLayerStyle } from './tabTheme';\n\nconst PRIMARY_TAB_UNDERLINE_HEIGHT = 2;\n\ninterface TabProps\n extends\n Omit<PressableProps, 'children' | 'style' | 'disabled' | 'onPress'>,\n Omit<UniversalTabProps, 'asChild' | 'className' | 'startIcon' | 'endIcon'> {\n children: UniversalTabProps['children'];\n startIcon?: IconSlotType;\n endIcon?: IconSlotType;\n style?: ViewStyle;\n}\n\nconst CLEAR_SELECTION_CHROME: ViewStyle = {\n backgroundColor: 'transparent',\n borderWidth: 0,\n borderColor: 'transparent',\n shadowOpacity: 0,\n elevation: 0,\n boxShadow: [],\n};\n\nfunction TabLabel({ style, children }: { style: TextStyle; children: ReactNode }) {\n if (typeof children === 'string' || typeof children === 'number') {\n return <RNText style={style}>{children}</RNText>;\n }\n return children as ReactElement;\n}\n\n/**\n * **⚙️ Tab**\n *\n * @description\n * A single selectable tab. Must be used inside {@link TabList} within {@link Tabs}.\n *\n * @category Navigation\n * @platform mobile\n */\nconst Tab = memo(function Tab({\n value,\n children,\n startIcon,\n endIcon,\n disabled,\n style,\n ...pressableRest\n}: TabProps) {\n const generatedId = useId();\n const uid = value ?? `uds-tab-${generatedId}`;\n const { variant: visualVariant, reduceMotion } = useTabsVisualContext();\n const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } =\n useTabSelectionContext();\n const { theme } = useUnistyles();\n const [pressed, setPressed] = useState(false);\n\n const selected = !disabled && selectedId === uid;\n const active: 'on' | 'off' = selected ? 'on' : 'off';\n const interaction: 'rest' | 'pressed' = pressed ? 'pressed' : 'rest';\n\n useEffect(() => {\n registerTab(uid);\n return () => {\n unregisterTab(uid);\n };\n }, [uid, registerTab, unregisterTab]);\n\n const rootBase = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'root', interaction) as ViewStyle,\n [theme, visualVariant, active, interaction],\n );\n const textStyle = useMemo(\n () =>\n getMergedTabLayerStyle(theme, visualVariant, active, 'rootText', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n const iconStyle = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'icon', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n\n const iconColor = ((): StyleProps['color'] | undefined => {\n const c = iconStyle?.color;\n if (c === undefined || c === null) {\n return undefined;\n }\n return c as StyleProps['color'];\n })();\n\n /** Inactive primary tabs use transparent underline tokens on web; RN has no CSS vars for that layer. */\n const showPrimaryPerTabUnderline = visualVariant === 'primary' && !(selected && !reduceMotion);\n\n const primaryUnderlineColor = useMemo(() => {\n if (visualVariant !== 'primary') {\n return undefined;\n }\n if (selected && reduceMotion) {\n const onText = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as TextStyle;\n const c = onText.color;\n if (typeof c === 'string') {\n return c;\n }\n }\n return 'transparent';\n }, [visualVariant, selected, reduceMotion, theme]);\n\n const rootStyle = useMemo((): ViewStyle => {\n const base: ViewStyle = {\n ...rootBase,\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n zIndex: 1,\n position: 'relative',\n };\n if (selected && !reduceMotion) {\n return { ...base, ...CLEAR_SELECTION_CHROME };\n }\n return base;\n }, [rootBase, selected, reduceMotion]);\n\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n setTabLayout(uid, e.nativeEvent.layout);\n },\n [uid, setTabLayout],\n );\n\n const onPress = useCallback(() => {\n if (disabled) {\n return;\n }\n setSelectedId(uid);\n }, [disabled, setSelectedId, uid]);\n\n return (\n <Pressable\n accessibilityRole=\"tab\"\n accessibilityState={{ selected, disabled: !!disabled }}\n disabled={disabled}\n onPress={onPress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onLayout={onLayout}\n style={[rootStyle, style]}\n {...pressableRest}\n >\n {startIcon ? (\n <IconSlot\n icon={startIcon}\n size=\"sm\"\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n <TabLabel style={textStyle}>{children}</TabLabel>\n {endIcon ? (\n <IconSlot\n icon={endIcon}\n size=\"sm\"\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n {showPrimaryPerTabUnderline &&\n primaryUnderlineColor &&\n primaryUnderlineColor !== 'transparent' ? (\n <View\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: PRIMARY_TAB_UNDERLINE_HEIGHT,\n backgroundColor: primaryUnderlineColor,\n }}\n />\n ) : null}\n </Pressable>\n );\n});\n\nTab.displayName = 'Tab';\n\nexport { Tab };\nexport type { TabProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tab.js","names":["RNText","Pressable"],"sources":["../../../src/components/Tabs/Tab.tsx"],"sourcesContent":["import type { UniversalTabProps } from '@yahoo/uds-types';\nimport type { ReactElement, ReactNode } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { LayoutChangeEvent, PressableProps, TextStyle, ViewStyle } from 'react-native';\nimport { Text as RNText, View } from 'react-native';\n// eslint-disable-next-line uds/no-use-unistyles -- theme.components path lookups for tab layers\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport { ResolvedControlFontScalingProvider } from '../../fontScaling/FontScalingContext';\nimport { useComponentFontScale } from '../../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport type { IconSlotType } from '../IconSlot';\nimport { IconSlot } from '../IconSlot';\nimport { Pressable } from '../Pressable';\nimport { useTabSelectionContext, useTabsVisualContext } from './tabsContexts';\nimport { getMergedTabLayerStyle, getTabLayerStyle } from './tabTheme';\n\nconst PRIMARY_TAB_UNDERLINE_HEIGHT = 2;\n\ninterface TabProps\n extends\n Omit<PressableProps, 'children' | 'style' | 'disabled' | 'onPress'>,\n Omit<UniversalTabProps, 'asChild' | 'className' | 'startIcon' | 'endIcon'> {\n children: UniversalTabProps['children'];\n startIcon?: IconSlotType;\n endIcon?: IconSlotType;\n style?: ViewStyle;\n}\n\nconst CLEAR_SELECTION_CHROME: ViewStyle = {\n backgroundColor: 'transparent',\n borderWidth: 0,\n borderColor: 'transparent',\n shadowOpacity: 0,\n elevation: 0,\n boxShadow: [],\n};\n\nfunction TabLabel({\n style,\n maxFontSizeMultiplier,\n children,\n}: {\n style: TextStyle;\n maxFontSizeMultiplier?: number;\n children: ReactNode;\n}) {\n if (typeof children === 'string' || typeof children === 'number') {\n return (\n <RNText style={style} maxFontSizeMultiplier={maxFontSizeMultiplier}>\n {children}\n </RNText>\n );\n }\n return (\n <ResolvedControlFontScalingProvider maxFontSizeMultiplier={maxFontSizeMultiplier}>\n {children as ReactElement}\n </ResolvedControlFontScalingProvider>\n );\n}\n\n/**\n * **⚙️ Tab**\n *\n * @description\n * A single selectable tab. Must be used inside {@link TabList} within {@link Tabs}.\n *\n * @category Navigation\n * @platform mobile\n */\nconst Tab = memo(function Tab({\n value,\n children,\n startIcon,\n endIcon,\n disabled,\n style,\n ...pressableRest\n}: TabProps) {\n const generatedId = useId();\n const uid = value ?? `uds-tab-${generatedId}`;\n const { variant: visualVariant, reduceMotion, maxFontSizeMultiplier } = useTabsVisualContext();\n const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } =\n useTabSelectionContext();\n const { theme } = useUnistyles();\n const [pressed, setPressed] = useState(false);\n\n // One capped factor governs the label, icons, and the tab's fixed height.\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier('control', maxFontSizeMultiplier);\n\n const selected = !disabled && selectedId === uid;\n const active: 'on' | 'off' = selected ? 'on' : 'off';\n const interaction: 'rest' | 'pressed' = pressed ? 'pressed' : 'rest';\n\n useEffect(() => {\n registerTab(uid);\n return () => {\n unregisterTab(uid);\n };\n }, [uid, registerTab, unregisterTab]);\n\n const rootBase = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'root', interaction) as ViewStyle,\n [theme, visualVariant, active, interaction],\n );\n const textStyle = useMemo(\n () =>\n getMergedTabLayerStyle(theme, visualVariant, active, 'rootText', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n const fontScaleFactor = useComponentFontScale(\n resolvedMaxFontSizeMultiplier,\n (typeof textStyle.lineHeight === 'number' ? textStyle.lineHeight : undefined) ??\n (typeof textStyle.fontSize === 'number' ? textStyle.fontSize : undefined),\n );\n const iconStyle = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'icon', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n\n const iconColor = ((): StyleProps['color'] | undefined => {\n const c = iconStyle?.color;\n if (c === undefined || c === null) {\n return undefined;\n }\n return c as StyleProps['color'];\n })();\n\n /** Inactive primary tabs use transparent underline tokens on web; RN has no CSS vars for that layer. */\n const showPrimaryPerTabUnderline = visualVariant === 'primary' && !(selected && !reduceMotion);\n\n const primaryUnderlineColor = useMemo(() => {\n if (visualVariant !== 'primary') {\n return undefined;\n }\n if (selected && reduceMotion) {\n const onText = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as TextStyle;\n const c = onText.color;\n if (typeof c === 'string') {\n return c;\n }\n }\n return 'transparent';\n }, [visualVariant, selected, reduceMotion, theme]);\n\n const rootStyle = useMemo((): ViewStyle => {\n const base: ViewStyle = {\n ...rootBase,\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n zIndex: 1,\n position: 'relative',\n };\n // A fixed token height grows with the capped label so text never clips.\n if (fontScaleFactor !== 1 && typeof base.height === 'number') {\n base.height = Math.round(base.height * fontScaleFactor);\n }\n if (selected && !reduceMotion) {\n return { ...base, ...CLEAR_SELECTION_CHROME };\n }\n return base;\n }, [rootBase, fontScaleFactor, selected, reduceMotion]);\n\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n setTabLayout(uid, e.nativeEvent.layout);\n },\n [uid, setTabLayout],\n );\n\n const onPress = useCallback(() => {\n if (disabled) {\n return;\n }\n setSelectedId(uid);\n }, [disabled, setSelectedId, uid]);\n\n return (\n <Pressable\n accessibilityRole=\"tab\"\n accessibilityState={{ selected, disabled: !!disabled }}\n disabled={disabled}\n onPress={onPress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onLayout={onLayout}\n style={[rootStyle, style]}\n {...pressableRest}\n >\n {startIcon ? (\n <IconSlot\n icon={startIcon}\n size=\"sm\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n <TabLabel style={textStyle} maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}>\n {children}\n </TabLabel>\n {endIcon ? (\n <IconSlot\n icon={endIcon}\n size=\"sm\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n {showPrimaryPerTabUnderline &&\n primaryUnderlineColor &&\n primaryUnderlineColor !== 'transparent' ? (\n <View\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: PRIMARY_TAB_UNDERLINE_HEIGHT,\n backgroundColor: primaryUnderlineColor,\n }}\n />\n ) : null}\n </Pressable>\n );\n});\n\nTab.displayName = 'Tab';\n\nexport { Tab };\nexport type { TabProps };\n"],"mappings":"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"}
@@ -30,11 +30,16 @@ let react_jsx_runtime = require("react/jsx-runtime");
30
30
  * </Tabs>
31
31
  * ```
32
32
  */
33
- const Tabs = (0, react.memo)(function Tabs({ children, variant = "primary", reduceMotion = false, defaultSelectedId, selectedId, onSelectionChange }) {
33
+ const Tabs = (0, react.memo)(function Tabs({ children, variant = "primary", reduceMotion = false, maxFontSizeMultiplier, defaultSelectedId, selectedId, onSelectionChange }) {
34
34
  const visual = (0, react.useMemo)(() => ({
35
35
  variant,
36
- reduceMotion
37
- }), [variant, reduceMotion]);
36
+ reduceMotion,
37
+ maxFontSizeMultiplier
38
+ }), [
39
+ variant,
40
+ reduceMotion,
41
+ maxFontSizeMultiplier
42
+ ]);
38
43
  const selection = require_components_Tabs_tabsContexts.useTabSelectionState({
39
44
  defaultSelectedId,
40
45
  selectedId,
@@ -3,7 +3,15 @@ import { UniversalTabsProps } from "../../types/dist/index.cjs";
3
3
  import * as _$react from "react";
4
4
 
5
5
  //#region src/components/Tabs/Tabs.d.ts
6
- interface TabsProps extends UniversalTabsProps {}
6
+ interface TabsProps extends UniversalTabsProps {
7
+ /**
8
+ * Caps how far tab labels and icons grow with the OS text-size setting;
9
+ * tabs grow to fit. Set null to remove the cap; override app-wide via
10
+ * UDSFontScalingProvider.
11
+ * @default 2
12
+ */
13
+ maxFontSizeMultiplier?: number | null;
14
+ }
7
15
  /**
8
16
  * **⚙️ Tabs**
9
17
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.cts","names":[],"sources":["../../../src/components/Tabs/Tabs.tsx"],"mappings":";;;;;UAMU,SAAA,SAAkB,kBAAA;;AAN+B;;;;;AAMb;;;;;;;;;;;;;;;;;;;cA2BxC,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"Tabs.d.cts","names":[],"sources":["../../../src/components/Tabs/Tabs.tsx"],"mappings":";;;;;UAKU,SAAA,SAAkB,kBAAA;;;AAL+B;;;;EAYzD,qBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;cA4BI,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
@@ -3,7 +3,15 @@ import { UniversalTabsProps } from "../../types/dist/index.js";
3
3
  import * as _$react from "react";
4
4
 
5
5
  //#region src/components/Tabs/Tabs.d.ts
6
- interface TabsProps extends UniversalTabsProps {}
6
+ interface TabsProps extends UniversalTabsProps {
7
+ /**
8
+ * Caps how far tab labels and icons grow with the OS text-size setting;
9
+ * tabs grow to fit. Set null to remove the cap; override app-wide via
10
+ * UDSFontScalingProvider.
11
+ * @default 2
12
+ */
13
+ maxFontSizeMultiplier?: number | null;
14
+ }
7
15
  /**
8
16
  * **⚙️ Tabs**
9
17
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","names":[],"sources":["../../../src/components/Tabs/Tabs.tsx"],"mappings":";;;;;UAMU,SAAA,SAAkB,kBAAA;;AAN+B;;;;;AAMb;;;;;;;;;;;;;;;;;;;cA2BxC,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"Tabs.d.ts","names":[],"sources":["../../../src/components/Tabs/Tabs.tsx"],"mappings":";;;;;UAKU,SAAA,SAAkB,kBAAA;;;AAL+B;;;;EAYzD,qBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;cA4BI,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
@@ -28,11 +28,16 @@ import { jsx } from "react/jsx-runtime";
28
28
  * </Tabs>
29
29
  * ```
30
30
  */
31
- const Tabs = memo(function Tabs({ children, variant = "primary", reduceMotion = false, defaultSelectedId, selectedId, onSelectionChange }) {
31
+ const Tabs = memo(function Tabs({ children, variant = "primary", reduceMotion = false, maxFontSizeMultiplier, defaultSelectedId, selectedId, onSelectionChange }) {
32
32
  const visual = useMemo(() => ({
33
33
  variant,
34
- reduceMotion
35
- }), [variant, reduceMotion]);
34
+ reduceMotion,
35
+ maxFontSizeMultiplier
36
+ }), [
37
+ variant,
38
+ reduceMotion,
39
+ maxFontSizeMultiplier
40
+ ]);
36
41
  const selection = useTabSelectionState({
37
42
  defaultSelectedId,
38
43
  selectedId,
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import type { UniversalTabsProps } from '@yahoo/uds-types';\nimport { memo, useMemo } from 'react';\n\nimport { TabSelectionContext, TabsVisualContext, useTabSelectionState } from './tabsContexts';\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type -- alias for doc extraction / parity with web\ninterface TabsProps extends UniversalTabsProps {}\n\n/**\n * **⚙️ Tabs**\n *\n * @description\n * Organizes content into sections with a tab list and tab panels. Supports `primary` and\n * `secondary` variants. When `reduceMotion` is false, a sliding indicator animates between\n * tabs (240ms, cubic-bezier(0.2, 0, 0, 1)) to match web UDS.\n *\n * @category Navigation\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Tabs, TabList, Tab, TabPanel } from '@yahoo/uds-mobile/Tabs';\n *\n * <Tabs variant=\"primary\" defaultSelectedId=\"home\">\n * <TabList accessibilityLabel=\"Main\">\n * <Tab value=\"home\">Home</Tab>\n * <Tab value=\"about\">About</Tab>\n * </TabList>\n * <TabPanel tabId=\"home\">Home content</TabPanel>\n * <TabPanel tabId=\"about\">About content</TabPanel>\n * </Tabs>\n * ```\n */\nconst Tabs = memo(function Tabs({\n children,\n variant = 'primary',\n reduceMotion = false,\n defaultSelectedId,\n selectedId,\n onSelectionChange,\n}: TabsProps) {\n const visual = useMemo(() => ({ variant, reduceMotion }), [variant, reduceMotion]);\n const selection = useTabSelectionState({\n defaultSelectedId,\n selectedId,\n onSelectionChange,\n });\n\n return (\n <TabsVisualContext.Provider value={visual}>\n <TabSelectionContext.Provider value={selection}>{children}</TabSelectionContext.Provider>\n </TabsVisualContext.Provider>\n );\n});\n\nTabs.displayName = 'Tabs';\n\nexport { Tabs };\nexport type { TabsProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAM,OAAO,KAAK,SAAS,KAAK,EAC9B,UACA,UAAU,WACV,eAAe,OACf,mBACA,YACA,qBACY;CACZ,MAAM,SAAS,eAAe;EAAE;EAAS;EAAc,GAAG,CAAC,SAAS,aAAa,CAAC;CAClF,MAAM,YAAY,qBAAqB;EACrC;EACA;EACA;EACD,CAAC;CAEF,OACE,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;YACjC,oBAAC,oBAAoB,UAArB;GAA8B,OAAO;GAAY;GAAwC,CAAA;EAC9D,CAAA;EAE/B;AAEF,KAAK,cAAc"}
1
+ {"version":3,"file":"Tabs.js","names":[],"sources":["../../../src/components/Tabs/Tabs.tsx"],"sourcesContent":["import type { UniversalTabsProps } from '@yahoo/uds-types';\nimport { memo, useMemo } from 'react';\n\nimport { TabSelectionContext, TabsVisualContext, useTabSelectionState } from './tabsContexts';\n\ninterface TabsProps extends UniversalTabsProps {\n /**\n * Caps how far tab labels and icons grow with the OS text-size setting;\n * tabs grow to fit. Set null to remove the cap; override app-wide via\n * UDSFontScalingProvider.\n * @default 2\n */\n maxFontSizeMultiplier?: number | null;\n}\n\n/**\n * **⚙️ Tabs**\n *\n * @description\n * Organizes content into sections with a tab list and tab panels. Supports `primary` and\n * `secondary` variants. When `reduceMotion` is false, a sliding indicator animates between\n * tabs (240ms, cubic-bezier(0.2, 0, 0, 1)) to match web UDS.\n *\n * @category Navigation\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Tabs, TabList, Tab, TabPanel } from '@yahoo/uds-mobile/Tabs';\n *\n * <Tabs variant=\"primary\" defaultSelectedId=\"home\">\n * <TabList accessibilityLabel=\"Main\">\n * <Tab value=\"home\">Home</Tab>\n * <Tab value=\"about\">About</Tab>\n * </TabList>\n * <TabPanel tabId=\"home\">Home content</TabPanel>\n * <TabPanel tabId=\"about\">About content</TabPanel>\n * </Tabs>\n * ```\n */\nconst Tabs = memo(function Tabs({\n children,\n variant = 'primary',\n reduceMotion = false,\n maxFontSizeMultiplier,\n defaultSelectedId,\n selectedId,\n onSelectionChange,\n}: TabsProps) {\n const visual = useMemo(\n () => ({ variant, reduceMotion, maxFontSizeMultiplier }),\n [variant, reduceMotion, maxFontSizeMultiplier],\n );\n const selection = useTabSelectionState({\n defaultSelectedId,\n selectedId,\n onSelectionChange,\n });\n\n return (\n <TabsVisualContext.Provider value={visual}>\n <TabSelectionContext.Provider value={selection}>{children}</TabSelectionContext.Provider>\n </TabsVisualContext.Provider>\n );\n});\n\nTabs.displayName = 'Tabs';\n\nexport { Tabs };\nexport type { TabsProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,MAAM,OAAO,KAAK,SAAS,KAAK,EAC9B,UACA,UAAU,WACV,eAAe,OACf,uBACA,mBACA,YACA,qBACY;CACZ,MAAM,SAAS,eACN;EAAE;EAAS;EAAc;EAAuB,GACvD;EAAC;EAAS;EAAc;EAAsB,CAC/C;CACD,MAAM,YAAY,qBAAqB;EACrC;EACA;EACA;EACD,CAAC;CAEF,OACE,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;YACjC,oBAAC,oBAAoB,UAArB;GAA8B,OAAO;GAAY;GAAwC,CAAA;EAC9D,CAAA;EAE/B;AAEF,KAAK,cAAc"}
@@ -7,6 +7,8 @@ import { LayoutRectangle } from "react-native";
7
7
  interface TabsVisualContextValue {
8
8
  variant: UniversalTabsVariant;
9
9
  reduceMotion: boolean;
10
+ /** Tabs-level font-scaling cap; undefined = resolve from the control cap. */
11
+ maxFontSizeMultiplier?: number | null;
10
12
  }
11
13
  declare const TabsVisualContext: _$react.Context<TabsVisualContextValue>;
12
14
  declare function useTabsVisualContext(): TabsVisualContextValue;
@@ -1 +1 @@
1
- {"version":3,"file":"tabsContexts.d.cts","names":[],"sources":["../../../src/components/Tabs/tabsContexts.tsx"],"mappings":";;;;;;UAIiB,sBAAA;EACf,OAAA,EAAS,oBAAA;EACT,YAAA;AAAA;AAAA,cAGW,iBAAA,EAAiB,OAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,iBAKd,oBAAA,CAAA,GAAwB,sBAAA;AAAA,UAIvB,wBAAA;EACf,UAAA;EACA,aAAA,GAAgB,EAAA;EAChB,WAAA,GAAc,EAAA;EACd,aAAA,GAAgB,EAAA;EAChB,UAAA,EAAY,WAAA,SAAoB,eAAA;EAChC,YAAA,GAAe,EAAA,UAAY,MAAA,EAAQ,eAAA;EACnC,cAAA,GAAiB,EAAA;AAAA;AAAA,cAGN,mBAAA,EAAmB,OAAA,CAAA,OAAA,CAAA,wBAAA;AAAA,iBAEhB,sBAAA,CAAA,GAA0B,wBAAA;AAAA,iBAQ1B,oBAAA,CAAA;EACd,iBAAA;EACA,UAAA,EAAY,cAAA;EACZ;AAAA;EAEA,iBAAA;EACA,UAAA;EACA,iBAAA,IAAqB,UAAA;AAAA,IACnB,wBAAA"}
1
+ {"version":3,"file":"tabsContexts.d.cts","names":[],"sources":["../../../src/components/Tabs/tabsContexts.tsx"],"mappings":";;;;;;UAIiB,sBAAA;EACf,OAAA,EAAS,oBAAA;EACT,YAAA;EAFe;EAIf,qBAAA;AAAA;AAAA,cAGW,iBAAA,EAAiB,OAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,iBAKd,oBAAA,CAAA,GAAwB,sBAAA;AAAA,UAIvB,wBAAA;EACf,UAAA;EACA,aAAA,GAAgB,EAAA;EAChB,WAAA,GAAc,EAAA;EACd,aAAA,GAAgB,EAAA;EAChB,UAAA,EAAY,WAAA,SAAoB,eAAA;EAChC,YAAA,GAAe,EAAA,UAAY,MAAA,EAAQ,eAAA;EACnC,cAAA,GAAiB,EAAA;AAAA;AAAA,cAGN,mBAAA,EAAmB,OAAA,CAAA,OAAA,CAAA,wBAAA;AAAA,iBAEhB,sBAAA,CAAA,GAA0B,wBAAA;AAAA,iBAQ1B,oBAAA,CAAA;EACd,iBAAA;EACA,UAAA,EAAY,cAAA;EACZ;AAAA;EAEA,iBAAA;EACA,UAAA;EACA,iBAAA,IAAqB,UAAA;AAAA,IACnB,wBAAA"}
@@ -7,6 +7,8 @@ import { LayoutRectangle } from "react-native";
7
7
  interface TabsVisualContextValue {
8
8
  variant: UniversalTabsVariant;
9
9
  reduceMotion: boolean;
10
+ /** Tabs-level font-scaling cap; undefined = resolve from the control cap. */
11
+ maxFontSizeMultiplier?: number | null;
10
12
  }
11
13
  declare const TabsVisualContext: _$react.Context<TabsVisualContextValue>;
12
14
  declare function useTabsVisualContext(): TabsVisualContextValue;
@@ -1 +1 @@
1
- {"version":3,"file":"tabsContexts.d.ts","names":[],"sources":["../../../src/components/Tabs/tabsContexts.tsx"],"mappings":";;;;;;UAIiB,sBAAA;EACf,OAAA,EAAS,oBAAA;EACT,YAAA;AAAA;AAAA,cAGW,iBAAA,EAAiB,OAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,iBAKd,oBAAA,CAAA,GAAwB,sBAAA;AAAA,UAIvB,wBAAA;EACf,UAAA;EACA,aAAA,GAAgB,EAAA;EAChB,WAAA,GAAc,EAAA;EACd,aAAA,GAAgB,EAAA;EAChB,UAAA,EAAY,WAAA,SAAoB,eAAA;EAChC,YAAA,GAAe,EAAA,UAAY,MAAA,EAAQ,eAAA;EACnC,cAAA,GAAiB,EAAA;AAAA;AAAA,cAGN,mBAAA,EAAmB,OAAA,CAAA,OAAA,CAAA,wBAAA;AAAA,iBAEhB,sBAAA,CAAA,GAA0B,wBAAA;AAAA,iBAQ1B,oBAAA,CAAA;EACd,iBAAA;EACA,UAAA,EAAY,cAAA;EACZ;AAAA;EAEA,iBAAA;EACA,UAAA;EACA,iBAAA,IAAqB,UAAA;AAAA,IACnB,wBAAA"}
1
+ {"version":3,"file":"tabsContexts.d.ts","names":[],"sources":["../../../src/components/Tabs/tabsContexts.tsx"],"mappings":";;;;;;UAIiB,sBAAA;EACf,OAAA,EAAS,oBAAA;EACT,YAAA;EAFe;EAIf,qBAAA;AAAA;AAAA,cAGW,iBAAA,EAAiB,OAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,iBAKd,oBAAA,CAAA,GAAwB,sBAAA;AAAA,UAIvB,wBAAA;EACf,UAAA;EACA,aAAA,GAAgB,EAAA;EAChB,WAAA,GAAc,EAAA;EACd,aAAA,GAAgB,EAAA;EAChB,UAAA,EAAY,WAAA,SAAoB,eAAA;EAChC,YAAA,GAAe,EAAA,UAAY,MAAA,EAAQ,eAAA;EACnC,cAAA,GAAiB,EAAA;AAAA;AAAA,cAGN,mBAAA,EAAmB,OAAA,CAAA,OAAA,CAAA,wBAAA;AAAA,iBAEhB,sBAAA,CAAA,GAA0B,wBAAA;AAAA,iBAQ1B,oBAAA,CAAA;EACd,iBAAA;EACA,UAAA,EAAY,cAAA;EACZ;AAAA;EAEA,iBAAA;EACA,UAAA;EACA,iBAAA,IAAqB,UAAA;AAAA,IACnB,wBAAA"}