@yahoo/uds-mobile 2.24.0-beta.1 → 2.24.0-beta.11

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 (237) hide show
  1. package/README.md +37 -1
  2. package/dist/components/Avatar/AvatarIcon.cjs +8 -2
  3. package/dist/components/Avatar/AvatarIcon.d.cts.map +1 -1
  4. package/dist/components/Avatar/AvatarIcon.d.ts.map +1 -1
  5. package/dist/components/Avatar/AvatarIcon.js +9 -3
  6. package/dist/components/Avatar/AvatarIcon.js.map +1 -1
  7. package/dist/components/Avatar/AvatarImage.cjs +9 -2
  8. package/dist/components/Avatar/AvatarImage.d.cts.map +1 -1
  9. package/dist/components/Avatar/AvatarImage.d.ts.map +1 -1
  10. package/dist/components/Avatar/AvatarImage.js +10 -3
  11. package/dist/components/Avatar/AvatarImage.js.map +1 -1
  12. package/dist/components/Avatar/AvatarText.cjs +8 -2
  13. package/dist/components/Avatar/AvatarText.d.cts.map +1 -1
  14. package/dist/components/Avatar/AvatarText.d.ts.map +1 -1
  15. package/dist/components/Avatar/AvatarText.js +9 -3
  16. package/dist/components/Avatar/AvatarText.js.map +1 -1
  17. package/dist/components/Avatar/types.d.cts +7 -3
  18. package/dist/components/Avatar/types.d.cts.map +1 -1
  19. package/dist/components/Avatar/types.d.ts +7 -3
  20. package/dist/components/Avatar/types.d.ts.map +1 -1
  21. package/dist/components/Avatar/useAvatarFontScale.cjs +16 -0
  22. package/dist/components/Avatar/useAvatarFontScale.d.cts +7 -0
  23. package/dist/components/Avatar/useAvatarFontScale.d.cts.map +1 -0
  24. package/dist/components/Avatar/useAvatarFontScale.d.ts +7 -0
  25. package/dist/components/Avatar/useAvatarFontScale.d.ts.map +1 -0
  26. package/dist/components/Avatar/useAvatarFontScale.js +16 -0
  27. package/dist/components/Avatar/useAvatarFontScale.js.map +1 -0
  28. package/dist/components/Avatar/utils.cjs +9 -6
  29. package/dist/components/Avatar/utils.d.cts +2 -2
  30. package/dist/components/Avatar/utils.d.cts.map +1 -1
  31. package/dist/components/Avatar/utils.d.ts +2 -2
  32. package/dist/components/Avatar/utils.d.ts.map +1 -1
  33. package/dist/components/Avatar/utils.js +9 -6
  34. package/dist/components/Avatar/utils.js.map +1 -1
  35. package/dist/components/Button/buttonTheme.cjs +16 -7
  36. package/dist/components/Button/buttonTheme.d.cts +13 -6
  37. package/dist/components/Button/buttonTheme.d.cts.map +1 -1
  38. package/dist/components/Button/buttonTheme.d.ts +13 -6
  39. package/dist/components/Button/buttonTheme.d.ts.map +1 -1
  40. package/dist/components/Button/buttonTheme.js +16 -8
  41. package/dist/components/Button/buttonTheme.js.map +1 -1
  42. package/dist/components/Button.cjs +25 -11
  43. package/dist/components/Button.d.cts.map +1 -1
  44. package/dist/components/Button.d.ts.map +1 -1
  45. package/dist/components/Button.js +25 -11
  46. package/dist/components/Button.js.map +1 -1
  47. package/dist/components/Checkbox.cjs +16 -6
  48. package/dist/components/Checkbox.d.cts.map +1 -1
  49. package/dist/components/Checkbox.d.ts.map +1 -1
  50. package/dist/components/Checkbox.js +16 -6
  51. package/dist/components/Checkbox.js.map +1 -1
  52. package/dist/components/Chip/ChipBase.cjs +24 -21
  53. package/dist/components/Chip/ChipBase.js +24 -21
  54. package/dist/components/Chip/ChipBase.js.map +1 -1
  55. package/dist/components/Icon.cjs +22 -6
  56. package/dist/components/Icon.d.cts +6 -5
  57. package/dist/components/Icon.d.cts.map +1 -1
  58. package/dist/components/Icon.d.ts +6 -5
  59. package/dist/components/Icon.d.ts.map +1 -1
  60. package/dist/components/Icon.js +22 -6
  61. package/dist/components/Icon.js.map +1 -1
  62. package/dist/components/IconButton.cjs +17 -6
  63. package/dist/components/IconButton.d.cts +6 -0
  64. package/dist/components/IconButton.d.cts.map +1 -1
  65. package/dist/components/IconButton.d.ts +6 -0
  66. package/dist/components/IconButton.d.ts.map +1 -1
  67. package/dist/components/IconButton.js +18 -7
  68. package/dist/components/IconButton.js.map +1 -1
  69. package/dist/components/Input.cjs +56 -18
  70. package/dist/components/Input.d.cts +5 -0
  71. package/dist/components/Input.d.cts.map +1 -1
  72. package/dist/components/Input.d.ts +5 -0
  73. package/dist/components/Input.d.ts.map +1 -1
  74. package/dist/components/Input.js +56 -18
  75. package/dist/components/Input.js.map +1 -1
  76. package/dist/components/InputHelpText.cjs +7 -1
  77. package/dist/components/InputHelpText.d.cts +2 -0
  78. package/dist/components/InputHelpText.d.cts.map +1 -1
  79. package/dist/components/InputHelpText.d.ts +2 -0
  80. package/dist/components/InputHelpText.d.ts.map +1 -1
  81. package/dist/components/InputHelpText.js +7 -1
  82. package/dist/components/InputHelpText.js.map +1 -1
  83. package/dist/components/Link.cjs +16 -1
  84. package/dist/components/Link.d.cts +6 -0
  85. package/dist/components/Link.d.cts.map +1 -1
  86. package/dist/components/Link.d.ts +6 -0
  87. package/dist/components/Link.d.ts.map +1 -1
  88. package/dist/components/Link.js +16 -1
  89. package/dist/components/Link.js.map +1 -1
  90. package/dist/components/Pagination/Pagination.cjs +18 -10
  91. package/dist/components/Pagination/Pagination.d.cts +2 -0
  92. package/dist/components/Pagination/Pagination.d.cts.map +1 -1
  93. package/dist/components/Pagination/Pagination.d.ts +2 -0
  94. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  95. package/dist/components/Pagination/Pagination.js +18 -10
  96. package/dist/components/Pagination/Pagination.js.map +1 -1
  97. package/dist/components/Pagination/PaginationEllipsis.cjs +8 -2
  98. package/dist/components/Pagination/PaginationEllipsis.d.cts.map +1 -1
  99. package/dist/components/Pagination/PaginationEllipsis.d.ts.map +1 -1
  100. package/dist/components/Pagination/PaginationEllipsis.js +9 -3
  101. package/dist/components/Pagination/PaginationEllipsis.js.map +1 -1
  102. package/dist/components/Pagination/PaginationItem.cjs +2 -1
  103. package/dist/components/Pagination/PaginationItem.js +2 -1
  104. package/dist/components/Pagination/PaginationItem.js.map +1 -1
  105. package/dist/components/Pagination/PaginationLink.cjs +2 -1
  106. package/dist/components/Pagination/PaginationLink.js +2 -1
  107. package/dist/components/Pagination/PaginationLink.js.map +1 -1
  108. package/dist/components/Pagination/PaginationNext.cjs +3 -1
  109. package/dist/components/Pagination/PaginationNext.js +3 -1
  110. package/dist/components/Pagination/PaginationNext.js.map +1 -1
  111. package/dist/components/Pagination/PaginationPrev.cjs +3 -1
  112. package/dist/components/Pagination/PaginationPrev.js +3 -1
  113. package/dist/components/Pagination/PaginationPrev.js.map +1 -1
  114. package/dist/components/Pagination/paginationContext.d.cts +2 -0
  115. package/dist/components/Pagination/paginationContext.d.cts.map +1 -1
  116. package/dist/components/Pagination/paginationContext.d.ts +2 -0
  117. package/dist/components/Pagination/paginationContext.d.ts.map +1 -1
  118. package/dist/components/Pagination/paginationContext.js.map +1 -1
  119. package/dist/components/Pagination/usePaginationControlStyles.cjs +8 -1
  120. package/dist/components/Pagination/usePaginationControlStyles.d.cts.map +1 -1
  121. package/dist/components/Pagination/usePaginationControlStyles.d.ts.map +1 -1
  122. package/dist/components/Pagination/usePaginationControlStyles.js +9 -2
  123. package/dist/components/Pagination/usePaginationControlStyles.js.map +1 -1
  124. package/dist/components/Radio/Radio.cjs +4 -3
  125. package/dist/components/Radio/Radio.js +4 -3
  126. package/dist/components/Radio/Radio.js.map +1 -1
  127. package/dist/components/Select/Select.cjs +29 -6
  128. package/dist/components/Select/Select.d.cts +2 -0
  129. package/dist/components/Select/Select.d.cts.map +1 -1
  130. package/dist/components/Select/Select.d.ts +2 -0
  131. package/dist/components/Select/Select.d.ts.map +1 -1
  132. package/dist/components/Select/Select.js +29 -6
  133. package/dist/components/Select/Select.js.map +1 -1
  134. package/dist/components/Select/SelectContent.cjs +31 -23
  135. package/dist/components/Select/SelectContent.d.cts.map +1 -1
  136. package/dist/components/Select/SelectContent.d.ts.map +1 -1
  137. package/dist/components/Select/SelectContent.js +32 -24
  138. package/dist/components/Select/SelectContent.js.map +1 -1
  139. package/dist/components/Select/SelectItem.cjs +25 -15
  140. package/dist/components/Select/SelectItem.d.cts.map +1 -1
  141. package/dist/components/Select/SelectItem.d.ts.map +1 -1
  142. package/dist/components/Select/SelectItem.js +25 -15
  143. package/dist/components/Select/SelectItem.js.map +1 -1
  144. package/dist/components/Select/SelectTrigger.cjs +27 -13
  145. package/dist/components/Select/SelectTrigger.d.cts.map +1 -1
  146. package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
  147. package/dist/components/Select/SelectTrigger.js +27 -13
  148. package/dist/components/Select/SelectTrigger.js.map +1 -1
  149. package/dist/components/Select/types.d.cts +2 -0
  150. package/dist/components/Select/types.d.cts.map +1 -1
  151. package/dist/components/Select/types.d.ts +2 -0
  152. package/dist/components/Select/types.d.ts.map +1 -1
  153. package/dist/components/Switch.cjs +31 -14
  154. package/dist/components/Switch.d.cts.map +1 -1
  155. package/dist/components/Switch.d.ts.map +1 -1
  156. package/dist/components/Switch.js +31 -14
  157. package/dist/components/Switch.js.map +1 -1
  158. package/dist/components/Tabs/Tab.cjs +8 -4
  159. package/dist/components/Tabs/Tab.d.cts.map +1 -1
  160. package/dist/components/Tabs/Tab.d.ts.map +1 -1
  161. package/dist/components/Tabs/Tab.js +8 -4
  162. package/dist/components/Tabs/Tab.js.map +1 -1
  163. package/dist/components/Text.cjs +5 -0
  164. package/dist/components/Text.d.cts +6 -5
  165. package/dist/components/Text.d.cts.map +1 -1
  166. package/dist/components/Text.d.ts +6 -5
  167. package/dist/components/Text.d.ts.map +1 -1
  168. package/dist/components/Text.js +5 -0
  169. package/dist/components/Text.js.map +1 -1
  170. package/dist/components/UDSProvider.cjs +1 -1
  171. package/dist/components/UDSProvider.d.cts +4 -3
  172. package/dist/components/UDSProvider.d.cts.map +1 -1
  173. package/dist/components/UDSProvider.d.ts +4 -3
  174. package/dist/components/UDSProvider.d.ts.map +1 -1
  175. package/dist/components/UDSProvider.js +1 -1
  176. package/dist/components/UDSProvider.js.map +1 -1
  177. package/dist/fontScaling/FontScalingContext.cjs +35 -3
  178. package/dist/fontScaling/FontScalingContext.d.cts +20 -5
  179. package/dist/fontScaling/FontScalingContext.d.cts.map +1 -1
  180. package/dist/fontScaling/FontScalingContext.d.ts +20 -5
  181. package/dist/fontScaling/FontScalingContext.d.ts.map +1 -1
  182. package/dist/fontScaling/FontScalingContext.js +34 -5
  183. package/dist/fontScaling/FontScalingContext.js.map +1 -1
  184. package/dist/fontScaling/androidNonlinearFontScaling.cjs +250 -0
  185. package/dist/fontScaling/androidNonlinearFontScaling.d.cts +7 -0
  186. package/dist/fontScaling/androidNonlinearFontScaling.d.cts.map +1 -0
  187. package/dist/fontScaling/androidNonlinearFontScaling.d.ts +7 -0
  188. package/dist/fontScaling/androidNonlinearFontScaling.d.ts.map +1 -0
  189. package/dist/fontScaling/androidNonlinearFontScaling.js +251 -0
  190. package/dist/fontScaling/androidNonlinearFontScaling.js.map +1 -0
  191. package/dist/fontScaling/constants.cjs +37 -3
  192. package/dist/fontScaling/constants.d.cts +15 -4
  193. package/dist/fontScaling/constants.d.cts.map +1 -1
  194. package/dist/fontScaling/constants.d.ts +15 -4
  195. package/dist/fontScaling/constants.d.ts.map +1 -1
  196. package/dist/fontScaling/constants.js +37 -4
  197. package/dist/fontScaling/constants.js.map +1 -1
  198. package/dist/fontScaling/index.cjs +2 -1
  199. package/dist/fontScaling/index.d.cts +2 -2
  200. package/dist/fontScaling/index.d.ts +2 -2
  201. package/dist/fontScaling/index.js +3 -3
  202. package/dist/fontScaling/resolveMaxFontSizeMultiplier.cjs +1 -2
  203. package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.cts +1 -2
  204. package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.cts.map +1 -1
  205. package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.ts +1 -2
  206. package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.ts.map +1 -1
  207. package/dist/fontScaling/resolveMaxFontSizeMultiplier.js +1 -2
  208. package/dist/fontScaling/resolveMaxFontSizeMultiplier.js.map +1 -1
  209. package/dist/fontScaling/types.d.cts +11 -8
  210. package/dist/fontScaling/types.d.cts.map +1 -1
  211. package/dist/fontScaling/types.d.ts +11 -8
  212. package/dist/fontScaling/types.d.ts.map +1 -1
  213. package/dist/fontScaling/useFontScale.cjs +30 -4
  214. package/dist/fontScaling/useFontScale.d.cts +6 -12
  215. package/dist/fontScaling/useFontScale.d.cts.map +1 -1
  216. package/dist/fontScaling/useFontScale.d.ts +6 -12
  217. package/dist/fontScaling/useFontScale.d.ts.map +1 -1
  218. package/dist/fontScaling/useFontScale.js +31 -6
  219. package/dist/fontScaling/useFontScale.js.map +1 -1
  220. package/dist/jest/mocks/styles.cjs +14 -1
  221. package/dist/jest/mocks/styles.d.cts.map +1 -1
  222. package/dist/jest/mocks/styles.d.ts.map +1 -1
  223. package/dist/jest/mocks/styles.js +14 -1
  224. package/dist/jest/mocks/styles.js.map +1 -1
  225. package/dist/mobile/generated/fontMetrics.cjs +534 -534
  226. package/dist/mobile/generated/fontMetrics.js +534 -534
  227. package/dist/mobile/generated/fontMetrics.js.map +1 -1
  228. package/dist/portal.cjs +8 -2
  229. package/dist/portal.d.cts.map +1 -1
  230. package/dist/portal.d.ts.map +1 -1
  231. package/dist/portal.js +8 -2
  232. package/dist/portal.js.map +1 -1
  233. package/fonts/index.cjs +214 -214
  234. package/fonts/index.mjs +214 -214
  235. package/fonts/uds-icons.ttf +0 -0
  236. package/generated/fontMetrics.ts +534 -534
  237. package/package.json +2 -2
