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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/README.md +6 -1
  2. package/dist/components/Avatar/AvatarIcon.cjs +2 -2
  3. package/dist/components/Avatar/AvatarIcon.js +2 -2
  4. package/dist/components/Avatar/AvatarIcon.js.map +1 -1
  5. package/dist/components/Avatar/AvatarImage.cjs +2 -2
  6. package/dist/components/Avatar/AvatarImage.js +2 -2
  7. package/dist/components/Avatar/AvatarImage.js.map +1 -1
  8. package/dist/components/Avatar/AvatarText.cjs +2 -2
  9. package/dist/components/Avatar/AvatarText.js +2 -2
  10. package/dist/components/Avatar/AvatarText.js.map +1 -1
  11. package/dist/components/Avatar/useAvatarFontScale.cjs +16 -0
  12. package/dist/components/Avatar/useAvatarFontScale.d.cts +7 -0
  13. package/dist/components/Avatar/useAvatarFontScale.d.cts.map +1 -0
  14. package/dist/components/Avatar/useAvatarFontScale.d.ts +7 -0
  15. package/dist/components/Avatar/useAvatarFontScale.d.ts.map +1 -0
  16. package/dist/components/Avatar/useAvatarFontScale.js +16 -0
  17. package/dist/components/Avatar/useAvatarFontScale.js.map +1 -0
  18. package/dist/components/Button/buttonTheme.cjs +10 -6
  19. package/dist/components/Button/buttonTheme.d.cts +10 -5
  20. package/dist/components/Button/buttonTheme.d.cts.map +1 -1
  21. package/dist/components/Button/buttonTheme.d.ts +10 -5
  22. package/dist/components/Button/buttonTheme.d.ts.map +1 -1
  23. package/dist/components/Button/buttonTheme.js +10 -6
  24. package/dist/components/Button/buttonTheme.js.map +1 -1
  25. package/dist/components/Button.cjs +17 -8
  26. package/dist/components/Button.js +17 -8
  27. package/dist/components/Button.js.map +1 -1
  28. package/dist/components/Checkbox.cjs +4 -2
  29. package/dist/components/Checkbox.js +4 -2
  30. package/dist/components/Checkbox.js.map +1 -1
  31. package/dist/components/Chip/ChipBase.cjs +22 -19
  32. package/dist/components/Chip/ChipBase.js +22 -19
  33. package/dist/components/Chip/ChipBase.js.map +1 -1
  34. package/dist/components/Icon.cjs +3 -2
  35. package/dist/components/Icon.d.cts.map +1 -1
  36. package/dist/components/Icon.d.ts.map +1 -1
  37. package/dist/components/Icon.js +3 -2
  38. package/dist/components/Icon.js.map +1 -1
  39. package/dist/components/Input.cjs +1 -1
  40. package/dist/components/Input.js +1 -1
  41. package/dist/components/Input.js.map +1 -1
  42. package/dist/components/Link.cjs +10 -1
  43. package/dist/components/Link.d.cts +6 -0
  44. package/dist/components/Link.d.cts.map +1 -1
  45. package/dist/components/Link.d.ts +6 -0
  46. package/dist/components/Link.d.ts.map +1 -1
  47. package/dist/components/Link.js +10 -1
  48. package/dist/components/Link.js.map +1 -1
  49. package/dist/components/Pagination/Pagination.cjs +18 -10
  50. package/dist/components/Pagination/Pagination.d.cts +2 -0
  51. package/dist/components/Pagination/Pagination.d.cts.map +1 -1
  52. package/dist/components/Pagination/Pagination.d.ts +2 -0
  53. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  54. package/dist/components/Pagination/Pagination.js +18 -10
  55. package/dist/components/Pagination/Pagination.js.map +1 -1
  56. package/dist/components/Pagination/PaginationEllipsis.cjs +8 -2
  57. package/dist/components/Pagination/PaginationEllipsis.d.cts.map +1 -1
  58. package/dist/components/Pagination/PaginationEllipsis.d.ts.map +1 -1
  59. package/dist/components/Pagination/PaginationEllipsis.js +9 -3
  60. package/dist/components/Pagination/PaginationEllipsis.js.map +1 -1
  61. package/dist/components/Pagination/PaginationItem.cjs +2 -1
  62. package/dist/components/Pagination/PaginationItem.js +2 -1
  63. package/dist/components/Pagination/PaginationItem.js.map +1 -1
  64. package/dist/components/Pagination/PaginationLink.cjs +2 -1
  65. package/dist/components/Pagination/PaginationLink.js +2 -1
  66. package/dist/components/Pagination/PaginationLink.js.map +1 -1
  67. package/dist/components/Pagination/PaginationNext.cjs +3 -1
  68. package/dist/components/Pagination/PaginationNext.js +3 -1
  69. package/dist/components/Pagination/PaginationNext.js.map +1 -1
  70. package/dist/components/Pagination/PaginationPrev.cjs +3 -1
  71. package/dist/components/Pagination/PaginationPrev.js +3 -1
  72. package/dist/components/Pagination/PaginationPrev.js.map +1 -1
  73. package/dist/components/Pagination/paginationContext.d.cts +2 -0
  74. package/dist/components/Pagination/paginationContext.d.cts.map +1 -1
  75. package/dist/components/Pagination/paginationContext.d.ts +2 -0
  76. package/dist/components/Pagination/paginationContext.d.ts.map +1 -1
  77. package/dist/components/Pagination/paginationContext.js.map +1 -1
  78. package/dist/components/Pagination/usePaginationControlStyles.cjs +8 -1
  79. package/dist/components/Pagination/usePaginationControlStyles.d.cts.map +1 -1
  80. package/dist/components/Pagination/usePaginationControlStyles.d.ts.map +1 -1
  81. package/dist/components/Pagination/usePaginationControlStyles.js +9 -2
  82. package/dist/components/Pagination/usePaginationControlStyles.js.map +1 -1
  83. package/dist/components/Radio/Radio.cjs +2 -1
  84. package/dist/components/Radio/Radio.js +2 -1
  85. package/dist/components/Radio/Radio.js.map +1 -1
  86. package/dist/components/Select/Select.cjs +16 -4
  87. package/dist/components/Select/Select.js +16 -4
  88. package/dist/components/Select/Select.js.map +1 -1
  89. package/dist/components/Select/SelectContent.cjs +31 -23
  90. package/dist/components/Select/SelectContent.d.cts.map +1 -1
  91. package/dist/components/Select/SelectContent.d.ts.map +1 -1
  92. package/dist/components/Select/SelectContent.js +32 -24
  93. package/dist/components/Select/SelectContent.js.map +1 -1
  94. package/dist/components/Select/SelectItem.cjs +6 -6
  95. package/dist/components/Select/SelectItem.js +6 -6
  96. package/dist/components/Select/SelectItem.js.map +1 -1
  97. package/dist/components/Select/SelectTrigger.cjs +1 -1
  98. package/dist/components/Select/SelectTrigger.js +1 -1
  99. package/dist/components/Select/SelectTrigger.js.map +1 -1
  100. package/dist/components/Switch.cjs +4 -2
  101. package/dist/components/Switch.js +4 -2
  102. package/dist/components/Switch.js.map +1 -1
  103. package/dist/components/Tabs/Tab.cjs +1 -1
  104. package/dist/components/Tabs/Tab.js +1 -1
  105. package/dist/components/Tabs/Tab.js.map +1 -1
  106. package/dist/fontScaling/androidNonlinearFontScaling.cjs +174 -0
  107. package/dist/fontScaling/androidNonlinearFontScaling.d.cts +7 -0
  108. package/dist/fontScaling/androidNonlinearFontScaling.d.cts.map +1 -0
  109. package/dist/fontScaling/androidNonlinearFontScaling.d.ts +7 -0
  110. package/dist/fontScaling/androidNonlinearFontScaling.d.ts.map +1 -0
  111. package/dist/fontScaling/androidNonlinearFontScaling.js +175 -0
  112. package/dist/fontScaling/androidNonlinearFontScaling.js.map +1 -0
  113. package/dist/fontScaling/constants.cjs +4 -3
  114. package/dist/fontScaling/constants.d.cts +4 -3
  115. package/dist/fontScaling/constants.d.cts.map +1 -1
  116. package/dist/fontScaling/constants.d.ts +4 -3
  117. package/dist/fontScaling/constants.d.ts.map +1 -1
  118. package/dist/fontScaling/constants.js +4 -3
  119. package/dist/fontScaling/constants.js.map +1 -1
  120. package/dist/fontScaling/types.d.cts +3 -2
  121. package/dist/fontScaling/types.d.cts.map +1 -1
  122. package/dist/fontScaling/types.d.ts +3 -2
  123. package/dist/fontScaling/types.d.ts.map +1 -1
  124. package/dist/fontScaling/useFontScale.cjs +13 -4
  125. package/dist/fontScaling/useFontScale.d.cts +8 -3
  126. package/dist/fontScaling/useFontScale.d.cts.map +1 -1
  127. package/dist/fontScaling/useFontScale.d.ts +8 -3
  128. package/dist/fontScaling/useFontScale.d.ts.map +1 -1
  129. package/dist/fontScaling/useFontScale.js +14 -5
  130. package/dist/fontScaling/useFontScale.js.map +1 -1
  131. package/package.json +1 -1
@@ -17,7 +17,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
17
17
  * @platform mobile
18
18
  */
