@yahoo/uds-mobile 2.24.0-beta.8 → 2.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +1 -0
  2. package/dist/components/Avatar/useAvatarFontScale.cjs +2 -2
  3. package/dist/components/Avatar/useAvatarFontScale.js +3 -3
  4. package/dist/components/Avatar/useAvatarFontScale.js.map +1 -1
  5. package/dist/components/Button.cjs +4 -3
  6. package/dist/components/Button.js +5 -4
  7. package/dist/components/Button.js.map +1 -1
  8. package/dist/components/Checkbox.cjs +2 -2
  9. package/dist/components/Checkbox.js +3 -3
  10. package/dist/components/Checkbox.js.map +1 -1
  11. package/dist/components/Chip/ChipBase.cjs +1 -1
  12. package/dist/components/Chip/ChipBase.js +2 -2
  13. package/dist/components/Chip/ChipBase.js.map +1 -1
  14. package/dist/components/Icon.cjs +6 -5
  15. package/dist/components/Icon.d.cts +2 -0
  16. package/dist/components/Icon.d.cts.map +1 -1
  17. package/dist/components/Icon.d.ts +2 -0
  18. package/dist/components/Icon.d.ts.map +1 -1
  19. package/dist/components/Icon.js +7 -6
  20. package/dist/components/Icon.js.map +1 -1
  21. package/dist/components/IconButton.cjs +1 -1
  22. package/dist/components/IconButton.js +2 -2
  23. package/dist/components/IconButton.js.map +1 -1
  24. package/dist/components/Input.cjs +2 -1
  25. package/dist/components/Input.js +3 -2
  26. package/dist/components/Input.js.map +1 -1
  27. package/dist/components/InputHelpText.cjs +1 -0
  28. package/dist/components/InputHelpText.js +1 -0
  29. package/dist/components/InputHelpText.js.map +1 -1
  30. package/dist/components/Link.cjs +6 -2
  31. package/dist/components/Link.js +7 -3
  32. package/dist/components/Link.js.map +1 -1
  33. package/dist/components/Pagination/PaginationEllipsis.cjs +1 -1
  34. package/dist/components/Pagination/PaginationEllipsis.js +2 -2
  35. package/dist/components/Pagination/PaginationEllipsis.js.map +1 -1
  36. package/dist/components/Pagination/usePaginationControlStyles.cjs +1 -1
  37. package/dist/components/Pagination/usePaginationControlStyles.js +2 -2
  38. package/dist/components/Pagination/usePaginationControlStyles.js.map +1 -1
  39. package/dist/components/Radio/Radio.cjs +1 -1
  40. package/dist/components/Radio/Radio.js +2 -2
  41. package/dist/components/Radio/Radio.js.map +1 -1
  42. package/dist/components/Select/Select.cjs +1 -0
  43. package/dist/components/Select/Select.js +1 -0
  44. package/dist/components/Select/Select.js.map +1 -1
  45. package/dist/components/Select/SelectItem.cjs +1 -4
  46. package/dist/components/Select/SelectItem.d.cts.map +1 -1
  47. package/dist/components/Select/SelectItem.d.ts.map +1 -1
  48. package/dist/components/Select/SelectItem.js +2 -5
  49. package/dist/components/Select/SelectItem.js.map +1 -1
  50. package/dist/components/Select/SelectTrigger.cjs +1 -4
  51. package/dist/components/Select/SelectTrigger.d.cts.map +1 -1
  52. package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
  53. package/dist/components/Select/SelectTrigger.js +2 -5
  54. package/dist/components/Select/SelectTrigger.js.map +1 -1
  55. package/dist/components/Switch.cjs +4 -4
  56. package/dist/components/Switch.js +5 -5
  57. package/dist/components/Switch.js.map +1 -1
  58. package/dist/components/Tabs/Tab.cjs +1 -1
  59. package/dist/components/Tabs/Tab.js +2 -2
  60. package/dist/components/Tabs/Tab.js.map +1 -1
  61. package/dist/components/Text.cjs +1 -1
  62. package/dist/components/Text.js +2 -2
  63. package/dist/components/Text.js.map +1 -1
  64. package/dist/components/UDSProvider.cjs +6 -3
  65. package/dist/components/UDSProvider.d.cts.map +1 -1
  66. package/dist/components/UDSProvider.d.ts.map +1 -1
  67. package/dist/components/UDSProvider.js +8 -5
  68. package/dist/components/UDSProvider.js.map +1 -1
  69. package/dist/fontScaling/FontScalingContext.cjs +14 -3
  70. package/dist/fontScaling/FontScalingContext.d.cts +8 -2
  71. package/dist/fontScaling/FontScalingContext.d.cts.map +1 -1
  72. package/dist/fontScaling/FontScalingContext.d.ts +8 -2
  73. package/dist/fontScaling/FontScalingContext.d.ts.map +1 -1
  74. package/dist/fontScaling/FontScalingContext.js +14 -4
  75. package/dist/fontScaling/FontScalingContext.js.map +1 -1
  76. package/dist/fontScaling/androidNonlinearFontScaling.cjs +85 -9
  77. package/dist/fontScaling/androidNonlinearFontScaling.d.cts +2 -2
  78. package/dist/fontScaling/androidNonlinearFontScaling.d.cts.map +1 -1
  79. package/dist/fontScaling/androidNonlinearFontScaling.d.ts +2 -2
  80. package/dist/fontScaling/androidNonlinearFontScaling.d.ts.map +1 -1
  81. package/dist/fontScaling/androidNonlinearFontScaling.js +85 -9
  82. package/dist/fontScaling/androidNonlinearFontScaling.js.map +1 -1
  83. package/dist/fontScaling/useFontScale.cjs +18 -5
  84. package/dist/fontScaling/useFontScale.d.cts +6 -18
  85. package/dist/fontScaling/useFontScale.d.cts.map +1 -1
  86. package/dist/fontScaling/useFontScale.d.ts +6 -18
  87. package/dist/fontScaling/useFontScale.d.ts.map +1 -1
  88. package/dist/fontScaling/useFontScale.js +18 -6
  89. package/dist/fontScaling/useFontScale.js.map +1 -1
  90. package/dist/mobile/generated/fontMetrics.cjs +4 -4
  91. package/dist/mobile/generated/fontMetrics.js +4 -4
  92. package/dist/mobile/generated/fontMetrics.js.map +1 -1
  93. package/dist/types/dist/index.d.cts +4 -0
  94. package/dist/types/dist/index.d.cts.map +1 -1
  95. package/dist/types/dist/index.d.ts +4 -0
  96. package/dist/types/dist/index.d.ts.map +1 -1
  97. package/fonts/uds-icons.ttf +0 -0
  98. package/generated/fontMetrics.ts +4 -4
  99. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Tab.js","names":["RNText","Pressable"],"sources":["../../../src/components/Tabs/Tab.tsx"],"sourcesContent":["import type { UniversalTabProps } from '@yahoo/uds-types';\nimport type { ReactElement, ReactNode } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { LayoutChangeEvent, PressableProps, TextStyle, ViewStyle } from 'react-native';\nimport { Text as RNText, View } from 'react-native';\n// eslint-disable-next-line uds/no-use-unistyles -- theme.components path lookups for tab layers\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport { ResolvedControlFontScalingProvider } from '../../fontScaling/FontScalingContext';\nimport { useFontScale } from '../../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport type { IconSlotType } from '../IconSlot';\nimport { IconSlot } from '../IconSlot';\nimport { Pressable } from '../Pressable';\nimport { useTabSelectionContext, useTabsVisualContext } from './tabsContexts';\nimport { getMergedTabLayerStyle, getTabLayerStyle } from './tabTheme';\n\nconst PRIMARY_TAB_UNDERLINE_HEIGHT = 2;\n\ninterface TabProps\n extends\n Omit<PressableProps, 'children' | 'style' | 'disabled' | 'onPress'>,\n Omit<UniversalTabProps, 'asChild' | 'className' | 'startIcon' | 'endIcon'> {\n children: UniversalTabProps['children'];\n startIcon?: IconSlotType;\n endIcon?: IconSlotType;\n style?: ViewStyle;\n}\n\nconst CLEAR_SELECTION_CHROME: ViewStyle = {\n backgroundColor: 'transparent',\n borderWidth: 0,\n borderColor: 'transparent',\n shadowOpacity: 0,\n elevation: 0,\n boxShadow: [],\n};\n\nfunction TabLabel({\n style,\n maxFontSizeMultiplier,\n children,\n}: {\n style: TextStyle;\n maxFontSizeMultiplier?: number;\n children: ReactNode;\n}) {\n if (typeof children === 'string' || typeof children === 'number') {\n return (\n <RNText style={style} maxFontSizeMultiplier={maxFontSizeMultiplier}>\n {children}\n </RNText>\n );\n }\n return (\n <ResolvedControlFontScalingProvider maxFontSizeMultiplier={maxFontSizeMultiplier}>\n {children as ReactElement}\n </ResolvedControlFontScalingProvider>\n );\n}\n\n/**\n * **⚙️ Tab**\n *\n * @description\n * A single selectable tab. Must be used inside {@link TabList} within {@link Tabs}.\n *\n * @category Navigation\n * @platform mobile\n */\nconst Tab = memo(function Tab({\n value,\n children,\n startIcon,\n endIcon,\n disabled,\n style,\n ...pressableRest\n}: TabProps) {\n const generatedId = useId();\n const uid = value ?? `uds-tab-${generatedId}`;\n const { variant: visualVariant, reduceMotion, maxFontSizeMultiplier } = useTabsVisualContext();\n const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } =\n useTabSelectionContext();\n const { theme } = useUnistyles();\n const [pressed, setPressed] = useState(false);\n\n // One capped factor governs the label, icons, and the tab's fixed height.\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier('control', maxFontSizeMultiplier);\n\n const selected = !disabled && selectedId === uid;\n const active: 'on' | 'off' = selected ? 'on' : 'off';\n const interaction: 'rest' | 'pressed' = pressed ? 'pressed' : 'rest';\n\n useEffect(() => {\n registerTab(uid);\n return () => {\n unregisterTab(uid);\n };\n }, [uid, registerTab, unregisterTab]);\n\n const rootBase = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'root', interaction) as ViewStyle,\n [theme, visualVariant, active, interaction],\n );\n const textStyle = useMemo(\n () =>\n getMergedTabLayerStyle(theme, visualVariant, active, 'rootText', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n const fontScaleFactor = useFontScale(\n resolvedMaxFontSizeMultiplier,\n (typeof textStyle.lineHeight === 'number' ? textStyle.lineHeight : undefined) ??\n (typeof textStyle.fontSize === 'number' ? textStyle.fontSize : undefined),\n );\n const iconStyle = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'icon', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n\n const iconColor = ((): StyleProps['color'] | undefined => {\n const c = iconStyle?.color;\n if (c === undefined || c === null) {\n return undefined;\n }\n return c as StyleProps['color'];\n })();\n\n /** Inactive primary tabs use transparent underline tokens on web; RN has no CSS vars for that layer. */\n const showPrimaryPerTabUnderline = visualVariant === 'primary' && !(selected && !reduceMotion);\n\n const primaryUnderlineColor = useMemo(() => {\n if (visualVariant !== 'primary') {\n return undefined;\n }\n if (selected && reduceMotion) {\n const onText = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as TextStyle;\n const c = onText.color;\n if (typeof c === 'string') {\n return c;\n }\n }\n return 'transparent';\n }, [visualVariant, selected, reduceMotion, theme]);\n\n const rootStyle = useMemo((): ViewStyle => {\n const base: ViewStyle = {\n ...rootBase,\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n zIndex: 1,\n position: 'relative',\n };\n // A fixed token height grows with the capped label so text never clips.\n if (fontScaleFactor !== 1 && typeof base.height === 'number') {\n base.height = Math.round(base.height * fontScaleFactor);\n }\n if (selected && !reduceMotion) {\n return { ...base, ...CLEAR_SELECTION_CHROME };\n }\n return base;\n }, [rootBase, fontScaleFactor, selected, reduceMotion]);\n\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n setTabLayout(uid, e.nativeEvent.layout);\n },\n [uid, setTabLayout],\n );\n\n const onPress = useCallback(() => {\n if (disabled) {\n return;\n }\n setSelectedId(uid);\n }, [disabled, setSelectedId, uid]);\n\n return (\n <Pressable\n accessibilityRole=\"tab\"\n accessibilityState={{ selected, disabled: !!disabled }}\n disabled={disabled}\n onPress={onPress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onLayout={onLayout}\n style={[rootStyle, style]}\n {...pressableRest}\n >\n {startIcon ? (\n <IconSlot\n icon={startIcon}\n size=\"sm\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n <TabLabel style={textStyle} maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}>\n {children}\n </TabLabel>\n {endIcon ? (\n <IconSlot\n icon={endIcon}\n size=\"sm\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n {showPrimaryPerTabUnderline &&\n primaryUnderlineColor &&\n primaryUnderlineColor !== 'transparent' ? (\n <View\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: PRIMARY_TAB_UNDERLINE_HEIGHT,\n backgroundColor: primaryUnderlineColor,\n }}\n />\n ) : null}\n </Pressable>\n );\n});\n\nTab.displayName = 'Tab';\n\nexport { Tab };\nexport type { TabProps };\n"],"mappings":"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"}