@@ -1,5 +1,7 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
2
  import { HStack } from "./HStack.js";
3
+ import { useComponentFontScale } from "../fontScaling/useFontScale.js";
4
+ import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
3
5
  import { IconSlot } from "./IconSlot.js";
4
6
  import { Text as Text$1 } from "./Text.js";
5
7
  import { InputHelpText } from "./InputHelpText.js";
@@ -45,8 +47,9 @@ import { isFunction } from "lodash-es";
45
47
  * @see {@link Checkbox} for boolean selections
46
48
  * @see {@link Radio} for single-select options
47
49
  */
48
- const Input = memo(function Input({ label, size = "md", startIcon, endIcon, helpText, helperTextIcon, hasError, disabled, readOnly, required, width = "100%", defaultValue, value: controlledValue, onChangeText, onFocus, onBlur, placeholder, placeholderTextColor, ref, ...textInputProps }) {
50
+ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, helpText, helperTextIcon, hasError, disabled, readOnly, required, width = "100%", defaultValue, value: controlledValue, onChangeText, onFocus, onBlur, placeholder, placeholderTextColor, maxFontSizeMultiplier, ref, ...textInputProps }) {
49
51
  const uid = `uds-input-${useId()}`;
52
+ const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
50
53
  const [internalValue, setInternalValue] = useState(defaultValue ?? "");
51
54
  const [isFocused, setIsFocused] = useState(false);
52
55
  const isControlled = controlledValue !== void 0;
@@ -71,30 +74,47 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
71
74
  readonly: readOnly,
72
75
  invalid: hasError
73
76
  });
77
+ const fontScaleFactor = useComponentFontScale(resolvedMaxFontSizeMultiplier, (typeof inputStyles.inputWrapperStatic.lineHeight === "number" ? inputStyles.inputWrapperStatic.lineHeight : void 0) ?? (typeof inputStyles.inputWrapperStatic.fontSize === "number" ? inputStyles.inputWrapperStatic.fontSize : void 0));
74
78
  const computedPlaceholderColor = placeholderTextColor ?? inputStyles.inputPlaceholder.color;
75
79
  const rootStyle = useMemo(() => [{
76
80
  width,
77
81
  opacity: disabled ? .5 : 1
78
82
  }], [width, disabled]);
79
- const inputWrapperStyle = useMemo(() => [
80
- inputStyles.inputWrapper,
81
- inputStyles.inputWrapperStatic,
82
- inputStyles.inputWrapperDynamic,
83
- {
84
- flexDirection: "row",
85
- alignItems: "center"
86
- }
87
- ], [
83
+ const inputWrapperStyle = useMemo(() => {
84
+ const { gap, paddingVertical } = inputStyles.inputWrapperStatic;
85
+ const scaledMetrics = fontScaleFactor === 1 ? void 0 : {
86
+ ...typeof gap === "number" && { gap: Math.round(gap * fontScaleFactor) },
87
+ ...typeof paddingVertical === "number" && { paddingVertical: Math.round(paddingVertical * fontScaleFactor) }
88
+ };
89
+ return [
90
+ inputStyles.inputWrapper,
91
+ inputStyles.inputWrapperStatic,
92
+ inputStyles.inputWrapperDynamic,
93
+ scaledMetrics,
94
+ {
95
+ flexDirection: "row",
96
+ alignItems: "center"
97
+ }
98
+ ];
99
+ }, [
100
+ fontScaleFactor,
88
101
  inputStyles.inputWrapper,
89
102
  inputStyles.inputWrapperStatic,
90
103
  inputStyles.inputWrapperDynamic
91
104
  ]);
92
- const textInputStyle = useMemo(() => [inputStyles.input, {
93
- flex: 1,
94
- includeFontPadding: false,
95
- textAlignVertical: "center",
96
- paddingVertical: 0
97
- }], [inputStyles.input]);
105
+ const textInputStyle = useMemo(() => {
106
+ const inputHeight = inputStyles.input.height;
107
+ return [
108
+ inputStyles.input,
109
+ typeof inputHeight === "number" ? { height: Math.round(inputHeight * fontScaleFactor) } : void 0,
110
+ {
111
+ flex: 1,
112
+ includeFontPadding: false,
113
+ textAlignVertical: "center",
114
+ paddingVertical: 0
115
+ }
116
+ ];
117
+ }, [fontScaleFactor, inputStyles.input]);
98
118
  const labelContent = useMemo(() => {
99
119
  if (!label) return null;
100
120
  const content = isFunction(label) ? label() : label;
@@ -103,9 +123,13 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
103
123
  alignItems: "flex-end",
104
124
  spacingBottom: "2",
105
125
  children: [/* @__PURE__ */ jsx(Text$1, {
126
+ variant: "inherit",
127
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
106
128
  style: inputStyles.label,
107
129
  children: content
108
130
  }), required && /* @__PURE__ */ jsx(Text$1, {
131
+ variant: "inherit",
132
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
109
133
  style: inputStyles.labelRequired,
110
134
  children: "*"
111
135
  })]
@@ -113,6 +137,7 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
113
137
  }, [
114
138
  label,
115
139
  required,
140
+ resolvedMaxFontSizeMultiplier,
116
141
  inputStyles.label,
117
142
  inputStyles.labelRequired
118
143
  ]);
@@ -121,17 +146,27 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
121
146
  return /* @__PURE__ */ jsx(IconSlot, {
122
147
  icon: startIcon,
123
148
  variant: "outline",
149
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
124
150
  style: inputStyles.startIcon
125
151
  });
126
- }, [startIcon, inputStyles.startIcon]);
152
+ }, [
153
+ startIcon,
154
+ resolvedMaxFontSizeMultiplier,
155
+ inputStyles.startIcon
156
+ ]);
127
157
  const endIconContent = useMemo(() => {
128
158
  if (!endIcon) return null;
129
159
  return /* @__PURE__ */ jsx(IconSlot, {
130
160
  icon: endIcon,
131
161
  variant: "outline",
162
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
132
163
  style: inputStyles.endIcon
133
164
  });
134
- }, [endIcon, inputStyles.endIcon]);
165
+ }, [
166
+ endIcon,
167
+ resolvedMaxFontSizeMultiplier,
168
+ inputStyles.endIcon
169
+ ]);
135
170
  const helpTextContent = useMemo(() => {
136
171
  if (!helpText) return null;
137
172
  const content = isFunction(helpText) ? helpText() : helpText;
@@ -143,6 +178,7 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
143
178
  readOnly,
144
179
  hasError,
145
180
  pressed: isFocused,
181
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
146
182
  children: content
147
183
  });
148
184
  }, [
@@ -152,6 +188,7 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
152
188
  helperTextIcon,
153
189
  isFocused,
154
190
  readOnly,
191
+ resolvedMaxFontSizeMultiplier,
155
192
  size,
156
193
  valueState
157
194
  ]);