19
19
  const PaginationNext = memo(function PaginationNext({ label = "Next", children, onPress, ...rest }) {
20
- const { activePage, totalPages, size, variant, onPageChange } = usePaginationContext();
20
+ const { activePage, totalPages, size, variant, maxFontSizeMultiplier, onPageChange } = usePaginationContext();
21
21
  const [pressed, setPressed] = useState(false);
22
22
  useEffect(() => {
23
23
  setPressed(false);
@@ -45,6 +45,7 @@ const PaginationNext = memo(function PaginationNext({ label = "Next", children,
45
45
  const content = children ?? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text$1, {
46
46
  color: "inherit",
47
47
  variant: "inherit",
48
+ maxFontSizeMultiplier,
48
49
  style: textStyle,
49
50
  dangerouslySetColor: resolvedTextColor,
50
51
  children: label
@@ -52,6 +53,7 @@ const PaginationNext = memo(function PaginationNext({ label = "Next", children,
52
53
  name: "ChevronRight",
53
54
  size: "sm",
54
55
  color: iconStyle?.color,
56
+ maxFontSizeMultiplier,
55
57
  style: iconStyle
56
58
  })] });
57
59
  return /* @__PURE__ */ jsx(Pressable, {
@@ -1 +1 @@
1
- {"version":3,"file":"PaginationNext.js","names":["Text"],"sources":["../../../src/components/Pagination/PaginationNext.tsx"],"sourcesContent":["import type { UniversalPaginationNextProps } from '@yahoo/uds-types';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type { PressableProps, TextStyle } from 'react-native';\nimport { Pressable, StyleSheet } from 'react-native';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport { Icon } from '../Icon';\nimport { Text } from '../Text';\nimport { usePaginationContext } from './paginationContext';\nimport { usePaginationControlStyles } from './usePaginationControlStyles';\n\n/** RN Pressable types differ from web button HTML attributes; keep parity fields only. */\ninterface PaginationNextProps extends Omit<PressableProps, 'children' | 'style'> {\n label?: UniversalPaginationNextProps['label'];\n children?: UniversalPaginationNextProps['children'];\n}\n\n/**\n * **PaginationNext — next page control**\n *\n * @description\n * Hidden on the last page. Moves to the next page when pressed.\n *\n * @category Navigation\n * @platform mobile\n */\nconst PaginationNext = memo(function PaginationNext({\n label = 'Next',\n children,\n onPress,\n ...rest\n}: PaginationNextProps) {\n const { activePage, totalPages, size, variant, onPageChange } = usePaginationContext();\n const [pressed, setPressed] = useState(false);\n\n // Pressable unmounts when we return null before onPressOut runs; reset on page change.\n useEffect(() => {\n setPressed(false);\n }, [activePage]);\n const { rootStyle, textStyle, iconStyle } = usePaginationControlStyles({\n size,\n variant,\n isActive: false,\n pressed,\n layout: 'prevNext',\n });\n\n const handlePress = useCallback(\n (event: Parameters<NonNullable<PressableProps['onPress']>>[0]) => {\n onPress?.(event);\n onPageChange?.(activePage + 1);\n },\n [activePage, onPageChange, onPress],\n );\n\n const resolvedTextColor = useMemo(() => {\n const flat = StyleSheet.flatten(textStyle);\n return typeof flat?.color === 'string' ? flat.color : undefined;\n }, [textStyle]);\n\n if (activePage >= totalPages) {\n return null;\n }\n\n const content = children ?? (\n <>\n <Text\n color=\"inherit\"\n variant=\"inherit\"\n style={textStyle}\n dangerouslySetColor={resolvedTextColor}\n >\n {label}\n </Text>\n <Icon\n name=\"ChevronRight\"\n size=\"sm\"\n color={(iconStyle as TextStyle)?.color as StyleProps['color'] | undefined}\n style={iconStyle}\n />\n </>\n );\n\n return (\n <Pressable\n accessibilityLabel=\"Go to next page\"\n accessibilityRole=\"button\"\n onPress={handlePress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n style={rootStyle}\n {...rest}\n >\n {content}\n </Pressable>\n );\n});\n\nPaginationNext.displayName = 'PaginationNext';\n\nexport { PaginationNext, type PaginationNextProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,MAAM,iBAAiB,KAAK,SAAS,eAAe,EAClD,QAAQ,QACR,UACA,SACA,GAAG,QACmB;CACtB,MAAM,EAAE,YAAY,YAAY,MAAM,SAAS,iBAAiB,sBAAsB;CACtF,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAG7C,gBAAgB;EACd,WAAW,MAAM;IAChB,CAAC,WAAW,CAAC;CAChB,MAAM,EAAE,WAAW,WAAW,cAAc,2BAA2B;EACrE;EACA;EACA,UAAU;EACV;EACA,QAAQ;EACT,CAAC;CAEF,MAAM,cAAc,aACjB,UAAiE;EAChE,UAAU,MAAM;EAChB,eAAe,aAAa,EAAE;IAEhC;EAAC;EAAY;EAAc;EAAQ,CACpC;CAED,MAAM,oBAAoB,cAAc;EACtC,MAAM,OAAO,WAAW,QAAQ,UAAU;EAC1C,OAAO,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ,KAAA;IACrD,CAAC,UAAU,CAAC;CAEf,IAAI,cAAc,YAChB,OAAO;CAGT,MAAM,UAAU,YACd,qBAAA,UAAA,EAAA,UAAA,CACE,oBAACA,QAAD;EACE,OAAM;EACN,SAAQ;EACR,OAAO;EACP,qBAAqB;YAEpB;EACI,CAAA,EACP,oBAAC,MAAD;EACE,MAAK;EACL,MAAK;EACL,OAAQ,WAAyB;EACjC,OAAO;EACP,CAAA,CACD,EAAA,CAAA;CAGL,OACE,oBAAC,WAAD;EACE,oBAAmB;EACnB,mBAAkB;EAClB,SAAS;EACT,iBAAiB,WAAW,KAAK;EACjC,kBAAkB,WAAW,MAAM;EACnC,OAAO;EACP,GAAI;YAEH;EACS,CAAA;EAEd;AAEF,eAAe,cAAc"}
1
+ {"version":3,"file":"PaginationNext.js","names":["Text"],"sources":["../../../src/components/Pagination/PaginationNext.tsx"],"sourcesContent":["import type { UniversalPaginationNextProps } from '@yahoo/uds-types';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type { PressableProps, TextStyle } from 'react-native';\nimport { Pressable, StyleSheet } from 'react-native';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport { Icon } from '../Icon';\nimport { Text } from '../Text';\nimport { usePaginationContext } from './paginationContext';\nimport { usePaginationControlStyles } from './usePaginationControlStyles';\n\n/** RN Pressable types differ from web button HTML attributes; keep parity fields only. */\ninterface PaginationNextProps extends Omit<PressableProps, 'children' | 'style'> {\n label?: UniversalPaginationNextProps['label'];\n children?: UniversalPaginationNextProps['children'];\n}\n\n/**\n * **PaginationNext — next page control**\n *\n * @description\n * Hidden on the last page. Moves to the next page when pressed.\n *\n * @category Navigation\n * @platform mobile\n */\nconst PaginationNext = memo(function PaginationNext({\n label = 'Next',\n children,\n onPress,\n ...rest\n}: PaginationNextProps) {\n const { activePage, totalPages, size, variant, maxFontSizeMultiplier, onPageChange } =\n usePaginationContext();\n const [pressed, setPressed] = useState(false);\n\n // Pressable unmounts when we return null before onPressOut runs; reset on page change.\n useEffect(() => {\n setPressed(false);\n }, [activePage]);\n const { rootStyle, textStyle, iconStyle } = usePaginationControlStyles({\n size,\n variant,\n isActive: false,\n pressed,\n layout: 'prevNext',\n });\n\n const handlePress = useCallback(\n (event: Parameters<NonNullable<PressableProps['onPress']>>[0]) => {\n onPress?.(event);\n onPageChange?.(activePage + 1);\n },\n [activePage, onPageChange, onPress],\n );\n\n const resolvedTextColor = useMemo(() => {\n const flat = StyleSheet.flatten(textStyle);\n return typeof flat?.color === 'string' ? flat.color : undefined;\n }, [textStyle]);\n\n if (activePage >= totalPages) {\n return null;\n }\n\n const content = children ?? (\n <>\n <Text\n color=\"inherit\"\n variant=\"inherit\"\n maxFontSizeMultiplier={maxFontSizeMultiplier}\n style={textStyle}\n dangerouslySetColor={resolvedTextColor}\n >\n {label}\n </Text>\n <Icon\n name=\"ChevronRight\"\n size=\"sm\"\n color={(iconStyle as TextStyle)?.color as StyleProps['color'] | undefined}\n maxFontSizeMultiplier={maxFontSizeMultiplier}\n style={iconStyle}\n />\n </>\n );\n\n return (\n <Pressable\n accessibilityLabel=\"Go to next page\"\n accessibilityRole=\"button\"\n onPress={handlePress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n style={rootStyle}\n {...rest}\n >\n {content}\n </Pressable>\n );\n});\n\nPaginationNext.displayName = 'PaginationNext';\n\nexport { PaginationNext, type PaginationNextProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,MAAM,iBAAiB,KAAK,SAAS,eAAe,EAClD,QAAQ,QACR,UACA,SACA,GAAG,QACmB;CACtB,MAAM,EAAE,YAAY,YAAY,MAAM,SAAS,uBAAuB,iBACpE,sBAAsB;CACxB,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAG7C,gBAAgB;EACd,WAAW,MAAM;IAChB,CAAC,WAAW,CAAC;CAChB,MAAM,EAAE,WAAW,WAAW,cAAc,2BAA2B;EACrE;EACA;EACA,UAAU;EACV;EACA,QAAQ;EACT,CAAC;CAEF,MAAM,cAAc,aACjB,UAAiE;EAChE,UAAU,MAAM;EAChB,eAAe,aAAa,EAAE;IAEhC;EAAC;EAAY;EAAc;EAAQ,CACpC;CAED,MAAM,oBAAoB,cAAc;EACtC,MAAM,OAAO,WAAW,QAAQ,UAAU;EAC1C,OAAO,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ,KAAA;IACrD,CAAC,UAAU,CAAC;CAEf,IAAI,cAAc,YAChB,OAAO;CAGT,MAAM,UAAU,YACd,qBAAA,UAAA,EAAA,UAAA,CACE,oBAACA,QAAD;EACE,OAAM;EACN,SAAQ;EACe;EACvB,OAAO;EACP,qBAAqB;YAEpB;EACI,CAAA,EACP,oBAAC,MAAD;EACE,MAAK;EACL,MAAK;EACL,OAAQ,WAAyB;EACV;EACvB,OAAO;EACP,CAAA,CACD,EAAA,CAAA;CAGL,OACE,oBAAC,WAAD;EACE,oBAAmB;EACnB,mBAAkB;EAClB,SAAS;EACT,iBAAiB,WAAW,KAAK;EACjC,kBAAkB,WAAW,MAAM;EACnC,OAAO;EACP,GAAI;YAEH;EACS,CAAA;EAEd;AAEF,eAAe,cAAc"}
@@ -19,7 +19,7 @@ let react_jsx_runtime = require("react/jsx-runtime");
19
19
  * @platform mobile
20
20
  */
21
21
  const PaginationPrev = (0, react.memo)(function PaginationPrev({ label = "Prev", children, onPress, ...rest }) {
22
- const { activePage, size, variant, onPageChange } = require_components_Pagination_paginationContext.usePaginationContext();
22
+ const { activePage, size, variant, maxFontSizeMultiplier, onPageChange } = require_components_Pagination_paginationContext.usePaginationContext();
23
23
  const [pressed, setPressed] = (0, react.useState)(false);
24
24
  (0, react.useEffect)(() => {
25
25
  setPressed(false);
@@ -48,10 +48,12 @@ const PaginationPrev = (0, react.memo)(function PaginationPrev({ label = "Prev",
48
48
  name: "ChevronLeft",
49
49
  size: "sm",
50
50
  color: iconStyle?.color,
51
+ maxFontSizeMultiplier,
51
52
  style: iconStyle
52
53
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Text.Text, {
53
54
  color: "inherit",
54
55
  variant: "inherit",
56
+ maxFontSizeMultiplier,
55
57
  style: textStyle,
56
58
  dangerouslySetColor: resolvedTextColor,
57
59
  children: label
@@ -17,7 +17,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
17
17
  * @platform mobile
18
18
  */
19
19
  const PaginationPrev = memo(function PaginationPrev({ label = "Prev", children, onPress, ...rest }) {
20
- const { activePage, size, variant, onPageChange } = usePaginationContext();
20
+ const { activePage, size, variant, maxFontSizeMultiplier, onPageChange } = usePaginationContext();
21
21
  const [pressed, setPressed] = useState(false);
22
22
  useEffect(() => {
23
23
  setPressed(false);
@@ -46,10 +46,12 @@ const PaginationPrev = memo(function PaginationPrev({ label = "Prev", children,
46
46
  name: "ChevronLeft",
47
47
  size: "sm",
48
48
  color: iconStyle?.color,
49
+ maxFontSizeMultiplier,
49
50
  style: iconStyle
50
51
  }), /* @__PURE__ */ jsx(Text$1, {
51
52
  color: "inherit",
52
53
  variant: "inherit",
54
+ maxFontSizeMultiplier,
53
55
  style: textStyle,
54
56
  dangerouslySetColor: resolvedTextColor,
55
57
  children: label
@@ -1 +1 @@
1
- {"version":3,"file":"PaginationPrev.js","names":["Text"],"sources":["../../../src/components/Pagination/PaginationPrev.tsx"],"sourcesContent":["import type { UniversalPaginationPrevProps } from '@yahoo/uds-types';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type { PressableProps, TextStyle } from 'react-native';\nimport { Pressable, StyleSheet } from 'react-native';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport { Icon } from '../Icon';\nimport { Text } from '../Text';\nimport { usePaginationContext } from './paginationContext';\nimport { usePaginationControlStyles } from './usePaginationControlStyles';\n\n/** RN Pressable types differ from web button HTML attributes; keep parity fields only. */\ninterface PaginationPrevProps extends Omit<PressableProps, 'children' | 'style'> {\n label?: UniversalPaginationPrevProps['label'];\n children?: UniversalPaginationPrevProps['children'];\n}\n\n/**\n * **PaginationPrev — previous page control**\n *\n * @description\n * Hidden on the first page. Moves to the previous page when pressed.\n *\n * @category Navigation\n * @platform mobile\n */\nconst PaginationPrev = memo(function PaginationPrev({\n label = 'Prev',\n children,\n onPress,\n ...rest\n}: PaginationPrevProps) {\n const { activePage, size, variant, onPageChange } = usePaginationContext();\n const [pressed, setPressed] = useState(false);\n\n // Pressable unmounts when we return null before onPressOut runs; reset on page change.\n useEffect(() => {\n setPressed(false);\n }, [activePage]);\n const { rootStyle, textStyle, iconStyle } = usePaginationControlStyles({\n size,\n variant,\n isActive: false,\n pressed,\n layout: 'prevNext',\n });\n\n const handlePress = useCallback(\n (event: Parameters<NonNullable<PressableProps['onPress']>>[0]) => {\n onPress?.(event);\n onPageChange?.(activePage - 1);\n },\n [activePage, onPageChange, onPress],\n );\n\n const resolvedTextColor = useMemo(() => {\n const flat = StyleSheet.flatten(textStyle);\n return typeof flat?.color === 'string' ? flat.color : undefined;\n }, [textStyle]);\n\n if (activePage <= 1) {\n return null;\n }\n\n const content = children ?? (\n <>\n <Icon\n name=\"ChevronLeft\"\n size=\"sm\"\n color={(iconStyle as TextStyle)?.color as StyleProps['color'] | undefined}\n style={iconStyle}\n />\n <Text\n color=\"inherit\"\n variant=\"inherit\"\n style={textStyle}\n dangerouslySetColor={resolvedTextColor}\n >\n {label}\n </Text>\n </>\n );\n\n return (\n <Pressable\n accessibilityLabel=\"Go to previous page\"\n accessibilityRole=\"button\"\n onPress={handlePress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n style={rootStyle}\n {...rest}\n >\n {content}\n </Pressable>\n );\n});\n\nPaginationPrev.displayName = 'PaginationPrev';\n\nexport { PaginationPrev, type PaginationPrevProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,MAAM,iBAAiB,KAAK,SAAS,eAAe,EAClD,QAAQ,QACR,UACA,SACA,GAAG,QACmB;CACtB,MAAM,EAAE,YAAY,MAAM,SAAS,iBAAiB,sBAAsB;CAC1E,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAG7C,gBAAgB;EACd,WAAW,MAAM;IAChB,CAAC,WAAW,CAAC;CAChB,MAAM,EAAE,WAAW,WAAW,cAAc,2BAA2B;EACrE;EACA;EACA,UAAU;EACV;EACA,QAAQ;EACT,CAAC;CAEF,MAAM,cAAc,aACjB,UAAiE;EAChE,UAAU,MAAM;EAChB,eAAe,aAAa,EAAE;IAEhC;EAAC;EAAY;EAAc;EAAQ,CACpC;CAED,MAAM,oBAAoB,cAAc;EACtC,MAAM,OAAO,WAAW,QAAQ,UAAU;EAC1C,OAAO,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ,KAAA;IACrD,CAAC,UAAU,CAAC;CAEf,IAAI,cAAc,GAChB,OAAO;CAGT,MAAM,UAAU,YACd,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;EACE,MAAK;EACL,MAAK;EACL,OAAQ,WAAyB;EACjC,OAAO;EACP,CAAA,EACF,oBAACA,QAAD;EACE,OAAM;EACN,SAAQ;EACR,OAAO;EACP,qBAAqB;YAEpB;EACI,CAAA,CACN,EAAA,CAAA;CAGL,OACE,oBAAC,WAAD;EACE,oBAAmB;EACnB,mBAAkB;EAClB,SAAS;EACT,iBAAiB,WAAW,KAAK;EACjC,kBAAkB,WAAW,MAAM;EACnC,OAAO;EACP,GAAI;YAEH;EACS,CAAA;EAEd;AAEF,eAAe,cAAc"}
1
+ {"version":3,"file":"PaginationPrev.js","names":["Text"],"sources":["../../../src/components/Pagination/PaginationPrev.tsx"],"sourcesContent":["import type { UniversalPaginationPrevProps } from '@yahoo/uds-types';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type { PressableProps, TextStyle } from 'react-native';\nimport { Pressable, StyleSheet } from 'react-native';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport { Icon } from '../Icon';\nimport { Text } from '../Text';\nimport { usePaginationContext } from './paginationContext';\nimport { usePaginationControlStyles } from './usePaginationControlStyles';\n\n/** RN Pressable types differ from web button HTML attributes; keep parity fields only. */\ninterface PaginationPrevProps extends Omit<PressableProps, 'children' | 'style'> {\n label?: UniversalPaginationPrevProps['label'];\n children?: UniversalPaginationPrevProps['children'];\n}\n\n/**\n * **PaginationPrev — previous page control**\n *\n * @description\n * Hidden on the first page. Moves to the previous page when pressed.\n *\n * @category Navigation\n * @platform mobile\n */\nconst PaginationPrev = memo(function PaginationPrev({\n label = 'Prev',\n children,\n onPress,\n ...rest\n}: PaginationPrevProps) {\n const { activePage, size, variant, maxFontSizeMultiplier, onPageChange } = usePaginationContext();\n const [pressed, setPressed] = useState(false);\n\n // Pressable unmounts when we return null before onPressOut runs; reset on page change.\n useEffect(() => {\n setPressed(false);\n }, [activePage]);\n const { rootStyle, textStyle, iconStyle } = usePaginationControlStyles({\n size,\n variant,\n isActive: false,\n pressed,\n layout: 'prevNext',\n });\n\n const handlePress = useCallback(\n (event: Parameters<NonNullable<PressableProps['onPress']>>[0]) => {\n onPress?.(event);\n onPageChange?.(activePage - 1);\n },\n [activePage, onPageChange, onPress],\n );\n\n const resolvedTextColor = useMemo(() => {\n const flat = StyleSheet.flatten(textStyle);\n return typeof flat?.color === 'string' ? flat.color : undefined;\n }, [textStyle]);\n\n if (activePage <= 1) {\n return null;\n }\n\n const content = children ?? (\n <>\n <Icon\n name=\"ChevronLeft\"\n size=\"sm\"\n color={(iconStyle as TextStyle)?.color as StyleProps['color'] | undefined}\n maxFontSizeMultiplier={maxFontSizeMultiplier}\n style={iconStyle}\n />\n <Text\n color=\"inherit\"\n variant=\"inherit\"\n maxFontSizeMultiplier={maxFontSizeMultiplier}\n style={textStyle}\n dangerouslySetColor={resolvedTextColor}\n >\n {label}\n </Text>\n </>\n );\n\n return (\n <Pressable\n accessibilityLabel=\"Go to previous page\"\n accessibilityRole=\"button\"\n onPress={handlePress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n style={rootStyle}\n {...rest}\n >\n {content}\n </Pressable>\n );\n});\n\nPaginationPrev.displayName = 'PaginationPrev';\n\nexport { PaginationPrev, type PaginationPrevProps };\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0BA,MAAM,iBAAiB,KAAK,SAAS,eAAe,EAClD,QAAQ,QACR,UACA,SACA,GAAG,QACmB;CACtB,MAAM,EAAE,YAAY,MAAM,SAAS,uBAAuB,iBAAiB,sBAAsB;CACjG,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;CAG7C,gBAAgB;EACd,WAAW,MAAM;IAChB,CAAC,WAAW,CAAC;CAChB,MAAM,EAAE,WAAW,WAAW,cAAc,2BAA2B;EACrE;EACA;EACA,UAAU;EACV;EACA,QAAQ;EACT,CAAC;CAEF,MAAM,cAAc,aACjB,UAAiE;EAChE,UAAU,MAAM;EAChB,eAAe,aAAa,EAAE;IAEhC;EAAC;EAAY;EAAc;EAAQ,CACpC;CAED,MAAM,oBAAoB,cAAc;EACtC,MAAM,OAAO,WAAW,QAAQ,UAAU;EAC1C,OAAO,OAAO,MAAM,UAAU,WAAW,KAAK,QAAQ,KAAA;IACrD,CAAC,UAAU,CAAC;CAEf,IAAI,cAAc,GAChB,OAAO;CAGT,MAAM,UAAU,YACd,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,MAAD;EACE,MAAK;EACL,MAAK;EACL,OAAQ,WAAyB;EACV;EACvB,OAAO;EACP,CAAA,EACF,oBAACA,QAAD;EACE,OAAM;EACN,SAAQ;EACe;EACvB,OAAO;EACP,qBAAqB;YAEpB;EACI,CAAA,CACN,EAAA,CAAA;CAGL,OACE,oBAAC,WAAD;EACE,oBAAmB;EACnB,mBAAkB;EAClB,SAAS;EACT,iBAAiB,WAAW,KAAK;EACjC,kBAAkB,WAAW,MAAM;EACnC,OAAO;EACP,GAAI;YAEH;EACS,CAAA;EAEd;AAEF,eAAe,cAAc"}
@@ -10,6 +10,8 @@ interface PaginationContextValue {
10
10
  ellipsisPlacement: PaginationEllipsisPlacement;
11
11
  size: PaginationSize;
12
12
  variant: PaginationVariant;
13
+ /** Resolved React Native control cap (0 means explicitly uncapped). */
14
+ maxFontSizeMultiplier: number;
13
15
  getPageHref?: (page: number) => string;
14
16
  getItemAriaLabel: (page: number, isActive: boolean) => string;
15
17
  onPageChange?: (page: number) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"paginationContext.d.cts","names":[],"sources":["../../../src/components/Pagination/paginationContext.tsx"],"mappings":";;;;;UASU,sBAAA;EACR,UAAA;EACA,UAAA;EACA,qBAAA;EACA,iBAAA,EAAmB,2BAAA;EACnB,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,iBAAA;EACT,WAAA,IAAe,IAAA;EACf,gBAAA,GAAmB,IAAA,UAAc,QAAA;EACjC,YAAA,IAAgB,IAAA;AAAA;AAAA,cAGZ,uBAAA,GAA2B,IAAA,UAAc,QAAA;AAAA,cAGzC,iBAAA,EAAiB,OAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,UAEb,uBAAA;EACR,KAAA,EAAO,sBAAA;EACP,QAAA,EAAU,KAAA,CAAM,SAAA;AAAA;AAAA,cAGZ,kBAAA;EAAA;;;KAA2C,uBAAA,GAAuB,OAAA,CAAA,GAAA,CAAA,OAAA;;;iBAO/D,oBAAA,CAAA,GAAwB,sBAAA;AAAA,iBAQxB,eAAA,CAAA,GAAe,qBAAA"}
1
+ {"version":3,"file":"paginationContext.d.cts","names":[],"sources":["../../../src/components/Pagination/paginationContext.tsx"],"mappings":";;;;;UASU,sBAAA;EACR,UAAA;EACA,UAAA;EACA,qBAAA;EACA,iBAAA,EAAmB,2BAAA;EACnB,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,iBAAA;EADH;EAGN,qBAAA;EACA,WAAA,IAAe,IAAA;EACf,gBAAA,GAAmB,IAAA,UAAc,QAAA;EACjC,YAAA,IAAgB,IAAA;AAAA;AAAA,cAGZ,uBAAA,GAA2B,IAAA,UAAc,QAAA;AAAA,cAGzC,iBAAA,EAAiB,OAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,UAEb,uBAAA;EACR,KAAA,EAAO,sBAAA;EACP,QAAA,EAAU,KAAA,CAAM,SAAA;AAAA;AAAA,cAGZ,kBAAA;EAAA;;;KAA2C,uBAAA,GAAuB,OAAA,CAAA,GAAA,CAAA,OAAA;;;iBAO/D,oBAAA,CAAA,GAAwB,sBAAA;AAAA,iBAQxB,eAAA,CAAA,GAAe,qBAAA"}
@@ -10,6 +10,8 @@ interface PaginationContextValue {
10
10
  ellipsisPlacement: PaginationEllipsisPlacement;
11
11
  size: PaginationSize;
12
12
  variant: PaginationVariant;
13
+ /** Resolved React Native control cap (0 means explicitly uncapped). */
14
+ maxFontSizeMultiplier: number;
13
15
  getPageHref?: (page: number) => string;
14
16
  getItemAriaLabel: (page: number, isActive: boolean) => string;
15
17
  onPageChange?: (page: number) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"paginationContext.d.ts","names":[],"sources":["../../../src/components/Pagination/paginationContext.tsx"],"mappings":";;;;;UASU,sBAAA;EACR,UAAA;EACA,UAAA;EACA,qBAAA;EACA,iBAAA,EAAmB,2BAAA;EACnB,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,iBAAA;EACT,WAAA,IAAe,IAAA;EACf,gBAAA,GAAmB,IAAA,UAAc,QAAA;EACjC,YAAA,IAAgB,IAAA;AAAA;AAAA,cAGZ,uBAAA,GAA2B,IAAA,UAAc,QAAA;AAAA,cAGzC,iBAAA,EAAiB,OAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,UAEb,uBAAA;EACR,KAAA,EAAO,sBAAA;EACP,QAAA,EAAU,KAAA,CAAM,SAAA;AAAA;AAAA,cAGZ,kBAAA;EAAA;;;KAA2C,uBAAA,GAAuB,OAAA,CAAA,GAAA,CAAA,OAAA;;;iBAO/D,oBAAA,CAAA,GAAwB,sBAAA;AAAA,iBAQxB,eAAA,CAAA,GAAe,qBAAA"}
1
+ {"version":3,"file":"paginationContext.d.ts","names":[],"sources":["../../../src/components/Pagination/paginationContext.tsx"],"mappings":";;;;;UASU,sBAAA;EACR,UAAA;EACA,UAAA;EACA,qBAAA;EACA,iBAAA,EAAmB,2BAAA;EACnB,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,iBAAA;EADH;EAGN,qBAAA;EACA,WAAA,IAAe,IAAA;EACf,gBAAA,GAAmB,IAAA,UAAc,QAAA;EACjC,YAAA,IAAgB,IAAA;AAAA;AAAA,cAGZ,uBAAA,GAA2B,IAAA,UAAc,QAAA;AAAA,cAGzC,iBAAA,EAAiB,OAAA,CAAA,OAAA,CAAA,sBAAA;AAAA,UAEb,uBAAA;EACR,KAAA,EAAO,sBAAA;EACP,QAAA,EAAU,KAAA,CAAM,SAAA;AAAA;AAAA,cAGZ,kBAAA;EAAA;;;KAA2C,uBAAA,GAAuB,OAAA,CAAA,GAAA,CAAA,OAAA;;;iBAO/D,oBAAA,CAAA,GAAwB,sBAAA;AAAA,iBAQxB,eAAA,CAAA,GAAe,qBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"paginationContext.js","names":[],"sources":["../../../src/components/Pagination/paginationContext.tsx"],"sourcesContent":["import type {\n PaginationEllipsisPlacement,\n PaginationSize,\n PaginationVariant,\n} from '@yahoo/uds-types';\nimport { createContext, useContext, useMemo } from 'react';\n\nimport { computeVisiblePages } from './computeVisiblePages';\n\ninterface PaginationContextValue {\n activePage: number;\n totalPages: number;\n maxVisiblePageNumbers: number;\n ellipsisPlacement: PaginationEllipsisPlacement;\n size: PaginationSize;\n variant: PaginationVariant;\n getPageHref?: (page: number) => string;\n getItemAriaLabel: (page: number, isActive: boolean) => string;\n onPageChange?: (page: number) => void;\n}\n\nconst defaultGetItemAriaLabel = (page: number, isActive: boolean) =>\n isActive ? `Page ${page}, current page` : `Go to page ${page}`;\n\nconst PaginationContext = createContext<PaginationContextValue | null>(null);\n\ninterface PaginationProviderProps {\n value: PaginationContextValue;\n children: React.ReactNode;\n}\n\nconst PaginationProvider = ({ value, children }: PaginationProviderProps) => {\n const contextValue = useMemo(() => value, [value]);\n return <PaginationContext.Provider value={contextValue}>{children}</PaginationContext.Provider>;\n};\n\nPaginationProvider.displayName = 'PaginationProvider';\n\nfunction usePaginationContext(): PaginationContextValue {\n const context = useContext(PaginationContext);\n if (!context) {\n throw new Error('Pagination components must be used within a Pagination provider.');\n }\n return context;\n}\n\nfunction useVisiblePages() {\n const { activePage, totalPages, maxVisiblePageNumbers, ellipsisPlacement } =\n usePaginationContext();\n return useMemo(\n () =>\n computeVisiblePages({\n activePage,\n totalPages,\n maxVisiblePageNumbers,\n ellipsisPlacement,\n }),\n [activePage, totalPages, maxVisiblePageNumbers, ellipsisPlacement],\n );\n}\n\nexport {\n defaultGetItemAriaLabel,\n PaginationContext,\n PaginationProvider,\n usePaginationContext,\n useVisiblePages,\n};\n"],"mappings":";;;;;AAqBA,MAAM,2BAA2B,MAAc,aAC7C,WAAW,QAAQ,KAAK,kBAAkB,cAAc;AAE1D,MAAM,oBAAoB,cAA6C,KAAK;AAO5E,MAAM,sBAAsB,EAAE,OAAO,eAAwC;CAC3E,MAAM,eAAe,cAAc,OAAO,CAAC,MAAM,CAAC;CAClD,OAAO,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;EAAe;EAAsC,CAAA;;AAGjG,mBAAmB,cAAc;AAEjC,SAAS,uBAA+C;CACtD,MAAM,UAAU,WAAW,kBAAkB;CAC7C,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,mEAAmE;CAErF,OAAO;;AAGT,SAAS,kBAAkB;CACzB,MAAM,EAAE,YAAY,YAAY,uBAAuB,sBACrD,sBAAsB;CACxB,OAAO,cAEH,oBAAoB;EAClB;EACA;EACA;EACA;EACD,CAAC,EACJ;EAAC;EAAY;EAAY;EAAuB;EAAkB,CACnE"}
1
+ {"version":3,"file":"paginationContext.js","names":[],"sources":["../../../src/components/Pagination/paginationContext.tsx"],"sourcesContent":["import type {\n PaginationEllipsisPlacement,\n PaginationSize,\n PaginationVariant,\n} from '@yahoo/uds-types';\nimport { createContext, useContext, useMemo } from 'react';\n\nimport { computeVisiblePages } from './computeVisiblePages';\n\ninterface PaginationContextValue {\n activePage: number;\n totalPages: number;\n maxVisiblePageNumbers: number;\n ellipsisPlacement: PaginationEllipsisPlacement;\n size: PaginationSize;\n variant: PaginationVariant;\n /** Resolved React Native control cap (0 means explicitly uncapped). */\n maxFontSizeMultiplier: number;\n getPageHref?: (page: number) => string;\n getItemAriaLabel: (page: number, isActive: boolean) => string;\n onPageChange?: (page: number) => void;\n}\n\nconst defaultGetItemAriaLabel = (page: number, isActive: boolean) =>\n isActive ? `Page ${page}, current page` : `Go to page ${page}`;\n\nconst PaginationContext = createContext<PaginationContextValue | null>(null);\n\ninterface PaginationProviderProps {\n value: PaginationContextValue;\n children: React.ReactNode;\n}\n\nconst PaginationProvider = ({ value, children }: PaginationProviderProps) => {\n const contextValue = useMemo(() => value, [value]);\n return <PaginationContext.Provider value={contextValue}>{children}</PaginationContext.Provider>;\n};\n\nPaginationProvider.displayName = 'PaginationProvider';\n\nfunction usePaginationContext(): PaginationContextValue {\n const context = useContext(PaginationContext);\n if (!context) {\n throw new Error('Pagination components must be used within a Pagination provider.');\n }\n return context;\n}\n\nfunction useVisiblePages() {\n const { activePage, totalPages, maxVisiblePageNumbers, ellipsisPlacement } =\n usePaginationContext();\n return useMemo(\n () =>\n computeVisiblePages({\n activePage,\n totalPages,\n maxVisiblePageNumbers,\n ellipsisPlacement,\n }),\n [activePage, totalPages, maxVisiblePageNumbers, ellipsisPlacement],\n );\n}\n\nexport {\n defaultGetItemAriaLabel,\n PaginationContext,\n PaginationProvider,\n usePaginationContext,\n useVisiblePages,\n};\n"],"mappings":";;;;;AAuBA,MAAM,2BAA2B,MAAc,aAC7C,WAAW,QAAQ,KAAK,kBAAkB,cAAc;AAE1D,MAAM,oBAAoB,cAA6C,KAAK;AAO5E,MAAM,sBAAsB,EAAE,OAAO,eAAwC;CAC3E,MAAM,eAAe,cAAc,OAAO,CAAC,MAAM,CAAC;CAClD,OAAO,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;EAAe;EAAsC,CAAA;;AAGjG,mBAAmB,cAAc;AAEjC,SAAS,uBAA+C;CACtD,MAAM,UAAU,WAAW,kBAAkB;CAC7C,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,mEAAmE;CAErF,OAAO;;AAGT,SAAS,kBAAkB;CACzB,MAAM,EAAE,YAAY,YAAY,uBAAuB,sBACrD,sBAAsB;CACxB,OAAO,cAEH,oBAAoB;EAClB;EACA;EACA;EACA;EACD,CAAC,EACJ;EAAC;EAAY;EAAY;EAAuB;EAAkB,CACnE"}
@@ -1,6 +1,8 @@
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_useFontScale = require("../../fontScaling/useFontScale.cjs");
5
+ const require_components_Pagination_paginationContext = require("./paginationContext.cjs");
4
6
  const require_components_Pagination_paginationTheme = require("./paginationTheme.cjs");
5
7
  let react = require("react");
6
8
  let react_native = require("react-native");
@@ -8,12 +10,16 @@ let react_native_unistyles = require("react-native-unistyles");
8
10
  //#region src/components/Pagination/usePaginationControlStyles.ts
9
11
  function usePaginationControlStyles({ size, variant, isActive, pressed, layout = "page" }) {
10
12
  const { theme } = (0, react_native_unistyles.useUnistyles)();
13
+ const { maxFontSizeMultiplier } = require_components_Pagination_paginationContext.usePaginationContext();
11
14
  const active = isActive ? "on" : "off";
12
15
  const interaction = pressed ? "pressed" : "rest";
13
16
  const prevNextActive = "off";
17
+ const sizeTextStyle = require_components_Pagination_paginationTheme.getPaginationSizeLayerStyle(theme, size, "text");
18
+ const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(maxFontSizeMultiplier, typeof sizeTextStyle.lineHeight === "number" ? sizeTextStyle.lineHeight : sizeTextStyle.fontSize);
14
19
  return {
15
20
  rootStyle: (0, react.useMemo)(() => {
16
- const { controlSize, borderRadius } = require_components_Pagination_paginationTheme.getPaginationControlMetrics(theme, size);
21
+ const { controlSize: baseControlSize, borderRadius } = require_components_Pagination_paginationTheme.getPaginationControlMetrics(theme, size);
22
+ const controlSize = Math.round(baseControlSize * fontScaleFactor);
17
23
  const variantActive = layout === "prevNext" ? prevNextActive : active;
18
24
  return [
19
25
  layout === "page" ? paginationStaticStyles.pageRoot : paginationStaticStyles.prevNextRoot,
@@ -28,6 +34,7 @@ function usePaginationControlStyles({ size, variant, isActive, pressed, layout =
28
34
  ];
29
35
  }, [
30
36
  active,
37
+ fontScaleFactor,
31
38
  interaction,
32
39
  layout,
33
40
  size,
@@ -1 +1 @@
1
- {"version":3,"file":"usePaginationControlStyles.d.cts","names":[],"sources":["../../../src/components/Pagination/usePaginationControlStyles.ts"],"mappings":";;;;;UAcU,iCAAA;EACR,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,iBAAA;EACT,QAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,iBAGO,0BAAA,CAAA;EACP,IAAA;EACA,OAAA;EACA,QAAA;EACA,OAAA;EACA;AAAA,GACC,iCAAA"}
1
+ {"version":3,"file":"usePaginationControlStyles.d.cts","names":[],"sources":["../../../src/components/Pagination/usePaginationControlStyles.ts"],"mappings":";;;;;UAiBU,iCAAA;EACR,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,iBAAA;EACT,QAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,iBAGO,0BAAA,CAAA;EACP,IAAA;EACA,OAAA;EACA,QAAA;EACA,OAAA;EACA;AAAA,GACC,iCAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePaginationControlStyles.d.ts","names":[],"sources":["../../../src/components/Pagination/usePaginationControlStyles.ts"],"mappings":";;;;;UAcU,iCAAA;EACR,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,iBAAA;EACT,QAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,iBAGO,0BAAA,CAAA;EACP,IAAA;EACA,OAAA;EACA,QAAA;EACA,OAAA;EACA;AAAA,GACC,iCAAA"}
1
+ {"version":3,"file":"usePaginationControlStyles.d.ts","names":[],"sources":["../../../src/components/Pagination/usePaginationControlStyles.ts"],"mappings":";;;;;UAiBU,iCAAA;EACR,IAAA,EAAM,cAAA;EACN,OAAA,EAAS,iBAAA;EACT,QAAA;EACA,OAAA;EACA,MAAA;AAAA;AAAA,iBAGO,0BAAA,CAAA;EACP,IAAA;EACA,OAAA;EACA,QAAA;EACA,OAAA;EACA;AAAA,GACC,iCAAA"}
@@ -1,17 +1,23 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
- import { getMergedPaginationControlRootStyle, getMergedPaginationIconStyle, getMergedPaginationTextStyle, getPaginationControlMetrics } from "./paginationTheme.js";
2
+ import { useFontScale } from "../../fontScaling/useFontScale.js";
3
+ import { usePaginationContext } from "./paginationContext.js";
4
+ import { getMergedPaginationControlRootStyle, getMergedPaginationIconStyle, getMergedPaginationTextStyle, getPaginationControlMetrics, getPaginationSizeLayerStyle } from "./paginationTheme.js";
3
5
  import { useMemo } from "react";
4
6
  import { StyleSheet } from "react-native";
5
7
  import { useUnistyles } from "react-native-unistyles";
6
8
  //#region src/components/Pagination/usePaginationControlStyles.ts
7
9
  function usePaginationControlStyles({ size, variant, isActive, pressed, layout = "page" }) {
8
10
  const { theme } = useUnistyles();
11
+ const { maxFontSizeMultiplier } = usePaginationContext();
9
12
  const active = isActive ? "on" : "off";
10
13
  const interaction = pressed ? "pressed" : "rest";
11
14
  const prevNextActive = "off";
15
+ const sizeTextStyle = getPaginationSizeLayerStyle(theme, size, "text");
16
+ const fontScaleFactor = useFontScale(maxFontSizeMultiplier, typeof sizeTextStyle.lineHeight === "number" ? sizeTextStyle.lineHeight : sizeTextStyle.fontSize);
12
17
  return {
13
18
  rootStyle: useMemo(() => {
14
- const { controlSize, borderRadius } = getPaginationControlMetrics(theme, size);
19
+ const { controlSize: baseControlSize, borderRadius } = getPaginationControlMetrics(theme, size);
20
+ const controlSize = Math.round(baseControlSize * fontScaleFactor);
15
21
  const variantActive = layout === "prevNext" ? prevNextActive : active;
16
22
  return [
17
23
  layout === "page" ? paginationStaticStyles.pageRoot : paginationStaticStyles.prevNextRoot,
@@ -26,6 +32,7 @@ function usePaginationControlStyles({ size, variant, isActive, pressed, layout =
26
32
  ];
27
33
  }, [
28
34
  active,
35
+ fontScaleFactor,
29
36
  interaction,
30
37
  layout,
31
38
  size,
@@ -1 +1 @@
1
- {"version":3,"file":"usePaginationControlStyles.js","names":[],"sources":["../../../src/components/Pagination/usePaginationControlStyles.ts"],"sourcesContent":["import type { PaginationSize, PaginationVariant } from '@yahoo/uds-types';\nimport { useMemo } from 'react';\nimport type { StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport { StyleSheet } from 'react-native';\n// eslint-disable-next-line uds/no-use-unistyles -- pagination token lookups for variant + size layers\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport {\n getMergedPaginationControlRootStyle,\n getMergedPaginationIconStyle,\n getMergedPaginationTextStyle,\n getPaginationControlMetrics,\n} from './paginationTheme';\n\ninterface UsePaginationControlStylesOptions {\n size: PaginationSize;\n variant: PaginationVariant;\n isActive: boolean;\n pressed: boolean;\n layout?: 'page' | 'prevNext';\n}\n\nfunction usePaginationControlStyles({\n size,\n variant,\n isActive,\n pressed,\n layout = 'page',\n}: UsePaginationControlStylesOptions) {\n const { theme } = useUnistyles();\n const active: 'on' | 'off' = isActive ? 'on' : 'off';\n const interaction = pressed ? 'pressed' : 'rest';\n const prevNextActive: 'on' | 'off' = 'off';\n\n const rootStyle = useMemo<StyleProp<ViewStyle>>(() => {\n const { controlSize, borderRadius } = getPaginationControlMetrics(theme, size);\n const variantActive = layout === 'prevNext' ? prevNextActive : active;\n\n return [\n layout === 'page' ? paginationStaticStyles.pageRoot : paginationStaticStyles.prevNextRoot,\n getMergedPaginationControlRootStyle(theme, size, variant, variantActive, interaction),\n {\n borderRadius,\n ...(layout === 'page'\n ? { height: controlSize, width: controlSize }\n : { minHeight: controlSize }),\n },\n ];\n }, [active, interaction, layout, size, theme, variant]);\n\n const textStyle = useMemo<StyleProp<TextStyle>>(() => {\n const variantActive = layout === 'prevNext' ? prevNextActive : active;\n\n return [\n paginationStaticStyles.text,\n getMergedPaginationTextStyle(theme, size, variant, variantActive, interaction),\n ];\n }, [active, interaction, layout, size, theme, variant]);\n\n const iconStyle = useMemo<StyleProp<TextStyle>>(\n () =>\n getMergedPaginationIconStyle(\n theme,\n size,\n variant,\n layout === 'prevNext' ? prevNextActive : active,\n interaction,\n ),\n [active, interaction, layout, size, theme, variant],\n );\n\n return { rootStyle, textStyle, iconStyle };\n}\n\nconst paginationStaticStyles = StyleSheet.create({\n pageRoot: {\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n },\n prevNextRoot: {\n alignItems: 'center',\n flexDirection: 'row',\n flexShrink: 0,\n gap: 4,\n justifyContent: 'center',\n },\n text: {\n flexShrink: 0,\n fontVariant: ['tabular-nums'],\n textAlign: 'center',\n },\n});\n\nexport { usePaginationControlStyles };\n"],"mappings":";;;;;;AAsBA,SAAS,2BAA2B,EAClC,MACA,SACA,UACA,SACA,SAAS,UAC2B;CACpC,MAAM,EAAE,UAAU,cAAc;CAChC,MAAM,SAAuB,WAAW,OAAO;CAC/C,MAAM,cAAc,UAAU,YAAY;CAC1C,MAAM,iBAA+B;CAuCrC,OAAO;EAAE,WArCS,cAAoC;GACpD,MAAM,EAAE,aAAa,iBAAiB,4BAA4B,OAAO,KAAK;GAC9E,MAAM,gBAAgB,WAAW,aAAa,iBAAiB;GAE/D,OAAO;IACL,WAAW,SAAS,uBAAuB,WAAW,uBAAuB;IAC7E,oCAAoC,OAAO,MAAM,SAAS,eAAe,YAAY;IACrF;KACE;KACA,GAAI,WAAW,SACX;MAAE,QAAQ;MAAa,OAAO;MAAa,GAC3C,EAAE,WAAW,aAAa;KAC/B;IACF;KACA;GAAC;GAAQ;GAAa;GAAQ;GAAM;GAAO;GAAQ,CAuBpC;EAAE,WArBF,cAAoC;GACpD,MAAM,gBAAgB,WAAW,aAAa,iBAAiB;GAE/D,OAAO,CACL,uBAAuB,MACvB,6BAA6B,OAAO,MAAM,SAAS,eAAe,YAAY,CAC/E;KACA;GAAC;GAAQ;GAAa;GAAQ;GAAM;GAAO;GAAQ,CAczB;EAAE,WAZb,cAEd,6BACE,OACA,MACA,SACA,WAAW,aAAa,iBAAiB,QACzC,YACD,EACH;GAAC;GAAQ;GAAa;GAAQ;GAAM;GAAO;GAAQ,CAGb;EAAE;;AAG5C,MAAM,yBAAyB,WAAW,OAAO;CAC/C,UAAU;EACR,YAAY;EACZ,gBAAgB;EAChB,YAAY;EACb;CACD,cAAc;EACZ,YAAY;EACZ,eAAe;EACf,YAAY;EACZ,KAAK;EACL,gBAAgB;EACjB;CACD,MAAM;EACJ,YAAY;EACZ,aAAa,CAAC,eAAe;EAC7B,WAAW;EACZ;CACF,CAAC"}
1
+ {"version":3,"file":"usePaginationControlStyles.js","names":[],"sources":["../../../src/components/Pagination/usePaginationControlStyles.ts"],"sourcesContent":["import type { PaginationSize, PaginationVariant } from '@yahoo/uds-types';\nimport { useMemo } from 'react';\nimport type { StyleProp, TextStyle, ViewStyle } from 'react-native';\nimport { StyleSheet } from 'react-native';\n// eslint-disable-next-line uds/no-use-unistyles -- pagination token lookups for variant + size layers\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport { useFontScale } from '../../fontScaling/useFontScale';\nimport { usePaginationContext } from './paginationContext';\nimport {\n getMergedPaginationControlRootStyle,\n getMergedPaginationIconStyle,\n getMergedPaginationTextStyle,\n getPaginationControlMetrics,\n getPaginationSizeLayerStyle,\n} from './paginationTheme';\n\ninterface UsePaginationControlStylesOptions {\n size: PaginationSize;\n variant: PaginationVariant;\n isActive: boolean;\n pressed: boolean;\n layout?: 'page' | 'prevNext';\n}\n\nfunction usePaginationControlStyles({\n size,\n variant,\n isActive,\n pressed,\n layout = 'page',\n}: UsePaginationControlStylesOptions) {\n const { theme } = useUnistyles();\n const { maxFontSizeMultiplier } = usePaginationContext();\n const active: 'on' | 'off' = isActive ? 'on' : 'off';\n const interaction = pressed ? 'pressed' : 'rest';\n const prevNextActive: 'on' | 'off' = 'off';\n const sizeTextStyle = getPaginationSizeLayerStyle(theme, size, 'text') as TextStyle;\n const fontScaleFactor = useFontScale(\n maxFontSizeMultiplier,\n typeof sizeTextStyle.lineHeight === 'number'\n ? sizeTextStyle.lineHeight\n : sizeTextStyle.fontSize,\n );\n\n const rootStyle = useMemo<StyleProp<ViewStyle>>(() => {\n const { controlSize: baseControlSize, borderRadius } = getPaginationControlMetrics(theme, size);\n const controlSize = Math.round(baseControlSize * fontScaleFactor);\n const variantActive = layout === 'prevNext' ? prevNextActive : active;\n\n return [\n layout === 'page' ? paginationStaticStyles.pageRoot : paginationStaticStyles.prevNextRoot,\n getMergedPaginationControlRootStyle(theme, size, variant, variantActive, interaction),\n {\n borderRadius,\n ...(layout === 'page'\n ? { height: controlSize, width: controlSize }\n : { minHeight: controlSize }),\n },\n ];\n }, [active, fontScaleFactor, interaction, layout, size, theme, variant]);\n\n const textStyle = useMemo<StyleProp<TextStyle>>(() => {\n const variantActive = layout === 'prevNext' ? prevNextActive : active;\n\n return [\n paginationStaticStyles.text,\n getMergedPaginationTextStyle(theme, size, variant, variantActive, interaction),\n ];\n }, [active, interaction, layout, size, theme, variant]);\n\n const iconStyle = useMemo<StyleProp<TextStyle>>(\n () =>\n getMergedPaginationIconStyle(\n theme,\n size,\n variant,\n layout === 'prevNext' ? prevNextActive : active,\n interaction,\n ),\n [active, interaction, layout, size, theme, variant],\n );\n\n return { rootStyle, textStyle, iconStyle };\n}\n\nconst paginationStaticStyles = StyleSheet.create({\n pageRoot: {\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n },\n prevNextRoot: {\n alignItems: 'center',\n flexDirection: 'row',\n flexShrink: 0,\n gap: 4,\n justifyContent: 'center',\n },\n text: {\n flexShrink: 0,\n fontVariant: ['tabular-nums'],\n textAlign: 'center',\n },\n});\n\nexport { usePaginationControlStyles };\n"],"mappings":";;;;;;;;AAyBA,SAAS,2BAA2B,EAClC,MACA,SACA,UACA,SACA,SAAS,UAC2B;CACpC,MAAM,EAAE,UAAU,cAAc;CAChC,MAAM,EAAE,0BAA0B,sBAAsB;CACxD,MAAM,SAAuB,WAAW,OAAO;CAC/C,MAAM,cAAc,UAAU,YAAY;CAC1C,MAAM,iBAA+B;CACrC,MAAM,gBAAgB,4BAA4B,OAAO,MAAM,OAAO;CACtE,MAAM,kBAAkB,aACtB,uBACA,OAAO,cAAc,eAAe,WAChC,cAAc,aACd,cAAc,SACnB;CAwCD,OAAO;EAAE,WAtCS,cAAoC;GACpD,MAAM,EAAE,aAAa,iBAAiB,iBAAiB,4BAA4B,OAAO,KAAK;GAC/F,MAAM,cAAc,KAAK,MAAM,kBAAkB,gBAAgB;GACjE,MAAM,gBAAgB,WAAW,aAAa,iBAAiB;GAE/D,OAAO;IACL,WAAW,SAAS,uBAAuB,WAAW,uBAAuB;IAC7E,oCAAoC,OAAO,MAAM,SAAS,eAAe,YAAY;IACrF;KACE;KACA,GAAI,WAAW,SACX;MAAE,QAAQ;MAAa,OAAO;MAAa,GAC3C,EAAE,WAAW,aAAa;KAC/B;IACF;KACA;GAAC;GAAQ;GAAiB;GAAa;GAAQ;GAAM;GAAO;GAAQ,CAuBrD;EAAE,WArBF,cAAoC;GACpD,MAAM,gBAAgB,WAAW,aAAa,iBAAiB;GAE/D,OAAO,CACL,uBAAuB,MACvB,6BAA6B,OAAO,MAAM,SAAS,eAAe,YAAY,CAC/E;KACA;GAAC;GAAQ;GAAa;GAAQ;GAAM;GAAO;GAAQ,CAczB;EAAE,WAZb,cAEd,6BACE,OACA,MACA,SACA,WAAW,aAAa,iBAAiB,QACzC,YACD,EACH;GAAC;GAAQ;GAAa;GAAQ;GAAM;GAAO;GAAQ,CAGb;EAAE;;AAG5C,MAAM,yBAAyB,WAAW,OAAO;CAC/C,UAAU;EACR,YAAY;EACZ,gBAAgB;EAChB,YAAY;EACb;CACD,cAAc;EACZ,YAAY;EACZ,eAAe;EACf,YAAY;EACZ,KAAK;EACL,gBAAgB;EACjB;CACD,MAAM;EACJ,YAAY;EACZ,aAAa,CAAC,eAAe;EAC7B,WAAW;EACZ;CACF,CAAC"}
@@ -55,7 +55,6 @@ const Radio = (0, react.memo)(function Radio({ label, labelPosition = "start", v
55
55
  const uid = `uds-radio-${(0, react.useId)()}`;
56
56
  const radioGroup = require_components_Radio_RadioGroupContext.useRadioGroupContext();
57
57
  const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
58
- const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier);
59
58
  const disabled = Boolean(disabledProp || radioGroup?.disabled);
60
59
  const hasError = hasErrorProp ?? radioGroup?.hasError;
61
60
  const reduceMotion = reduceMotionProp ?? radioGroup?.reduceMotion;
@@ -110,6 +109,8 @@ const Radio = (0, react.memo)(function Radio({ label, labelPosition = "start", v
110
109
  value: valueState,
111
110
  pressed
112
111
  });
112
+ const radioBaseSize = generated_styles.radioStyles.radio.width;
113
+ const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier, typeof radioBaseSize === "number" ? radioBaseSize : void 0);
113
114
  const rootStyle = (0, react.useMemo)(() => [generated_styles.radioStyles.root, { opacity: disabled ? .5 : 1 }], [generated_styles.radioStyles.root, disabled]);
114
115
  const radioBoxStyle = (0, react.useMemo)(() => {
115
116
  const { width, height } = generated_styles.radioStyles.radio;
@@ -52,7 +52,6 @@ const Radio = memo(function Radio({ label, labelPosition = "start", variant: var
52
52
  const uid = `uds-radio-${useId()}`;
53
53
  const radioGroup = useRadioGroupContext();
54
54
  const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier) ?? 0;
55
- const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);
56
55
  const disabled = Boolean(disabledProp || radioGroup?.disabled);
57
56
  const hasError = hasErrorProp ?? radioGroup?.hasError;
58
57
  const reduceMotion = reduceMotionProp ?? radioGroup?.reduceMotion;
@@ -107,6 +106,8 @@ const Radio = memo(function Radio({ label, labelPosition = "start", variant: var
107
106
  value: valueState,
108
107
  pressed
109
108
  });
109
+ const radioBaseSize = radioStyles.radio.width;
110
+ const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier, typeof radioBaseSize === "number" ? radioBaseSize : void 0);
110
111
  const rootStyle = useMemo(() => [radioStyles.root, { opacity: disabled ? .5 : 1 }], [radioStyles.root, disabled]);
111
112
  const radioBoxStyle = useMemo(() => {
112
113
  const { width, height } = radioStyles.radio;
@@ -1 +1 @@
1
- {"version":3,"file":"Radio.js","names":["Pressable"],"sources":["../../../src/components/Radio/Radio.tsx"],"sourcesContent":["import type { RadioVariant, UniversalRadioProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { ViewProps } from 'react-native';\nimport { View } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withSpring } from 'react-native-reanimated';\n\nimport { radioStyles } from '../../../generated/styles';\nimport { useFontScale } from '../../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { BUTTON_SPRING_CONFIG, SCALE_EFFECTS } from '../../motion';\nimport { FormLabel } from '../FormLabel';\nimport { Pressable } from '../Pressable';\nimport { useRadioGroupContext } from './RadioGroupContext';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\n/** Derived from RadioValue - maps boolean to 'checked'/'unchecked' string literals */\ntype RadioValueState = 'checked' | 'unchecked';\n\ninterface RadioProps extends Omit<ViewProps, 'style'>, UniversalRadioProps {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Default checked state for uncontrolled mode */\n defaultChecked?: boolean;\n /** Whether the radio is disabled */\n disabled?: boolean;\n /** Whether the radio is required */\n required?: boolean;\n /**\n * Caps how far the circle, dot, and label grow with the OS text-size\n * setting; all three 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 /** Callback fired when the checked state changes */\n onChange?: (checked: boolean) => void;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Variant Mapping */\n/* -------------------------------------------------------------------------- */\n\n/** All style variants available in the generated styles (includes error variants) */\ntype RadioStyleVariant = 'primary' | 'secondary' | 'alert' | 'alert-secondary';\n\nconst VARIANT_ERROR_MAP: Record<RadioVariant, RadioStyleVariant> = {\n primary: 'alert',\n secondary: 'alert-secondary',\n};\n\n/* -------------------------------------------------------------------------- */\n/* Radio Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **⚙️ A radio component**\n *\n * @description\n * A radio component allows users to select one option from a set.\n * Unlike checkbox, radio buttons cannot have multiple selected in a group,\n * allowing only one selection at a time.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Radio } from '@yahoo/uds-mobile/Radio';\n *\n * <Radio label=\"Option A\" />\n * <Radio label=\"Option B\" checked={true} onChange={setChecked} />\n * ```\n *\n * @usage\n * - Forms: For selecting a single option from multiple choices\n * - Settings: For toggling between mutually exclusive preferences\n *\n * @accessibility\n * - Sets `accessibilityRole=\"radio\"` automatically\n * - Announces checked/unchecked state\n * - Label is used as accessibility label\n * - Supports `reduceMotion` for users who prefer reduced motion\n *\n * @see {@link Checkbox} for multi-select options\n * @see {@link Switch} for binary toggles\n */\nconst Radio = memo(function Radio({\n // Radio props\n label,\n labelPosition = 'start',\n variant: variantInput,\n size: sizeInput,\n value: valueProp,\n checked: checkedProp,\n hasError: hasErrorProp,\n reduceMotion: reduceMotionProp,\n // Native props\n defaultChecked,\n disabled: disabledProp,\n required,\n maxFontSizeMultiplier,\n onChange,\n ref,\n ...viewProps\n}: RadioProps) {\n const generatedId = useId();\n const uid = `uds-radio-${generatedId}`;\n const radioGroup = useRadioGroupContext();\n\n // One capped factor governs circle, dot, and label so they stay cohesive.\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);\n\n const disabled = Boolean(disabledProp || radioGroup?.disabled);\n const hasError = hasErrorProp ?? radioGroup?.hasError;\n const reduceMotion = reduceMotionProp ?? radioGroup?.reduceMotion;\n const size = sizeInput ?? radioGroup?.size ?? 'md';\n const variantProp = variantInput ?? radioGroup?.variant ?? 'primary';\n const value = valueProp ?? '';\n\n /* --------------------------------- State ---------------------------------- */\n const isInRadioGroup = radioGroup !== undefined;\n const isControlled = checkedProp !== undefined;\n const [internalChecked, setInternalChecked] = useState<boolean>(\n isControlled ? checkedProp : (defaultChecked ?? false),\n );\n const [pressed, setPressed] = useState(false);\n\n // Use controlled value if provided, otherwise use internal state\n const checked = isInRadioGroup\n ? radioGroup.value === value\n : isControlled\n ? checkedProp\n : internalChecked;\n\n useEffect(() => {\n if (!__DEV__ || !isInRadioGroup || valueProp) {\n return;\n }\n\n console.warn(\n '[UDS Mobile] Radio: A Radio rendered inside RadioGroup requires a unique, non-empty value prop.',\n );\n }, [isInRadioGroup, valueProp]);\n\n /* ------------------------------ Derived Values ---------------------------- */\n const valueState: RadioValueState = useMemo(() => {\n return checked ? 'checked' : 'unchecked';\n }, [checked]);\n\n /* -------------------------------- Animation ------------------------------- */\n const shouldAnimate = !reduceMotion;\n\n // Scale animation for press feedback (disabled when reduceMotion is true)\n const scaleProgress = useDerivedValue(\n () =>\n shouldAnimate\n ? withSpring(pressed ? SCALE_EFFECTS.down : SCALE_EFFECTS.none, BUTTON_SPRING_CONFIG)\n : SCALE_EFFECTS.none, // No scale effect when reduceMotion is true\n [pressed, shouldAnimate],\n );\n\n const radioAnimatedStyle = useAnimatedStyle(() => ({\n transform: [{ scale: scaleProgress.value }],\n }));\n\n /* -------------------------------- Handlers -------------------------------- */\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n if (isInRadioGroup) {\n if (radioGroup.value === value) {\n return;\n }\n\n radioGroup.setValue(value);\n onChange?.(true);\n return;\n }\n\n const newChecked = !checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(newChecked);\n }, [disabled, isInRadioGroup, checked, isControlled, onChange, radioGroup, value]);\n\n const handlePressIn = useCallback(() => {\n setPressed(true);\n }, []);\n\n const handlePressOut = useCallback(() => {\n setPressed(false);\n }, []);\n\n /* --------------------------------- Styles --------------------------------- */\n // Compute the style variant (primary/secondary maps to alert variants when hasError)\n const styleVariant: RadioStyleVariant = hasError ? VARIANT_ERROR_MAP[variantProp] : variantProp;\n\n radioStyles.useVariants({\n size,\n variant: styleVariant, // primary, secondary, alert, alert-secondary\n value: valueState, // checked, unchecked\n pressed,\n });\n\n const rootStyle = useMemo(\n () => [radioStyles.root, { opacity: disabled ? 0.5 : 1 }],\n [radioStyles.root, disabled],\n );\n\n const radioBoxStyle = useMemo(() => {\n // The circle grows by the capped factor alongside its label; borderWidth\n // stays fixed (stroke weight doesn't scale in the OS's own controls).\n const { width, height } = radioStyles.radio;\n const scaledBox =\n fontScaleFactor !== 1 && typeof width === 'number' && typeof height === 'number'\n ? {\n width: Math.round(width * fontScaleFactor),\n height: Math.round(height * fontScaleFactor),\n }\n : undefined;\n\n return [\n radioStyles.radio,\n scaledBox,\n {\n alignItems: 'center' as const,\n justifyContent: 'center' as const,\n borderRadius: 9999,\n },\n radioAnimatedStyle,\n ];\n }, [radioStyles.radio, fontScaleFactor, radioAnimatedStyle]);\n\n // Inner circle size: fixed 8x8px to match web implementation\n const INNER_CIRCLE_SIZE = 8;\n\n const circleStyle = useMemo(\n () => [\n radioStyles.radioCircle,\n {\n width: Math.round(INNER_CIRCLE_SIZE * fontScaleFactor),\n height: Math.round(INNER_CIRCLE_SIZE * fontScaleFactor),\n borderRadius: 9999,\n },\n ],\n [radioStyles.radioCircle, fontScaleFactor],\n );\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n return (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n hasError={hasError}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={radioStyles.text}\n />\n );\n }, [label, required, hasError, resolvedMaxFontSizeMultiplier, radioStyles.text]);\n\n const a11yState = useMemo(\n () => ({\n disabled,\n checked,\n }),\n [disabled, checked],\n );\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <Pressable\n ref={ref}\n nativeID={uid}\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n disabled={disabled}\n flexDirection={labelPosition === 'start' ? 'row' : 'row-reverse'}\n alignItems=\"center\"\n alignSelf=\"flex-start\"\n accessibilityRole=\"radio\"\n accessibilityState={a11yState}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n {...viewProps}\n style={rootStyle}\n >\n <Animated.View style={radioBoxStyle}>{checked && <View style={circleStyle} />}</Animated.View>\n\n {labelContent}\n </Pressable>\n );\n});\n\nRadio.displayName = 'Radio';\n\nexport { Radio, type RadioProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"Radio.js","names":["Pressable"],"sources":["../../../src/components/Radio/Radio.tsx"],"sourcesContent":["import type { RadioVariant, UniversalRadioProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { ViewProps } from 'react-native';\nimport { View } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withSpring } from 'react-native-reanimated';\n\nimport { radioStyles } from '../../../generated/styles';\nimport { useFontScale } from '../../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { BUTTON_SPRING_CONFIG, SCALE_EFFECTS } from '../../motion';\nimport { FormLabel } from '../FormLabel';\nimport { Pressable } from '../Pressable';\nimport { useRadioGroupContext } from './RadioGroupContext';\n\n/* -------------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------------- */\n\n/** Derived from RadioValue - maps boolean to 'checked'/'unchecked' string literals */\ntype RadioValueState = 'checked' | 'unchecked';\n\ninterface RadioProps extends Omit<ViewProps, 'style'>, UniversalRadioProps {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Default checked state for uncontrolled mode */\n defaultChecked?: boolean;\n /** Whether the radio is disabled */\n disabled?: boolean;\n /** Whether the radio is required */\n required?: boolean;\n /**\n * Caps how far the circle, dot, and label grow with the OS text-size\n * setting; all three 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 /** Callback fired when the checked state changes */\n onChange?: (checked: boolean) => void;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Variant Mapping */\n/* -------------------------------------------------------------------------- */\n\n/** All style variants available in the generated styles (includes error variants) */\ntype RadioStyleVariant = 'primary' | 'secondary' | 'alert' | 'alert-secondary';\n\nconst VARIANT_ERROR_MAP: Record<RadioVariant, RadioStyleVariant> = {\n primary: 'alert',\n secondary: 'alert-secondary',\n};\n\n/* -------------------------------------------------------------------------- */\n/* Radio Component */\n/* -------------------------------------------------------------------------- */\n\n/**\n * **⚙️ A radio component**\n *\n * @description\n * A radio component allows users to select one option from a set.\n * Unlike checkbox, radio buttons cannot have multiple selected in a group,\n * allowing only one selection at a time.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Radio } from '@yahoo/uds-mobile/Radio';\n *\n * <Radio label=\"Option A\" />\n * <Radio label=\"Option B\" checked={true} onChange={setChecked} />\n * ```\n *\n * @usage\n * - Forms: For selecting a single option from multiple choices\n * - Settings: For toggling between mutually exclusive preferences\n *\n * @accessibility\n * - Sets `accessibilityRole=\"radio\"` automatically\n * - Announces checked/unchecked state\n * - Label is used as accessibility label\n * - Supports `reduceMotion` for users who prefer reduced motion\n *\n * @see {@link Checkbox} for multi-select options\n * @see {@link Switch} for binary toggles\n */\nconst Radio = memo(function Radio({\n // Radio props\n label,\n labelPosition = 'start',\n variant: variantInput,\n size: sizeInput,\n value: valueProp,\n checked: checkedProp,\n hasError: hasErrorProp,\n reduceMotion: reduceMotionProp,\n // Native props\n defaultChecked,\n disabled: disabledProp,\n required,\n maxFontSizeMultiplier,\n onChange,\n ref,\n ...viewProps\n}: RadioProps) {\n const generatedId = useId();\n const uid = `uds-radio-${generatedId}`;\n const radioGroup = useRadioGroupContext();\n\n // One resolved cap governs circle, dot, and label. Android resolves the\n // geometry from the circle's base size on its nonlinear curve.\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n\n const disabled = Boolean(disabledProp || radioGroup?.disabled);\n const hasError = hasErrorProp ?? radioGroup?.hasError;\n const reduceMotion = reduceMotionProp ?? radioGroup?.reduceMotion;\n const size = sizeInput ?? radioGroup?.size ?? 'md';\n const variantProp = variantInput ?? radioGroup?.variant ?? 'primary';\n const value = valueProp ?? '';\n\n /* --------------------------------- State ---------------------------------- */\n const isInRadioGroup = radioGroup !== undefined;\n const isControlled = checkedProp !== undefined;\n const [internalChecked, setInternalChecked] = useState<boolean>(\n isControlled ? checkedProp : (defaultChecked ?? false),\n );\n const [pressed, setPressed] = useState(false);\n\n // Use controlled value if provided, otherwise use internal state\n const checked = isInRadioGroup\n ? radioGroup.value === value\n : isControlled\n ? checkedProp\n : internalChecked;\n\n useEffect(() => {\n if (!__DEV__ || !isInRadioGroup || valueProp) {\n return;\n }\n\n console.warn(\n '[UDS Mobile] Radio: A Radio rendered inside RadioGroup requires a unique, non-empty value prop.',\n );\n }, [isInRadioGroup, valueProp]);\n\n /* ------------------------------ Derived Values ---------------------------- */\n const valueState: RadioValueState = useMemo(() => {\n return checked ? 'checked' : 'unchecked';\n }, [checked]);\n\n /* -------------------------------- Animation ------------------------------- */\n const shouldAnimate = !reduceMotion;\n\n // Scale animation for press feedback (disabled when reduceMotion is true)\n const scaleProgress = useDerivedValue(\n () =>\n shouldAnimate\n ? withSpring(pressed ? SCALE_EFFECTS.down : SCALE_EFFECTS.none, BUTTON_SPRING_CONFIG)\n : SCALE_EFFECTS.none, // No scale effect when reduceMotion is true\n [pressed, shouldAnimate],\n );\n\n const radioAnimatedStyle = useAnimatedStyle(() => ({\n transform: [{ scale: scaleProgress.value }],\n }));\n\n /* -------------------------------- Handlers -------------------------------- */\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n if (isInRadioGroup) {\n if (radioGroup.value === value) {\n return;\n }\n\n radioGroup.setValue(value);\n onChange?.(true);\n return;\n }\n\n const newChecked = !checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(newChecked);\n }, [disabled, isInRadioGroup, checked, isControlled, onChange, radioGroup, value]);\n\n const handlePressIn = useCallback(() => {\n setPressed(true);\n }, []);\n\n const handlePressOut = useCallback(() => {\n setPressed(false);\n }, []);\n\n /* --------------------------------- Styles --------------------------------- */\n // Compute the style variant (primary/secondary maps to alert variants when hasError)\n const styleVariant: RadioStyleVariant = hasError ? VARIANT_ERROR_MAP[variantProp] : variantProp;\n\n radioStyles.useVariants({\n size,\n variant: styleVariant, // primary, secondary, alert, alert-secondary\n value: valueState, // checked, unchecked\n pressed,\n });\n\n const radioBaseSize = radioStyles.radio.width;\n const fontScaleFactor = useFontScale(\n resolvedMaxFontSizeMultiplier,\n typeof radioBaseSize === 'number' ? radioBaseSize : undefined,\n );\n\n const rootStyle = useMemo(\n () => [radioStyles.root, { opacity: disabled ? 0.5 : 1 }],\n [radioStyles.root, disabled],\n );\n\n const radioBoxStyle = useMemo(() => {\n // The circle grows by the capped factor alongside its label; borderWidth\n // stays fixed (stroke weight doesn't scale in the OS's own controls).\n const { width, height } = radioStyles.radio;\n const scaledBox =\n fontScaleFactor !== 1 && typeof width === 'number' && typeof height === 'number'\n ? {\n width: Math.round(width * fontScaleFactor),\n height: Math.round(height * fontScaleFactor),\n }\n : undefined;\n\n return [\n radioStyles.radio,\n scaledBox,\n {\n alignItems: 'center' as const,\n justifyContent: 'center' as const,\n borderRadius: 9999,\n },\n radioAnimatedStyle,\n ];\n }, [radioStyles.radio, fontScaleFactor, radioAnimatedStyle]);\n\n // Inner circle size: fixed 8x8px to match web implementation\n const INNER_CIRCLE_SIZE = 8;\n\n const circleStyle = useMemo(\n () => [\n radioStyles.radioCircle,\n {\n width: Math.round(INNER_CIRCLE_SIZE * fontScaleFactor),\n height: Math.round(INNER_CIRCLE_SIZE * fontScaleFactor),\n borderRadius: 9999,\n },\n ],\n [radioStyles.radioCircle, fontScaleFactor],\n );\n\n /* ---------------------------- Render Helpers ------------------------------ */\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n return (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n hasError={hasError}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={radioStyles.text}\n />\n );\n }, [label, required, hasError, resolvedMaxFontSizeMultiplier, radioStyles.text]);\n\n const a11yState = useMemo(\n () => ({\n disabled,\n checked,\n }),\n [disabled, checked],\n );\n\n /* --------------------------------- Render --------------------------------- */\n return (\n <Pressable\n ref={ref}\n nativeID={uid}\n onPress={handlePress}\n onPressIn={handlePressIn}\n onPressOut={handlePressOut}\n disabled={disabled}\n flexDirection={labelPosition === 'start' ? 'row' : 'row-reverse'}\n alignItems=\"center\"\n alignSelf=\"flex-start\"\n accessibilityRole=\"radio\"\n accessibilityState={a11yState}\n accessibilityLabel={typeof label === 'string' ? label : undefined}\n {...viewProps}\n style={rootStyle}\n >\n <Animated.View style={radioBoxStyle}>{checked && <View style={circleStyle} />}</Animated.View>\n\n {labelContent}\n </Pressable>\n );\n});\n\nRadio.displayName = 'Radio';\n\nexport { Radio, type RadioProps };\n"],"mappings":"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"}
@@ -56,16 +56,28 @@ const Select = (0, react.memo)(function Select({ label, helpText, helperTextIcon
56
56
  }
57
57
  });
58
58
  const registerItem = (0, react.useCallback)((itemValue, itemLabel) => {
59
- if (itemsRef.current.get(itemValue) === itemLabel) return;
60
- itemsRef.current.set(itemValue, itemLabel);
59
+ const existing = itemsRef.current.get(itemValue);
60
+ itemsRef.current.set(itemValue, {
61
+ label: itemLabel,
62
+ registrations: (existing?.registrations ?? 0) + 1
63
+ });
64
+ if (existing?.label === itemLabel) return;
61
65
  setItemsVersion((version) => version + 1);
62
66
  }, []);
63
67
  const unregisterItem = (0, react.useCallback)((itemValue) => {
64
- if (!itemsRef.current.has(itemValue)) return;
68
+ const existing = itemsRef.current.get(itemValue);
69
+ if (!existing) return;
70
+ if (existing.registrations > 1) {
71
+ itemsRef.current.set(itemValue, {
72
+ ...existing,
73
+ registrations: existing.registrations - 1
74
+ });
75
+ return;
76
+ }
65
77
  itemsRef.current.delete(itemValue);
66
78
  setItemsVersion((version) => version + 1);
67
79
  }, []);
68
- const getItemLabel = (0, react.useCallback)((itemValue) => itemsRef.current.get(itemValue), []);
80
+ const getItemLabel = (0, react.useCallback)((itemValue) => itemsRef.current.get(itemValue)?.label, []);
69
81
  const fieldContext = (0, react.useMemo)(() => ({
70
82
  size,
71
83
  disabled,
@@ -54,16 +54,28 @@ const Select = memo(function Select({ label, helpText, helperTextIcon, placehold
54
54
  }
55
55
  });
56
56
  const registerItem = useCallback((itemValue, itemLabel) => {
57
- if (itemsRef.current.get(itemValue) === itemLabel) return;
58
- itemsRef.current.set(itemValue, itemLabel);
57
+ const existing = itemsRef.current.get(itemValue);
58
+ itemsRef.current.set(itemValue, {
59
+ label: itemLabel,
60
+ registrations: (existing?.registrations ?? 0) + 1
61
+ });
62
+ if (existing?.label === itemLabel) return;
59
63
  setItemsVersion((version) => version + 1);
60
64
  }, []);
61
65
  const unregisterItem = useCallback((itemValue) => {
62
- if (!itemsRef.current.has(itemValue)) return;
66
+ const existing = itemsRef.current.get(itemValue);
67
+ if (!existing) return;
68
+ if (existing.registrations > 1) {
69
+ itemsRef.current.set(itemValue, {
70
+ ...existing,
71
+ registrations: existing.registrations - 1
72
+ });
73
+ return;
74
+ }
63
75
  itemsRef.current.delete(itemValue);
64
76
  setItemsVersion((version) => version + 1);
65
77
  }, []);
66
- const getItemLabel = useCallback((itemValue) => itemsRef.current.get(itemValue), []);
78
+ const getItemLabel = useCallback((itemValue) => itemsRef.current.get(itemValue)?.label, []);
67
79
  const fieldContext = useMemo(() => ({
68
80
  size,
69
81
  disabled,
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import type { UniversalSelectProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { ReactNode } from 'react';\nimport { memo, useCallback, useId, useMemo, useRef, useState } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../../generated/styles';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { HStack } from '../HStack';\nimport type { IconSlotType } from '../IconSlot';\nimport { InputHelpText } from '../InputHelpText';\nimport { useControllableState } from '../internal/Overlay';\nimport { Text } from '../Text';\nimport { VStack } from '../VStack';\nimport { SelectContext, SelectFieldContext } from './selectContext';\nimport { SelectTrigger } from './SelectTrigger';\nimport type { SelectContextValue, SelectFieldContextValue } from './types';\n\ninterface SelectProps extends Omit<UniversalSelectProps<IconSlotType>, 'width'> {\n /** Placeholder text shown when no value is selected. */\n placeholder?: string;\n /** Selected value for controlled usage. */\n value?: string;\n /** Initial value for uncontrolled usage. @default '' */\n defaultValue?: string;\n /** Called when the selected value changes. */\n onChange?: (value: string) => void;\n /** Container width. @default '100%' */\n width?: number | `${number}%` | '100%';\n /** Caps text, icons, and field geometry at the control scale. Set null to remove the cap. @default 2 */\n maxFontSizeMultiplier?: number | null;\n children?: ReactNode;\n testID?: string;\n}\n\n/**\n * **⚙️ A composable Select component**\n *\n * @description\n * Select lets users pick one value from a list. Compose with `SelectContent` and\n * `SelectItem`, similar to `Tabs` with `TabList` and `Tab`.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Select, SelectContent, SelectItem } from '@yahoo/uds-mobile/Select';\n *\n * <Select label=\"Country\" placeholder=\"Select a country\" defaultValue=\"us\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"ca\">Canada</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nconst Select = memo(function Select({\n label,\n helpText,\n helperTextIcon,\n placeholder,\n size = 'md',\n disabled,\n required,\n hasError,\n readOnly,\n width = '100%',\n maxFontSizeMultiplier,\n reduceMotion = false,\n startIcon,\n endIcon,\n value: valueProp,\n defaultValue = '',\n onChange,\n children,\n testID,\n}: SelectProps) {\n const generatedId = useId();\n const uid = `uds-select-${generatedId}`;\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const triggerRef = useRef<View | null>(null);\n const [triggerRect, setTriggerRect] = useState<SelectContextValue['triggerRect']>(null);\n const [highlightedValue, setHighlightedValue] = useState<string | null>(null);\n const itemsRef = useRef(new Map<string, string>());\n const [, setItemsVersion] = useState(0);\n\n const [value, setValue] = useControllableState({\n value: valueProp,\n defaultValue,\n onChange,\n });\n\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: (nextOpen) => {\n if (!nextOpen) {\n setHighlightedValue(null);\n }\n },\n });\n\n const registerItem = useCallback((itemValue: string, itemLabel: string) => {\n if (itemsRef.current.get(itemValue) === itemLabel) {\n return;\n }\n\n itemsRef.current.set(itemValue, itemLabel);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const unregisterItem = useCallback((itemValue: string) => {\n if (!itemsRef.current.has(itemValue)) {\n return;\n }\n\n itemsRef.current.delete(itemValue);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const getItemLabel = useCallback((itemValue: string) => itemsRef.current.get(itemValue), []);\n\n const fieldContext = useMemo<SelectFieldContextValue>(\n () => ({\n size,\n disabled,\n readOnly,\n required,\n hasError,\n width,\n reduceMotion,\n placeholder,\n uid,\n maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,\n }),\n [\n disabled,\n hasError,\n placeholder,\n readOnly,\n reduceMotion,\n required,\n resolvedMaxFontSizeMultiplier,\n size,\n uid,\n width,\n ],\n );\n\n const contextValue = useMemo<SelectContextValue>(\n () => ({\n value,\n setValue,\n open,\n setOpen,\n triggerRef,\n triggerRect,\n setTriggerRect,\n registerItem,\n unregisterItem,\n getItemLabel,\n highlightedValue,\n setHighlightedValue,\n field: fieldContext,\n reduceMotion,\n }),\n [\n fieldContext,\n getItemLabel,\n highlightedValue,\n open,\n reduceMotion,\n registerItem,\n setOpen,\n setValue,\n triggerRect,\n unregisterItem,\n value,\n ],\n );\n\n const hasValue = value.length > 0;\n const valueState = hasValue ? 'filled' : 'empty';\n\n inputStyles.useVariants({\n size,\n value: valueState,\n pressed: open,\n readonly: readOnly,\n invalid: hasError,\n });\n\n const rootStyle = useMemo(() => [{ width, opacity: disabled ? 0.5 : 1 }], [disabled, width]);\n\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n const content = isFunction(label) ? label() : label;\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-end\" spacingBottom=\"2\">\n <Text maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier} style={inputStyles.label}>\n {content}\n </Text>\n {required && (\n <Text\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 helpTextContent = useMemo(() => {\n if (!helpText) {\n return null;\n }\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={open}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n >\n {content}\n </InputHelpText>\n );\n }, [\n disabled,\n hasError,\n helpText,\n helperTextIcon,\n open,\n readOnly,\n resolvedMaxFontSizeMultiplier,\n size,\n valueState,\n ]);\n\n return (\n <SelectContext.Provider value={contextValue}>\n <SelectFieldContext.Provider value={fieldContext}>\n <VStack testID={testID} style={rootStyle}>\n {labelContent}\n\n <SelectTrigger startIcon={startIcon} endIcon={endIcon} />\n\n {helpTextContent}\n\n {children}\n </VStack>\n </SelectFieldContext.Provider>\n </SelectContext.Provider>\n );\n});\n\nSelect.displayName = 'Select';\n\nexport { Select, type SelectProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"Select.js","names":[],"sources":["../../../src/components/Select/Select.tsx"],"sourcesContent":["import type { UniversalSelectProps } from '@yahoo/uds-types';\nimport { isFunction } from 'lodash-es';\nimport type { ReactNode } from 'react';\nimport { memo, useCallback, useId, useMemo, useRef, useState } from 'react';\nimport type { View } from 'react-native';\n\nimport { inputStyles } from '../../../generated/styles';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport { HStack } from '../HStack';\nimport type { IconSlotType } from '../IconSlot';\nimport { InputHelpText } from '../InputHelpText';\nimport { useControllableState } from '../internal/Overlay';\nimport { Text } from '../Text';\nimport { VStack } from '../VStack';\nimport { SelectContext, SelectFieldContext } from './selectContext';\nimport { SelectTrigger } from './SelectTrigger';\nimport type { SelectContextValue, SelectFieldContextValue } from './types';\n\ninterface SelectProps extends Omit<UniversalSelectProps<IconSlotType>, 'width'> {\n /** Placeholder text shown when no value is selected. */\n placeholder?: string;\n /** Selected value for controlled usage. */\n value?: string;\n /** Initial value for uncontrolled usage. @default '' */\n defaultValue?: string;\n /** Called when the selected value changes. */\n onChange?: (value: string) => void;\n /** Container width. @default '100%' */\n width?: number | `${number}%` | '100%';\n /** Caps text, icons, and field geometry at the control scale. Set null to remove the cap. @default 2 */\n maxFontSizeMultiplier?: number | null;\n children?: ReactNode;\n testID?: string;\n}\n\n/**\n * **⚙️ A composable Select component**\n *\n * @description\n * Select lets users pick one value from a list. Compose with `SelectContent` and\n * `SelectItem`, similar to `Tabs` with `TabList` and `Tab`.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Select, SelectContent, SelectItem } from '@yahoo/uds-mobile/Select';\n *\n * <Select label=\"Country\" placeholder=\"Select a country\" defaultValue=\"us\">\n * <SelectContent>\n * <SelectItem value=\"us\">United States</SelectItem>\n * <SelectItem value=\"ca\">Canada</SelectItem>\n * </SelectContent>\n * </Select>\n * ```\n */\nconst Select = memo(function Select({\n label,\n helpText,\n helperTextIcon,\n placeholder,\n size = 'md',\n disabled,\n required,\n hasError,\n readOnly,\n width = '100%',\n maxFontSizeMultiplier,\n reduceMotion = false,\n startIcon,\n endIcon,\n value: valueProp,\n defaultValue = '',\n onChange,\n children,\n testID,\n}: SelectProps) {\n const generatedId = useId();\n const uid = `uds-select-${generatedId}`;\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const triggerRef = useRef<View | null>(null);\n const [triggerRect, setTriggerRect] = useState<SelectContextValue['triggerRect']>(null);\n const [highlightedValue, setHighlightedValue] = useState<string | null>(null);\n // Android's portal can briefly overlap the hidden registry item and its visible copy.\n // Count registrations so one copy unmounting does not erase the selected value's label.\n const itemsRef = useRef(new Map<string, { label: string; registrations: number }>());\n const [, setItemsVersion] = useState(0);\n\n const [value, setValue] = useControllableState({\n value: valueProp,\n defaultValue,\n onChange,\n });\n\n const [open, setOpen] = useControllableState({\n defaultValue: false,\n onChange: (nextOpen) => {\n if (!nextOpen) {\n setHighlightedValue(null);\n }\n },\n });\n\n const registerItem = useCallback((itemValue: string, itemLabel: string) => {\n const existing = itemsRef.current.get(itemValue);\n itemsRef.current.set(itemValue, {\n label: itemLabel,\n registrations: (existing?.registrations ?? 0) + 1,\n });\n\n if (existing?.label === itemLabel) {\n return;\n }\n\n setItemsVersion((version) => version + 1);\n }, []);\n\n const unregisterItem = useCallback((itemValue: string) => {\n const existing = itemsRef.current.get(itemValue);\n if (!existing) {\n return;\n }\n\n if (existing.registrations > 1) {\n itemsRef.current.set(itemValue, {\n ...existing,\n registrations: existing.registrations - 1,\n });\n return;\n }\n\n itemsRef.current.delete(itemValue);\n setItemsVersion((version) => version + 1);\n }, []);\n\n const getItemLabel = useCallback(\n (itemValue: string) => itemsRef.current.get(itemValue)?.label,\n [],\n );\n\n const fieldContext = useMemo<SelectFieldContextValue>(\n () => ({\n size,\n disabled,\n readOnly,\n required,\n hasError,\n width,\n reduceMotion,\n placeholder,\n uid,\n maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,\n }),\n [\n disabled,\n hasError,\n placeholder,\n readOnly,\n reduceMotion,\n required,\n resolvedMaxFontSizeMultiplier,\n size,\n uid,\n width,\n ],\n );\n\n const contextValue = useMemo<SelectContextValue>(\n () => ({\n value,\n setValue,\n open,\n setOpen,\n triggerRef,\n triggerRect,\n setTriggerRect,\n registerItem,\n unregisterItem,\n getItemLabel,\n highlightedValue,\n setHighlightedValue,\n field: fieldContext,\n reduceMotion,\n }),\n [\n fieldContext,\n getItemLabel,\n highlightedValue,\n open,\n reduceMotion,\n registerItem,\n setOpen,\n setValue,\n triggerRect,\n unregisterItem,\n value,\n ],\n );\n\n const hasValue = value.length > 0;\n const valueState = hasValue ? 'filled' : 'empty';\n\n inputStyles.useVariants({\n size,\n value: valueState,\n pressed: open,\n readonly: readOnly,\n invalid: hasError,\n });\n\n const rootStyle = useMemo(() => [{ width, opacity: disabled ? 0.5 : 1 }], [disabled, width]);\n\n const labelContent = useMemo(() => {\n if (!label) {\n return null;\n }\n\n const content = isFunction(label) ? label() : label;\n return (\n <HStack columnGap=\"1\" alignItems=\"flex-end\" spacingBottom=\"2\">\n <Text maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier} style={inputStyles.label}>\n {content}\n </Text>\n {required && (\n <Text\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 helpTextContent = useMemo(() => {\n if (!helpText) {\n return null;\n }\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={open}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n >\n {content}\n </InputHelpText>\n );\n }, [\n disabled,\n hasError,\n helpText,\n helperTextIcon,\n open,\n readOnly,\n resolvedMaxFontSizeMultiplier,\n size,\n valueState,\n ]);\n\n return (\n <SelectContext.Provider value={contextValue}>\n <SelectFieldContext.Provider value={fieldContext}>\n <VStack testID={testID} style={rootStyle}>\n {labelContent}\n\n <SelectTrigger startIcon={startIcon} endIcon={endIcon} />\n\n {helpTextContent}\n\n {children}\n </VStack>\n </SelectFieldContext.Provider>\n </SelectContext.Provider>\n );\n});\n\nSelect.displayName = 'Select';\n\nexport { Select, type SelectProps };\n"],"mappings":"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"}
@@ -31,7 +31,9 @@ const OFFSCREEN_REGISTRY_STYLE = react_native.StyleSheet.create({ registry: {
31
31
  * Floating listbox container for {@link SelectItem} options.
32
32
  */
33
33
  const SelectContent = (0, react.memo)(function SelectContent({ children, size: _size = "default", variant: _variant = "default", keepOpenOnInteractOutside = false, maxHeight = DEFAULT_MAX_HEIGHT, gutter = DEFAULT_OFFSET, sameWidth = true, style, testID }) {
34
- const { open, setOpen, triggerRect, reduceMotion } = require_components_Select_selectContext.useSelectContext();
34
+ const selectContext = require_components_Select_selectContext.useSelectContext();
35
+ const fieldContext = require_components_Select_selectContext.useSelectFieldContext();
36
+ const { open, setOpen, triggerRect, reduceMotion } = selectContext;
35
37
  const [contentSize, setContentSize] = (0, react.useState)({
36
38
  width: 0,
37
39
  height: 0
@@ -115,28 +117,34 @@ const SelectContent = (0, react.memo)(function SelectContent({ children, size: _
115
117
  open,
116
118
  dismissible: !keepOpenOnInteractOutside,
117
119
  onDismiss: dismiss,
118
- children: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
119
- testID,
120
- style: [
121
- contentStyle,
122
- animatedStyle,
123
- {
124
- overflow: "visible",
125
- zIndex: 1e3
126
- }
127
- ],
128
- onLayout: handleLayout,
129
- accessibilityRole: "menu",
130
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
131
- style: panelStyle,
132
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
133
- keyboardShouldPersistTaps: "handled",
134
- nestedScrollEnabled: true,
135
- style: { maxHeight },
136
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_VStack.VStack, {
137
- alignItems: "stretch",
138
- justifyContent: "flex-start",
139
- children
120
+ children: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Select_selectContext.SelectContext.Provider, {
121
+ value: selectContext,
122
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_Select_selectContext.SelectFieldContext.Provider, {
123
+ value: fieldContext,
124
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
125
+ testID,
126
+ style: [
127
+ contentStyle,
128
+ animatedStyle,
129
+ {
130
+ overflow: "visible",
131
+ zIndex: 1e3
132
+ }
133
+ ],
134
+ onLayout: handleLayout,
135
+ accessibilityRole: "menu",
136
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.View, {
137
+ style: panelStyle,
138
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native.ScrollView, {
139
+ keyboardShouldPersistTaps: "handled",
140
+ nestedScrollEnabled: true,
141
+ style: { maxHeight },
142
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_components_VStack.VStack, {
143
+ alignItems: "stretch",
144
+ justifyContent: "flex-start",
145
+ children
146
+ })
147
+ })
140
148
  })
141
149
  })
142
150
  })
@@ -1 +1 @@
1
- {"version":3,"file":"SelectContent.d.cts","names":[],"sources":["../../../src/components/Select/SelectContent.tsx"],"mappings":";;;;;;;UAmCU,kBAAA;EACR,QAAA,GAAW,SAAA;EACX,IAAA,GAAO,iBAAA;EACP,OAAA,GAAU,oBAAA;EAHgB;EAK1B,yBAAA;EAJW;EAMX,SAAA;EAJU;EAMV,MAAA;EAGQ;EADR,SAAA;EACA,KAAA,GAAQ,SAAA,CAAU,SAAA;EAClB,MAAA;AAAA;;;;;;cAQI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
1
+ {"version":3,"file":"SelectContent.d.cts","names":[],"sources":["../../../src/components/Select/SelectContent.tsx"],"mappings":";;;;;;;UAwCU,kBAAA;EACR,QAAA,GAAW,SAAA;EACX,IAAA,GAAO,iBAAA;EACP,OAAA,GAAU,oBAAA;EAHgB;EAK1B,yBAAA;EAJW;EAMX,SAAA;EAJU;EAMV,MAAA;EAGQ;EADR,SAAA;EACA,KAAA,GAAQ,SAAA,CAAU,SAAA;EAClB,MAAA;AAAA;;;;;;cAQI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"SelectContent.d.ts","names":[],"sources":["../../../src/components/Select/SelectContent.tsx"],"mappings":";;;;;;;UAmCU,kBAAA;EACR,QAAA,GAAW,SAAA;EACX,IAAA,GAAO,iBAAA;EACP,OAAA,GAAU,oBAAA;EAHgB;EAK1B,yBAAA;EAJW;EAMX,SAAA;EAJU;EAMV,MAAA;EAGQ;EADR,SAAA;EACA,KAAA,GAAQ,SAAA,CAAU,SAAA;EAClB,MAAA;AAAA;;;;;;cAQI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}
1
+ {"version":3,"file":"SelectContent.d.ts","names":[],"sources":["../../../src/components/Select/SelectContent.tsx"],"mappings":";;;;;;;UAwCU,kBAAA;EACR,QAAA,GAAW,SAAA;EACX,IAAA,GAAO,iBAAA;EACP,OAAA,GAAU,oBAAA;EAHgB;EAK1B,yBAAA;EAJW;EAMX,SAAA;EAJU;EAMV,MAAA;EAGQ;EADR,SAAA;EACA,KAAA,GAAQ,SAAA,CAAU,SAAA;EAClB,MAAA;AAAA;;;;;;cAQI,aAAA,EAAa,OAAA,CAAA,oBAAA,CAAA,kBAAA"}