1
+ {"version":3,"file":"Tab.js","names":["RNText","Pressable"],"sources":["../../../src/components/Tabs/Tab.tsx"],"sourcesContent":["import type { UniversalTabProps } from '@yahoo/uds-types';\nimport type { ReactElement, ReactNode } from 'react';\nimport { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';\nimport type { LayoutChangeEvent, PressableProps, TextStyle, ViewStyle } from 'react-native';\nimport { Text as RNText, View } from 'react-native';\n// eslint-disable-next-line uds/no-use-unistyles -- theme.components path lookups for tab layers\nimport { useUnistyles } from 'react-native-unistyles';\n\nimport type { StyleProps } from '../../../generated/styles';\nimport { ResolvedControlFontScalingProvider } from '../../fontScaling/FontScalingContext';\nimport { useComponentFontScale } from '../../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../../fontScaling/useMaxFontSizeMultiplier';\nimport type { IconSlotType } from '../IconSlot';\nimport { IconSlot } from '../IconSlot';\nimport { Pressable } from '../Pressable';\nimport { useTabSelectionContext, useTabsVisualContext } from './tabsContexts';\nimport { getMergedTabLayerStyle, getTabLayerStyle } from './tabTheme';\n\nconst PRIMARY_TAB_UNDERLINE_HEIGHT = 2;\n\ninterface TabProps\n extends\n Omit<PressableProps, 'children' | 'style' | 'disabled' | 'onPress'>,\n Omit<UniversalTabProps, 'asChild' | 'className' | 'startIcon' | 'endIcon'> {\n children: UniversalTabProps['children'];\n startIcon?: IconSlotType;\n endIcon?: IconSlotType;\n style?: ViewStyle;\n}\n\nconst CLEAR_SELECTION_CHROME: ViewStyle = {\n backgroundColor: 'transparent',\n borderWidth: 0,\n borderColor: 'transparent',\n shadowOpacity: 0,\n elevation: 0,\n boxShadow: [],\n};\n\nfunction TabLabel({\n style,\n maxFontSizeMultiplier,\n children,\n}: {\n style: TextStyle;\n maxFontSizeMultiplier?: number;\n children: ReactNode;\n}) {\n if (typeof children === 'string' || typeof children === 'number') {\n return (\n <RNText style={style} maxFontSizeMultiplier={maxFontSizeMultiplier}>\n {children}\n </RNText>\n );\n }\n return (\n <ResolvedControlFontScalingProvider maxFontSizeMultiplier={maxFontSizeMultiplier}>\n {children as ReactElement}\n </ResolvedControlFontScalingProvider>\n );\n}\n\n/**\n * **⚙️ Tab**\n *\n * @description\n * A single selectable tab. Must be used inside {@link TabList} within {@link Tabs}.\n *\n * @category Navigation\n * @platform mobile\n */\nconst Tab = memo(function Tab({\n value,\n children,\n startIcon,\n endIcon,\n disabled,\n style,\n ...pressableRest\n}: TabProps) {\n const generatedId = useId();\n const uid = value ?? `uds-tab-${generatedId}`;\n const { variant: visualVariant, reduceMotion, maxFontSizeMultiplier } = useTabsVisualContext();\n const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } =\n useTabSelectionContext();\n const { theme } = useUnistyles();\n const [pressed, setPressed] = useState(false);\n\n // One capped factor governs the label, icons, and the tab's fixed height.\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier('control', maxFontSizeMultiplier);\n\n const selected = !disabled && selectedId === uid;\n const active: 'on' | 'off' = selected ? 'on' : 'off';\n const interaction: 'rest' | 'pressed' = pressed ? 'pressed' : 'rest';\n\n useEffect(() => {\n registerTab(uid);\n return () => {\n unregisterTab(uid);\n };\n }, [uid, registerTab, unregisterTab]);\n\n const rootBase = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'root', interaction) as ViewStyle,\n [theme, visualVariant, active, interaction],\n );\n const textStyle = useMemo(\n () =>\n getMergedTabLayerStyle(theme, visualVariant, active, 'rootText', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n const fontScaleFactor = useComponentFontScale(\n resolvedMaxFontSizeMultiplier,\n (typeof textStyle.lineHeight === 'number' ? textStyle.lineHeight : undefined) ??\n (typeof textStyle.fontSize === 'number' ? textStyle.fontSize : undefined),\n );\n const iconStyle = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'icon', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n\n const iconColor = ((): StyleProps['color'] | undefined => {\n const c = iconStyle?.color;\n if (c === undefined || c === null) {\n return undefined;\n }\n return c as StyleProps['color'];\n })();\n\n /** Inactive primary tabs use transparent underline tokens on web; RN has no CSS vars for that layer. */\n const showPrimaryPerTabUnderline = visualVariant === 'primary' && !(selected && !reduceMotion);\n\n const primaryUnderlineColor = useMemo(() => {\n if (visualVariant !== 'primary') {\n return undefined;\n }\n if (selected && reduceMotion) {\n const onText = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as TextStyle;\n const c = onText.color;\n if (typeof c === 'string') {\n return c;\n }\n }\n return 'transparent';\n }, [visualVariant, selected, reduceMotion, theme]);\n\n const rootStyle = useMemo((): ViewStyle => {\n const base: ViewStyle = {\n ...rootBase,\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n zIndex: 1,\n position: 'relative',\n };\n // A fixed token height grows with the capped label so text never clips.\n if (fontScaleFactor !== 1 && typeof base.height === 'number') {\n base.height = Math.round(base.height * fontScaleFactor);\n }\n if (selected && !reduceMotion) {\n return { ...base, ...CLEAR_SELECTION_CHROME };\n }\n return base;\n }, [rootBase, fontScaleFactor, selected, reduceMotion]);\n\n const onLayout = useCallback(\n (e: LayoutChangeEvent) => {\n setTabLayout(uid, e.nativeEvent.layout);\n },\n [uid, setTabLayout],\n );\n\n const onPress = useCallback(() => {\n if (disabled) {\n return;\n }\n setSelectedId(uid);\n }, [disabled, setSelectedId, uid]);\n\n return (\n <Pressable\n accessibilityRole=\"tab\"\n accessibilityState={{ selected, disabled: !!disabled }}\n disabled={disabled}\n onPress={onPress}\n onPressIn={() => setPressed(true)}\n onPressOut={() => setPressed(false)}\n onLayout={onLayout}\n style={[rootStyle, style]}\n {...pressableRest}\n >\n {startIcon ? (\n <IconSlot\n icon={startIcon}\n size=\"sm\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n <TabLabel style={textStyle} maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}>\n {children}\n </TabLabel>\n {endIcon ? (\n <IconSlot\n icon={endIcon}\n size=\"sm\"\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={iconStyle}\n {...(iconColor !== undefined ? { color: iconColor } : {})}\n />\n ) : null}\n {showPrimaryPerTabUnderline &&\n primaryUnderlineColor &&\n primaryUnderlineColor !== 'transparent' ? (\n <View\n accessibilityElementsHidden\n importantForAccessibility=\"no-hide-descendants\"\n pointerEvents=\"none\"\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n height: PRIMARY_TAB_UNDERLINE_HEIGHT,\n backgroundColor: primaryUnderlineColor,\n }}\n />\n ) : null}\n </Pressable>\n );\n});\n\nTab.displayName = 'Tab';\n\nexport { Tab };\nexport type { TabProps };\n"],"mappings":"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"}
@@ -58,7 +58,7 @@ const Text = (0, react.memo)(function Text({ color = "primary", variant = "body1
58
58
  const resolvedLineHeight = lineHeight === "none" ? void 0 : lineHeight ?? (hasCJKContent(children) ? void 0 : resolvedVariant);
59
59
  const resolvedLetterSpacing = letterSpacing ?? resolvedVariant;
60
60
  const baseVariant = resolvedVariant?.split("/")[0];
61
- const defaultDynamicTypeRamp = require_fontScaling_FontScalingContext.useFontScalingEnabled() && baseVariant ? require_fontScaling_constants.DEFAULT_DYNAMIC_TYPE_RAMPS[baseVariant] : void 0;
61
+ const defaultDynamicTypeRamp = require_fontScaling_FontScalingContext.useDynamicTypeRampEnabled() && baseVariant ? require_fontScaling_constants.DEFAULT_DYNAMIC_TYPE_RAMPS[baseVariant] : void 0;
62
62
  const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier(resolvedVariant, maxFontSizeMultiplier);
63
63
  generated_styles.styles.useVariants({
64
64
  color: resolvedColor,
@@ -1,5 +1,5 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
- import { useFontScalingEnabled } from "../fontScaling/FontScalingContext.js";
2
+ import { useDynamicTypeRampEnabled } from "../fontScaling/FontScalingContext.js";
3
3
  import { DEFAULT_DYNAMIC_TYPE_RAMPS } from "../fontScaling/constants.js";
4
4
  import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
5
5
  import { memo, useMemo } from "react";
@@ -56,7 +56,7 @@ const Text = memo(function Text({ color = "primary", variant = "body1", fontFami
56
56
  const resolvedLineHeight = lineHeight === "none" ? void 0 : lineHeight ?? (hasCJKContent(children) ? void 0 : resolvedVariant);
57
57
  const resolvedLetterSpacing = letterSpacing ?? resolvedVariant;
58
58
  const baseVariant = resolvedVariant?.split("/")[0];
59
- const defaultDynamicTypeRamp = useFontScalingEnabled() && baseVariant ? DEFAULT_DYNAMIC_TYPE_RAMPS[baseVariant] : void 0;
59
+ const defaultDynamicTypeRamp = useDynamicTypeRampEnabled() && baseVariant ? DEFAULT_DYNAMIC_TYPE_RAMPS[baseVariant] : void 0;
60
60
  const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier(resolvedVariant, maxFontSizeMultiplier);
61
61
  styles.useVariants({
62
62
  color: resolvedColor,
@@ -1 +1 @@
1
- {"version":3,"file":"Text.js","names":["RNText"],"sources":["../../src/components/Text.tsx"],"sourcesContent":["import type { ReactNode, Ref } from 'react';\nimport { memo, useMemo } from 'react';\nimport type { StyleProp, TextProps as RNTextProps, TextStyle } from 'react-native';\nimport { Text as RNText } from 'react-native';\n\nimport type { StyleProps } from '../../generated/styles';\nimport { styles } from '../../generated/styles';\nimport { DEFAULT_DYNAMIC_TYPE_RAMPS } from '../fontScaling/constants';\nimport { useFontScalingEnabled } from '../fontScaling/FontScalingContext';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\n\n// TextVariant is a subset of fontFamily that represents typography variants\ntype TextVariant = Exclude<\n NonNullable<StyleProps['fontFamily']>,\n 'sans' | 'sans-alt' | 'serif' | 'serif-alt' | 'mono' | 'icons'\n>;\ntype TextVariantProp = TextVariant | 'inherit';\n\n// React Native text decoration line values\n// See: https://reactnative.dev/docs/text-style-props#textdecorationline\ntype TextDecorationLine = 'none' | 'underline' | 'line-through' | 'underline line-through';\n\n// Chinese/Japanese/Korean scripts: Hangul Jamo, CJK radicals + punctuation,\n// Kana, Han ideographs, Hangul syllables, compatibility ideographs, and\n// full/half-width forms.\nconst CJK_RE =\n /[\\u1100-\\u11FF\\u2E80-\\u303F\\u3040-\\u30FF\\u31C0-\\u9FFF\\uAC00-\\uD7AF\\uF900-\\uFAFF\\uFF00-\\uFFEF]/;\n\n/**\n * Detects CJK characters in string children (including strings inside a\n * children array, e.g. from `{city}` interpolation). Nested elements are not\n * inspected - a nested <Text> runs its own detection.\n */\nfunction hasCJKContent(children: ReactNode): boolean {\n if (typeof children === 'string') {\n return CJK_RE.test(children);\n }\n if (Array.isArray(children)) {\n return children.some((child) => typeof child === 'string' && CJK_RE.test(child));\n }\n return false;\n}\n\ninterface TextProps extends RNTextProps {\n /** Ref to the underlying Text element */\n ref?: Ref<RNText>;\n /** Text color from the theme palette */\n color?: StyleProps['color'] | 'inherit';\n /** Typography variant - sets fontSize, lineHeight, letterSpacing, and fontFamily together */\n variant?: TextVariantProp;\n /**\n * Caps how far this text grows with the OS text-size setting. Every text\n * variant is capped at 2x or below by default, with the largest display and\n * title variants tapering further (see DEFAULT_MAX_FONT_SIZE_MULTIPLIERS).\n * Set null to remove the cap (maps to React Native's 0, which also overrides\n * an inherited cap); inherit-variant text inherits its parent's cap.\n * Override app-wide via UDSFontScalingProvider.\n */\n maxFontSizeMultiplier?: number | null;\n /** Override the fontFamily independently */\n fontFamily?: StyleProps['fontFamily'];\n /** Override the fontSize independently */\n fontSize?: StyleProps['fontSize'];\n /** Set font weight (not derived from variant) */\n fontWeight?: StyleProps['fontWeight'];\n /** Override the lineHeight independently. Use 'none' to remove the variant lineHeight and let the font's natural line height apply */\n lineHeight?: StyleProps['lineHeight'] | 'none';\n /** Override the letterSpacing independently */\n letterSpacing?: StyleProps['letterSpacing'];\n /** Text alignment (left, center, right) */\n textAlign?: StyleProps['textAlign'];\n /** Set text transform (not derived from variant) */\n textTransform?: StyleProps['textTransform'];\n /** Text decoration (underline, line-through, etc.) */\n textDecorationLine?: TextDecorationLine;\n // Background\n backgroundColor?: StyleProps['backgroundColor'];\n // Border\n borderRadius?: StyleProps['borderRadius'];\n borderTopStartRadius?: StyleProps['borderTopStartRadius'];\n borderTopEndRadius?: StyleProps['borderTopEndRadius'];\n borderBottomStartRadius?: StyleProps['borderBottomStartRadius'];\n borderBottomEndRadius?: StyleProps['borderBottomEndRadius'];\n borderColor?: StyleProps['borderColor'];\n borderStartColor?: StyleProps['borderStartColor'];\n borderEndColor?: StyleProps['borderEndColor'];\n borderTopColor?: StyleProps['borderTopColor'];\n borderBottomColor?: StyleProps['borderBottomColor'];\n borderWidth?: StyleProps['borderWidth'];\n borderVerticalWidth?: StyleProps['borderVerticalWidth'];\n borderHorizontalWidth?: StyleProps['borderHorizontalWidth'];\n borderStartWidth?: StyleProps['borderStartWidth'];\n borderEndWidth?: StyleProps['borderEndWidth'];\n borderTopWidth?: StyleProps['borderTopWidth'];\n borderBottomWidth?: StyleProps['borderBottomWidth'];\n // Spacing\n spacing?: StyleProps['spacing'];\n spacingHorizontal?: StyleProps['spacingHorizontal'];\n spacingVertical?: StyleProps['spacingVertical'];\n spacingBottom?: StyleProps['spacingBottom'];\n spacingEnd?: StyleProps['spacingEnd'];\n spacingStart?: StyleProps['spacingStart'];\n spacingTop?: StyleProps['spacingTop'];\n // Offset\n offset?: StyleProps['offset'];\n offsetVertical?: StyleProps['offsetVertical'];\n offsetHorizontal?: StyleProps['offsetHorizontal'];\n offsetBottom?: StyleProps['offsetBottom'];\n offsetEnd?: StyleProps['offsetEnd'];\n offsetStart?: StyleProps['offsetStart'];\n offsetTop?: StyleProps['offsetTop'];\n // Flex\n flexShrink?: StyleProps['flexShrink'];\n // Vertical Alignment\n verticalAlign?: TextStyle['textAlignVertical'];\n // Size\n height?: number | `${number}%`;\n width?: number | `${number}%`;\n minHeight?: number | `${number}%`;\n maxHeight?: number | `${number}%`;\n minWidth?: number | `${number}%`;\n maxWidth?: number | `${number}%`;\n // Dangerously set props\n dangerouslySetColor?: string;\n}\n\n/**\n * **📝 A text component with UDS styling**\n *\n * @description\n * A styled text component that supports UDS typography variants and colors.\n *\n * @category Display\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Text } from '@yahoo/uds-mobile/Text';\n *\n * <Text variant=\"body1\" color=\"primary\">Hello, World!</Text>\n * <Text variant=\"display1\" fontWeight=\"bold\">Heading</Text>\n * <Text variant=\"label1\" color=\"secondary\">Caption text</Text>\n * ```\n *\n * @usage\n * - Use variant prop to set typography (display1, body1, label1, etc.)\n * - Use color prop to set text color from the palette\n * - Use fontWeight to override the variant's default weight\n *\n * @accessibility\n * - Text is readable by screen readers by default\n * - Use appropriate variant sizes for readability\n * - Ensure sufficient color contrast with background\n *\n * @see {@link Link} for interactive text links\n */\nconst Text = memo(function Text({\n // Text-specific\n color = 'primary',\n variant = 'body1',\n fontFamily,\n fontSize,\n fontWeight,\n lineHeight,\n letterSpacing,\n maxFontSizeMultiplier,\n textAlign,\n textTransform,\n textDecorationLine,\n style,\n // Background\n backgroundColor,\n // Border\n borderRadius,\n borderTopStartRadius,\n borderTopEndRadius,\n borderBottomStartRadius,\n borderBottomEndRadius,\n borderColor,\n borderStartColor,\n borderEndColor,\n borderTopColor,\n borderBottomColor,\n borderWidth,\n borderVerticalWidth,\n borderHorizontalWidth,\n borderStartWidth,\n borderEndWidth,\n borderTopWidth,\n borderBottomWidth,\n // Spacing\n spacing,\n spacingHorizontal,\n spacingVertical,\n spacingBottom,\n spacingEnd,\n spacingStart,\n spacingTop,\n // Offset\n offset,\n offsetVertical,\n offsetHorizontal,\n offsetBottom,\n offsetEnd,\n offsetStart,\n offsetTop,\n // Flex\n flexShrink,\n // Vertical Alignment\n verticalAlign,\n // Size\n height,\n minHeight,\n maxHeight,\n width,\n minWidth,\n maxWidth,\n // Dangerously set props\n dangerouslySetColor,\n ref,\n children,\n // Rest\n ...props\n}: TextProps) {\n const resolvedColor = color === 'inherit' ? undefined : color;\n const resolvedVariant = variant === 'inherit' ? undefined : variant;\n const resolvedFontFamily = fontFamily ?? resolvedVariant;\n const resolvedFontSize = fontSize ?? resolvedVariant;\n // React Native clips glyphs when lineHeight is smaller than the font's\n // natural line box. CJK fallback fonts are ~1.4x taller than Latin ones, so\n // Latin-tuned variant lineHeights clip CJK text - drop the variant lineHeight\n // for CJK content so the line grows to fit.\n const resolvedLineHeight =\n lineHeight === 'none'\n ? undefined\n : (lineHeight ?? (hasCJKContent(children) ? undefined : resolvedVariant));\n const resolvedLetterSpacing = letterSpacing ?? resolvedVariant;\n const baseVariant = resolvedVariant?.split('/')[0] as TextVariant | undefined;\n const fontScalingEnabled = useFontScalingEnabled();\n const defaultDynamicTypeRamp =\n fontScalingEnabled && baseVariant ? DEFAULT_DYNAMIC_TYPE_RAMPS[baseVariant] : undefined;\n // Explicit prop wins, including explicit null (?? would swallow it).\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier(\n resolvedVariant,\n maxFontSizeMultiplier,\n );\n\n styles.useVariants({\n // Text styles\n color: resolvedColor,\n fontFamily: resolvedFontFamily,\n fontSize: resolvedFontSize,\n fontWeight,\n lineHeight: resolvedLineHeight,\n letterSpacing: resolvedLetterSpacing,\n textAlign,\n textTransform,\n // Background\n backgroundColor,\n // Border\n borderRadius,\n borderTopStartRadius,\n borderTopEndRadius,\n borderBottomStartRadius,\n borderBottomEndRadius,\n borderColor,\n borderStartColor,\n borderEndColor,\n borderTopColor,\n borderBottomColor,\n borderWidth,\n borderVerticalWidth,\n borderHorizontalWidth,\n borderStartWidth,\n borderEndWidth,\n borderTopWidth,\n borderBottomWidth,\n // Spacing\n spacing,\n spacingHorizontal,\n spacingVertical,\n spacingBottom,\n spacingEnd,\n spacingStart,\n spacingTop,\n // Offset\n offset,\n offsetVertical,\n offsetHorizontal,\n offsetBottom,\n offsetEnd,\n offsetStart,\n offsetTop,\n // Flex\n flexShrink,\n });\n\n // styles.foundation must be in deps - it returns a new reference when variants change.\n const computedStyle: StyleProp<TextStyle> = useMemo(\n () => [\n textDecorationLine ? { textDecorationLine } : undefined,\n dangerouslySetColor ? { color: dangerouslySetColor } : undefined,\n verticalAlign ? { textAlignVertical: verticalAlign } : undefined,\n height ? { height } : undefined,\n minHeight ? { minHeight } : undefined,\n maxHeight ? { maxHeight } : undefined,\n width ? { width } : undefined,\n minWidth ? { minWidth } : undefined,\n maxWidth ? { maxWidth } : undefined,\n styles.foundation,\n style,\n ],\n [\n textDecorationLine,\n dangerouslySetColor,\n verticalAlign,\n height,\n minHeight,\n maxHeight,\n width,\n minWidth,\n maxWidth,\n style,\n styles.foundation,\n ],\n );\n\n return (\n <RNText\n ref={ref}\n style={computedStyle}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n dynamicTypeRamp={defaultDynamicTypeRamp}\n {...props}\n >\n {children}\n </RNText>\n );\n});\n\nText.displayName = 'Text';\n\nexport { Text, type TextProps, type TextVariant };\n"],"mappings":";;;;;;;;;AAyBA,MAAM,SACJ;;;;;;AAOF,SAAS,cAAc,UAA8B;CACnD,IAAI,OAAO,aAAa,UACtB,OAAO,OAAO,KAAK,SAAS;CAE9B,IAAI,MAAM,QAAQ,SAAS,EACzB,OAAO,SAAS,MAAM,UAAU,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM,CAAC;CAElF,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHT,MAAM,OAAO,KAAK,SAAS,KAAK,EAE9B,QAAQ,WACR,UAAU,SACV,YACA,UACA,YACA,YACA,eACA,uBACA,WACA,eACA,oBACA,OAEA,iBAEA,cACA,sBACA,oBACA,yBACA,uBACA,aACA,kBACA,gBACA,gBACA,mBACA,aACA,qBACA,uBACA,kBACA,gBACA,gBACA,mBAEA,SACA,mBACA,iBACA,eACA,YACA,cACA,YAEA,QACA,gBACA,kBACA,cACA,WACA,aACA,WAEA,YAEA,eAEA,QACA,WACA,WACA,OACA,UACA,UAEA,qBACA,KACA,UAEA,GAAG,SACS;CACZ,MAAM,gBAAgB,UAAU,YAAY,KAAA,IAAY;CACxD,MAAM,kBAAkB,YAAY,YAAY,KAAA,IAAY;CAC5D,MAAM,qBAAqB,cAAc;CACzC,MAAM,mBAAmB,YAAY;CAKrC,MAAM,qBACJ,eAAe,SACX,KAAA,IACC,eAAe,cAAc,SAAS,GAAG,KAAA,IAAY;CAC5D,MAAM,wBAAwB,iBAAiB;CAC/C,MAAM,cAAc,iBAAiB,MAAM,IAAI,CAAC;CAEhD,MAAM,yBADqB,uBAEP,IAAI,cAAc,2BAA2B,eAAe,KAAA;CAEhF,MAAM,gCAAgC,yBACpC,iBACA,sBACD;CAED,OAAO,YAAY;EAEjB,OAAO;EACP,YAAY;EACZ,UAAU;EACV;EACA,YAAY;EACZ,eAAe;EACf;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACD,CAAC;CAgCF,OACE,oBAACA,QAAD;EACO;EACL,OAhCwC,cACpC;GACJ,qBAAqB,EAAE,oBAAoB,GAAG,KAAA;GAC9C,sBAAsB,EAAE,OAAO,qBAAqB,GAAG,KAAA;GACvD,gBAAgB,EAAE,mBAAmB,eAAe,GAAG,KAAA;GACvD,SAAS,EAAE,QAAQ,GAAG,KAAA;GACtB,YAAY,EAAE,WAAW,GAAG,KAAA;GAC5B,YAAY,EAAE,WAAW,GAAG,KAAA;GAC5B,QAAQ,EAAE,OAAO,GAAG,KAAA;GACpB,WAAW,EAAE,UAAU,GAAG,KAAA;GAC1B,WAAW,EAAE,UAAU,GAAG,KAAA;GAC1B,OAAO;GACP;GACD,EACD;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,OAAO;GACR,CAMqB;EACpB,uBAAuB;EACvB,iBAAiB;EACjB,GAAI;EAEH;EACM,CAAA;EAEX;AAEF,KAAK,cAAc"}
1
+ {"version":3,"file":"Text.js","names":["RNText"],"sources":["../../src/components/Text.tsx"],"sourcesContent":["import type { ReactNode, Ref } from 'react';\nimport { memo, useMemo } from 'react';\nimport type { StyleProp, TextProps as RNTextProps, TextStyle } from 'react-native';\nimport { Text as RNText } from 'react-native';\n\nimport type { StyleProps } from '../../generated/styles';\nimport { styles } from '../../generated/styles';\nimport { DEFAULT_DYNAMIC_TYPE_RAMPS } from '../fontScaling/constants';\nimport { useDynamicTypeRampEnabled } from '../fontScaling/FontScalingContext';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\n\n// TextVariant is a subset of fontFamily that represents typography variants\ntype TextVariant = Exclude<\n NonNullable<StyleProps['fontFamily']>,\n 'sans' | 'sans-alt' | 'serif' | 'serif-alt' | 'mono' | 'icons'\n>;\ntype TextVariantProp = TextVariant | 'inherit';\n\n// React Native text decoration line values\n// See: https://reactnative.dev/docs/text-style-props#textdecorationline\ntype TextDecorationLine = 'none' | 'underline' | 'line-through' | 'underline line-through';\n\n// Chinese/Japanese/Korean scripts: Hangul Jamo, CJK radicals + punctuation,\n// Kana, Han ideographs, Hangul syllables, compatibility ideographs, and\n// full/half-width forms.\nconst CJK_RE =\n /[\\u1100-\\u11FF\\u2E80-\\u303F\\u3040-\\u30FF\\u31C0-\\u9FFF\\uAC00-\\uD7AF\\uF900-\\uFAFF\\uFF00-\\uFFEF]/;\n\n/**\n * Detects CJK characters in string children (including strings inside a\n * children array, e.g. from `{city}` interpolation). Nested elements are not\n * inspected - a nested <Text> runs its own detection.\n */\nfunction hasCJKContent(children: ReactNode): boolean {\n if (typeof children === 'string') {\n return CJK_RE.test(children);\n }\n if (Array.isArray(children)) {\n return children.some((child) => typeof child === 'string' && CJK_RE.test(child));\n }\n return false;\n}\n\ninterface TextProps extends RNTextProps {\n /** Ref to the underlying Text element */\n ref?: Ref<RNText>;\n /** Text color from the theme palette */\n color?: StyleProps['color'] | 'inherit';\n /** Typography variant - sets fontSize, lineHeight, letterSpacing, and fontFamily together */\n variant?: TextVariantProp;\n /**\n * Caps how far this text grows with the OS text-size setting. Every text\n * variant is capped at 2x or below by default, with the largest display and\n * title variants tapering further (see DEFAULT_MAX_FONT_SIZE_MULTIPLIERS).\n * Set null to remove the cap (maps to React Native's 0, which also overrides\n * an inherited cap); inherit-variant text inherits its parent's cap.\n * Override app-wide via UDSFontScalingProvider.\n */\n maxFontSizeMultiplier?: number | null;\n /** Override the fontFamily independently */\n fontFamily?: StyleProps['fontFamily'];\n /** Override the fontSize independently */\n fontSize?: StyleProps['fontSize'];\n /** Set font weight (not derived from variant) */\n fontWeight?: StyleProps['fontWeight'];\n /** Override the lineHeight independently. Use 'none' to remove the variant lineHeight and let the font's natural line height apply */\n lineHeight?: StyleProps['lineHeight'] | 'none';\n /** Override the letterSpacing independently */\n letterSpacing?: StyleProps['letterSpacing'];\n /** Text alignment (left, center, right) */\n textAlign?: StyleProps['textAlign'];\n /** Set text transform (not derived from variant) */\n textTransform?: StyleProps['textTransform'];\n /** Text decoration (underline, line-through, etc.) */\n textDecorationLine?: TextDecorationLine;\n // Background\n backgroundColor?: StyleProps['backgroundColor'];\n // Border\n borderRadius?: StyleProps['borderRadius'];\n borderTopStartRadius?: StyleProps['borderTopStartRadius'];\n borderTopEndRadius?: StyleProps['borderTopEndRadius'];\n borderBottomStartRadius?: StyleProps['borderBottomStartRadius'];\n borderBottomEndRadius?: StyleProps['borderBottomEndRadius'];\n borderColor?: StyleProps['borderColor'];\n borderStartColor?: StyleProps['borderStartColor'];\n borderEndColor?: StyleProps['borderEndColor'];\n borderTopColor?: StyleProps['borderTopColor'];\n borderBottomColor?: StyleProps['borderBottomColor'];\n borderWidth?: StyleProps['borderWidth'];\n borderVerticalWidth?: StyleProps['borderVerticalWidth'];\n borderHorizontalWidth?: StyleProps['borderHorizontalWidth'];\n borderStartWidth?: StyleProps['borderStartWidth'];\n borderEndWidth?: StyleProps['borderEndWidth'];\n borderTopWidth?: StyleProps['borderTopWidth'];\n borderBottomWidth?: StyleProps['borderBottomWidth'];\n // Spacing\n spacing?: StyleProps['spacing'];\n spacingHorizontal?: StyleProps['spacingHorizontal'];\n spacingVertical?: StyleProps['spacingVertical'];\n spacingBottom?: StyleProps['spacingBottom'];\n spacingEnd?: StyleProps['spacingEnd'];\n spacingStart?: StyleProps['spacingStart'];\n spacingTop?: StyleProps['spacingTop'];\n // Offset\n offset?: StyleProps['offset'];\n offsetVertical?: StyleProps['offsetVertical'];\n offsetHorizontal?: StyleProps['offsetHorizontal'];\n offsetBottom?: StyleProps['offsetBottom'];\n offsetEnd?: StyleProps['offsetEnd'];\n offsetStart?: StyleProps['offsetStart'];\n offsetTop?: StyleProps['offsetTop'];\n // Flex\n flexShrink?: StyleProps['flexShrink'];\n // Vertical Alignment\n verticalAlign?: TextStyle['textAlignVertical'];\n // Size\n height?: number | `${number}%`;\n width?: number | `${number}%`;\n minHeight?: number | `${number}%`;\n maxHeight?: number | `${number}%`;\n minWidth?: number | `${number}%`;\n maxWidth?: number | `${number}%`;\n // Dangerously set props\n dangerouslySetColor?: string;\n}\n\n/**\n * **📝 A text component with UDS styling**\n *\n * @description\n * A styled text component that supports UDS typography variants and colors.\n *\n * @category Display\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Text } from '@yahoo/uds-mobile/Text';\n *\n * <Text variant=\"body1\" color=\"primary\">Hello, World!</Text>\n * <Text variant=\"display1\" fontWeight=\"bold\">Heading</Text>\n * <Text variant=\"label1\" color=\"secondary\">Caption text</Text>\n * ```\n *\n * @usage\n * - Use variant prop to set typography (display1, body1, label1, etc.)\n * - Use color prop to set text color from the palette\n * - Use fontWeight to override the variant's default weight\n *\n * @accessibility\n * - Text is readable by screen readers by default\n * - Use appropriate variant sizes for readability\n * - Ensure sufficient color contrast with background\n *\n * @see {@link Link} for interactive text links\n */\nconst Text = memo(function Text({\n // Text-specific\n color = 'primary',\n variant = 'body1',\n fontFamily,\n fontSize,\n fontWeight,\n lineHeight,\n letterSpacing,\n maxFontSizeMultiplier,\n textAlign,\n textTransform,\n textDecorationLine,\n style,\n // Background\n backgroundColor,\n // Border\n borderRadius,\n borderTopStartRadius,\n borderTopEndRadius,\n borderBottomStartRadius,\n borderBottomEndRadius,\n borderColor,\n borderStartColor,\n borderEndColor,\n borderTopColor,\n borderBottomColor,\n borderWidth,\n borderVerticalWidth,\n borderHorizontalWidth,\n borderStartWidth,\n borderEndWidth,\n borderTopWidth,\n borderBottomWidth,\n // Spacing\n spacing,\n spacingHorizontal,\n spacingVertical,\n spacingBottom,\n spacingEnd,\n spacingStart,\n spacingTop,\n // Offset\n offset,\n offsetVertical,\n offsetHorizontal,\n offsetBottom,\n offsetEnd,\n offsetStart,\n offsetTop,\n // Flex\n flexShrink,\n // Vertical Alignment\n verticalAlign,\n // Size\n height,\n minHeight,\n maxHeight,\n width,\n minWidth,\n maxWidth,\n // Dangerously set props\n dangerouslySetColor,\n ref,\n children,\n // Rest\n ...props\n}: TextProps) {\n const resolvedColor = color === 'inherit' ? undefined : color;\n const resolvedVariant = variant === 'inherit' ? undefined : variant;\n const resolvedFontFamily = fontFamily ?? resolvedVariant;\n const resolvedFontSize = fontSize ?? resolvedVariant;\n // React Native clips glyphs when lineHeight is smaller than the font's\n // natural line box. CJK fallback fonts are ~1.4x taller than Latin ones, so\n // Latin-tuned variant lineHeights clip CJK text - drop the variant lineHeight\n // for CJK content so the line grows to fit.\n const resolvedLineHeight =\n lineHeight === 'none'\n ? undefined\n : (lineHeight ?? (hasCJKContent(children) ? undefined : resolvedVariant));\n const resolvedLetterSpacing = letterSpacing ?? resolvedVariant;\n const baseVariant = resolvedVariant?.split('/')[0] as TextVariant | undefined;\n const dynamicTypeRampEnabled = useDynamicTypeRampEnabled();\n const defaultDynamicTypeRamp =\n dynamicTypeRampEnabled && baseVariant ? DEFAULT_DYNAMIC_TYPE_RAMPS[baseVariant] : undefined;\n // Explicit prop wins, including explicit null (?? would swallow it).\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier(\n resolvedVariant,\n maxFontSizeMultiplier,\n );\n\n styles.useVariants({\n // Text styles\n color: resolvedColor,\n fontFamily: resolvedFontFamily,\n fontSize: resolvedFontSize,\n fontWeight,\n lineHeight: resolvedLineHeight,\n letterSpacing: resolvedLetterSpacing,\n textAlign,\n textTransform,\n // Background\n backgroundColor,\n // Border\n borderRadius,\n borderTopStartRadius,\n borderTopEndRadius,\n borderBottomStartRadius,\n borderBottomEndRadius,\n borderColor,\n borderStartColor,\n borderEndColor,\n borderTopColor,\n borderBottomColor,\n borderWidth,\n borderVerticalWidth,\n borderHorizontalWidth,\n borderStartWidth,\n borderEndWidth,\n borderTopWidth,\n borderBottomWidth,\n // Spacing\n spacing,\n spacingHorizontal,\n spacingVertical,\n spacingBottom,\n spacingEnd,\n spacingStart,\n spacingTop,\n // Offset\n offset,\n offsetVertical,\n offsetHorizontal,\n offsetBottom,\n offsetEnd,\n offsetStart,\n offsetTop,\n // Flex\n flexShrink,\n });\n\n // styles.foundation must be in deps - it returns a new reference when variants change.\n const computedStyle: StyleProp<TextStyle> = useMemo(\n () => [\n textDecorationLine ? { textDecorationLine } : undefined,\n dangerouslySetColor ? { color: dangerouslySetColor } : undefined,\n verticalAlign ? { textAlignVertical: verticalAlign } : undefined,\n height ? { height } : undefined,\n minHeight ? { minHeight } : undefined,\n maxHeight ? { maxHeight } : undefined,\n width ? { width } : undefined,\n minWidth ? { minWidth } : undefined,\n maxWidth ? { maxWidth } : undefined,\n styles.foundation,\n style,\n ],\n [\n textDecorationLine,\n dangerouslySetColor,\n verticalAlign,\n height,\n minHeight,\n maxHeight,\n width,\n minWidth,\n maxWidth,\n style,\n styles.foundation,\n ],\n );\n\n return (\n <RNText\n ref={ref}\n style={computedStyle}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n dynamicTypeRamp={defaultDynamicTypeRamp}\n {...props}\n >\n {children}\n </RNText>\n );\n});\n\nText.displayName = 'Text';\n\nexport { Text, type TextProps, type TextVariant };\n"],"mappings":";;;;;;;;;AAyBA,MAAM,SACJ;;;;;;AAOF,SAAS,cAAc,UAA8B;CACnD,IAAI,OAAO,aAAa,UACtB,OAAO,OAAO,KAAK,SAAS;CAE9B,IAAI,MAAM,QAAQ,SAAS,EACzB,OAAO,SAAS,MAAM,UAAU,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM,CAAC;CAElF,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoHT,MAAM,OAAO,KAAK,SAAS,KAAK,EAE9B,QAAQ,WACR,UAAU,SACV,YACA,UACA,YACA,YACA,eACA,uBACA,WACA,eACA,oBACA,OAEA,iBAEA,cACA,sBACA,oBACA,yBACA,uBACA,aACA,kBACA,gBACA,gBACA,mBACA,aACA,qBACA,uBACA,kBACA,gBACA,gBACA,mBAEA,SACA,mBACA,iBACA,eACA,YACA,cACA,YAEA,QACA,gBACA,kBACA,cACA,WACA,aACA,WAEA,YAEA,eAEA,QACA,WACA,WACA,OACA,UACA,UAEA,qBACA,KACA,UAEA,GAAG,SACS;CACZ,MAAM,gBAAgB,UAAU,YAAY,KAAA,IAAY;CACxD,MAAM,kBAAkB,YAAY,YAAY,KAAA,IAAY;CAC5D,MAAM,qBAAqB,cAAc;CACzC,MAAM,mBAAmB,YAAY;CAKrC,MAAM,qBACJ,eAAe,SACX,KAAA,IACC,eAAe,cAAc,SAAS,GAAG,KAAA,IAAY;CAC5D,MAAM,wBAAwB,iBAAiB;CAC/C,MAAM,cAAc,iBAAiB,MAAM,IAAI,CAAC;CAEhD,MAAM,yBADyB,2BAEP,IAAI,cAAc,2BAA2B,eAAe,KAAA;CAEpF,MAAM,gCAAgC,yBACpC,iBACA,sBACD;CAED,OAAO,YAAY;EAEjB,OAAO;EACP,YAAY;EACZ,UAAU;EACV;EACA,YAAY;EACZ,eAAe;EACf;EACA;EAEA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACD,CAAC;CAgCF,OACE,oBAACA,QAAD;EACO;EACL,OAhCwC,cACpC;GACJ,qBAAqB,EAAE,oBAAoB,GAAG,KAAA;GAC9C,sBAAsB,EAAE,OAAO,qBAAqB,GAAG,KAAA;GACvD,gBAAgB,EAAE,mBAAmB,eAAe,GAAG,KAAA;GACvD,SAAS,EAAE,QAAQ,GAAG,KAAA;GACtB,YAAY,EAAE,WAAW,GAAG,KAAA;GAC5B,YAAY,EAAE,WAAW,GAAG,KAAA;GAC5B,QAAQ,EAAE,OAAO,GAAG,KAAA;GACpB,WAAW,EAAE,UAAU,GAAG,KAAA;GAC1B,WAAW,EAAE,UAAU,GAAG,KAAA;GAC1B,OAAO;GACP;GACD,EACD;GACE;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA,OAAO;GACR,CAMqB;EACpB,uBAAuB;EACvB,iBAAiB;EACjB,GAAI;EAEH;EACM,CAAA;EAEX;AAEF,KAAK,cAAc"}
@@ -8,6 +8,7 @@ let react_native = require("react-native");
8
8
  let react_jsx_runtime = require("react/jsx-runtime");
9
9
  let react_native_gesture_handler = require("react-native-gesture-handler");
10
10
  //#region src/components/UDSProvider.tsx
11
+ const DEFAULT_FONT_SCALING_CONFIG = {};
11
12
  /**
12
13
  * Root gesture and portal provider for UDS Mobile overlays.
13
14
  *
@@ -27,12 +28,14 @@ let react_native_gesture_handler = require("react-native-gesture-handler");
27
28
  * ```
28
29
  */
29
30
  const UDSGestureProvider = (0, react.memo)(function UDSGestureProvider({ children, fontScaling }) {
31
+ const inheritedFontScaling = (0, react.useContext)(require_fontScaling_FontScalingContext.FontScalingContext);
32
+ const resolvedFontScaling = fontScaling ?? inheritedFontScaling ?? DEFAULT_FONT_SCALING_CONFIG;
30
33
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_gesture_handler.GestureHandlerRootView, {
31
34
  style: styles.root,
32
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_portal.PortalProvider, { children: fontScaling ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_fontScaling_FontScalingContext.UDSFontScalingProvider, {
33
- config: fontScaling,
35
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_portal.PortalProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_fontScaling_FontScalingContext.UDSFontScalingProvider, {
36
+ config: resolvedFontScaling,
34
37
  children
35
- }) : children })
38
+ }) })
36
39
  });
37
40
  });
38
41
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"UDSProvider.d.cts","names":[],"sources":["../../src/components/UDSProvider.tsx"],"mappings":";;;;;;UASU,uBAAA;EACR,QAAA,EAAU,SAAA;;AAJkD;;;;;;EAY5D,WAAA,GAAc,iBAAA;AAAA;;;AAAiB;;;;;AAqBT;;;;;AAiCxB;;;;;;cAjCM,kBAAA,EAAkB,OAAA,CAAA,oBAAA,CAAA,uBAAA;;;;cAoBlB,WAAA,EAAW,OAAA,CAAA,oBAAA,CAAA,uBAAA;;;;KAaL,gBAAA,GAAmB,uBAAA"}
1
+ {"version":3,"file":"UDSProvider.d.cts","names":[],"sources":["../../src/components/UDSProvider.tsx"],"mappings":";;;;;;UASU,uBAAA;EACR,QAAA,EAAU,SAAA;;AAJkD;;;;;;EAY5D,WAAA,GAAc,iBAAA;AAAA;;;AAAiB;;;;;AAwBT;;;;;AAmCxB;;;;;;cAnCM,kBAAA,EAAkB,OAAA,CAAA,oBAAA,CAAA,uBAAA;;;;cAsBlB,WAAA,EAAW,OAAA,CAAA,oBAAA,CAAA,uBAAA;;;;KAaL,gBAAA,GAAmB,uBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"UDSProvider.d.ts","names":[],"sources":["../../src/components/UDSProvider.tsx"],"mappings":";;;;;;UASU,uBAAA;EACR,QAAA,EAAU,SAAA;;AAJkD;;;;;;EAY5D,WAAA,GAAc,iBAAA;AAAA;;;AAAiB;;;;;AAqBT;;;;;AAiCxB;;;;;;cAjCM,kBAAA,EAAkB,OAAA,CAAA,oBAAA,CAAA,uBAAA;;;;cAoBlB,WAAA,EAAW,OAAA,CAAA,oBAAA,CAAA,uBAAA;;;;KAaL,gBAAA,GAAmB,uBAAA"}
1
+ {"version":3,"file":"UDSProvider.d.ts","names":[],"sources":["../../src/components/UDSProvider.tsx"],"mappings":";;;;;;UASU,uBAAA;EACR,QAAA,EAAU,SAAA;;AAJkD;;;;;;EAY5D,WAAA,GAAc,iBAAA;AAAA;;;AAAiB;;;;;AAwBT;;;;;AAmCxB;;;;;;cAnCM,kBAAA,EAAkB,OAAA,CAAA,oBAAA,CAAA,uBAAA;;;;cAsBlB,WAAA,EAAW,OAAA,CAAA,oBAAA,CAAA,uBAAA;;;;KAaL,gBAAA,GAAmB,uBAAA"}
@@ -1,11 +1,12 @@
1
1
  /*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
2
- import { UDSFontScalingProvider } from "../fontScaling/FontScalingContext.js";
2
+ import { FontScalingContext, UDSFontScalingProvider } from "../fontScaling/FontScalingContext.js";
3
3
  import { PortalProvider } from "../portal.js";
4
- import { memo } from "react";
4
+ import { memo, useContext } from "react";
5
5
  import { StyleSheet } from "react-native";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { GestureHandlerRootView } from "react-native-gesture-handler";
8
8
  //#region src/components/UDSProvider.tsx
9
+ const DEFAULT_FONT_SCALING_CONFIG = {};
9
10
  /**
10
11
  * Root gesture and portal provider for UDS Mobile overlays.
11
12
  *
@@ -25,12 +26,14 @@ import { GestureHandlerRootView } from "react-native-gesture-handler";
25
26
  * ```
26
27
  */
27
28
  const UDSGestureProvider = memo(function UDSGestureProvider({ children, fontScaling }) {
29
+ const inheritedFontScaling = useContext(FontScalingContext);
30
+ const resolvedFontScaling = fontScaling ?? inheritedFontScaling ?? DEFAULT_FONT_SCALING_CONFIG;
28
31
  return /* @__PURE__ */ jsx(GestureHandlerRootView, {
29
32
  style: styles.root,
30
- children: /* @__PURE__ */ jsx(PortalProvider, { children: fontScaling ? /* @__PURE__ */ jsx(UDSFontScalingProvider, {
31
- config: fontScaling,
33
+ children: /* @__PURE__ */ jsx(PortalProvider, { children: /* @__PURE__ */ jsx(UDSFontScalingProvider, {
34
+ config: resolvedFontScaling,
32
35
  children
33
- }) : children })
36
+ }) })
34
37
  });
35
38
  });
36
39
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"UDSProvider.js","names":[],"sources":["../../src/components/UDSProvider.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { memo } from 'react';\nimport { StyleSheet } from 'react-native';\nimport { GestureHandlerRootView } from 'react-native-gesture-handler';\n\nimport { UDSFontScalingProvider } from '../fontScaling/FontScalingContext';\nimport type { FontScalingConfig } from '../fontScaling/types';\nimport { PortalProvider } from '../portal';\n\ninterface UDSGestureProviderProps {\n children: ReactNode;\n /**\n * App-wide font-scaling caps, overriding the built-in defaults. Omit to use\n * the defaults (every text style capped at 2x or below, with the largest\n * display/title tiers tapered further, and control internals capped at 2x).\n * Should be identity-stable (a module constant or memoized) — every UDS text\n * element reads it from context.\n */\n fontScaling?: FontScalingConfig;\n}\n\n/**\n * Root gesture and portal provider for UDS Mobile overlays.\n *\n * Place this at the top of your app layout:\n *\n * @example\n * ```tsx\n * import { UDSGestureProvider } from '@yahoo/uds-mobile/UDSGestureProvider';\n *\n * export default function RootLayout() {\n * return (\n * <UDSGestureProvider>\n * <Stack />\n * </UDSGestureProvider>\n * );\n * }\n * ```\n */\nconst UDSGestureProvider = memo(function UDSGestureProvider({\n children,\n fontScaling,\n}: UDSGestureProviderProps) {\n return (\n <GestureHandlerRootView style={styles.root}>\n <PortalProvider>\n {fontScaling ? (\n <UDSFontScalingProvider config={fontScaling}>{children}</UDSFontScalingProvider>\n ) : (\n children\n )}\n </PortalProvider>\n </GestureHandlerRootView>\n );\n});\n\n/**\n * @deprecated Use {@link UDSGestureProvider} from `@yahoo/uds-mobile/UDSGestureProvider`.\n */\nconst UDSProvider = UDSGestureProvider;\n\nconst styles = StyleSheet.create({\n root: {\n flex: 1,\n },\n});\n\nexport { UDSGestureProvider, UDSProvider };\nexport type { UDSGestureProviderProps };\n/**\n * @deprecated Use {@link UDSGestureProviderProps}.\n */\nexport type UDSProviderProps = UDSGestureProviderProps;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,MAAM,qBAAqB,KAAK,SAAS,mBAAmB,EAC1D,UACA,eAC0B;CAC1B,OACE,oBAAC,wBAAD;EAAwB,OAAO,OAAO;YACpC,oBAAC,gBAAD,EAAA,UACG,cACC,oBAAC,wBAAD;GAAwB,QAAQ;GAAc;GAAkC,CAAA,GAEhF,UAEa,CAAA;EACM,CAAA;EAE3B;;;;AAKF,MAAM,cAAc;AAEpB,MAAM,SAAS,WAAW,OAAO,EAC/B,MAAM,EACJ,MAAM,GACP,EACF,CAAC"}
1
+ {"version":3,"file":"UDSProvider.js","names":[],"sources":["../../src/components/UDSProvider.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { memo, useContext } from 'react';\nimport { StyleSheet } from 'react-native';\nimport { GestureHandlerRootView } from 'react-native-gesture-handler';\n\nimport { FontScalingContext, UDSFontScalingProvider } from '../fontScaling/FontScalingContext';\nimport type { FontScalingConfig } from '../fontScaling/types';\nimport { PortalProvider } from '../portal';\n\ninterface UDSGestureProviderProps {\n children: ReactNode;\n /**\n * App-wide font-scaling caps, overriding the built-in defaults. Omit to use\n * the defaults (every text style capped at 2x or below, with the largest\n * display/title tiers tapered further, and control internals capped at 2x).\n * Should be identity-stable (a module constant or memoized) — every UDS text\n * element reads it from context.\n */\n fontScaling?: FontScalingConfig;\n}\n\n// An empty config resolves identically to \"no provider\" (built-in defaults).\nconst DEFAULT_FONT_SCALING_CONFIG: FontScalingConfig = {};\n\n/**\n * Root gesture and portal provider for UDS Mobile overlays.\n *\n * Place this at the top of your app layout:\n *\n * @example\n * ```tsx\n * import { UDSGestureProvider } from '@yahoo/uds-mobile/UDSGestureProvider';\n *\n * export default function RootLayout() {\n * return (\n * <UDSGestureProvider>\n * <Stack />\n * </UDSGestureProvider>\n * );\n * }\n * ```\n */\nconst UDSGestureProvider = memo(function UDSGestureProvider({\n children,\n fontScaling,\n}: UDSGestureProviderProps) {\n const inheritedFontScaling = useContext(FontScalingContext);\n const resolvedFontScaling = fontScaling ?? inheritedFontScaling ?? DEFAULT_FONT_SCALING_CONFIG;\n\n return (\n <GestureHandlerRootView style={styles.root}>\n <PortalProvider>\n {/* Always mounted: a `fontScaling` value that arrives after first\n render (e.g. a remote rollback flag) must not change the children's\n tree position, which would remount the entire app subtree. */}\n <UDSFontScalingProvider config={resolvedFontScaling}>{children}</UDSFontScalingProvider>\n </PortalProvider>\n </GestureHandlerRootView>\n );\n});\n\n/**\n * @deprecated Use {@link UDSGestureProvider} from `@yahoo/uds-mobile/UDSGestureProvider`.\n */\nconst UDSProvider = UDSGestureProvider;\n\nconst styles = StyleSheet.create({\n root: {\n flex: 1,\n },\n});\n\nexport { UDSGestureProvider, UDSProvider };\nexport type { UDSGestureProviderProps };\n/**\n * @deprecated Use {@link UDSGestureProviderProps}.\n */\nexport type UDSProviderProps = UDSGestureProviderProps;\n"],"mappings":";;;;;;;;AAsBA,MAAM,8BAAiD,EAAE;;;;;;;;;;;;;;;;;;;AAoBzD,MAAM,qBAAqB,KAAK,SAAS,mBAAmB,EAC1D,UACA,eAC0B;CAC1B,MAAM,uBAAuB,WAAW,mBAAmB;CAC3D,MAAM,sBAAsB,eAAe,wBAAwB;CAEnE,OACE,oBAAC,wBAAD;EAAwB,OAAO,OAAO;YACpC,oBAAC,gBAAD,EAAA,UAIE,oBAAC,wBAAD;GAAwB,QAAQ;GAAsB;GAAkC,CAAA,EACzE,CAAA;EACM,CAAA;EAE3B;;;;AAKF,MAAM,cAAc;AAEpB,MAAM,SAAS,WAAW,OAAO,EAC/B,MAAM,EACJ,MAAM,GACP,EACF,CAAC"}
@@ -9,6 +9,11 @@ const FontScalingContext = (0, react.createContext)(void 0);
9
9
  function useFontScalingEnabled() {
10
10
  return (0, react.useContext)(FontScalingContext)?.enabled !== false;
11
11
  }
12
+ /** Whether Text should supply its variant's default iOS Dynamic Type ramp. */
13
+ function useDynamicTypeRampEnabled() {
14
+ const config = (0, react.useContext)(FontScalingContext);
15
+ return config?.enabled !== false && config?.disableDynamicTypeRamp !== true;
16
+ }
12
17
  /**
13
18
  * **🔠 Overrides UDS font-scaling caps for a subtree**
14
19
  *
@@ -39,10 +44,15 @@ UDSFontScalingProvider.displayName = "UDSFontScalingProvider";
39
44
  const ResolvedControlFontScalingProvider = (0, react.memo)(function ResolvedControlFontScalingProvider({ maxFontSizeMultiplier, children }) {
40
45
  const parentConfig = (0, react.useContext)(FontScalingContext);
41
46
  const cap = maxFontSizeMultiplier === 0 ? null : maxFontSizeMultiplier;
42
- const config = (0, react.useMemo)(() => parentConfig?.enabled === false ? { enabled: false } : {
47
+ const config = (0, react.useMemo)(() => parentConfig?.enabled === false && maxFontSizeMultiplier === void 0 ? { enabled: false } : {
43
48
  default: cap,
44
- control: cap
45
- }, [cap, parentConfig?.enabled]);
49
+ control: cap,
50
+ disableDynamicTypeRamp: true
51
+ }, [
52
+ cap,
53
+ maxFontSizeMultiplier,
54
+ parentConfig?.enabled
55
+ ]);
46
56
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FontScalingContext.Provider, {
47
57
  value: config,
48
58
  children
@@ -53,4 +63,5 @@ ResolvedControlFontScalingProvider.displayName = "ResolvedControlFontScalingProv
53
63
  exports.FontScalingContext = FontScalingContext;
54
64
  exports.ResolvedControlFontScalingProvider = ResolvedControlFontScalingProvider;
55
65
  exports.UDSFontScalingProvider = UDSFontScalingProvider;
66
+ exports.useDynamicTypeRampEnabled = useDynamicTypeRampEnabled;
56
67
  exports.useFontScalingEnabled = useFontScalingEnabled;
@@ -4,9 +4,15 @@ import * as _$react from "react";
4
4
  import { ReactNode } from "react";
5
5
 
6
6
  //#region src/fontScaling/FontScalingContext.d.ts
7
- declare const FontScalingContext: _$react.Context<FontScalingConfig | undefined>;
7
+ interface FontScalingContextValue extends FontScalingConfig {
8
+ /** Internal: bounded controls use the global curve for text, icons, and geometry. */
9
+ disableDynamicTypeRamp?: boolean;
10
+ }
11
+ declare const FontScalingContext: _$react.Context<FontScalingContextValue | undefined>;
8
12
  /** Whether UDS-added caps, ramps, and scale-aware geometry are enabled. */
9
13
  declare function useFontScalingEnabled(): boolean;
14
+ /** Whether Text should supply its variant's default iOS Dynamic Type ramp. */
15
+ declare function useDynamicTypeRampEnabled(): boolean;
10
16
  interface UDSFontScalingProviderProps {
11
17
  /**
12
18
  * Font-scaling caps for the subtree. Should be identity-stable (a module
@@ -43,5 +49,5 @@ interface ResolvedControlFontScalingProviderProps {
43
49
  /** Keeps custom UDS content inside a control on the control's resolved cap. */
44
50
  declare const ResolvedControlFontScalingProvider: _$react.NamedExoticComponent<ResolvedControlFontScalingProviderProps>;
45
51
  //#endregion
46
- export { FontScalingContext, ResolvedControlFontScalingProvider, UDSFontScalingProvider, type UDSFontScalingProviderProps, useFontScalingEnabled };
52
+ export { FontScalingContext, ResolvedControlFontScalingProvider, UDSFontScalingProvider, type UDSFontScalingProviderProps, useDynamicTypeRampEnabled, useFontScalingEnabled };
47
53
  //# sourceMappingURL=FontScalingContext.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FontScalingContext.d.cts","names":[],"sources":["../../src/fontScaling/FontScalingContext.tsx"],"mappings":";;;;;;cAMM,kBAAA,EAAkB,OAAA,CAAA,OAAA,CAAA,iBAAA;;iBAGf,qBAAA,CAAA;AAAA,UAIC,2BAAA;EAPwE;;;;AAA1D;EAatB,MAAA,EAAQ,iBAAA;EACR,QAAA,EAAU,SAAA;AAAA;;AAXkB;;;;;;;;;;AAWT;;;;;AAsBO;;;cAAtB,sBAAA,EAAsB,OAAA,CAAA,oBAAA,CAAA,2BAAA;AAAA,UASlB,uCAAA;EACR,qBAAA;EACA,QAAA,EAAU,SAAA;AAAA;;cAIN,kCAAA,EAAkC,OAAA,CAAA,oBAAA,CAAA,uCAAA"}
1
+ {"version":3,"file":"FontScalingContext.d.cts","names":[],"sources":["../../src/fontScaling/FontScalingContext.tsx"],"mappings":";;;;;;UAKU,uBAAA,SAAgC,iBAAA;;EAExC,sBAAA;AAAA;AAAA,cAII,kBAAA,EAAkB,OAAA,CAAA,OAAA,CAAA,uBAAA;;iBAGf,qBAAA,CAAA;;iBAKA,yBAAA,CAAA;AAAA,UAKC,2BAAA;;;;AAbc;;EAmBtB,MAAA,EAAQ,iBAAA;EACR,QAAA,EAAU,SAAA;AAAA;AAjBkB;;;;;AAKI;;;;;;;;;;AAYb;;;;AAjBS,cAuCxB,sBAAA,EAAsB,OAAA,CAAA,oBAAA,CAAA,2BAAA;AAAA,UASlB,uCAAA;EACR,qBAAA;EACA,QAAA,EAAU,SAAA;AAAA;;cAIN,kCAAA,EAAkC,OAAA,CAAA,oBAAA,CAAA,uCAAA"}
@@ -4,9 +4,15 @@ import * as _$react from "react";
4
4
  import { ReactNode } from "react";
5
5
 
6
6
  //#region src/fontScaling/FontScalingContext.d.ts
7
- declare const FontScalingContext: _$react.Context<FontScalingConfig | undefined>;
7
+ interface FontScalingContextValue extends FontScalingConfig {
8
+ /** Internal: bounded controls use the global curve for text, icons, and geometry. */
9
+ disableDynamicTypeRamp?: boolean;
10
+ }
11
+ declare const FontScalingContext: _$react.Context<FontScalingContextValue | undefined>;
8
12
  /** Whether UDS-added caps, ramps, and scale-aware geometry are enabled. */
9
13
  declare function useFontScalingEnabled(): boolean;
14
+ /** Whether Text should supply its variant's default iOS Dynamic Type ramp. */
15
+ declare function useDynamicTypeRampEnabled(): boolean;
10
16
  interface UDSFontScalingProviderProps {
11
17
  /**
12
18
  * Font-scaling caps for the subtree. Should be identity-stable (a module
@@ -43,5 +49,5 @@ interface ResolvedControlFontScalingProviderProps {
43
49
  /** Keeps custom UDS content inside a control on the control's resolved cap. */
44
50
  declare const ResolvedControlFontScalingProvider: _$react.NamedExoticComponent<ResolvedControlFontScalingProviderProps>;
45
51
  //#endregion
46
- export { FontScalingContext, ResolvedControlFontScalingProvider, UDSFontScalingProvider, type UDSFontScalingProviderProps, useFontScalingEnabled };
52
+ export { FontScalingContext, ResolvedControlFontScalingProvider, UDSFontScalingProvider, type UDSFontScalingProviderProps, useDynamicTypeRampEnabled, useFontScalingEnabled };
47
53
  //# sourceMappingURL=FontScalingContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FontScalingContext.d.ts","names":[],"sources":["../../src/fontScaling/FontScalingContext.tsx"],"mappings":";;;;;;cAMM,kBAAA,EAAkB,OAAA,CAAA,OAAA,CAAA,iBAAA;;iBAGf,qBAAA,CAAA;AAAA,UAIC,2BAAA;EAPwE;;;;AAA1D;EAatB,MAAA,EAAQ,iBAAA;EACR,QAAA,EAAU,SAAA;AAAA;;AAXkB;;;;;;;;;;AAWT;;;;;AAsBO;;;cAAtB,sBAAA,EAAsB,OAAA,CAAA,oBAAA,CAAA,2BAAA;AAAA,UASlB,uCAAA;EACR,qBAAA;EACA,QAAA,EAAU,SAAA;AAAA;;cAIN,kCAAA,EAAkC,OAAA,CAAA,oBAAA,CAAA,uCAAA"}
1
+ {"version":3,"file":"FontScalingContext.d.ts","names":[],"sources":["../../src/fontScaling/FontScalingContext.tsx"],"mappings":";;;;;;UAKU,uBAAA,SAAgC,iBAAA;;EAExC,sBAAA;AAAA;AAAA,cAII,kBAAA,EAAkB,OAAA,CAAA,OAAA,CAAA,uBAAA;;iBAGf,qBAAA,CAAA;;iBAKA,yBAAA,CAAA;AAAA,UAKC,2BAAA;;;;AAbc;;EAmBtB,MAAA,EAAQ,iBAAA;EACR,QAAA,EAAU,SAAA;AAAA;AAjBkB;;;;;AAKI;;;;;;;;;;AAYb;;;;AAjBS,cAuCxB,sBAAA,EAAsB,OAAA,CAAA,oBAAA,CAAA,2BAAA;AAAA,UASlB,uCAAA;EACR,qBAAA;EACA,QAAA,EAAU,SAAA;AAAA;;cAIN,kCAAA,EAAkC,OAAA,CAAA,oBAAA,CAAA,uCAAA"}
@@ -7,6 +7,11 @@ const FontScalingContext = createContext(void 0);
7
7
  function useFontScalingEnabled() {
8
8
  return useContext(FontScalingContext)?.enabled !== false;
9
9
  }
10
+ /** Whether Text should supply its variant's default iOS Dynamic Type ramp. */
11
+ function useDynamicTypeRampEnabled() {
12
+ const config = useContext(FontScalingContext);
13
+ return config?.enabled !== false && config?.disableDynamicTypeRamp !== true;
14
+ }
10
15
  /**
11
16
  * **🔠 Overrides UDS font-scaling caps for a subtree**
12
17
  *
@@ -37,10 +42,15 @@ UDSFontScalingProvider.displayName = "UDSFontScalingProvider";
37
42
  const ResolvedControlFontScalingProvider = memo(function ResolvedControlFontScalingProvider({ maxFontSizeMultiplier, children }) {
38
43
  const parentConfig = useContext(FontScalingContext);
39
44
  const cap = maxFontSizeMultiplier === 0 ? null : maxFontSizeMultiplier;
40
- const config = useMemo(() => parentConfig?.enabled === false ? { enabled: false } : {
45
+ const config = useMemo(() => parentConfig?.enabled === false && maxFontSizeMultiplier === void 0 ? { enabled: false } : {
41
46
  default: cap,
42
- control: cap
43
- }, [cap, parentConfig?.enabled]);
47
+ control: cap,
48
+ disableDynamicTypeRamp: true
49
+ }, [
50
+ cap,
51
+ maxFontSizeMultiplier,
52
+ parentConfig?.enabled
53
+ ]);
44
54
  return /* @__PURE__ */ jsx(FontScalingContext.Provider, {
45
55
  value: config,
46
56
  children
@@ -48,6 +58,6 @@ const ResolvedControlFontScalingProvider = memo(function ResolvedControlFontScal
48
58
  });
49
59
  ResolvedControlFontScalingProvider.displayName = "ResolvedControlFontScalingProvider";
50
60
  //#endregion
51
- export { FontScalingContext, ResolvedControlFontScalingProvider, UDSFontScalingProvider, useFontScalingEnabled };
61
+ export { FontScalingContext, ResolvedControlFontScalingProvider, UDSFontScalingProvider, useDynamicTypeRampEnabled, useFontScalingEnabled };
52
62
 
53
63
  //# sourceMappingURL=FontScalingContext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FontScalingContext.js","names":[],"sources":["../../src/fontScaling/FontScalingContext.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { createContext, memo, useContext, useMemo } from 'react';\n\nimport type { FontScalingConfig } from './types';\n\n// undefined = no provider mounted; built-in defaults apply.\nconst FontScalingContext = createContext<FontScalingConfig | undefined>(undefined);\n\n/** Whether UDS-added caps, ramps, and scale-aware geometry are enabled. */\nfunction useFontScalingEnabled(): boolean {\n return useContext(FontScalingContext)?.enabled !== false;\n}\n\ninterface UDSFontScalingProviderProps {\n /**\n * Font-scaling caps for the subtree. Should be identity-stable (a module\n * constant or memoized) — every UDS text element reads it from context.\n * The nearest provider wins wholesale; configs are not merged.\n */\n config: FontScalingConfig;\n children: ReactNode;\n}\n\n/**\n * **🔠 Overrides UDS font-scaling caps for a subtree**\n *\n * @description\n * Configures how UDS text and controls respond to the OS text-size setting.\n * Without a provider, built-in defaults apply (every text style is capped at\n * 2x or below, with the largest display/title tiers tapered further, and\n * control internals capped at 2x). Most apps set this once at the root via the\n * `fontScaling` prop on `UDSGestureProvider`.\n *\n * @example\n * ```tsx\n * const FONT_SCALING = { default: 2, variants: { display1: 1.75 } };\n *\n * <UDSFontScalingProvider config={FONT_SCALING}>\n * <App />\n * </UDSFontScalingProvider>\n * ```\n */\nconst UDSFontScalingProvider = memo(function UDSFontScalingProvider({\n config,\n children,\n}: UDSFontScalingProviderProps) {\n return <FontScalingContext.Provider value={config}>{children}</FontScalingContext.Provider>;\n});\n\nUDSFontScalingProvider.displayName = 'UDSFontScalingProvider';\n\ninterface ResolvedControlFontScalingProviderProps {\n maxFontSizeMultiplier?: number;\n children: ReactNode;\n}\n\n/** Keeps custom UDS content inside a control on the control's resolved cap. */\nconst ResolvedControlFontScalingProvider = memo(function ResolvedControlFontScalingProvider({\n maxFontSizeMultiplier,\n children,\n}: ResolvedControlFontScalingProviderProps) {\n const parentConfig = useContext(FontScalingContext);\n const cap = maxFontSizeMultiplier === 0 ? null : maxFontSizeMultiplier;\n const config = useMemo<FontScalingConfig>(\n () => (parentConfig?.enabled === false ? { enabled: false } : { default: cap, control: cap }),\n [cap, parentConfig?.enabled],\n );\n\n return <FontScalingContext.Provider value={config}>{children}</FontScalingContext.Provider>;\n});\n\nResolvedControlFontScalingProvider.displayName = 'ResolvedControlFontScalingProvider';\n\nexport {\n FontScalingContext,\n ResolvedControlFontScalingProvider,\n UDSFontScalingProvider,\n useFontScalingEnabled,\n};\nexport type { UDSFontScalingProviderProps };\n"],"mappings":";;;;AAMA,MAAM,qBAAqB,cAA6C,KAAA,EAAU;;AAGlF,SAAS,wBAAiC;CACxC,OAAO,WAAW,mBAAmB,EAAE,YAAY;;;;;;;;;;;;;;;;;;;;;AAgCrD,MAAM,yBAAyB,KAAK,SAAS,uBAAuB,EAClE,QACA,YAC8B;CAC9B,OAAO,oBAAC,mBAAmB,UAApB;EAA6B,OAAO;EAAS;EAAuC,CAAA;EAC3F;AAEF,uBAAuB,cAAc;;AAQrC,MAAM,qCAAqC,KAAK,SAAS,mCAAmC,EAC1F,uBACA,YAC0C;CAC1C,MAAM,eAAe,WAAW,mBAAmB;CACnD,MAAM,MAAM,0BAA0B,IAAI,OAAO;CACjD,MAAM,SAAS,cACN,cAAc,YAAY,QAAQ,EAAE,SAAS,OAAO,GAAG;EAAE,SAAS;EAAK,SAAS;EAAK,EAC5F,CAAC,KAAK,cAAc,QAAQ,CAC7B;CAED,OAAO,oBAAC,mBAAmB,UAApB;EAA6B,OAAO;EAAS;EAAuC,CAAA;EAC3F;AAEF,mCAAmC,cAAc"}
1
+ {"version":3,"file":"FontScalingContext.js","names":[],"sources":["../../src/fontScaling/FontScalingContext.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { createContext, memo, useContext, useMemo } from 'react';\n\nimport type { FontScalingConfig } from './types';\n\ninterface FontScalingContextValue extends FontScalingConfig {\n /** Internal: bounded controls use the global curve for text, icons, and geometry. */\n disableDynamicTypeRamp?: boolean;\n}\n\n// undefined = no provider mounted; built-in defaults apply.\nconst FontScalingContext = createContext<FontScalingContextValue | undefined>(undefined);\n\n/** Whether UDS-added caps, ramps, and scale-aware geometry are enabled. */\nfunction useFontScalingEnabled(): boolean {\n return useContext(FontScalingContext)?.enabled !== false;\n}\n\n/** Whether Text should supply its variant's default iOS Dynamic Type ramp. */\nfunction useDynamicTypeRampEnabled(): boolean {\n const config = useContext(FontScalingContext);\n return config?.enabled !== false && config?.disableDynamicTypeRamp !== true;\n}\n\ninterface UDSFontScalingProviderProps {\n /**\n * Font-scaling caps for the subtree. Should be identity-stable (a module\n * constant or memoized) — every UDS text element reads it from context.\n * The nearest provider wins wholesale; configs are not merged.\n */\n config: FontScalingConfig;\n children: ReactNode;\n}\n\n/**\n * **🔠 Overrides UDS font-scaling caps for a subtree**\n *\n * @description\n * Configures how UDS text and controls respond to the OS text-size setting.\n * Without a provider, built-in defaults apply (every text style is capped at\n * 2x or below, with the largest display/title tiers tapered further, and\n * control internals capped at 2x). Most apps set this once at the root via the\n * `fontScaling` prop on `UDSGestureProvider`.\n *\n * @example\n * ```tsx\n * const FONT_SCALING = { default: 2, variants: { display1: 1.75 } };\n *\n * <UDSFontScalingProvider config={FONT_SCALING}>\n * <App />\n * </UDSFontScalingProvider>\n * ```\n */\nconst UDSFontScalingProvider = memo(function UDSFontScalingProvider({\n config,\n children,\n}: UDSFontScalingProviderProps) {\n return <FontScalingContext.Provider value={config}>{children}</FontScalingContext.Provider>;\n});\n\nUDSFontScalingProvider.displayName = 'UDSFontScalingProvider';\n\ninterface ResolvedControlFontScalingProviderProps {\n maxFontSizeMultiplier?: number;\n children: ReactNode;\n}\n\n/** Keeps custom UDS content inside a control on the control's resolved cap. */\nconst ResolvedControlFontScalingProvider = memo(function ResolvedControlFontScalingProvider({\n maxFontSizeMultiplier,\n children,\n}: ResolvedControlFontScalingProviderProps) {\n const parentConfig = useContext(FontScalingContext);\n const cap = maxFontSizeMultiplier === 0 ? null : maxFontSizeMultiplier;\n const config = useMemo<FontScalingContextValue>(\n () =>\n parentConfig?.enabled === false && maxFontSizeMultiplier === undefined\n ? { enabled: false }\n : { default: cap, control: cap, disableDynamicTypeRamp: true },\n [cap, maxFontSizeMultiplier, parentConfig?.enabled],\n );\n\n return <FontScalingContext.Provider value={config}>{children}</FontScalingContext.Provider>;\n});\n\nResolvedControlFontScalingProvider.displayName = 'ResolvedControlFontScalingProvider';\n\nexport {\n FontScalingContext,\n ResolvedControlFontScalingProvider,\n UDSFontScalingProvider,\n useDynamicTypeRampEnabled,\n useFontScalingEnabled,\n};\nexport type { UDSFontScalingProviderProps };\n"],"mappings":";;;;AAWA,MAAM,qBAAqB,cAAmD,KAAA,EAAU;;AAGxF,SAAS,wBAAiC;CACxC,OAAO,WAAW,mBAAmB,EAAE,YAAY;;;AAIrD,SAAS,4BAAqC;CAC5C,MAAM,SAAS,WAAW,mBAAmB;CAC7C,OAAO,QAAQ,YAAY,SAAS,QAAQ,2BAA2B;;;;;;;;;;;;;;;;;;;;;AAgCzE,MAAM,yBAAyB,KAAK,SAAS,uBAAuB,EAClE,QACA,YAC8B;CAC9B,OAAO,oBAAC,mBAAmB,UAApB;EAA6B,OAAO;EAAS;EAAuC,CAAA;EAC3F;AAEF,uBAAuB,cAAc;;AAQrC,MAAM,qCAAqC,KAAK,SAAS,mCAAmC,EAC1F,uBACA,YAC0C;CAC1C,MAAM,eAAe,WAAW,mBAAmB;CACnD,MAAM,MAAM,0BAA0B,IAAI,OAAO;CACjD,MAAM,SAAS,cAEX,cAAc,YAAY,SAAS,0BAA0B,KAAA,IACzD,EAAE,SAAS,OAAO,GAClB;EAAE,SAAS;EAAK,SAAS;EAAK,wBAAwB;EAAM,EAClE;EAAC;EAAK;EAAuB,cAAc;EAAQ,CACpD;CAED,OAAO,oBAAC,mBAAmB,UAApB;EAA6B,OAAO;EAAS;EAAuC,CAAA;EAC3F;AAEF,mCAAmC,cAAc"}
@@ -6,10 +6,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
6
6
  * is only the user's preference; multiplying by it directly does not reproduce the
7
7
  * size that native Text renders.
8
8
  *
9
- * These lookup tables mirror Android's `FontScaleConverterFactory`. Values between
9
+ * These lookup tables mirror Android's `FontScaleConverterFactory`. Android 14
10
+ * shipped fewer preference curves than Android 15+, so callers must provide the
11
+ * platform version to select the same table native Text uses. Values between
10
12
  * table entries are linearly interpolated, as they are in the platform implementation.
11
13
  *
12
14
  * @see https://android.googlesource.com/platform/frameworks/base/+/refs/heads/main/core/java/android/content/res/FontScaleConverterFactory.java
15
+ * @see https://android.googlesource.com/platform/prebuilts/fullsdk/sources/+/refs/heads/androidx-compose-integration-release/android-34/android/content/res/FontScaleConverterFactory.java
13
16
  */
14
17
  const COMMON_SP_SIZES = [
15
18
  8,
@@ -22,7 +25,79 @@ const COMMON_SP_SIZES = [
22
25
  30,
23
26
  100
24
27
  ];
25
- const ANDROID_FONT_SCALE_CURVES = [
28
+ const ANDROID_14_FONT_SCALE_CURVES = [
29
+ {
30
+ scale: 1.15,
31
+ dp: [
32
+ 9.2,
33
+ 11.5,
34
+ 13.8,
35
+ 16.4,
36
+ 19.8,
37
+ 21.8,
38
+ 25.2,
39
+ 30,
40
+ 100
41
+ ]
42
+ },
43
+ {
44
+ scale: 1.3,
45
+ dp: [
46
+ 10.4,
47
+ 13,
48
+ 15.6,
49
+ 18.8,
50
+ 21.6,
51
+ 23.6,
52
+ 26.4,
53
+ 30,
54
+ 100
55
+ ]
56
+ },
57
+ {
58
+ scale: 1.5,
59
+ dp: [
60
+ 12,
61
+ 15,
62
+ 18,
63
+ 22,
64
+ 24,
65
+ 26,
66
+ 28,
67
+ 30,
68
+ 100
69
+ ]
70
+ },
71
+ {
72
+ scale: 1.8,
73
+ dp: [
74
+ 14.4,
75
+ 18,
76
+ 21.6,
77
+ 24.4,
78
+ 27.6,
79
+ 30.8,
80
+ 32.8,
81
+ 34.8,
82
+ 100
83
+ ]
84
+ },
85
+ {
86
+ scale: 2,
87
+ dp: [
88
+ 16,
89
+ 20,
90
+ 24,
91
+ 26,
92
+ 30,
93
+ 34,
94
+ 36,
95
+ 38,
96
+ 100
97
+ ]
98
+ }
99
+ ];
100
+ const ANDROID_15_FONT_SCALE_CURVES = [
26
101
  {
27
102
  scale: 1.05,
28
103
  dp: [
@@ -154,16 +229,17 @@ function interpolateSize(fontSize, dpValues) {
154
229
  const lastIndex = COMMON_SP_SIZES.length - 1;
155
230
  return fontSize * (dpValues[lastIndex] / COMMON_SP_SIZES[lastIndex]);
156
231
  }
157
- /** Converts an SP value to its Android 14+ nonlinear DP size. */
158
- function convertAndroidSpToDp(fontSize, fontScale) {
159
- const firstCurve = ANDROID_FONT_SCALE_CURVES[0];
160
- const lastCurve = ANDROID_FONT_SCALE_CURVES[ANDROID_FONT_SCALE_CURVES.length - 1];
232
+ /** Converts an SP value to the nonlinear DP size used by this Android API level. */
233
+ function convertAndroidSpToDp(fontSize, fontScale, platformVersion = 35) {
234
+ const curves = platformVersion === 34 ? ANDROID_14_FONT_SCALE_CURVES : ANDROID_15_FONT_SCALE_CURVES;
235
+ const firstCurve = curves[0];
236
+ const lastCurve = curves[curves.length - 1];
161
237
  if (fontScale < firstCurve.scale || fontScale > lastCurve.scale) return fontSize * fontScale;
162
- for (let index = 0; index < ANDROID_FONT_SCALE_CURVES.length; index += 1) {
163
- const curve = ANDROID_FONT_SCALE_CURVES[index];
238
+ for (let index = 0; index < curves.length; index += 1) {
239
+ const curve = curves[index];
164
240
  if (fontScale === curve.scale) return interpolateSize(fontSize, curve.dp);
165
241
  if (fontScale < curve.scale) {
166
- const previousCurve = ANDROID_FONT_SCALE_CURVES[index - 1];
242
+ const previousCurve = curves[index - 1];
167
243
  const amount = (fontScale - previousCurve.scale) / (curve.scale - previousCurve.scale);
168
244
  return lerp(interpolateSize(fontSize, previousCurve.dp), interpolateSize(fontSize, curve.dp), amount);
169
245
  }
@@ -1,7 +1,7 @@
1
1
 
2
2
  //#region src/fontScaling/androidNonlinearFontScaling.d.ts
3
- /** Converts an SP value to its Android 14+ nonlinear DP size. */
4
- declare function convertAndroidSpToDp(fontSize: number, fontScale: number): number;
3
+ /** Converts an SP value to the nonlinear DP size used by this Android API level. */
4
+ declare function convertAndroidSpToDp(fontSize: number, fontScale: number, platformVersion?: number): number;
5
5
  //#endregion
6
6
  export { convertAndroidSpToDp };
7
7
  //# sourceMappingURL=androidNonlinearFontScaling.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"androidNonlinearFontScaling.d.cts","names":[],"sources":["../../src/fontScaling/androidNonlinearFontScaling.ts"],"mappings":";;;iBAmDS,oBAAA,CAAqB,QAAA,UAAkB,SAAA"}
1
+ {"version":3,"file":"androidNonlinearFontScaling.d.cts","names":[],"sources":["../../src/fontScaling/androidNonlinearFontScaling.ts"],"mappings":";;;iBA8DS,oBAAA,CACP,QAAA,UACA,SAAA,UACA,eAAA"}
@@ -1,7 +1,7 @@
1
1
 
2
2
  //#region src/fontScaling/androidNonlinearFontScaling.d.ts
3
- /** Converts an SP value to its Android 14+ nonlinear DP size. */
4
- declare function convertAndroidSpToDp(fontSize: number, fontScale: number): number;
3
+ /** Converts an SP value to the nonlinear DP size used by this Android API level. */
4
+ declare function convertAndroidSpToDp(fontSize: number, fontScale: number, platformVersion?: number): number;
5
5
  //#endregion
6
6
  export { convertAndroidSpToDp };
7
7
  //# sourceMappingURL=androidNonlinearFontScaling.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"androidNonlinearFontScaling.d.ts","names":[],"sources":["../../src/fontScaling/androidNonlinearFontScaling.ts"],"mappings":";;;iBAmDS,oBAAA,CAAqB,QAAA,UAAkB,SAAA"}
1
+ {"version":3,"file":"androidNonlinearFontScaling.d.ts","names":[],"sources":["../../src/fontScaling/androidNonlinearFontScaling.ts"],"mappings":";;;iBA8DS,oBAAA,CACP,QAAA,UACA,SAAA,UACA,eAAA"}