@@ -176,6 +213,7 @@ const Input = memo(function Input({ label, size = "md", startIcon, endIcon, help
176
213
  placeholder,
177
214
  placeholderTextColor: computedPlaceholderColor,
178
215
  editable: !disabled && !readOnly,
216
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
179
217
  style: textInputStyle,
180
218
  accessibilityLabel: typeof label === "string" ? label : void 0,
181
219
  accessibilityHint: typeof helpText === "string" ? helpText : void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","names":["Text"],"sources":["../../src/components/Input.tsx"],"sourcesContent":["import type { UniversalInputProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useId, useMemo, useState } from 'react';\nimport type { TextInputProps } from 'react-native';\nimport { TextInput, View } from 'react-native';\n\nimport { inputStyles } from '../../generated/styles';\nimport type { SizeProps } from '../types';\nimport { HStack } from './HStack';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport { InputHelpText } from './InputHelpText';\nimport { Text } from './Text';\nimport { VStack } from './VStack';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\ninterface InputProps\n extends\n Omit<UniversalInputProps<IconSlotType>, 'width'>,\n Omit<TextInputProps, 'style' | 'editable'>,\n Pick<SizeProps, 'width'> {\n /** Ref to the underlying TextInput element */\n ref?: Ref<TextInput>;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Input Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **📦 An input that allows users to enter text and collect data.**\n *\n * @description\n * An input field is a component that takes text typed into it. It can also serve\n * as a way to display a selection and trigger a dropdown menu. Inputs are interactive\n * elements that users can click, tap, or otherwise engage with to collect data.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Input } from '@yahoo/uds-mobile/Input';\n *\n * <Input label=\"Name\" placeholder=\"Enter your name\" required />\n * <Input label=\"Email\" startIcon=\"Mail\" helpText=\"We'll never share your email\" />\n * <Input label=\"Password\" secureTextEntry hasError helpText=\"Password is required\" />\n * ```\n *\n * @usage\n * - Forms: For collecting data like names, emails, passwords, etc.\n * - Search Bars: Allowing users to enter search queries\n * - Filters/Settings: When users need to specify preferences\n * - Feedback/Comments: Letting users leave reviews or comments\n *\n * @accessibility\n * - Label is automatically associated with the input\n * - Help text is announced as accessibility hint\n * - Error state is communicated to screen readers\n * - Disabled state prevents interaction\n *\n * @see {@link Checkbox} for boolean selections\n * @see {@link Radio} for single-select options\n */\nconst Input = memo(function Input({\n // Input props\n label,\n size = 'md',\n startIcon,\n endIcon,\n helpText,\n helperTextIcon,\n hasError,\n disabled,\n readOnly,\n required,\n // Size props\n width = '100%',\n // TextInput props\n defaultValue,\n value: controlledValue,\n onChangeText,\n onFocus,\n onBlur,\n placeholder,\n placeholderTextColor,\n ref,\n ...textInputProps\n}: InputProps) {\n const generatedId = useId();\n const uid = `uds-input-${generatedId}`;\n\n /* --------------------------------- State ---------------------------------- */\n const [internalValue, setInternalValue] = useState(defaultValue ?? '');\n const [isFocused, setIsFocused] = useState(false);\n\n // Support both controlled and uncontrolled modes\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n const valueState = value ? 'filled' : 'empty';\n\n /* -------------------------------- Handlers -------------------------------- */\n const handleChangeText = useCallback(\n (text: string) => {\n if (!isControlled) {\n setInternalValue(text);\n }\n onChangeText?.(text);\n },\n [isControlled, onChangeText],\n );\n\n const handleFocus = useCallback<NonNullable<TextInputProps['onFocus']>>(\n (e) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n\n const handleBlur = useCallback<NonNullable<TextInputProps['onBlur']>>(\n (e) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n\n /* --------------------------------- Styles --------------------------------- */\n inputStyles.useVariants({\n size,\n value: valueState,\n pressed: isFocused,\n readonly: readOnly,\n invalid: hasError,\n });\n\n // Get placeholder color from theme styles\n const computedPlaceholderColor = placeholderTextColor ?? inputStyles.inputPlaceholder.color;\n\n const rootStyle = useMemo(() => [{ width, opacity: disabled ? 0.5 : 1 }], [width, disabled]);\n\n // `inputWrapper` carries only background/border colors; the size-axis spacing\n // (`inputWrapperStatic`) and border width/radius (`inputWrapperDynamic`) live\n // on their own layers after the wrapper split. All three must be applied to\n // the wrapper View — matching the web component, which drives the static and\n // dynamic layers via separate variants — or the input loses its padding, gap,\n // and border sizing.\n const inputWrapperStyle = useMemo(\n () => [\n inputStyles.inputWrapper,\n inputStyles.inputWrapperStatic,\n inputStyles.inputWrapperDynamic,\n { flexDirection: 'row' as const, alignItems: 'center' as const },\n ],\n [inputStyles.inputWrapper, inputStyles.inputWrapperStatic, inputStyles.inputWrapperDynamic],\n );\n\n // Android-specific fixes: TextInput on Android has rendering issues with text visibility\n // - includeFontPadding: false removes Android's extra font padding that can clip text\n // - textAlignVertical: 'center' ensures text is vertically centered in the input\n // - paddingVertical: 0 removes default padding that interferes with flex layout\n const textInputStyle = useMemo(\n () => [\n inputStyles.input,\n {\n flex: 1,\n includeFontPadding: false,\n textAlignVertical: 'center' as const,\n paddingVertical: 0,\n },\n ],\n [inputStyles.input],\n );\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n const content = isFunction(label) ? label() : label;\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-end\" spacingBottom=\"2\">\n <Text style={inputStyles.label}>{content}</Text>\n {required && <Text style={inputStyles.labelRequired}>*</Text>}\n </HStack>\n );\n }, [label, required, inputStyles.label, inputStyles.labelRequired]);\n\n const startIconContent = useMemo(() => {\n if (!startIcon) {\n return null;\n }\n return <IconSlot icon={startIcon} variant=\"outline\" style={inputStyles.startIcon} />;\n }, [startIcon, inputStyles.startIcon]);\n\n const endIconContent = useMemo(() => {\n if (!endIcon) {\n return null;\n }\n return <IconSlot icon={endIcon} variant=\"outline\" style={inputStyles.endIcon} />;\n }, [endIcon, inputStyles.endIcon]);\n\n const helpTextContent = useMemo(() => {\n if (!helpText) {\n return null;\n }\n const content = isFunction(helpText) ? helpText() : helpText;\n return (\n <InputHelpText\n startIcon={helperTextIcon}\n size={size}\n isFilled={valueState === 'filled'}\n disabled={disabled}\n readOnly={readOnly}\n hasError={hasError}\n pressed={isFocused}\n >\n {content}\n </InputHelpText>\n );\n }, [disabled, hasError, helpText, helperTextIcon, isFocused, readOnly, size, valueState]);\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <VStack style={rootStyle}>\n {labelContent}\n\n <View\n style={inputWrapperStyle}\n accessible\n accessibilityRole=\"none\"\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n >\n {startIconContent}\n\n <TextInput\n ref={ref}\n nativeID={uid}\n value={value}\n onChangeText={handleChangeText}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={placeholder}\n placeholderTextColor={computedPlaceholderColor}\n editable={!disabled && !readOnly}\n style={textInputStyle}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n accessibilityHint={typeof helpText === 'string' ? helpText : undefined}\n accessibilityState={{ disabled }}\n {...textInputProps}\n />\n\n {endIconContent}\n </View>\n\n {helpTextContent}\n </VStack>\n );\n});\n\nInput.displayName = 'Input';\n\nexport { Input, type InputProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"Input.js","names":["Text"],"sources":["../../src/components/Input.tsx"],"sourcesContent":["import type { UniversalInputProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useId, useMemo, useState } from 'react';\nimport type { TextInputProps } from 'react-native';\nimport { TextInput, View } from 'react-native';\n\nimport { inputStyles } from '../../generated/styles';\nimport { useComponentFontScale } from '../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\nimport type { SizeProps } from '../types';\nimport { HStack } from './HStack';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport { InputHelpText } from './InputHelpText';\nimport { Text } from './Text';\nimport { VStack } from './VStack';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\ninterface InputProps\n extends\n Omit<UniversalInputProps<IconSlotType>, 'width'>,\n Omit<TextInputProps, 'style' | 'editable'>,\n Pick<SizeProps, 'width'> {\n /** Ref to the underlying TextInput element */\n ref?: Ref<TextInput>;\n /**\n * Caps the field text, labels, icons, and geometry at the control scale.\n * Set null to remove the cap. @default 2\n */\n maxFontSizeMultiplier?: number | null;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Input Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **📦 An input that allows users to enter text and collect data.**\n *\n * @description\n * An input field is a component that takes text typed into it. It can also serve\n * as a way to display a selection and trigger a dropdown menu. Inputs are interactive\n * elements that users can click, tap, or otherwise engage with to collect data.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Input } from '@yahoo/uds-mobile/Input';\n *\n * <Input label=\"Name\" placeholder=\"Enter your name\" required />\n * <Input label=\"Email\" startIcon=\"Mail\" helpText=\"We'll never share your email\" />\n * <Input label=\"Password\" secureTextEntry hasError helpText=\"Password is required\" />\n * ```\n *\n * @usage\n * - Forms: For collecting data like names, emails, passwords, etc.\n * - Search Bars: Allowing users to enter search queries\n * - Filters/Settings: When users need to specify preferences\n * - Feedback/Comments: Letting users leave reviews or comments\n *\n * @accessibility\n * - Label is automatically associated with the input\n * - Help text is announced as accessibility hint\n * - Error state is communicated to screen readers\n * - Disabled state prevents interaction\n *\n * @see {@link Checkbox} for boolean selections\n * @see {@link Radio} for single-select options\n */\nconst Input = memo(function Input({\n // Input props\n label,\n size = 'md',\n startIcon,\n endIcon,\n helpText,\n helperTextIcon,\n hasError,\n disabled,\n readOnly,\n required,\n // Size props\n width = '100%',\n // TextInput props\n defaultValue,\n value: controlledValue,\n onChangeText,\n onFocus,\n onBlur,\n placeholder,\n placeholderTextColor,\n maxFontSizeMultiplier,\n ref,\n ...textInputProps\n}: InputProps) {\n const generatedId = useId();\n const uid = `uds-input-${generatedId}`;\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier('control', maxFontSizeMultiplier);\n\n /* --------------------------------- State ---------------------------------- */\n const [internalValue, setInternalValue] = useState(defaultValue ?? '');\n const [isFocused, setIsFocused] = useState(false);\n\n // Support both controlled and uncontrolled modes\n const isControlled = controlledValue !== undefined;\n const value = isControlled ? controlledValue : internalValue;\n const valueState = value ? 'filled' : 'empty';\n\n /* -------------------------------- Handlers -------------------------------- */\n const handleChangeText = useCallback(\n (text: string) => {\n if (!isControlled) {\n setInternalValue(text);\n }\n onChangeText?.(text);\n },\n [isControlled, onChangeText],\n );\n\n const handleFocus = useCallback<NonNullable<TextInputProps['onFocus']>>(\n (e) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n\n const handleBlur = useCallback<NonNullable<TextInputProps['onBlur']>>(\n (e) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n\n /* --------------------------------- Styles --------------------------------- */\n inputStyles.useVariants({\n size,\n value: valueState,\n pressed: isFocused,\n readonly: readOnly,\n invalid: hasError,\n });\n const fontScaleFactor = useComponentFontScale(\n resolvedMaxFontSizeMultiplier,\n (typeof inputStyles.inputWrapperStatic.lineHeight === 'number'\n ? inputStyles.inputWrapperStatic.lineHeight\n : undefined) ??\n (typeof inputStyles.inputWrapperStatic.fontSize === 'number'\n ? inputStyles.inputWrapperStatic.fontSize\n : undefined),\n );\n\n // Get placeholder color from theme styles\n const computedPlaceholderColor = placeholderTextColor ?? inputStyles.inputPlaceholder.color;\n\n const rootStyle = useMemo(() => [{ width, opacity: disabled ? 0.5 : 1 }], [width, disabled]);\n\n // `inputWrapper` carries only background/border colors; the size-axis spacing\n // (`inputWrapperStatic`) and border width/radius (`inputWrapperDynamic`) live\n // on their own layers after the wrapper split. All three must be applied to\n // the wrapper View — matching the web component, which drives the static and\n // dynamic layers via separate variants — or the input loses its padding, gap,\n // and border sizing.\n const inputWrapperStyle = useMemo(() => {\n const { gap, paddingVertical } = inputStyles.inputWrapperStatic;\n const scaledMetrics =\n fontScaleFactor === 1\n ? undefined\n : {\n ...(typeof gap === 'number' && { gap: Math.round(gap * fontScaleFactor) }),\n ...(typeof paddingVertical === 'number' && {\n paddingVertical: Math.round(paddingVertical * fontScaleFactor),\n }),\n };\n\n return [\n inputStyles.inputWrapper,\n inputStyles.inputWrapperStatic,\n inputStyles.inputWrapperDynamic,\n scaledMetrics,\n { flexDirection: 'row' as const, alignItems: 'center' as const },\n ];\n }, [\n fontScaleFactor,\n inputStyles.inputWrapper,\n inputStyles.inputWrapperStatic,\n inputStyles.inputWrapperDynamic,\n ]);\n\n // Android-specific fixes: TextInput on Android has rendering issues with text visibility\n // - includeFontPadding: false removes Android's extra font padding that can clip text\n // - textAlignVertical: 'center' ensures text is vertically centered in the input\n // - paddingVertical: 0 removes default padding that interferes with flex layout\n const textInputStyle = useMemo(() => {\n const inputHeight = inputStyles.input.height;\n return [\n inputStyles.input,\n typeof inputHeight === 'number'\n ? { height: Math.round(inputHeight * fontScaleFactor) }\n : undefined,\n {\n flex: 1,\n includeFontPadding: false,\n textAlignVertical: 'center' as const,\n paddingVertical: 0,\n },\n ];\n }, [fontScaleFactor, inputStyles.input]);\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n const content = isFunction(label) ? label() : label;\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-end\" spacingBottom=\"2\">\n <Text\n variant=\"inherit\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.label}\n >\n {content}\n </Text>\n {required && (\n <Text\n variant=\"inherit\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.labelRequired}\n >\n *\n </Text>\n )}\n </HStack>\n );\n }, [\n label,\n required,\n resolvedMaxFontSizeMultiplier,\n inputStyles.label,\n inputStyles.labelRequired,\n ]);\n\n const startIconContent = useMemo(() => {\n if (!startIcon) {\n return null;\n }\n return (\n <IconSlot\n icon={startIcon}\n variant=\"outline\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.startIcon}\n />\n );\n }, [startIcon, resolvedMaxFontSizeMultiplier, inputStyles.startIcon]);\n\n const endIconContent = useMemo(() => {\n if (!endIcon) {\n return null;\n }\n return (\n <IconSlot\n icon={endIcon}\n variant=\"outline\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.endIcon}\n />\n );\n }, [endIcon, resolvedMaxFontSizeMultiplier, inputStyles.endIcon]);\n\n const helpTextContent = useMemo(() => {\n if (!helpText) {\n return null;\n }\n const content = isFunction(helpText) ? helpText() : helpText;\n return (\n <InputHelpText\n startIcon={helperTextIcon}\n size={size}\n isFilled={valueState === 'filled'}\n disabled={disabled}\n readOnly={readOnly}\n hasError={hasError}\n pressed={isFocused}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n >\n {content}\n </InputHelpText>\n );\n }, [\n disabled,\n hasError,\n helpText,\n helperTextIcon,\n isFocused,\n readOnly,\n resolvedMaxFontSizeMultiplier,\n size,\n valueState,\n ]);\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <VStack style={rootStyle}>\n {labelContent}\n\n <View\n style={inputWrapperStyle}\n accessible\n accessibilityRole=\"none\"\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n >\n {startIconContent}\n\n <TextInput\n ref={ref}\n nativeID={uid}\n value={value}\n onChangeText={handleChangeText}\n onFocus={handleFocus}\n onBlur={handleBlur}\n placeholder={placeholder}\n placeholderTextColor={computedPlaceholderColor}\n editable={!disabled && !readOnly}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={textInputStyle}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n accessibilityHint={typeof helpText === 'string' ? helpText : undefined}\n accessibilityState={{ disabled }}\n {...textInputProps}\n />\n\n {endIconContent}\n </View>\n\n {helpTextContent}\n </VStack>\n );\n});\n\nInput.displayName = 'Input';\n\nexport { Input, type InputProps };\n"],"mappings":"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"}
@@ -2,15 +2,17 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  require("../_virtual/_rolldown/runtime.cjs");
4
4
  const require_components_HStack = require("./HStack.cjs");
5
+ const require_fontScaling_useMaxFontSizeMultiplier = require("../fontScaling/useMaxFontSizeMultiplier.cjs");
5
6
  const require_components_IconSlot = require("./IconSlot.cjs");
6
7
  const require_components_Text = require("./Text.cjs");
7
8
  let react = require("react");
8
9
  let react_jsx_runtime = require("react/jsx-runtime");
9
10
  let generated_styles = require("../../generated/styles");
10
11
  //#region src/components/InputHelpText.tsx
11
- const InputHelpText = (0, react.memo)(function InputHelpText({ children, startIcon, endIcon, iconProps, size = "md", isFilled = false, disabled: _disabled, readOnly, hasError, pressed, ref, ...hStackProps }) {
12
+ const InputHelpText = (0, react.memo)(function InputHelpText({ children, startIcon, endIcon, iconProps, size = "md", isFilled = false, disabled: _disabled, readOnly, hasError, pressed, maxFontSizeMultiplier, ref, ...hStackProps }) {
12
13
  const { style: iconStyle, variant = "outline", ...resolvedIconProps } = iconProps ?? {};
13
14
  const value = isFilled ? "filled" : "empty";
15
+ const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
14
16
  generated_styles.inputStyles.useVariants({
15
17
  size,
16
18
  value,
@@ -30,16 +32,20 @@ const InputHelpText = (0, react.memo)(function InputHelpText({ children, startIc
30
32
  startIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_IconSlot.IconSlot, {
31
33
  icon: startIcon,
32
34
  variant,
35
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
33
36
  style: resolvedIconStyle,
34
37
  ...resolvedIconProps
35
38
  }),
36
39
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
40
+ variant: "inherit",
41
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
37
42
  style: generated_styles.inputStyles.helperText,
38
43
  children
39
44
  }),
40
45
  endIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_IconSlot.IconSlot, {
41
46
  icon: endIcon,
42
47
  variant,
48
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
43
49
  style: resolvedIconStyle,
44
50
  ...resolvedIconProps
45
51
  })
@@ -30,6 +30,8 @@ interface InputHelpTextProps extends Omit<HStackProps, 'children' | 'ref'> {
30
30
  hasError?: boolean;
31
31
  /** Whether the associated input is focused or pressed. */
32
32
  pressed?: boolean;
33
+ /** Caps helper text and icons at the control scale. Set null to remove the cap. @default 2 */
34
+ maxFontSizeMultiplier?: number | null;
33
35
  }
34
36
  declare const InputHelpText: _$react.NamedExoticComponent<InputHelpTextProps>;
35
37
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"InputHelpText.d.cts","names":[],"sources":["../../src/components/InputHelpText.tsx"],"mappings":";;;;;;;;;UAaU,kBAAA,SAA2B,IAAA,CAAK,WAAA;;EAExC,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,GAAW,SAAA;;EAEX,SAAA,GAAY,YAAA;EAJF;EAMV,OAAA,GAAU,YAAA;EAJC;EAMX,SAAA,GAAY,IAAA,CAAK,aAAA;EAFP;EAIV,IAAA,GAAO,SAAA;EAFK;EAIZ,QAAA;EAdmC;EAgBnC,QAAA;EAhBuC;EAkBvC,QAAA;EAlBwC;EAoBxC,QAAA;EAlBM;EAoBN,OAAA;AAAA;AAAA,cAGI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
1
+ {"version":3,"file":"InputHelpText.d.cts","names":[],"sources":["../../src/components/InputHelpText.tsx"],"mappings":";;;;;;;;;UAcU,kBAAA,SAA2B,IAAA,CAAK,WAAA;;EAExC,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,GAAW,SAAA;;EAEX,SAAA,GAAY,YAAA;EAJF;EAMV,OAAA,GAAU,YAAA;EAJC;EAMX,SAAA,GAAY,IAAA,CAAK,aAAA;EAFP;EAIV,IAAA,GAAO,SAAA;EAFK;EAIZ,QAAA;EAdmC;EAgBnC,QAAA;EAhBuC;EAkBvC,QAAA;EAlBwC;EAoBxC,QAAA;EAlBM;EAoBN,OAAA;EAlBA;EAoBA,qBAAA;AAAA;AAAA,cAGI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
@@ -30,6 +30,8 @@ interface InputHelpTextProps extends Omit<HStackProps, 'children' | 'ref'> {
30
30
  hasError?: boolean;
31
31
  /** Whether the associated input is focused or pressed. */
32
32
  pressed?: boolean;
33
+ /** Caps helper text and icons at the control scale. Set null to remove the cap. @default 2 */
34
+ maxFontSizeMultiplier?: number | null;
33
35
  }
34
36
  declare const InputHelpText: _$react.NamedExoticComponent<InputHelpTextProps>;
35
37
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"InputHelpText.d.ts","names":[],"sources":["../../src/components/InputHelpText.tsx"],"mappings":";;;;;;;;;UAaU,kBAAA,SAA2B,IAAA,CAAK,WAAA;;EAExC,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,GAAW,SAAA;;EAEX,SAAA,GAAY,YAAA;EAJF;EAMV,OAAA,GAAU,YAAA;EAJC;EAMX,SAAA,GAAY,IAAA,CAAK,aAAA;EAFP;EAIV,IAAA,GAAO,SAAA;EAFK;EAIZ,QAAA;EAdmC;EAgBnC,QAAA;EAhBuC;EAkBvC,QAAA;EAlBwC;EAoBxC,QAAA;EAlBM;EAoBN,OAAA;AAAA;AAAA,cAGI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
1
+ {"version":3,"file":"InputHelpText.d.ts","names":[],"sources":["../../src/components/InputHelpText.tsx"],"mappings":";;;;;;;;;UAcU,kBAAA,SAA2B,IAAA,CAAK,WAAA;;EAExC,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,GAAW,SAAA;;EAEX,SAAA,GAAY,YAAA;EAJF;EAMV,OAAA,GAAU,YAAA;EAJC;EAMX,SAAA,GAAY,IAAA,CAAK,aAAA;EAFP;EAIV,IAAA,GAAO,SAAA;EAFK;EAIZ,QAAA;EAdmC;EAgBnC,QAAA;EAhBuC;EAkBvC,QAAA;EAlBwC;EAoBxC,QAAA;EAlBM;EAoBN,OAAA;EAlBA;EAoBA,qBAAA;AAAA;AAAA,cAGI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
@@ -1,14 +1,16 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
2
  import { HStack } from "./HStack.js";
3
+ import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
3
4
  import { IconSlot } from "./IconSlot.js";
4
5
  import { Text } from "./Text.js";
5
6
  import { memo, useMemo } from "react";
6
7
  import { jsx, jsxs } from "react/jsx-runtime";
7
8
  import { inputStyles } from "../../generated/styles";
8
9
  //#region src/components/InputHelpText.tsx
9
- const InputHelpText = memo(function InputHelpText({ children, startIcon, endIcon, iconProps, size = "md", isFilled = false, disabled: _disabled, readOnly, hasError, pressed, ref, ...hStackProps }) {
10
+ const InputHelpText = memo(function InputHelpText({ children, startIcon, endIcon, iconProps, size = "md", isFilled = false, disabled: _disabled, readOnly, hasError, pressed, maxFontSizeMultiplier, ref, ...hStackProps }) {
10
11
  const { style: iconStyle, variant = "outline", ...resolvedIconProps } = iconProps ?? {};
11
12
  const value = isFilled ? "filled" : "empty";
13
+ const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
12
14
  inputStyles.useVariants({
13
15
  size,
14
16
  value,
@@ -28,16 +30,20 @@ const InputHelpText = memo(function InputHelpText({ children, startIcon, endIcon
28
30
  startIcon && /* @__PURE__ */ jsx(IconSlot, {
29
31
  icon: startIcon,
30
32
  variant,
33
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
31
34
  style: resolvedIconStyle,
32
35
  ...resolvedIconProps
33
36
  }),
34
37
  /* @__PURE__ */ jsx(Text, {
38
+ variant: "inherit",
39
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
35
40
  style: inputStyles.helperText,
36
41
  children
37
42
  }),
38
43
  endIcon && /* @__PURE__ */ jsx(IconSlot, {
39
44
  icon: endIcon,
40
45
  variant,
46
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
41
47
  style: resolvedIconStyle,
42
48
  ...resolvedIconProps
43
49
  })
@@ -1 +1 @@
1
- {"version":3,"file":"InputHelpText.js","names":[],"sources":["../../src/components/InputHelpText.tsx"],"sourcesContent":["import type { InputSize } from '@yahoo/uds-types';\nimport type { ReactNode, Ref } from 'react';\nimport { memo, useMemo } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../generated/styles';\nimport type { HStackProps } from './HStack';\nimport { HStack } from './HStack';\nimport type { IconSlotProps, IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport type { TextProps } from './Text';\nimport { Text } from './Text';\n\ninterface InputHelpTextProps extends Omit<HStackProps, 'children' | 'ref'> {\n /** Ref to the underlying root View. */\n ref?: Ref<View>;\n /** Helper text content. */\n children?: ReactNode;\n /** Icon to render before the help text. */\n startIcon?: IconSlotType;\n /** Icon to render after the help text. */\n endIcon?: IconSlotType;\n /** Props to apply to both helper icons. */\n iconProps?: Omit<IconSlotProps, 'icon' | 'ref'>;\n /** Input size used to resolve configured helper text styles. */\n size?: InputSize;\n /** Whether the associated input has a value. */\n isFilled?: boolean;\n /** Whether the associated input is disabled. */\n disabled?: boolean;\n /** Whether the associated input is read-only. */\n readOnly?: boolean;\n /** Whether the associated input has a validation error. */\n hasError?: boolean;\n /** Whether the associated input is focused or pressed. */\n pressed?: boolean;\n}\n\nconst InputHelpText = memo(function InputHelpText({\n children,\n startIcon,\n endIcon,\n iconProps,\n size = 'md',\n isFilled = false,\n disabled: _disabled,\n readOnly,\n hasError,\n pressed,\n ref,\n ...hStackProps\n}: InputHelpTextProps) {\n const { style: iconStyle, variant = 'outline', ...resolvedIconProps } = iconProps ?? {};\n const value = isFilled ? 'filled' : 'empty';\n\n inputStyles.useVariants({\n size,\n value,\n pressed,\n readonly: readOnly,\n invalid: hasError,\n });\n\n const resolvedIconStyle = useMemo(\n () => [inputStyles.helperIcon, iconStyle],\n [iconStyle, inputStyles.helperIcon],\n );\n\n if (children === null || children === undefined || children === false) {\n return null;\n }\n\n return (\n <HStack ref={ref} columnGap=\"1\" alignItems=\"center\" spacingTop=\"2\" {...hStackProps}>\n {startIcon && (\n <IconSlot\n icon={startIcon}\n variant={variant}\n style={resolvedIconStyle}\n {...resolvedIconProps}\n />\n )}\n\n <Text style={inputStyles.helperText as TextProps['style']}>{children}</Text>\n\n {endIcon && (\n <IconSlot\n icon={endIcon}\n variant={variant}\n style={resolvedIconStyle}\n {...resolvedIconProps}\n />\n )}\n </HStack>\n );\n});\n\nInputHelpText.displayName = 'InputHelpText';\n\nexport { InputHelpText, type InputHelpTextProps };\n"],"mappings":";;;;;;;;AAsCA,MAAM,gBAAgB,KAAK,SAAS,cAAc,EAChD,UACA,WACA,SACA,WACA,OAAO,MACP,WAAW,OACX,UAAU,WACV,UACA,UACA,SACA,KACA,GAAG,eACkB;CACrB,MAAM,EAAE,OAAO,WAAW,UAAU,WAAW,GAAG,sBAAsB,aAAa,EAAE;CACvF,MAAM,QAAQ,WAAW,WAAW;CAEpC,YAAY,YAAY;EACtB;EACA;EACA;EACA,UAAU;EACV,SAAS;EACV,CAAC;CAEF,MAAM,oBAAoB,cAClB,CAAC,YAAY,YAAY,UAAU,EACzC,CAAC,WAAW,YAAY,WAAW,CACpC;CAED,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAGT,OACE,qBAAC,QAAD;EAAa;EAAK,WAAU;EAAI,YAAW;EAAS,YAAW;EAAI,GAAI;YAAvE;GACG,aACC,oBAAC,UAAD;IACE,MAAM;IACG;IACT,OAAO;IACP,GAAI;IACJ,CAAA;GAGJ,oBAAC,MAAD;IAAM,OAAO,YAAY;IAAmC;IAAgB,CAAA;GAE3E,WACC,oBAAC,UAAD;IACE,MAAM;IACG;IACT,OAAO;IACP,GAAI;IACJ,CAAA;GAEG;;EAEX;AAEF,cAAc,cAAc"}
1
+ {"version":3,"file":"InputHelpText.js","names":[],"sources":["../../src/components/InputHelpText.tsx"],"sourcesContent":["import type { InputSize } from '@yahoo/uds-types';\nimport type { ReactNode, Ref } from 'react';\nimport { memo, useMemo } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../generated/styles';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\nimport type { HStackProps } from './HStack';\nimport { HStack } from './HStack';\nimport type { IconSlotProps, IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport type { TextProps } from './Text';\nimport { Text } from './Text';\n\ninterface InputHelpTextProps extends Omit<HStackProps, 'children' | 'ref'> {\n /** Ref to the underlying root View. */\n ref?: Ref<View>;\n /** Helper text content. */\n children?: ReactNode;\n /** Icon to render before the help text. */\n startIcon?: IconSlotType;\n /** Icon to render after the help text. */\n endIcon?: IconSlotType;\n /** Props to apply to both helper icons. */\n iconProps?: Omit<IconSlotProps, 'icon' | 'ref'>;\n /** Input size used to resolve configured helper text styles. */\n size?: InputSize;\n /** Whether the associated input has a value. */\n isFilled?: boolean;\n /** Whether the associated input is disabled. */\n disabled?: boolean;\n /** Whether the associated input is read-only. */\n readOnly?: boolean;\n /** Whether the associated input has a validation error. */\n hasError?: boolean;\n /** Whether the associated input is focused or pressed. */\n pressed?: boolean;\n /** Caps helper text and icons at the control scale. Set null to remove the cap. @default 2 */\n maxFontSizeMultiplier?: number | null;\n}\n\nconst InputHelpText = memo(function InputHelpText({\n children,\n startIcon,\n endIcon,\n iconProps,\n size = 'md',\n isFilled = false,\n disabled: _disabled,\n readOnly,\n hasError,\n pressed,\n maxFontSizeMultiplier,\n ref,\n ...hStackProps\n}: InputHelpTextProps) {\n const { style: iconStyle, variant = 'outline', ...resolvedIconProps } = iconProps ?? {};\n const value = isFilled ? 'filled' : 'empty';\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier('control', maxFontSizeMultiplier);\n\n inputStyles.useVariants({\n size,\n value,\n pressed,\n readonly: readOnly,\n invalid: hasError,\n });\n\n const resolvedIconStyle = useMemo(\n () => [inputStyles.helperIcon, iconStyle],\n [iconStyle, inputStyles.helperIcon],\n );\n\n if (children === null || children === undefined || children === false) {\n return null;\n }\n\n return (\n <HStack ref={ref} columnGap=\"1\" alignItems=\"center\" spacingTop=\"2\" {...hStackProps}>\n {startIcon && (\n <IconSlot\n icon={startIcon}\n variant={variant}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={resolvedIconStyle}\n {...resolvedIconProps}\n />\n )}\n\n <Text\n variant=\"inherit\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={inputStyles.helperText as TextProps['style']}\n >\n {children}\n </Text>\n\n {endIcon && (\n <IconSlot\n icon={endIcon}\n variant={variant}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={resolvedIconStyle}\n {...resolvedIconProps}\n />\n )}\n </HStack>\n );\n});\n\nInputHelpText.displayName = 'InputHelpText';\n\nexport { InputHelpText, type InputHelpTextProps };\n"],"mappings":";;;;;;;;;AAyCA,MAAM,gBAAgB,KAAK,SAAS,cAAc,EAChD,UACA,WACA,SACA,WACA,OAAO,MACP,WAAW,OACX,UAAU,WACV,UACA,UACA,SACA,uBACA,KACA,GAAG,eACkB;CACrB,MAAM,EAAE,OAAO,WAAW,UAAU,WAAW,GAAG,sBAAsB,aAAa,EAAE;CACvF,MAAM,QAAQ,WAAW,WAAW;CACpC,MAAM,gCAAgC,yBAAyB,WAAW,sBAAsB;CAEhG,YAAY,YAAY;EACtB;EACA;EACA;EACA,UAAU;EACV,SAAS;EACV,CAAC;CAEF,MAAM,oBAAoB,cAClB,CAAC,YAAY,YAAY,UAAU,EACzC,CAAC,WAAW,YAAY,WAAW,CACpC;CAED,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAGT,OACE,qBAAC,QAAD;EAAa;EAAK,WAAU;EAAI,YAAW;EAAS,YAAW;EAAI,GAAI;YAAvE;GACG,aACC,oBAAC,UAAD;IACE,MAAM;IACG;IACT,uBAAuB;IACvB,OAAO;IACP,GAAI;IACJ,CAAA;GAGJ,oBAAC,MAAD;IACE,SAAQ;IACR,uBAAuB;IACvB,OAAO,YAAY;IAElB;IACI,CAAA;GAEN,WACC,oBAAC,UAAD;IACE,MAAM;IACG;IACT,uBAAuB;IACvB,OAAO;IACP,GAAI;IACJ,CAAA;GAEG;;EAEX;AAEF,cAAc,cAAc"}
@@ -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
  const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
4
+ const require_fontScaling_FontScalingContext = require("../fontScaling/FontScalingContext.cjs");
5
+ const require_fontScaling_constants = require("../fontScaling/constants.cjs");
6
+ const require_fontScaling_useMaxFontSizeMultiplier = require("../fontScaling/useMaxFontSizeMultiplier.cjs");
4
7
  const require_components_IconSlot = require("./IconSlot.cjs");
5
8
  let react = require("react");
6
9
  let react_native = require("react-native");
@@ -50,8 +53,12 @@ const noUnderline = { textDecorationLine: "none" };
50
53
  * @see {@link Button} for primary actions
51
54
  * @see {@link Text} for non-interactive text
52
55
  */
53
- const Link = (0, react.memo)(function Link({ children, variant = "primary", textVariant, alwaysUnderline = false, startIcon, endIcon, onPress, style, ref, ...rest }) {
56
+ const Link = (0, react.memo)(function Link({ children, variant = "primary", textVariant, alwaysUnderline = false, startIcon, endIcon, maxFontSizeMultiplier, onPress, style, ref, ...rest }) {
54
57
  const [pressed, setPressed] = (0, react.useState)(false);
58
+ const dynamicTypeRampEnabled = require_fontScaling_FontScalingContext.useDynamicTypeRampEnabled();
59
+ const resolvedTextVariant = textVariant;
60
+ const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier(resolvedTextVariant, maxFontSizeMultiplier);
61
+ const dynamicTypeRamp = dynamicTypeRampEnabled && resolvedTextVariant ? require_fontScaling_constants.DEFAULT_DYNAMIC_TYPE_RAMPS[resolvedTextVariant] : void 0;
55
62
  const handlePressIn = (0, react.useCallback)(() => {
56
63
  setPressed(true);
57
64
  }, []);
@@ -125,12 +132,17 @@ const Link = (0, react.memo)(function Link({ children, variant = "primary", text
125
132
  onPressIn: handlePressIn,
126
133
  onPressOut: handlePressOut,
127
134
  suppressHighlighting: true,
135
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
136
+ dynamicTypeRamp,
128
137
  style: textStyles,
129
138
  ...rest,
130
139
  children: [
131
140
  startIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_IconSlot.IconSlot, {
132
141
  icon: startIcon,
133
142
  variant: "outline",
143
+ inheritFontScaling: true,
144
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
145
+ dynamicTypeRamp,
134
146
  style: startIconStyles
135
147
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.Text, {
136
148
  style: noUnderline,
@@ -143,6 +155,9 @@ const Link = (0, react.memo)(function Link({ children, variant = "primary", text
143
155
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_IconSlot.IconSlot, {
144
156
  icon: endIcon,
145
157
  variant: "outline",
158
+ inheritFontScaling: true,
159
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
160
+ dynamicTypeRamp,
146
161
  style: endIconStyles
147
162
  })] })
148
163
  ]
@@ -16,6 +16,12 @@ interface LinkProps extends UniversalLinkProps<IconSlotType> {
16
16
  ref?: Ref<Text>;
17
17
  /** Link content, typically text */
18
18
  children?: ReactNode;
19
+ /**
20
+ * Caps how far the link text and inline icons grow with the OS text-size
21
+ * setting. Set null to remove the cap; override app-wide via
22
+ * UDSFontScalingProvider.
23
+ */
24
+ maxFontSizeMultiplier?: number | null;
19
25
  }
20
26
  /**
21
27
  * **🔗 A navigation link component**
@@ -1 +1 @@
1
- {"version":3,"file":"Link.d.cts","names":[],"sources":["../../src/components/Link.tsx"],"mappings":";;;;;;;;;UAwBU,SAAA,SAAkB,kBAAA,CAAmB,YAAA;;EAE7C,KAAA,GAAQ,SAAA;EAFU;EAIlB,OAAA,GAAU,WAAA;EAJmC;EAM7C,GAAA,GAAM,GAAA,CAAI,IAAA;EAFA;EAIV,QAAA,GAAW,SAAA;AAAA;;;;;;;;;;;;;;;;;;AAAS;;;;;;;;;;;;;;;;;;;;;cAyChB,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"Link.d.cts","names":[],"sources":["../../src/components/Link.tsx"],"mappings":";;;;;;;;;UA2BU,SAAA,SAAkB,kBAAA,CAAmB,YAAA;;EAE7C,KAAA,GAAQ,SAAA;EAFU;EAIlB,OAAA,GAAU,WAAA;EAJmC;EAM7C,GAAA,GAAM,GAAA,CAAI,IAAA;EAFA;EAIV,QAAA,GAAW,SAAA;EAFL;;;;;EAQN,qBAAA;AAAA;;;;;;;;;;;;;AAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;cAyCjB,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
@@ -16,6 +16,12 @@ interface LinkProps extends UniversalLinkProps<IconSlotType> {
16
16
  ref?: Ref<Text>;
17
17
  /** Link content, typically text */
18
18
  children?: ReactNode;
19
+ /**
20
+ * Caps how far the link text and inline icons grow with the OS text-size
21
+ * setting. Set null to remove the cap; override app-wide via
22
+ * UDSFontScalingProvider.
23
+ */
24
+ maxFontSizeMultiplier?: number | null;
19
25
  }
20
26
  /**
21
27
  * **🔗 A navigation link component**
@@ -1 +1 @@
1
- {"version":3,"file":"Link.d.ts","names":[],"sources":["../../src/components/Link.tsx"],"mappings":";;;;;;;;;UAwBU,SAAA,SAAkB,kBAAA,CAAmB,YAAA;;EAE7C,KAAA,GAAQ,SAAA;EAFU;EAIlB,OAAA,GAAU,WAAA;EAJmC;EAM7C,GAAA,GAAM,GAAA,CAAI,IAAA;EAFA;EAIV,QAAA,GAAW,SAAA;AAAA;;;;;;;;;;;;;;;;;;AAAS;;;;;;;;;;;;;;;;;;;;;cAyChB,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"Link.d.ts","names":[],"sources":["../../src/components/Link.tsx"],"mappings":";;;;;;;;;UA2BU,SAAA,SAAkB,kBAAA,CAAmB,YAAA;;EAE7C,KAAA,GAAQ,SAAA;EAFU;EAIlB,OAAA,GAAU,WAAA;EAJmC;EAM7C,GAAA,GAAM,GAAA,CAAI,IAAA;EAFA;EAIV,QAAA,GAAW,SAAA;EAFL;;;;;EAQN,qBAAA;AAAA;;;;;;;;;;;;;AAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;cAyCjB,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
@@ -1,4 +1,7 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
+ import { useDynamicTypeRampEnabled } from "../fontScaling/FontScalingContext.js";
3
+ import { DEFAULT_DYNAMIC_TYPE_RAMPS } from "../fontScaling/constants.js";
4
+ import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
2
5
  import { IconSlot } from "./IconSlot.js";
3
6
  import { memo, useCallback, useMemo, useState } from "react";
4
7
  import { Text } from "react-native";
@@ -47,8 +50,12 @@ const noUnderline = { textDecorationLine: "none" };
47
50
  * @see {@link Button} for primary actions
48
51
  * @see {@link Text} for non-interactive text
49
52
  */
50
- const Link = memo(function Link({ children, variant = "primary", textVariant, alwaysUnderline = false, startIcon, endIcon, onPress, style, ref, ...rest }) {
53
+ const Link = memo(function Link({ children, variant = "primary", textVariant, alwaysUnderline = false, startIcon, endIcon, maxFontSizeMultiplier, onPress, style, ref, ...rest }) {
51
54
  const [pressed, setPressed] = useState(false);
55
+ const dynamicTypeRampEnabled = useDynamicTypeRampEnabled();
56
+ const resolvedTextVariant = textVariant;
57
+ const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier(resolvedTextVariant, maxFontSizeMultiplier);
58
+ const dynamicTypeRamp = dynamicTypeRampEnabled && resolvedTextVariant ? DEFAULT_DYNAMIC_TYPE_RAMPS[resolvedTextVariant] : void 0;
52
59
  const handlePressIn = useCallback(() => {
53
60
  setPressed(true);
54
61
  }, []);
@@ -122,12 +129,17 @@ const Link = memo(function Link({ children, variant = "primary", textVariant, al
122
129
  onPressIn: handlePressIn,
123
130
  onPressOut: handlePressOut,
124
131
  suppressHighlighting: true,
132
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
133
+ dynamicTypeRamp,
125
134
  style: textStyles,
126
135
  ...rest,
127
136
  children: [
128
137
  startIcon && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(IconSlot, {
129
138
  icon: startIcon,
130
139
  variant: "outline",
140
+ inheritFontScaling: true,
141
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
142
+ dynamicTypeRamp,
131
143
  style: startIconStyles
132
144
  }), /* @__PURE__ */ jsx(Text, {
133
145
  style: noUnderline,
@@ -140,6 +152,9 @@ const Link = memo(function Link({ children, variant = "primary", textVariant, al
140
152
  }), /* @__PURE__ */ jsx(IconSlot, {
141
153
  icon: endIcon,
142
154
  variant: "outline",
155
+ inheritFontScaling: true,
156
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
157
+ dynamicTypeRamp,
143
158
  style: endIconStyles
144
159
  })] })
145
160
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"Link.js","names":["RNText"],"sources":["../../src/components/Link.tsx"],"sourcesContent":["import type { UniversalLinkProps } from '@yahoo/uds-types';\nimport type { ReactNode, Ref } from 'react';\nimport { memo, useCallback, useMemo, useState } from 'react';\nimport type { GestureResponderEvent, TextStyle } from 'react-native';\nimport { Text as RNText } from 'react-native';\nimport Animated, {\n Easing,\n interpolateColor,\n useAnimatedStyle,\n useDerivedValue,\n withTiming,\n} from 'react-native-reanimated';\nimport { useAnimatedTheme } from 'react-native-unistyles/reanimated';\n\nimport { linkStyles } from '../../generated/styles';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport type { TextProps } from './Text';\n\nconst AnimatedText = Animated.Text;\n\n// Prevent icons from inheriting underline from parent/theme (matches web behavior)\nconst noUnderline: TextStyle = { textDecorationLine: 'none' };\n\ninterface LinkProps extends UniversalLinkProps<IconSlotType> {\n /** Style override for the link text */\n style?: TextStyle;\n /** Callback fired when the link is pressed */\n onPress?: TextProps['onPress'];\n /** Ref to the underlying Text element */\n ref?: Ref<RNText>;\n /** Link content, typically text */\n children?: ReactNode;\n}\n\n/**\n * **🔗 A navigation link component**\n *\n * @description\n * A styled link component for navigation. Rendered as Text so it can be\n * nested inline within other Text. Supports optional start/end icons.\n *\n * @category Interactive\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Link } from '@yahoo/uds-mobile/Link';\n *\n * // Standalone link\n * <Link onPress={() => navigate('/profile')}>Go to Profile</Link>\n *\n * // Inline within text\n * <Text>Read our <Link>Terms of Service</Link> and <Link>Privacy Policy</Link>.</Text>\n *\n * // With icons\n * <Link startIcon=\"AffiliateLink\">External link</Link>\n * <Link endIcon=\"ChevronRight\">Navigate forward</Link>\n * ```\n *\n * @usage\n * - Use for navigation actions\n * - Can be nested within Text for inline links\n * - Use alwaysUnderline for links that need to be visually distinct\n *\n * @accessibility\n * - Link text is the accessible name\n * - Shows underline on press for visual feedback\n * - Use descriptive link text (avoid \"click here\")\n *\n * @see {@link Button} for primary actions\n * @see {@link Text} for non-interactive text\n */\nconst Link = memo(function Link({\n children,\n variant = 'primary',\n textVariant,\n alwaysUnderline = false,\n startIcon,\n endIcon,\n onPress,\n style,\n ref,\n ...rest\n}: LinkProps) {\n const [pressed, setPressed] = useState(false);\n\n const handlePressIn = useCallback(() => {\n setPressed(true);\n }, []);\n\n const handlePressOut = useCallback(() => {\n setPressed(false);\n }, []);\n\n // Must have onPress for touch events to register (RN requirement)\n // Even without a user-provided handler, we need a function to make text touchable\n const handlePress = useCallback(\n (event: GestureResponderEvent) => {\n onPress?.(event);\n },\n [onPress],\n );\n\n linkStyles.useVariants({\n textStyle: textVariant,\n variant,\n pressed,\n });\n\n // Get theme as SharedValue for worklet access (zero re-renders)\n const animatedTheme = useAnimatedTheme();\n\n // Derive underline visibility from pressed state\n // useDerivedValue handles the animation automatically when deps change\n const underlineProgress = useDerivedValue(() => {\n const targetValue = pressed || alwaysUnderline ? 1 : 0;\n return withTiming(targetValue, {\n duration: 150,\n easing: Easing.bezier(0, 0, 0.2, 1),\n });\n }, [pressed, alwaysUnderline]);\n\n // Combined animated style for color and underline\n const animatedTextStyle = useAnimatedStyle(() => {\n // Access text color from theme using variant path\n const components = animatedTheme.value.components;\n const state = pressed ? 'pressed' : 'rest';\n const textVariantPath = `link/variant/${variant}/rootText/${state}` as const;\n const textColor = components[textVariantPath]?.color;\n\n if (!textColor) {\n return {};\n }\n\n const color = withTiming(textColor, {\n duration: 150,\n easing: Easing.bezier(0, 0, 0.2, 1),\n });\n\n // Interpolate underline opacity: 0 = transparent, 1 = text color\n const underlineColor = interpolateColor(\n underlineProgress.value,\n [0, 1],\n ['transparent', textColor],\n );\n\n return {\n color,\n textDecorationColor: underlineColor,\n };\n });\n\n const textStyles = useMemo(() => {\n return [linkStyles.root, linkStyles.text, animatedTextStyle, style];\n }, [linkStyles.text, animatedTextStyle, style, linkStyles.root]);\n\n const startIconStyles = useMemo(() => {\n return [linkStyles.icon, linkStyles.iconStart, noUnderline];\n }, [linkStyles.icon, linkStyles.iconStart, noUnderline]);\n\n const endIconStyles = useMemo(() => {\n return [linkStyles.icon, linkStyles.iconEnd, noUnderline];\n }, [linkStyles.icon, linkStyles.iconEnd, noUnderline]);\n\n return (\n <AnimatedText\n ref={ref}\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n suppressHighlighting\n style={textStyles}\n {...rest}\n >\n {startIcon && (\n <>\n <IconSlot icon={startIcon} variant=\"outline\" style={startIconStyles} />\n {/* TODO: need to add hairline space character to icon font so we can have space between icon and text https://hybridheroes.de/blog/2022-11-17-text-with-inline-icons-in-react-native/ */}\n <RNText style={noUnderline}>{' \\u200A'}</RNText>\n </>\n )}\n {children}\n {endIcon && (\n <>\n {/* TODO: need to add hairline space character to icon font so we can have space between icon and text https://hybridheroes.de/blog/2022-11-17-text-with-inline-icons-in-react-native/ */}\n <RNText style={noUnderline}>{' \\u200A'}</RNText>\n <IconSlot icon={endIcon} variant=\"outline\" style={endIconStyles} />\n </>\n )}\n </AnimatedText>\n );\n});\n\nLink.displayName = 'Link';\n\nexport { Link, type LinkProps };\n"],"mappings":";;;;;;;;;AAmBA,MAAM,eAAe,SAAS;AAG9B,MAAM,cAAyB,EAAE,oBAAoB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmD7D,MAAM,OAAO,KAAK,SAAS,KAAK,EAC9B,UACA,UAAU,WACV,aACA,kBAAkB,OAClB,WACA,SACA,SACA,OACA,KACA,GAAG,QACS;CACZ,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAE7C,MAAM,gBAAgB,kBAAkB;EACtC,WAAW,KAAK;IACf,EAAE,CAAC;CAEN,MAAM,iBAAiB,kBAAkB;EACvC,WAAW,MAAM;IAChB,EAAE,CAAC;CAIN,MAAM,cAAc,aACjB,UAAiC;EAChC,UAAU,MAAM;IAElB,CAAC,QAAQ,CACV;CAED,WAAW,YAAY;EACrB,WAAW;EACX;EACA;EACD,CAAC;CAGF,MAAM,gBAAgB,kBAAkB;CAIxC,MAAM,oBAAoB,sBAAsB;EAE9C,OAAO,WADa,WAAW,kBAAkB,IAAI,GACtB;GAC7B,UAAU;GACV,QAAQ,OAAO,OAAO,GAAG,GAAG,IAAK,EAAE;GACpC,CAAC;IACD,CAAC,SAAS,gBAAgB,CAAC;CAG9B,MAAM,oBAAoB,uBAAuB;EAK/C,MAAM,YAHa,cAAc,MAAM,WAGV,gBADW,QAAQ,YADlC,UAAU,YAAY,WAEW;EAE/C,IAAI,CAAC,WACH,OAAO,EAAE;EAeX,OAAO;GACL,OAbY,WAAW,WAAW;IAClC,UAAU;IACV,QAAQ,OAAO,OAAO,GAAG,GAAG,IAAK,EAAE;IACpC,CAUM;GACL,qBARqB,iBACrB,kBAAkB,OAClB,CAAC,GAAG,EAAE,EACN,CAAC,eAAe,UAAU,CAKS;GACpC;GACD;CAEF,MAAM,aAAa,cAAc;EAC/B,OAAO;GAAC,WAAW;GAAM,WAAW;GAAM;GAAmB;GAAM;IAClE;EAAC,WAAW;EAAM;EAAmB;EAAO,WAAW;EAAK,CAAC;CAEhE,MAAM,kBAAkB,cAAc;EACpC,OAAO;GAAC,WAAW;GAAM,WAAW;GAAW;GAAY;IAC1D;EAAC,WAAW;EAAM,WAAW;EAAW;EAAY,CAAC;CAExD,MAAM,gBAAgB,cAAc;EAClC,OAAO;GAAC,WAAW;GAAM,WAAW;GAAS;GAAY;IACxD;EAAC,WAAW;EAAM,WAAW;EAAS;EAAY,CAAC;CAEtD,OACE,qBAAC,cAAD;EACO;EACL,SAAS;EACT,WAAW;EACX,YAAY;EACZ,sBAAA;EACA,OAAO;EACP,GAAI;YAPN;GASG,aACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,UAAD;IAAU,MAAM;IAAW,SAAQ;IAAU,OAAO;IAAmB,CAAA,EAEvE,oBAACA,MAAD;IAAQ,OAAO;cAAc;IAAmB,CAAA,CAC/C,EAAA,CAAA;GAEJ;GACA,WACC,qBAAA,UAAA,EAAA,UAAA,CAEE,oBAACA,MAAD;IAAQ,OAAO;cAAc;IAAmB,CAAA,EAChD,oBAAC,UAAD;IAAU,MAAM;IAAS,SAAQ;IAAU,OAAO;IAAiB,CAAA,CAClE,EAAA,CAAA;GAEQ;;EAEjB;AAEF,KAAK,cAAc"}
1
+ {"version":3,"file":"Link.js","names":["RNText"],"sources":["../../src/components/Link.tsx"],"sourcesContent":["import type { UniversalLinkProps } from '@yahoo/uds-types';\nimport type { ReactNode, Ref } from 'react';\nimport { memo, useCallback, useMemo, useState } from 'react';\nimport type { GestureResponderEvent, TextStyle } from 'react-native';\nimport { Text as RNText } from 'react-native';\nimport Animated, {\n Easing,\n interpolateColor,\n useAnimatedStyle,\n useDerivedValue,\n withTiming,\n} from 'react-native-reanimated';\nimport { useAnimatedTheme } from 'react-native-unistyles/reanimated';\n\nimport { linkStyles } from '../../generated/styles';\nimport { DEFAULT_DYNAMIC_TYPE_RAMPS } from '../fontScaling/constants';\nimport { useDynamicTypeRampEnabled } from '../fontScaling/FontScalingContext';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\nimport type { TextProps, TextVariant } from './Text';\n\nconst AnimatedText = Animated.Text;\n\n// Prevent icons from inheriting underline from parent/theme (matches web behavior)\nconst noUnderline: TextStyle = { textDecorationLine: 'none' };\n\ninterface LinkProps extends UniversalLinkProps<IconSlotType> {\n /** Style override for the link text */\n style?: TextStyle;\n /** Callback fired when the link is pressed */\n onPress?: TextProps['onPress'];\n /** Ref to the underlying Text element */\n ref?: Ref<RNText>;\n /** Link content, typically text */\n children?: ReactNode;\n /**\n * Caps how far the link text and inline icons grow with the OS text-size\n * setting. Set null to remove the cap; override app-wide via\n * UDSFontScalingProvider.\n */\n maxFontSizeMultiplier?: number | null;\n}\n\n/**\n * **🔗 A navigation link component**\n *\n * @description\n * A styled link component for navigation. Rendered as Text so it can be\n * nested inline within other Text. Supports optional start/end icons.\n *\n * @category Interactive\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Link } from '@yahoo/uds-mobile/Link';\n *\n * // Standalone link\n * <Link onPress={() => navigate('/profile')}>Go to Profile</Link>\n *\n * // Inline within text\n * <Text>Read our <Link>Terms of Service</Link> and <Link>Privacy Policy</Link>.</Text>\n *\n * // With icons\n * <Link startIcon=\"AffiliateLink\">External link</Link>\n * <Link endIcon=\"ChevronRight\">Navigate forward</Link>\n * ```\n *\n * @usage\n * - Use for navigation actions\n * - Can be nested within Text for inline links\n * - Use alwaysUnderline for links that need to be visually distinct\n *\n * @accessibility\n * - Link text is the accessible name\n * - Shows underline on press for visual feedback\n * - Use descriptive link text (avoid \"click here\")\n *\n * @see {@link Button} for primary actions\n * @see {@link Text} for non-interactive text\n */\nconst Link = memo(function Link({\n children,\n variant = 'primary',\n textVariant,\n alwaysUnderline = false,\n startIcon,\n endIcon,\n maxFontSizeMultiplier,\n onPress,\n style,\n ref,\n ...rest\n}: LinkProps) {\n const [pressed, setPressed] = useState(false);\n const dynamicTypeRampEnabled = useDynamicTypeRampEnabled();\n const resolvedTextVariant = textVariant as TextVariant | undefined;\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier(\n resolvedTextVariant,\n maxFontSizeMultiplier,\n );\n const dynamicTypeRamp =\n dynamicTypeRampEnabled && resolvedTextVariant\n ? DEFAULT_DYNAMIC_TYPE_RAMPS[resolvedTextVariant]\n : undefined;\n\n const handlePressIn = useCallback(() => {\n setPressed(true);\n }, []);\n\n const handlePressOut = useCallback(() => {\n setPressed(false);\n }, []);\n\n // Must have onPress for touch events to register (RN requirement)\n // Even without a user-provided handler, we need a function to make text touchable\n const handlePress = useCallback(\n (event: GestureResponderEvent) => {\n onPress?.(event);\n },\n [onPress],\n );\n\n linkStyles.useVariants({\n textStyle: textVariant,\n variant,\n pressed,\n });\n\n // Get theme as SharedValue for worklet access (zero re-renders)\n const animatedTheme = useAnimatedTheme();\n\n // Derive underline visibility from pressed state\n // useDerivedValue handles the animation automatically when deps change\n const underlineProgress = useDerivedValue(() => {\n const targetValue = pressed || alwaysUnderline ? 1 : 0;\n return withTiming(targetValue, {\n duration: 150,\n easing: Easing.bezier(0, 0, 0.2, 1),\n });\n }, [pressed, alwaysUnderline]);\n\n // Combined animated style for color and underline\n const animatedTextStyle = useAnimatedStyle(() => {\n // Access text color from theme using variant path\n const components = animatedTheme.value.components;\n const state = pressed ? 'pressed' : 'rest';\n const textVariantPath = `link/variant/${variant}/rootText/${state}` as const;\n const textColor = components[textVariantPath]?.color;\n\n if (!textColor) {\n return {};\n }\n\n const color = withTiming(textColor, {\n duration: 150,\n easing: Easing.bezier(0, 0, 0.2, 1),\n });\n\n // Interpolate underline opacity: 0 = transparent, 1 = text color\n const underlineColor = interpolateColor(\n underlineProgress.value,\n [0, 1],\n ['transparent', textColor],\n );\n\n return {\n color,\n textDecorationColor: underlineColor,\n };\n });\n\n const textStyles = useMemo(() => {\n return [linkStyles.root, linkStyles.text, animatedTextStyle, style];\n }, [linkStyles.text, animatedTextStyle, style, linkStyles.root]);\n\n const startIconStyles = useMemo(() => {\n return [linkStyles.icon, linkStyles.iconStart, noUnderline];\n }, [linkStyles.icon, linkStyles.iconStart, noUnderline]);\n\n const endIconStyles = useMemo(() => {\n return [linkStyles.icon, linkStyles.iconEnd, noUnderline];\n }, [linkStyles.icon, linkStyles.iconEnd, noUnderline]);\n\n return (\n <AnimatedText\n ref={ref}\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n suppressHighlighting\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n dynamicTypeRamp={dynamicTypeRamp}\n style={textStyles}\n {...rest}\n >\n {startIcon && (\n <>\n <IconSlot\n icon={startIcon}\n variant=\"outline\"\n inheritFontScaling\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n dynamicTypeRamp={dynamicTypeRamp}\n style={startIconStyles}\n />\n {/* TODO: need to add hairline space character to icon font so we can have space between icon and text https://hybridheroes.de/blog/2022-11-17-text-with-inline-icons-in-react-native/ */}\n <RNText style={noUnderline}>{' \\u200A'}</RNText>\n </>\n )}\n {children}\n {endIcon && (\n <>\n {/* TODO: need to add hairline space character to icon font so we can have space between icon and text https://hybridheroes.de/blog/2022-11-17-text-with-inline-icons-in-react-native/ */}\n <RNText style={noUnderline}>{' \\u200A'}</RNText>\n <IconSlot\n icon={endIcon}\n variant=\"outline\"\n inheritFontScaling\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n dynamicTypeRamp={dynamicTypeRamp}\n style={endIconStyles}\n />\n </>\n )}\n </AnimatedText>\n );\n});\n\nLink.displayName = 'Link';\n\nexport { Link, type LinkProps };\n"],"mappings":";;;;;;;;;;;;AAsBA,MAAM,eAAe,SAAS;AAG9B,MAAM,cAAyB,EAAE,oBAAoB,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyD7D,MAAM,OAAO,KAAK,SAAS,KAAK,EAC9B,UACA,UAAU,WACV,aACA,kBAAkB,OAClB,WACA,SACA,uBACA,SACA,OACA,KACA,GAAG,QACS;CACZ,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAC7C,MAAM,yBAAyB,2BAA2B;CAC1D,MAAM,sBAAsB;CAC5B,MAAM,gCAAgC,yBACpC,qBACA,sBACD;CACD,MAAM,kBACJ,0BAA0B,sBACtB,2BAA2B,uBAC3B,KAAA;CAEN,MAAM,gBAAgB,kBAAkB;EACtC,WAAW,KAAK;IACf,EAAE,CAAC;CAEN,MAAM,iBAAiB,kBAAkB;EACvC,WAAW,MAAM;IAChB,EAAE,CAAC;CAIN,MAAM,cAAc,aACjB,UAAiC;EAChC,UAAU,MAAM;IAElB,CAAC,QAAQ,CACV;CAED,WAAW,YAAY;EACrB,WAAW;EACX;EACA;EACD,CAAC;CAGF,MAAM,gBAAgB,kBAAkB;CAIxC,MAAM,oBAAoB,sBAAsB;EAE9C,OAAO,WADa,WAAW,kBAAkB,IAAI,GACtB;GAC7B,UAAU;GACV,QAAQ,OAAO,OAAO,GAAG,GAAG,IAAK,EAAE;GACpC,CAAC;IACD,CAAC,SAAS,gBAAgB,CAAC;CAG9B,MAAM,oBAAoB,uBAAuB;EAK/C,MAAM,YAHa,cAAc,MAAM,WAGV,gBADW,QAAQ,YADlC,UAAU,YAAY,WAEW;EAE/C,IAAI,CAAC,WACH,OAAO,EAAE;EAeX,OAAO;GACL,OAbY,WAAW,WAAW;IAClC,UAAU;IACV,QAAQ,OAAO,OAAO,GAAG,GAAG,IAAK,EAAE;IACpC,CAUM;GACL,qBARqB,iBACrB,kBAAkB,OAClB,CAAC,GAAG,EAAE,EACN,CAAC,eAAe,UAAU,CAKS;GACpC;GACD;CAEF,MAAM,aAAa,cAAc;EAC/B,OAAO;GAAC,WAAW;GAAM,WAAW;GAAM;GAAmB;GAAM;IAClE;EAAC,WAAW;EAAM;EAAmB;EAAO,WAAW;EAAK,CAAC;CAEhE,MAAM,kBAAkB,cAAc;EACpC,OAAO;GAAC,WAAW;GAAM,WAAW;GAAW;GAAY;IAC1D;EAAC,WAAW;EAAM,WAAW;EAAW;EAAY,CAAC;CAExD,MAAM,gBAAgB,cAAc;EAClC,OAAO;GAAC,WAAW;GAAM,WAAW;GAAS;GAAY;IACxD;EAAC,WAAW;EAAM,WAAW;EAAS;EAAY,CAAC;CAEtD,OACE,qBAAC,cAAD;EACO;EACL,SAAS;EACT,WAAW;EACX,YAAY;EACZ,sBAAA;EACA,uBAAuB;EACN;EACjB,OAAO;EACP,GAAI;YATN;GAWG,aACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,UAAD;IACE,MAAM;IACN,SAAQ;IACR,oBAAA;IACA,uBAAuB;IACN;IACjB,OAAO;IACP,CAAA,EAEF,oBAACA,MAAD;IAAQ,OAAO;cAAc;IAAmB,CAAA,CAC/C,EAAA,CAAA;GAEJ;GACA,WACC,qBAAA,UAAA,EAAA,UAAA,CAEE,oBAACA,MAAD;IAAQ,OAAO;cAAc;IAAmB,CAAA,EAChD,oBAAC,UAAD;IACE,MAAM;IACN,SAAQ;IACR,oBAAA;IACA,uBAAuB;IACN;IACjB,OAAO;IACP,CAAA,CACD,EAAA,CAAA;GAEQ;;EAEjB;AAEF,KAAK,cAAc"}
@@ -1,7 +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");
4
5
  const require_components_HStack = require("../HStack.cjs");
6
+ const require_fontScaling_useMaxFontSizeMultiplier = require("../../fontScaling/useMaxFontSizeMultiplier.cjs");
5
7
  const require_components_Pagination_paginationContext = require("./paginationContext.cjs");
6
8
  const require_components_Pagination_paginationTheme = require("./paginationTheme.cjs");
7
9
  let react = require("react");
@@ -34,8 +36,9 @@ let react_native_unistyles = require("react-native-unistyles");
34
36
  * </Pagination>
35
37
  * ```
36
38
  */
37
- const Pagination = (0, react.memo)(function Pagination({ activePage, totalPages, maxVisiblePageNumbers = 7, ellipsisPlacement = "none", size = "md", variant = "default", getPageHref, getItemAriaLabel = require_components_Pagination_paginationContext.defaultGetItemAriaLabel, onPageChange, children, accessibilityLabel = "Pagination", ...rest }) {
39
+ const Pagination = (0, react.memo)(function Pagination({ activePage, totalPages, maxVisiblePageNumbers = 7, ellipsisPlacement = "none", size = "md", variant = "default", getPageHref, getItemAriaLabel = require_components_Pagination_paginationContext.defaultGetItemAriaLabel, onPageChange, children, accessibilityLabel = "Pagination", maxFontSizeMultiplier, ...rest }) {
38
40
  const { theme } = (0, react_native_unistyles.useUnistyles)();
41
+ const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
39
42
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Pagination_paginationContext.PaginationProvider, {
40
43
  value: (0, react.useMemo)(() => ({
41
44
  activePage,
@@ -44,6 +47,7 @@ const Pagination = (0, react.memo)(function Pagination({ activePage, totalPages,
44
47
  ellipsisPlacement,
45
48
  size,
46
49
  variant,
50
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
47
51
  getPageHref,
48
52
  getItemAriaLabel,
49
53
  onPageChange
@@ -54,19 +58,23 @@ const Pagination = (0, react.memo)(function Pagination({ activePage, totalPages,
54
58
  ellipsisPlacement,
55
59
  size,
56
60
  variant,
61
+ resolvedMaxFontSizeMultiplier,
57
62
  getPageHref,
58
63
  getItemAriaLabel,
59
64
  onPageChange
60
65
  ]),
61
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_HStack.HStack, {
62
- alignItems: "center",
63
- justifyContent: "center",
64
- accessibilityLabel,
65
- accessibilityRole: "none",
66
- gap: (0, react.useMemo)(() => require_components_Pagination_paginationTheme.getPaginationRootGapStyle(theme, size), [size, theme]).gap,
67
- alignSelf: "stretch",
68
- ...rest,
69
- children
66
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_fontScaling_FontScalingContext.ResolvedControlFontScalingProvider, {
67
+ maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
68
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_HStack.HStack, {
69
+ alignItems: "center",
70
+ justifyContent: "center",
71
+ accessibilityLabel,
72
+ accessibilityRole: "none",
73
+ gap: (0, react.useMemo)(() => require_components_Pagination_paginationTheme.getPaginationRootGapStyle(theme, size), [size, theme]).gap,
74
+ alignSelf: "stretch",
75
+ ...rest,
76
+ children
77
+ })
70
78
  })
71
79
  });
72
80
  });
@@ -7,6 +7,8 @@ import { ViewProps } from "react-native";
7
7
  interface PaginationProps extends Omit<UniversalPaginationProps, 'className' | 'children'>, Pick<ViewProps, 'children'> {
8
8
  /** Accessible label for the pagination control group. @default 'Pagination' */
9
9
  accessibilityLabel?: string;
10
+ /** Caps page labels, icons, and control geometry. Set null to remove the cap. @default 2 */
11
+ maxFontSizeMultiplier?: number | null;
10
12
  }
11
13
  /**
12
14
  * **Pagination — numbered page navigation component**
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.d.cts","names":[],"sources":["../../../src/components/Pagination/Pagination.tsx"],"mappings":";;;;;;UAWU,eAAA,SACA,IAAA,CAAK,wBAAA,6BAAqD,IAAA,CAAK,SAAA;;EAEvE,kBAAA;AAAA;;;;;;;;;;;;;;;;AAAkB;;;;;;;;;;;cA6Bd,UAAA,EAAU,OAAA,CAAA,oBAAA,CAAA,eAAA"}
1
+ {"version":3,"file":"Pagination.d.cts","names":[],"sources":["../../../src/components/Pagination/Pagination.tsx"],"mappings":";;;;;;UAaU,eAAA,SACA,IAAA,CAAK,wBAAA,6BAAqD,IAAA,CAAK,SAAA;;EAEvE,kBAAA;EAHQ;EAKR,qBAAA;AAAA;;;;;;;;;;;;;;;AAAqB;;;;;;;;;;;;cA6BjB,UAAA,EAAU,OAAA,CAAA,oBAAA,CAAA,eAAA"}