@yahoo/uds-mobile 2.24.0-beta.1 → 2.24.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -1
- package/dist/components/Avatar/AvatarIcon.cjs +8 -2
- package/dist/components/Avatar/AvatarIcon.d.cts.map +1 -1
- package/dist/components/Avatar/AvatarIcon.d.ts.map +1 -1
- package/dist/components/Avatar/AvatarIcon.js +9 -3
- package/dist/components/Avatar/AvatarIcon.js.map +1 -1
- package/dist/components/Avatar/AvatarImage.cjs +9 -2
- package/dist/components/Avatar/AvatarImage.d.cts.map +1 -1
- package/dist/components/Avatar/AvatarImage.d.ts.map +1 -1
- package/dist/components/Avatar/AvatarImage.js +10 -3
- package/dist/components/Avatar/AvatarImage.js.map +1 -1
- package/dist/components/Avatar/AvatarText.cjs +8 -2
- package/dist/components/Avatar/AvatarText.d.cts.map +1 -1
- package/dist/components/Avatar/AvatarText.d.ts.map +1 -1
- package/dist/components/Avatar/AvatarText.js +9 -3
- package/dist/components/Avatar/AvatarText.js.map +1 -1
- package/dist/components/Avatar/types.d.cts +7 -3
- package/dist/components/Avatar/types.d.cts.map +1 -1
- package/dist/components/Avatar/types.d.ts +7 -3
- package/dist/components/Avatar/types.d.ts.map +1 -1
- package/dist/components/Avatar/useAvatarFontScale.cjs +16 -0
- package/dist/components/Avatar/useAvatarFontScale.d.cts +7 -0
- package/dist/components/Avatar/useAvatarFontScale.d.cts.map +1 -0
- package/dist/components/Avatar/useAvatarFontScale.d.ts +7 -0
- package/dist/components/Avatar/useAvatarFontScale.d.ts.map +1 -0
- package/dist/components/Avatar/useAvatarFontScale.js +16 -0
- package/dist/components/Avatar/useAvatarFontScale.js.map +1 -0
- package/dist/components/Avatar/utils.cjs +9 -6
- package/dist/components/Avatar/utils.d.cts +2 -2
- package/dist/components/Avatar/utils.d.cts.map +1 -1
- package/dist/components/Avatar/utils.d.ts +2 -2
- package/dist/components/Avatar/utils.d.ts.map +1 -1
- package/dist/components/Avatar/utils.js +9 -6
- package/dist/components/Avatar/utils.js.map +1 -1
- package/dist/components/Button/buttonTheme.cjs +16 -7
- package/dist/components/Button/buttonTheme.d.cts +13 -6
- package/dist/components/Button/buttonTheme.d.cts.map +1 -1
- package/dist/components/Button/buttonTheme.d.ts +13 -6
- package/dist/components/Button/buttonTheme.d.ts.map +1 -1
- package/dist/components/Button/buttonTheme.js +16 -8
- package/dist/components/Button/buttonTheme.js.map +1 -1
- package/dist/components/Button.cjs +25 -11
- package/dist/components/Button.d.cts.map +1 -1
- package/dist/components/Button.d.ts.map +1 -1
- package/dist/components/Button.js +25 -11
- package/dist/components/Button.js.map +1 -1
- package/dist/components/Checkbox.cjs +16 -6
- package/dist/components/Checkbox.d.cts.map +1 -1
- package/dist/components/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox.js +16 -6
- package/dist/components/Checkbox.js.map +1 -1
- package/dist/components/Chip/ChipBase.cjs +24 -21
- package/dist/components/Chip/ChipBase.js +24 -21
- package/dist/components/Chip/ChipBase.js.map +1 -1
- package/dist/components/Icon.cjs +22 -6
- package/dist/components/Icon.d.cts +6 -5
- package/dist/components/Icon.d.cts.map +1 -1
- package/dist/components/Icon.d.ts +6 -5
- package/dist/components/Icon.d.ts.map +1 -1
- package/dist/components/Icon.js +22 -6
- package/dist/components/Icon.js.map +1 -1
- package/dist/components/IconButton.cjs +17 -6
- package/dist/components/IconButton.d.cts +6 -0
- package/dist/components/IconButton.d.cts.map +1 -1
- package/dist/components/IconButton.d.ts +6 -0
- package/dist/components/IconButton.d.ts.map +1 -1
- package/dist/components/IconButton.js +18 -7
- package/dist/components/IconButton.js.map +1 -1
- package/dist/components/Input.cjs +56 -18
- package/dist/components/Input.d.cts +5 -0
- package/dist/components/Input.d.cts.map +1 -1
- package/dist/components/Input.d.ts +5 -0
- package/dist/components/Input.d.ts.map +1 -1
- package/dist/components/Input.js +56 -18
- package/dist/components/Input.js.map +1 -1
- package/dist/components/InputHelpText.cjs +7 -1
- package/dist/components/InputHelpText.d.cts +2 -0
- package/dist/components/InputHelpText.d.cts.map +1 -1
- package/dist/components/InputHelpText.d.ts +2 -0
- package/dist/components/InputHelpText.d.ts.map +1 -1
- package/dist/components/InputHelpText.js +7 -1
- package/dist/components/InputHelpText.js.map +1 -1
- package/dist/components/Link.cjs +13 -1
- package/dist/components/Link.d.cts +7 -0
- package/dist/components/Link.d.cts.map +1 -1
- package/dist/components/Link.d.ts +7 -0
- package/dist/components/Link.d.ts.map +1 -1
- package/dist/components/Link.js +13 -1
- package/dist/components/Link.js.map +1 -1
- package/dist/components/Pagination/Pagination.cjs +18 -10
- package/dist/components/Pagination/Pagination.d.cts +2 -0
- package/dist/components/Pagination/Pagination.d.cts.map +1 -1
- package/dist/components/Pagination/Pagination.d.ts +2 -0
- package/dist/components/Pagination/Pagination.d.ts.map +1 -1
- package/dist/components/Pagination/Pagination.js +18 -10
- package/dist/components/Pagination/Pagination.js.map +1 -1
- package/dist/components/Pagination/PaginationEllipsis.cjs +8 -2
- package/dist/components/Pagination/PaginationEllipsis.d.cts.map +1 -1
- package/dist/components/Pagination/PaginationEllipsis.d.ts.map +1 -1
- package/dist/components/Pagination/PaginationEllipsis.js +9 -3
- package/dist/components/Pagination/PaginationEllipsis.js.map +1 -1
- package/dist/components/Pagination/PaginationItem.cjs +2 -1
- package/dist/components/Pagination/PaginationItem.js +2 -1
- package/dist/components/Pagination/PaginationItem.js.map +1 -1
- package/dist/components/Pagination/PaginationLink.cjs +2 -1
- package/dist/components/Pagination/PaginationLink.js +2 -1
- package/dist/components/Pagination/PaginationLink.js.map +1 -1
- package/dist/components/Pagination/PaginationNext.cjs +3 -1
- package/dist/components/Pagination/PaginationNext.js +3 -1
- package/dist/components/Pagination/PaginationNext.js.map +1 -1
- package/dist/components/Pagination/PaginationPrev.cjs +3 -1
- package/dist/components/Pagination/PaginationPrev.js +3 -1
- package/dist/components/Pagination/PaginationPrev.js.map +1 -1
- package/dist/components/Pagination/paginationContext.d.cts +2 -0
- package/dist/components/Pagination/paginationContext.d.cts.map +1 -1
- package/dist/components/Pagination/paginationContext.d.ts +2 -0
- package/dist/components/Pagination/paginationContext.d.ts.map +1 -1
- package/dist/components/Pagination/paginationContext.js.map +1 -1
- package/dist/components/Pagination/usePaginationControlStyles.cjs +8 -1
- package/dist/components/Pagination/usePaginationControlStyles.d.cts.map +1 -1
- package/dist/components/Pagination/usePaginationControlStyles.d.ts.map +1 -1
- package/dist/components/Pagination/usePaginationControlStyles.js +9 -2
- package/dist/components/Pagination/usePaginationControlStyles.js.map +1 -1
- package/dist/components/Radio/Radio.cjs +4 -3
- package/dist/components/Radio/Radio.js +4 -3
- package/dist/components/Radio/Radio.js.map +1 -1
- package/dist/components/Select/Select.cjs +29 -6
- package/dist/components/Select/Select.d.cts +2 -0
- package/dist/components/Select/Select.d.cts.map +1 -1
- package/dist/components/Select/Select.d.ts +2 -0
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +29 -6
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/SelectContent.cjs +31 -23
- package/dist/components/Select/SelectContent.d.cts.map +1 -1
- package/dist/components/Select/SelectContent.d.ts.map +1 -1
- package/dist/components/Select/SelectContent.js +32 -24
- package/dist/components/Select/SelectContent.js.map +1 -1
- package/dist/components/Select/SelectItem.cjs +25 -15
- package/dist/components/Select/SelectItem.d.cts.map +1 -1
- package/dist/components/Select/SelectItem.d.ts.map +1 -1
- package/dist/components/Select/SelectItem.js +25 -15
- package/dist/components/Select/SelectItem.js.map +1 -1
- package/dist/components/Select/SelectTrigger.cjs +27 -13
- package/dist/components/Select/SelectTrigger.d.cts.map +1 -1
- package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
- package/dist/components/Select/SelectTrigger.js +27 -13
- package/dist/components/Select/SelectTrigger.js.map +1 -1
- package/dist/components/Select/types.d.cts +2 -0
- package/dist/components/Select/types.d.cts.map +1 -1
- package/dist/components/Select/types.d.ts +2 -0
- package/dist/components/Select/types.d.ts.map +1 -1
- package/dist/components/Switch.cjs +31 -14
- package/dist/components/Switch.d.cts.map +1 -1
- package/dist/components/Switch.d.ts.map +1 -1
- package/dist/components/Switch.js +31 -14
- package/dist/components/Switch.js.map +1 -1
- package/dist/components/Tabs/Tab.cjs +8 -4
- package/dist/components/Tabs/Tab.d.cts.map +1 -1
- package/dist/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/components/Tabs/Tab.js +8 -4
- package/dist/components/Tabs/Tab.js.map +1 -1
- package/dist/components/Text.cjs +5 -0
- package/dist/components/Text.d.cts +6 -5
- package/dist/components/Text.d.cts.map +1 -1
- package/dist/components/Text.d.ts +6 -5
- package/dist/components/Text.d.ts.map +1 -1
- package/dist/components/Text.js +5 -0
- package/dist/components/Text.js.map +1 -1
- package/dist/components/UDSProvider.cjs +1 -1
- package/dist/components/UDSProvider.d.cts +4 -3
- package/dist/components/UDSProvider.d.cts.map +1 -1
- package/dist/components/UDSProvider.d.ts +4 -3
- package/dist/components/UDSProvider.d.ts.map +1 -1
- package/dist/components/UDSProvider.js +1 -1
- package/dist/components/UDSProvider.js.map +1 -1
- package/dist/fontScaling/FontScalingContext.cjs +35 -3
- package/dist/fontScaling/FontScalingContext.d.cts +20 -5
- package/dist/fontScaling/FontScalingContext.d.cts.map +1 -1
- package/dist/fontScaling/FontScalingContext.d.ts +20 -5
- package/dist/fontScaling/FontScalingContext.d.ts.map +1 -1
- package/dist/fontScaling/FontScalingContext.js +34 -5
- package/dist/fontScaling/FontScalingContext.js.map +1 -1
- package/dist/fontScaling/androidNonlinearFontScaling.cjs +250 -0
- package/dist/fontScaling/androidNonlinearFontScaling.d.cts +7 -0
- package/dist/fontScaling/androidNonlinearFontScaling.d.cts.map +1 -0
- package/dist/fontScaling/androidNonlinearFontScaling.d.ts +7 -0
- package/dist/fontScaling/androidNonlinearFontScaling.d.ts.map +1 -0
- package/dist/fontScaling/androidNonlinearFontScaling.js +251 -0
- package/dist/fontScaling/androidNonlinearFontScaling.js.map +1 -0
- package/dist/fontScaling/constants.cjs +37 -3
- package/dist/fontScaling/constants.d.cts +15 -4
- package/dist/fontScaling/constants.d.cts.map +1 -1
- package/dist/fontScaling/constants.d.ts +15 -4
- package/dist/fontScaling/constants.d.ts.map +1 -1
- package/dist/fontScaling/constants.js +37 -4
- package/dist/fontScaling/constants.js.map +1 -1
- package/dist/fontScaling/index.cjs +2 -1
- package/dist/fontScaling/index.d.cts +2 -2
- package/dist/fontScaling/index.d.ts +2 -2
- package/dist/fontScaling/index.js +3 -3
- package/dist/fontScaling/resolveMaxFontSizeMultiplier.cjs +1 -2
- package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.cts +1 -2
- package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.cts.map +1 -1
- package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.ts +1 -2
- package/dist/fontScaling/resolveMaxFontSizeMultiplier.d.ts.map +1 -1
- package/dist/fontScaling/resolveMaxFontSizeMultiplier.js +1 -2
- package/dist/fontScaling/resolveMaxFontSizeMultiplier.js.map +1 -1
- package/dist/fontScaling/types.d.cts +11 -8
- package/dist/fontScaling/types.d.cts.map +1 -1
- package/dist/fontScaling/types.d.ts +11 -8
- package/dist/fontScaling/types.d.ts.map +1 -1
- package/dist/fontScaling/useFontScale.cjs +30 -4
- package/dist/fontScaling/useFontScale.d.cts +6 -12
- package/dist/fontScaling/useFontScale.d.cts.map +1 -1
- package/dist/fontScaling/useFontScale.d.ts +6 -12
- package/dist/fontScaling/useFontScale.d.ts.map +1 -1
- package/dist/fontScaling/useFontScale.js +31 -6
- package/dist/fontScaling/useFontScale.js.map +1 -1
- package/dist/jest/mocks/styles.cjs +14 -1
- package/dist/jest/mocks/styles.d.cts.map +1 -1
- package/dist/jest/mocks/styles.d.ts.map +1 -1
- package/dist/jest/mocks/styles.js +14 -1
- package/dist/jest/mocks/styles.js.map +1 -1
- package/dist/mobile/generated/fontMetrics.cjs +530 -530
- package/dist/mobile/generated/fontMetrics.js +530 -530
- package/dist/mobile/generated/fontMetrics.js.map +1 -1
- package/dist/portal.cjs +8 -2
- package/dist/portal.d.cts.map +1 -1
- package/dist/portal.d.ts.map +1 -1
- package/dist/portal.js +8 -2
- package/dist/portal.js.map +1 -1
- package/fonts/index.cjs +214 -214
- package/fonts/index.mjs +214 -214
- package/generated/fontMetrics.ts +530 -530
- package/package.json +1 -1
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
4
|
+
const require_fontScaling_useFontScale = require("../fontScaling/useFontScale.cjs");
|
|
4
5
|
const require_fontScaling_useMaxFontSizeMultiplier = require("../fontScaling/useMaxFontSizeMultiplier.cjs");
|
|
6
|
+
const require_components_Button_buttonTheme = require("./Button/buttonTheme.cjs");
|
|
5
7
|
const require_components_IconSlot = require("./IconSlot.cjs");
|
|
6
|
-
const require_fontScaling_useFontScale = require("../fontScaling/useFontScale.cjs");
|
|
7
8
|
const require_components_FormLabel = require("./FormLabel.cjs");
|
|
8
9
|
let react = require("react");
|
|
9
10
|
let react_native = require("react-native");
|
|
10
11
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
12
|
let generated_styles = require("../../generated/styles");
|
|
12
13
|
let react_native_unistyles = require("react-native-unistyles");
|
|
13
|
-
let _yahoo_uds_icons_tokens = require("@yahoo/uds-icons/tokens");
|
|
14
14
|
let react_native_reanimated = require("react-native-reanimated");
|
|
15
15
|
react_native_reanimated = require_runtime.__toESM(react_native_reanimated);
|
|
16
16
|
let react_native_unistyles_reanimated = require("react-native-unistyles/reanimated");
|
|
17
17
|
//#region src/components/Switch.tsx
|
|
18
|
-
const HANDLE_TRAVEL = {
|
|
19
|
-
md: 20,
|
|
20
|
-
sm: 12
|
|
21
|
-
};
|
|
22
18
|
const ANIMATION_DURATION = 120;
|
|
23
19
|
/**
|
|
24
20
|
* **Switch component for toggling options**
|
|
@@ -60,9 +56,7 @@ const Switch = (0, react.memo)(function Switch({ isOn: isOnProp, defaultIsOn = f
|
|
|
60
56
|
const isOn = isControlled ? isOnProp : internalIsOn;
|
|
61
57
|
const activeVariant = isOn ? "on" : "off";
|
|
62
58
|
const { theme } = (0, react_native_unistyles.useUnistyles)();
|
|
63
|
-
const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier)
|
|
64
|
-
const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier);
|
|
65
|
-
const scaledHandleIconSize = Math.round(_yahoo_uds_icons_tokens.ICON_SIZE_MAP.sm * fontScaleFactor);
|
|
59
|
+
const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
|
|
66
60
|
(0, react.useEffect)(() => {
|
|
67
61
|
const checkReducedMotion = async () => {
|
|
68
62
|
setPrefersReducedMotion(await react_native.AccessibilityInfo.isReduceMotionEnabled());
|
|
@@ -73,7 +67,6 @@ const Switch = (0, react.memo)(function Switch({ isOn: isOnProp, defaultIsOn = f
|
|
|
73
67
|
}, []);
|
|
74
68
|
const animationDuration = reduceMotion || prefersReducedMotion ? 0 : ANIMATION_DURATION;
|
|
75
69
|
const progress = (0, react_native_reanimated.useDerivedValue)(() => (0, react_native_reanimated.withTiming)(isOn ? 1 : 0, { duration: animationDuration }), [isOn, animationDuration]);
|
|
76
|
-
const travelDistance = Math.round(HANDLE_TRAVEL[size] * fontScaleFactor) * (react_native.I18nManager.isRTL ? -1 : 1);
|
|
77
70
|
const handlePress = (0, react.useCallback)(() => {
|
|
78
71
|
if (disabled) return;
|
|
79
72
|
const newValue = !isOn;
|
|
@@ -89,6 +82,15 @@ const Switch = (0, react.memo)(function Switch({ isOn: isOnProp, defaultIsOn = f
|
|
|
89
82
|
size,
|
|
90
83
|
variant: activeVariant
|
|
91
84
|
}) ?? generated_styles.switchStyles;
|
|
85
|
+
const labelBaseSize = resolvedSwitchStyles.text.lineHeight ?? resolvedSwitchStyles.text.fontSize;
|
|
86
|
+
const fontScaleFactor = require_fontScaling_useFontScale.useComponentFontScale(resolvedMaxFontSizeMultiplier, typeof labelBaseSize === "number" ? labelBaseSize : void 0);
|
|
87
|
+
const handleIconSize = resolvedSwitchStyles.handleIcon.fontSize;
|
|
88
|
+
const handleIconScaleFactor = require_fontScaling_useFontScale.useComponentFontScale(resolvedMaxFontSizeMultiplier, typeof handleIconSize === "number" ? handleIconSize : void 0);
|
|
89
|
+
const scaledHandleIconSize = typeof handleIconSize === "number" ? Math.round(handleIconSize * handleIconScaleFactor) : void 0;
|
|
90
|
+
const scaledTrackWidth = Math.round(resolvedSwitchStyles.switch.width * fontScaleFactor);
|
|
91
|
+
const scaledTrackPadding = Math.round(resolvedSwitchStyles.switch.padding * fontScaleFactor);
|
|
92
|
+
const scaledHandleWidth = Math.round(resolvedSwitchStyles.handle.width * fontScaleFactor);
|
|
93
|
+
const travelDistance = Math.max(0, scaledTrackWidth - scaledHandleWidth - scaledTrackPadding * 2) * (react_native.I18nManager.isRTL ? -1 : 1);
|
|
92
94
|
const variantLayerStyles = (0, react.useMemo)(() => {
|
|
93
95
|
const components = theme.components;
|
|
94
96
|
const getLayerStyle = (layer) => components[`switch/variant/default/active/${activeVariant}/${layer}/rest`];
|
|
@@ -111,10 +113,11 @@ const Switch = (0, react.memo)(function Switch({ isOn: isOnProp, defaultIsOn = f
|
|
|
111
113
|
const rootStyle = (0, react.useMemo)(() => [resolvedSwitchStyles.root, switchStaticStyles.root({ disabled })], [resolvedSwitchStyles.root, disabled]);
|
|
112
114
|
const scaleDimensions = (0, react.useCallback)((style) => {
|
|
113
115
|
if (!style || fontScaleFactor === 1) return;
|
|
114
|
-
const { width, height } = style;
|
|
116
|
+
const { width, height, padding } = style;
|
|
115
117
|
return typeof width === "number" && typeof height === "number" ? {
|
|
116
118
|
width: Math.round(width * fontScaleFactor),
|
|
117
|
-
height: Math.round(height * fontScaleFactor)
|
|
119
|
+
height: Math.round(height * fontScaleFactor),
|
|
120
|
+
...typeof padding === "number" && { padding: Math.round(padding * fontScaleFactor) }
|
|
118
121
|
} : void 0;
|
|
119
122
|
}, [fontScaleFactor]);
|
|
120
123
|
const trackStyle = (0, react.useMemo)(() => [
|
|
@@ -182,7 +185,14 @@ const Switch = (0, react.memo)(function Switch({ isOn: isOnProp, defaultIsOn = f
|
|
|
182
185
|
variant: "fill",
|
|
183
186
|
dangerouslySetSize: scaledHandleIconSize,
|
|
184
187
|
allowFontScaling: false,
|
|
185
|
-
style: [
|
|
188
|
+
style: [
|
|
189
|
+
resolvedSwitchStyles.handleIcon,
|
|
190
|
+
variantLayerStyles.handleIcon,
|
|
191
|
+
scaledHandleIconSize === void 0 ? void 0 : {
|
|
192
|
+
fontSize: scaledHandleIconSize,
|
|
193
|
+
lineHeight: require_components_Button_buttonTheme.getSafeIconCell(scaledHandleIconSize)
|
|
194
|
+
}
|
|
195
|
+
]
|
|
186
196
|
})
|
|
187
197
|
}), offIcon && !isOn && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_native_reanimated.default.View, {
|
|
188
198
|
style: switchStaticStyles.iconContainer,
|
|
@@ -191,7 +201,14 @@ const Switch = (0, react.memo)(function Switch({ isOn: isOnProp, defaultIsOn = f
|
|
|
191
201
|
variant: "fill",
|
|
192
202
|
dangerouslySetSize: scaledHandleIconSize,
|
|
193
203
|
allowFontScaling: false,
|
|
194
|
-
style: [
|
|
204
|
+
style: [
|
|
205
|
+
resolvedSwitchStyles.handleIcon,
|
|
206
|
+
variantLayerStyles.handleIcon,
|
|
207
|
+
scaledHandleIconSize === void 0 ? void 0 : {
|
|
208
|
+
fontSize: scaledHandleIconSize,
|
|
209
|
+
lineHeight: require_components_Button_buttonTheme.getSafeIconCell(scaledHandleIconSize)
|
|
210
|
+
}
|
|
211
|
+
]
|
|
195
212
|
})
|
|
196
213
|
})]
|
|
197
214
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.d.cts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAyBU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;;;;;;EAaN,qBAAA;EAfiC;EAiBjC,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"Switch.d.cts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAyBU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;;;;;;EAaN,qBAAA;EAfiC;EAiBjC,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;;;;;;;cAsClC,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.d.ts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAyBU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;;;;;;EAaN,qBAAA;EAfiC;EAiBjC,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"Switch.d.ts","names":[],"sources":["../../src/components/Switch.tsx"],"mappings":";;;;;;;;UAyBU,WAAA,SAAoB,IAAA,CAAK,SAAA,YAAqB,oBAAA,CAAqB,YAAA;;EAE3E,GAAA,GAAM,GAAA,CAAI,IAAA;EAFF;EAIR,QAAA,IAAY,KAAA;;EAEZ,QAAA;EAN2E;EAQ3E,QAAA;EANM;;;;;;EAaN,qBAAA;EAfiC;EAiBjC,iBAAA,GAAoB,kBAAA;AAAA;;;;;;;;;;;;;AAAkB;;;;;;;;;;;;;;;;;;;;;cAsClC,MAAA,EAAM,OAAA,CAAA,oBAAA,CAAA,WAAA"}
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
+
import { useComponentFontScale } from "../fontScaling/useFontScale.js";
|
|
2
3
|
import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
|
|
4
|
+
import { getSafeIconCell } from "./Button/buttonTheme.js";
|
|
3
5
|
import { IconSlot } from "./IconSlot.js";
|
|
4
|
-
import { useFontScale } from "../fontScaling/useFontScale.js";
|
|
5
6
|
import { FormLabel } from "./FormLabel.js";
|
|
6
7
|
import { memo, useCallback, useEffect, useMemo, useState } from "react";
|
|
7
8
|
import { AccessibilityInfo, I18nManager, Platform, Pressable } from "react-native";
|
|
8
9
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
10
|
import { switchStyles } from "../../generated/styles";
|
|
10
11
|
import { StyleSheet as StyleSheet$1, useUnistyles } from "react-native-unistyles";
|
|
11
|
-
import { ICON_SIZE_MAP } from "@yahoo/uds-icons/tokens";
|
|
12
12
|
import Animated, { useAnimatedStyle, useDerivedValue, withTiming } from "react-native-reanimated";
|
|
13
13
|
import { useAnimatedVariantColor } from "react-native-unistyles/reanimated";
|
|
14
14
|
//#region src/components/Switch.tsx
|
|
15
|
-
const HANDLE_TRAVEL = {
|
|
16
|
-
md: 20,
|
|
17
|
-
sm: 12
|
|
18
|
-
};
|
|
19
15
|
const ANIMATION_DURATION = 120;
|
|
20
16
|
/**
|
|
21
17
|
* **Switch component for toggling options**
|
|
@@ -57,9 +53,7 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
|
|
|
57
53
|
const isOn = isControlled ? isOnProp : internalIsOn;
|
|
58
54
|
const activeVariant = isOn ? "on" : "off";
|
|
59
55
|
const { theme } = useUnistyles();
|
|
60
|
-
const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier)
|
|
61
|
-
const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);
|
|
62
|
-
const scaledHandleIconSize = Math.round(ICON_SIZE_MAP.sm * fontScaleFactor);
|
|
56
|
+
const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
|
|
63
57
|
useEffect(() => {
|
|
64
58
|
const checkReducedMotion = async () => {
|
|
65
59
|
setPrefersReducedMotion(await AccessibilityInfo.isReduceMotionEnabled());
|
|
@@ -70,7 +64,6 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
|
|
|
70
64
|
}, []);
|
|
71
65
|
const animationDuration = reduceMotion || prefersReducedMotion ? 0 : ANIMATION_DURATION;
|
|
72
66
|
const progress = useDerivedValue(() => withTiming(isOn ? 1 : 0, { duration: animationDuration }), [isOn, animationDuration]);
|
|
73
|
-
const travelDistance = Math.round(HANDLE_TRAVEL[size] * fontScaleFactor) * (I18nManager.isRTL ? -1 : 1);
|
|
74
67
|
const handlePress = useCallback(() => {
|
|
75
68
|
if (disabled) return;
|
|
76
69
|
const newValue = !isOn;
|
|
@@ -86,6 +79,15 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
|
|
|
86
79
|
size,
|
|
87
80
|
variant: activeVariant
|
|
88
81
|
}) ?? switchStyles;
|
|
82
|
+
const labelBaseSize = resolvedSwitchStyles.text.lineHeight ?? resolvedSwitchStyles.text.fontSize;
|
|
83
|
+
const fontScaleFactor = useComponentFontScale(resolvedMaxFontSizeMultiplier, typeof labelBaseSize === "number" ? labelBaseSize : void 0);
|
|
84
|
+
const handleIconSize = resolvedSwitchStyles.handleIcon.fontSize;
|
|
85
|
+
const handleIconScaleFactor = useComponentFontScale(resolvedMaxFontSizeMultiplier, typeof handleIconSize === "number" ? handleIconSize : void 0);
|
|
86
|
+
const scaledHandleIconSize = typeof handleIconSize === "number" ? Math.round(handleIconSize * handleIconScaleFactor) : void 0;
|
|
87
|
+
const scaledTrackWidth = Math.round(resolvedSwitchStyles.switch.width * fontScaleFactor);
|
|
88
|
+
const scaledTrackPadding = Math.round(resolvedSwitchStyles.switch.padding * fontScaleFactor);
|
|
89
|
+
const scaledHandleWidth = Math.round(resolvedSwitchStyles.handle.width * fontScaleFactor);
|
|
90
|
+
const travelDistance = Math.max(0, scaledTrackWidth - scaledHandleWidth - scaledTrackPadding * 2) * (I18nManager.isRTL ? -1 : 1);
|
|
89
91
|
const variantLayerStyles = useMemo(() => {
|
|
90
92
|
const components = theme.components;
|
|
91
93
|
const getLayerStyle = (layer) => components[`switch/variant/default/active/${activeVariant}/${layer}/rest`];
|
|
@@ -108,10 +110,11 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
|
|
|
108
110
|
const rootStyle = useMemo(() => [resolvedSwitchStyles.root, switchStaticStyles.root({ disabled })], [resolvedSwitchStyles.root, disabled]);
|
|
109
111
|
const scaleDimensions = useCallback((style) => {
|
|
110
112
|
if (!style || fontScaleFactor === 1) return;
|
|
111
|
-
const { width, height } = style;
|
|
113
|
+
const { width, height, padding } = style;
|
|
112
114
|
return typeof width === "number" && typeof height === "number" ? {
|
|
113
115
|
width: Math.round(width * fontScaleFactor),
|
|
114
|
-
height: Math.round(height * fontScaleFactor)
|
|
116
|
+
height: Math.round(height * fontScaleFactor),
|
|
117
|
+
...typeof padding === "number" && { padding: Math.round(padding * fontScaleFactor) }
|
|
115
118
|
} : void 0;
|
|
116
119
|
}, [fontScaleFactor]);
|
|
117
120
|
const trackStyle = useMemo(() => [
|
|
@@ -179,7 +182,14 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
|
|
|
179
182
|
variant: "fill",
|
|
180
183
|
dangerouslySetSize: scaledHandleIconSize,
|
|
181
184
|
allowFontScaling: false,
|
|
182
|
-
style: [
|
|
185
|
+
style: [
|
|
186
|
+
resolvedSwitchStyles.handleIcon,
|
|
187
|
+
variantLayerStyles.handleIcon,
|
|
188
|
+
scaledHandleIconSize === void 0 ? void 0 : {
|
|
189
|
+
fontSize: scaledHandleIconSize,
|
|
190
|
+
lineHeight: getSafeIconCell(scaledHandleIconSize)
|
|
191
|
+
}
|
|
192
|
+
]
|
|
183
193
|
})
|
|
184
194
|
}), offIcon && !isOn && /* @__PURE__ */ jsx(Animated.View, {
|
|
185
195
|
style: switchStaticStyles.iconContainer,
|
|
@@ -188,7 +198,14 @@ const Switch = memo(function Switch({ isOn: isOnProp, defaultIsOn = false, onCha
|
|
|
188
198
|
variant: "fill",
|
|
189
199
|
dangerouslySetSize: scaledHandleIconSize,
|
|
190
200
|
allowFontScaling: false,
|
|
191
|
-
style: [
|
|
201
|
+
style: [
|
|
202
|
+
resolvedSwitchStyles.handleIcon,
|
|
203
|
+
variantLayerStyles.handleIcon,
|
|
204
|
+
scaledHandleIconSize === void 0 ? void 0 : {
|
|
205
|
+
fontSize: scaledHandleIconSize,
|
|
206
|
+
lineHeight: getSafeIconCell(scaledHandleIconSize)
|
|
207
|
+
}
|
|
208
|
+
]
|
|
192
209
|
})
|
|
193
210
|
})]
|
|
194
211
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Switch.js","names":["StyleSheet"],"sources":["../../src/components/Switch.tsx"],"sourcesContent":["import { ICON_SIZE_MAP } from '@yahoo/uds-icons/tokens';\nimport type { SwitchSize, UniversalSwitchProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type {\n AccessibilityProps,\n StyleProp,\n TextStyle,\n View,\n ViewProps,\n ViewStyle,\n} from 'react-native';\nimport { AccessibilityInfo, I18nManager, Platform, Pressable } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withTiming } from 'react-native-reanimated';\n// eslint-disable-next-line uds/no-use-unistyles -- switch variant layers need concrete web styles\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\nimport { useAnimatedVariantColor } from 'react-native-unistyles/reanimated';\n\nimport { switchStyles } from '../../generated/styles';\nimport { useFontScale } from '../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\nimport { FormLabel } from './FormLabel';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\n\ninterface SwitchProps extends Omit<ViewProps, 'style'>, UniversalSwitchProps<IconSlotType> {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Callback when the switch value changes */\n onChange?: (value: boolean) => void;\n /** Whether the switch is disabled */\n disabled?: boolean;\n /** Whether the switch is required (shows asterisk with label) */\n required?: boolean;\n /**\n * Caps how far the track, handle, and label grow with the OS text-size\n * setting; all scale by the same factor. Set null to remove the cap;\n * override app-wide via UDSFontScalingProvider.\n * @default 2\n */\n maxFontSizeMultiplier?: number | null;\n /** Accessibility hint describing what happens when activated */\n accessibilityHint?: AccessibilityProps['accessibilityHint'];\n}\n\nconst HANDLE_TRAVEL: Record<SwitchSize, number> = {\n md: 20,\n sm: 12,\n};\n\nconst ANIMATION_DURATION = 120;\n\n/**\n * **Switch component for toggling options**\n *\n * @description\n * A switch (also called a toggle) is a binary on/off input control.\n * It allows users to pick between two clearly opposite choices.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Switch } from '@yahoo/uds-mobile/Switch';\n *\n * <Switch label=\"Notifications\" />\n * <Switch isOn={enabled} onChange={setEnabled} label=\"Dark mode\" />\n * <Switch onIcon=\"Check\" offIcon=\"Cross\" label=\"Sync\" />\n * ```\n *\n * @usage\n * - Settings: For toggling preferences on/off\n * - Feature flags: For enabling/disabling features\n * - Immediate effect toggles (no submit button needed)\n *\n * @accessibility\n * - Sets `accessibilityRole=\"switch\"` automatically\n * - Announces on/off state to screen readers\n * - Respects system reduce motion preference\n * - Supports `reduceMotion` prop to disable animations\n *\n * @see {@link Checkbox} for forms with submit actions\n * @see {@link Radio} for single-select options\n */\nconst Switch = memo(function Switch({\n isOn: isOnProp,\n defaultIsOn = false,\n onChange,\n label,\n labelPosition = 'start',\n size = 'md',\n onIcon,\n offIcon,\n disabled = false,\n required,\n maxFontSizeMultiplier,\n accessibilityHint,\n reduceMotion = false,\n ref,\n ...viewProps\n}: SwitchProps) {\n const isControlled = isOnProp !== undefined;\n const [internalIsOn, setInternalIsOn] = useState(defaultIsOn);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const isOn = isControlled ? isOnProp : internalIsOn;\n const activeVariant = isOn ? 'on' : 'off';\n const { theme } = useUnistyles();\n\n // One capped factor governs track, handle, travel, and label.\n const resolvedMaxFontSizeMultiplier =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);\n // Size the handle glyph from the same factor as the handle it sits in, rather\n // than letting native font scaling size it on a separate path.\n const scaledHandleIconSize = Math.round(ICON_SIZE_MAP.sm * fontScaleFactor);\n\n // Check system reduced motion preference\n useEffect(() => {\n const checkReducedMotion = async () => {\n const isReduceMotionEnabled = await AccessibilityInfo.isReduceMotionEnabled();\n setPrefersReducedMotion(isReduceMotionEnabled);\n };\n checkReducedMotion();\n\n const subscription = AccessibilityInfo.addEventListener(\n 'reduceMotionChanged',\n setPrefersReducedMotion,\n );\n return () => subscription.remove();\n }, []);\n\n const shouldReduceMotion = reduceMotion || prefersReducedMotion;\n const animationDuration = shouldReduceMotion ? 0 : ANIMATION_DURATION;\n\n const progress = useDerivedValue(\n () => withTiming(isOn ? 1 : 0, { duration: animationDuration }),\n [isOn, animationDuration],\n );\n\n // RTL mirrors the track layout but not transforms, so travel flips sign.\n // Travel scales with the track/handle so the handle still lands flush.\n const travelDistance =\n Math.round(HANDLE_TRAVEL[size] * fontScaleFactor) * (I18nManager.isRTL ? -1 : 1);\n\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n const newValue = !isOn;\n\n if (!isControlled) {\n setInternalIsOn(newValue);\n }\n\n onChange?.(newValue);\n }, [disabled, isOn, isControlled, onChange]);\n\n // On web, useVariants returns the resolved style object instead of mutating\n // switchStyles in place.\n const variantSwitchStyles = switchStyles.useVariants({\n size,\n variant: activeVariant,\n }) as unknown as typeof switchStyles | undefined;\n const resolvedSwitchStyles = variantSwitchStyles ?? switchStyles;\n\n const variantLayerStyles = useMemo(() => {\n const components = theme.components as unknown as Record<string, Record<string, unknown>>;\n const getLayerStyle = <TStyle,>(layer: string) =>\n components[`switch/variant/default/active/${activeVariant}/${layer}/rest`] as\n TStyle | undefined;\n\n return {\n handle: getLayerStyle<ViewStyle>('handle'),\n handleIcon: getLayerStyle<TextStyle>('handleIcon'),\n switch: getLayerStyle<ViewStyle>('switch'),\n text: getLayerStyle<TextStyle>('rootText'),\n };\n }, [activeVariant, theme]);\n\n // Get animated track color from design tokens (changes when variant changes)\n const trackBackgroundColor = useAnimatedVariantColor(\n resolvedSwitchStyles.switch,\n 'backgroundColor',\n );\n\n const animatedTrackStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n backgroundColor: withTiming(trackBackgroundColor.value, { duration: animationDuration }),\n };\n });\n\n const animatedHandleStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n transform: [{ translateX: progress.value * travelDistance }],\n };\n });\n\n const rootStyle: StyleProp<ViewStyle> = useMemo(\n () => [resolvedSwitchStyles.root, switchStaticStyles.root({ disabled })],\n [resolvedSwitchStyles.root, disabled],\n );\n\n // Track and handle grow by the capped factor so the handle (and its icon,\n // which native scales by the same capped multiplier) stays contained.\n const scaleDimensions = useCallback(\n (style: ViewStyle | undefined): ViewStyle | undefined => {\n if (!style || fontScaleFactor === 1) {\n return undefined;\n }\n const { width, height } = style;\n return typeof width === 'number' && typeof height === 'number'\n ? {\n width: Math.round(width * fontScaleFactor),\n height: Math.round(height * fontScaleFactor),\n }\n : undefined;\n },\n [fontScaleFactor],\n );\n\n const trackStyle: StyleProp<ViewStyle> = useMemo(\n () => [\n resolvedSwitchStyles.switch,\n switchStaticStyles.track,\n variantLayerStyles.switch,\n scaleDimensions(resolvedSwitchStyles.switch as ViewStyle),\n // On web, the animated variant color hook currently resolves to Unistyles'\n // black fallback, so the concrete variant layer provides the track color.\n Platform.OS !== 'web' && animatedTrackStyle,\n ],\n [resolvedSwitchStyles.switch, variantLayerStyles.switch, scaleDimensions, animatedTrackStyle],\n );\n\n const handleStyle: StyleProp<ViewStyle> = useMemo(\n () => [\n resolvedSwitchStyles.handle,\n switchStaticStyles.handle,\n variantLayerStyles.handle,\n scaleDimensions(resolvedSwitchStyles.handle as ViewStyle),\n animatedHandleStyle,\n ],\n [resolvedSwitchStyles.handle, variantLayerStyles.handle, scaleDimensions, animatedHandleStyle],\n );\n\n const accessibilityLabel = typeof label === 'string' ? label : undefined;\n const resolvedAccessibilityHint = accessibilityHint ?? 'Double tap to toggle';\n\n const labelContent = label && (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={[resolvedSwitchStyles.text, variantLayerStyles.text]}\n />\n );\n\n const a11yValue = useMemo(() => ({ text: isOn ? 'On' : 'Off' }), [isOn]);\n\n return (\n <Pressable\n ref={ref}\n onPress={handlePress}\n disabled={disabled}\n accessible\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: isOn, disabled }}\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={resolvedAccessibilityHint}\n accessibilityValue={a11yValue}\n {...viewProps}\n style={rootStyle}\n >\n {labelPosition === 'start' && labelContent}\n\n <Animated.View style={trackStyle} importantForAccessibility=\"no-hide-descendants\">\n <Animated.View style={handleStyle}>\n {onIcon && isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot\n icon={onIcon}\n variant=\"fill\"\n dangerouslySetSize={scaledHandleIconSize}\n allowFontScaling={false}\n style={[resolvedSwitchStyles.handleIcon, variantLayerStyles.handleIcon]}\n />\n </Animated.View>\n )}\n {offIcon && !isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot\n icon={offIcon}\n variant=\"fill\"\n dangerouslySetSize={scaledHandleIconSize}\n allowFontScaling={false}\n style={[resolvedSwitchStyles.handleIcon, variantLayerStyles.handleIcon]}\n />\n </Animated.View>\n )}\n </Animated.View>\n </Animated.View>\n\n {labelPosition === 'end' && labelContent}\n </Pressable>\n );\n});\n\nSwitch.displayName = 'Switch';\n\nconst switchStaticStyles = StyleSheet.create((theme) => ({\n handle: {\n borderRadius: theme.borderRadius.full,\n alignItems: 'center',\n justifyContent: 'center',\n },\n iconContainer: {\n position: 'absolute',\n alignItems: 'center',\n justifyContent: 'center',\n },\n track: {\n justifyContent: 'center',\n borderRadius: theme.borderRadius.full,\n },\n root: ({ disabled }: { disabled: boolean }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n alignSelf: 'flex-start',\n opacity: disabled ? 0.5 : 1,\n }),\n}));\n\nexport { Switch, type SwitchProps };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Switch.js","names":["StyleSheet"],"sources":["../../src/components/Switch.tsx"],"sourcesContent":["import type { UniversalSwitchProps } from '@yahoo/uds-types';\nimport type { Ref } from 'react';\nimport { memo, useCallback, useEffect, useMemo, useState } from 'react';\nimport type {\n AccessibilityProps,\n StyleProp,\n TextStyle,\n View,\n ViewProps,\n ViewStyle,\n} from 'react-native';\nimport { AccessibilityInfo, I18nManager, Platform, Pressable } from 'react-native';\nimport Animated, { useAnimatedStyle, useDerivedValue, withTiming } from 'react-native-reanimated';\n// eslint-disable-next-line uds/no-use-unistyles -- switch variant layers need concrete web styles\nimport { StyleSheet, useUnistyles } from 'react-native-unistyles';\nimport { useAnimatedVariantColor } from 'react-native-unistyles/reanimated';\n\nimport { switchStyles } from '../../generated/styles';\nimport { useComponentFontScale } from '../fontScaling/useFontScale';\nimport { useMaxFontSizeMultiplier } from '../fontScaling/useMaxFontSizeMultiplier';\nimport { getSafeIconCell } from './Button/buttonTheme';\nimport { FormLabel } from './FormLabel';\nimport type { IconSlotType } from './IconSlot';\nimport { IconSlot } from './IconSlot';\n\ninterface SwitchProps extends Omit<ViewProps, 'style'>, UniversalSwitchProps<IconSlotType> {\n /** Ref to the underlying View */\n ref?: Ref<View>;\n /** Callback when the switch value changes */\n onChange?: (value: boolean) => void;\n /** Whether the switch is disabled */\n disabled?: boolean;\n /** Whether the switch is required (shows asterisk with label) */\n required?: boolean;\n /**\n * Caps how far the track, handle, and label grow with the OS text-size\n * setting; all scale by the same factor. Set null to remove the cap;\n * override app-wide via UDSFontScalingProvider.\n * @default 2\n */\n maxFontSizeMultiplier?: number | null;\n /** Accessibility hint describing what happens when activated */\n accessibilityHint?: AccessibilityProps['accessibilityHint'];\n}\n\nconst ANIMATION_DURATION = 120;\n\n/**\n * **Switch component for toggling options**\n *\n * @description\n * A switch (also called a toggle) is a binary on/off input control.\n * It allows users to pick between two clearly opposite choices.\n *\n * @category Form\n * @platform mobile\n *\n * @example\n * ```tsx\n * import { Switch } from '@yahoo/uds-mobile/Switch';\n *\n * <Switch label=\"Notifications\" />\n * <Switch isOn={enabled} onChange={setEnabled} label=\"Dark mode\" />\n * <Switch onIcon=\"Check\" offIcon=\"Cross\" label=\"Sync\" />\n * ```\n *\n * @usage\n * - Settings: For toggling preferences on/off\n * - Feature flags: For enabling/disabling features\n * - Immediate effect toggles (no submit button needed)\n *\n * @accessibility\n * - Sets `accessibilityRole=\"switch\"` automatically\n * - Announces on/off state to screen readers\n * - Respects system reduce motion preference\n * - Supports `reduceMotion` prop to disable animations\n *\n * @see {@link Checkbox} for forms with submit actions\n * @see {@link Radio} for single-select options\n */\nconst Switch = memo(function Switch({\n isOn: isOnProp,\n defaultIsOn = false,\n onChange,\n label,\n labelPosition = 'start',\n size = 'md',\n onIcon,\n offIcon,\n disabled = false,\n required,\n maxFontSizeMultiplier,\n accessibilityHint,\n reduceMotion = false,\n ref,\n ...viewProps\n}: SwitchProps) {\n const isControlled = isOnProp !== undefined;\n const [internalIsOn, setInternalIsOn] = useState(defaultIsOn);\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);\n const isOn = isControlled ? isOnProp : internalIsOn;\n const activeVariant = isOn ? 'on' : 'off';\n const { theme } = useUnistyles();\n\n // One resolved cap governs track, handle, travel, and label. Android may\n // resolve different nonlinear factors for the label and handle glyph.\n const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier('control', maxFontSizeMultiplier);\n // Check system reduced motion preference\n useEffect(() => {\n const checkReducedMotion = async () => {\n const isReduceMotionEnabled = await AccessibilityInfo.isReduceMotionEnabled();\n setPrefersReducedMotion(isReduceMotionEnabled);\n };\n checkReducedMotion();\n\n const subscription = AccessibilityInfo.addEventListener(\n 'reduceMotionChanged',\n setPrefersReducedMotion,\n );\n return () => subscription.remove();\n }, []);\n\n const shouldReduceMotion = reduceMotion || prefersReducedMotion;\n const animationDuration = shouldReduceMotion ? 0 : ANIMATION_DURATION;\n\n const progress = useDerivedValue(\n () => withTiming(isOn ? 1 : 0, { duration: animationDuration }),\n [isOn, animationDuration],\n );\n\n const handlePress = useCallback(() => {\n if (disabled) {\n return;\n }\n\n const newValue = !isOn;\n\n if (!isControlled) {\n setInternalIsOn(newValue);\n }\n\n onChange?.(newValue);\n }, [disabled, isOn, isControlled, onChange]);\n\n // On web, useVariants returns the resolved style object instead of mutating\n // switchStyles in place.\n const variantSwitchStyles = switchStyles.useVariants({\n size,\n variant: activeVariant,\n }) as unknown as typeof switchStyles | undefined;\n const resolvedSwitchStyles = variantSwitchStyles ?? switchStyles;\n const labelBaseSize = resolvedSwitchStyles.text.lineHeight ?? resolvedSwitchStyles.text.fontSize;\n const fontScaleFactor = useComponentFontScale(\n resolvedMaxFontSizeMultiplier,\n typeof labelBaseSize === 'number' ? labelBaseSize : undefined,\n );\n // Size the handle glyph from the configured size layer and the same factor\n // Android would apply to a native glyph of this size.\n const handleIconSize = resolvedSwitchStyles.handleIcon.fontSize;\n const handleIconScaleFactor = useComponentFontScale(\n resolvedMaxFontSizeMultiplier,\n typeof handleIconSize === 'number' ? handleIconSize : undefined,\n );\n const scaledHandleIconSize =\n typeof handleIconSize === 'number'\n ? Math.round(handleIconSize * handleIconScaleFactor)\n : undefined;\n\n // Derive travel from the same rounded metrics used to render the control.\n // Scaling the token travel independently can differ by a pixel at fractional\n // font scales, leaving unequal insets at opposite ends of the track.\n const scaledTrackWidth = Math.round(resolvedSwitchStyles.switch.width * fontScaleFactor);\n const scaledTrackPadding = Math.round(resolvedSwitchStyles.switch.padding * fontScaleFactor);\n const scaledHandleWidth = Math.round(resolvedSwitchStyles.handle.width * fontScaleFactor);\n const scaledHandleTravel = Math.max(\n 0,\n scaledTrackWidth - scaledHandleWidth - scaledTrackPadding * 2,\n );\n // RTL mirrors the track layout but not transforms, so travel flips sign.\n const travelDistance = scaledHandleTravel * (I18nManager.isRTL ? -1 : 1);\n\n const variantLayerStyles = useMemo(() => {\n const components = theme.components as unknown as Record<string, Record<string, unknown>>;\n const getLayerStyle = <TStyle,>(layer: string) =>\n components[`switch/variant/default/active/${activeVariant}/${layer}/rest`] as\n TStyle | undefined;\n\n return {\n handle: getLayerStyle<ViewStyle>('handle'),\n handleIcon: getLayerStyle<TextStyle>('handleIcon'),\n switch: getLayerStyle<ViewStyle>('switch'),\n text: getLayerStyle<TextStyle>('rootText'),\n };\n }, [activeVariant, theme]);\n\n // Get animated track color from design tokens (changes when variant changes)\n const trackBackgroundColor = useAnimatedVariantColor(\n resolvedSwitchStyles.switch,\n 'backgroundColor',\n );\n\n const animatedTrackStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n backgroundColor: withTiming(trackBackgroundColor.value, { duration: animationDuration }),\n };\n });\n\n const animatedHandleStyle = useAnimatedStyle(() => {\n 'worklet';\n return {\n transform: [{ translateX: progress.value * travelDistance }],\n };\n });\n\n const rootStyle: StyleProp<ViewStyle> = useMemo(\n () => [resolvedSwitchStyles.root, switchStaticStyles.root({ disabled })],\n [resolvedSwitchStyles.root, disabled],\n );\n\n // Track and handle grow by the capped factor so the handle (and its icon)\n // stays contained. Scale the track's inset too so the derived travel lands\n // the handle at the same distance from either end.\n const scaleDimensions = useCallback(\n (style: ViewStyle | undefined): ViewStyle | undefined => {\n if (!style || fontScaleFactor === 1) {\n return undefined;\n }\n const { width, height, padding } = style;\n return typeof width === 'number' && typeof height === 'number'\n ? {\n width: Math.round(width * fontScaleFactor),\n height: Math.round(height * fontScaleFactor),\n ...(typeof padding === 'number' && {\n padding: Math.round(padding * fontScaleFactor),\n }),\n }\n : undefined;\n },\n [fontScaleFactor],\n );\n\n const trackStyle: StyleProp<ViewStyle> = useMemo(\n () => [\n resolvedSwitchStyles.switch,\n switchStaticStyles.track,\n variantLayerStyles.switch,\n scaleDimensions(resolvedSwitchStyles.switch as ViewStyle),\n // On web, the animated variant color hook currently resolves to Unistyles'\n // black fallback, so the concrete variant layer provides the track color.\n Platform.OS !== 'web' && animatedTrackStyle,\n ],\n [resolvedSwitchStyles.switch, variantLayerStyles.switch, scaleDimensions, animatedTrackStyle],\n );\n\n const handleStyle: StyleProp<ViewStyle> = useMemo(\n () => [\n resolvedSwitchStyles.handle,\n switchStaticStyles.handle,\n variantLayerStyles.handle,\n scaleDimensions(resolvedSwitchStyles.handle as ViewStyle),\n animatedHandleStyle,\n ],\n [resolvedSwitchStyles.handle, variantLayerStyles.handle, scaleDimensions, animatedHandleStyle],\n );\n\n const accessibilityLabel = typeof label === 'string' ? label : undefined;\n const resolvedAccessibilityHint = accessibilityHint ?? 'Double tap to toggle';\n\n const labelContent = label && (\n <FormLabel\n color=\"inherit\"\n variant=\"inherit\"\n label={label}\n required={required}\n showRequiredAsterisk={required}\n maxFontSizeMultiplier={resolvedMaxFontSizeMultiplier}\n style={[resolvedSwitchStyles.text, variantLayerStyles.text]}\n />\n );\n\n const a11yValue = useMemo(() => ({ text: isOn ? 'On' : 'Off' }), [isOn]);\n\n return (\n <Pressable\n ref={ref}\n onPress={handlePress}\n disabled={disabled}\n accessible\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: isOn, disabled }}\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={resolvedAccessibilityHint}\n accessibilityValue={a11yValue}\n {...viewProps}\n style={rootStyle}\n >\n {labelPosition === 'start' && labelContent}\n\n <Animated.View style={trackStyle} importantForAccessibility=\"no-hide-descendants\">\n <Animated.View style={handleStyle}>\n {onIcon && isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot\n icon={onIcon}\n variant=\"fill\"\n dangerouslySetSize={scaledHandleIconSize}\n allowFontScaling={false}\n style={[\n resolvedSwitchStyles.handleIcon,\n variantLayerStyles.handleIcon,\n scaledHandleIconSize === undefined\n ? undefined\n : {\n fontSize: scaledHandleIconSize,\n lineHeight: getSafeIconCell(scaledHandleIconSize),\n },\n ]}\n />\n </Animated.View>\n )}\n {offIcon && !isOn && (\n <Animated.View style={switchStaticStyles.iconContainer}>\n <IconSlot\n icon={offIcon}\n variant=\"fill\"\n dangerouslySetSize={scaledHandleIconSize}\n allowFontScaling={false}\n style={[\n resolvedSwitchStyles.handleIcon,\n variantLayerStyles.handleIcon,\n scaledHandleIconSize === undefined\n ? undefined\n : {\n fontSize: scaledHandleIconSize,\n lineHeight: getSafeIconCell(scaledHandleIconSize),\n },\n ]}\n />\n </Animated.View>\n )}\n </Animated.View>\n </Animated.View>\n\n {labelPosition === 'end' && labelContent}\n </Pressable>\n );\n});\n\nSwitch.displayName = 'Switch';\n\nconst switchStaticStyles = StyleSheet.create((theme) => ({\n handle: {\n borderRadius: theme.borderRadius.full,\n alignItems: 'center',\n justifyContent: 'center',\n },\n iconContainer: {\n position: 'absolute',\n alignItems: 'center',\n justifyContent: 'center',\n },\n track: {\n justifyContent: 'center',\n borderRadius: theme.borderRadius.full,\n },\n root: ({ disabled }: { disabled: boolean }) => ({\n flexDirection: 'row',\n alignItems: 'center',\n alignSelf: 'flex-start',\n opacity: disabled ? 0.5 : 1,\n }),\n}));\n\nexport { Switch, type SwitchProps };\n"],"mappings":";;;;;;;;;;;;;;AA6CA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmC3B,MAAM,SAAS,KAAK,SAAS,OAAO,EAClC,MAAM,UACN,cAAc,OACd,UACA,OACA,gBAAgB,SAChB,OAAO,MACP,QACA,SACA,WAAW,OACX,UACA,uBACA,mBACA,eAAe,OACf,KACA,GAAG,aACW;CACd,MAAM,eAAe,aAAa,KAAA;CAClC,MAAM,CAAC,cAAc,mBAAmB,SAAS,YAAY;CAC7D,MAAM,CAAC,sBAAsB,2BAA2B,SAAS,MAAM;CACvE,MAAM,OAAO,eAAe,WAAW;CACvC,MAAM,gBAAgB,OAAO,OAAO;CACpC,MAAM,EAAE,UAAU,cAAc;CAIhC,MAAM,gCAAgC,yBAAyB,WAAW,sBAAsB;CAEhG,gBAAgB;EACd,MAAM,qBAAqB,YAAY;GAErC,wBAAwB,MADY,kBAAkB,uBAAuB,CAC/B;;EAEhD,oBAAoB;EAEpB,MAAM,eAAe,kBAAkB,iBACrC,uBACA,wBACD;EACD,aAAa,aAAa,QAAQ;IACjC,EAAE,CAAC;CAGN,MAAM,oBADqB,gBAAgB,uBACI,IAAI;CAEnD,MAAM,WAAW,sBACT,WAAW,OAAO,IAAI,GAAG,EAAE,UAAU,mBAAmB,CAAC,EAC/D,CAAC,MAAM,kBAAkB,CAC1B;CAED,MAAM,cAAc,kBAAkB;EACpC,IAAI,UACF;EAGF,MAAM,WAAW,CAAC;EAElB,IAAI,CAAC,cACH,gBAAgB,SAAS;EAG3B,WAAW,SAAS;IACnB;EAAC;EAAU;EAAM;EAAc;EAAS,CAAC;CAQ5C,MAAM,uBAJsB,aAAa,YAAY;EACnD;EACA,SAAS;EACV,CAC+C,IAAI;CACpD,MAAM,gBAAgB,qBAAqB,KAAK,cAAc,qBAAqB,KAAK;CACxF,MAAM,kBAAkB,sBACtB,+BACA,OAAO,kBAAkB,WAAW,gBAAgB,KAAA,EACrD;CAGD,MAAM,iBAAiB,qBAAqB,WAAW;CACvD,MAAM,wBAAwB,sBAC5B,+BACA,OAAO,mBAAmB,WAAW,iBAAiB,KAAA,EACvD;CACD,MAAM,uBACJ,OAAO,mBAAmB,WACtB,KAAK,MAAM,iBAAiB,sBAAsB,GAClD,KAAA;CAKN,MAAM,mBAAmB,KAAK,MAAM,qBAAqB,OAAO,QAAQ,gBAAgB;CACxF,MAAM,qBAAqB,KAAK,MAAM,qBAAqB,OAAO,UAAU,gBAAgB;CAC5F,MAAM,oBAAoB,KAAK,MAAM,qBAAqB,OAAO,QAAQ,gBAAgB;CAMzF,MAAM,iBALqB,KAAK,IAC9B,GACA,mBAAmB,oBAAoB,qBAAqB,EAGrB,IAAI,YAAY,QAAQ,KAAK;CAEtE,MAAM,qBAAqB,cAAc;EACvC,MAAM,aAAa,MAAM;EACzB,MAAM,iBAA0B,UAC9B,WAAW,iCAAiC,cAAc,GAAG,MAAM;EAGrE,OAAO;GACL,QAAQ,cAAyB,SAAS;GAC1C,YAAY,cAAyB,aAAa;GAClD,QAAQ,cAAyB,SAAS;GAC1C,MAAM,cAAyB,WAAW;GAC3C;IACA,CAAC,eAAe,MAAM,CAAC;CAG1B,MAAM,uBAAuB,wBAC3B,qBAAqB,QACrB,kBACD;CAED,MAAM,qBAAqB,uBAAuB;AAChD;EACA,OAAO,EACL,iBAAiB,WAAW,qBAAqB,OAAO,EAAE,UAAU,mBAAmB,CAAC,EACzF;GACD;CAEF,MAAM,sBAAsB,uBAAuB;AACjD;EACA,OAAO,EACL,WAAW,CAAC,EAAE,YAAY,SAAS,QAAQ,gBAAgB,CAAC,EAC7D;GACD;CAEF,MAAM,YAAkC,cAChC,CAAC,qBAAqB,MAAM,mBAAmB,KAAK,EAAE,UAAU,CAAC,CAAC,EACxE,CAAC,qBAAqB,MAAM,SAAS,CACtC;CAKD,MAAM,kBAAkB,aACrB,UAAwD;EACvD,IAAI,CAAC,SAAS,oBAAoB,GAChC;EAEF,MAAM,EAAE,OAAO,QAAQ,YAAY;EACnC,OAAO,OAAO,UAAU,YAAY,OAAO,WAAW,WAClD;GACE,OAAO,KAAK,MAAM,QAAQ,gBAAgB;GAC1C,QAAQ,KAAK,MAAM,SAAS,gBAAgB;GAC5C,GAAI,OAAO,YAAY,YAAY,EACjC,SAAS,KAAK,MAAM,UAAU,gBAAgB,EAC/C;GACF,GACD,KAAA;IAEN,CAAC,gBAAgB,CAClB;CAED,MAAM,aAAmC,cACjC;EACJ,qBAAqB;EACrB,mBAAmB;EACnB,mBAAmB;EACnB,gBAAgB,qBAAqB,OAAoB;EAGzD,SAAS,OAAO,SAAS;EAC1B,EACD;EAAC,qBAAqB;EAAQ,mBAAmB;EAAQ;EAAiB;EAAmB,CAC9F;CAED,MAAM,cAAoC,cAClC;EACJ,qBAAqB;EACrB,mBAAmB;EACnB,mBAAmB;EACnB,gBAAgB,qBAAqB,OAAoB;EACzD;EACD,EACD;EAAC,qBAAqB;EAAQ,mBAAmB;EAAQ;EAAiB;EAAoB,CAC/F;CAED,MAAM,qBAAqB,OAAO,UAAU,WAAW,QAAQ,KAAA;CAC/D,MAAM,4BAA4B,qBAAqB;CAEvD,MAAM,eAAe,SACnB,oBAAC,WAAD;EACE,OAAM;EACN,SAAQ;EACD;EACG;EACV,sBAAsB;EACtB,uBAAuB;EACvB,OAAO,CAAC,qBAAqB,MAAM,mBAAmB,KAAK;EAC3D,CAAA;CAGJ,MAAM,YAAY,eAAe,EAAE,MAAM,OAAO,OAAO,OAAO,GAAG,CAAC,KAAK,CAAC;CAExE,OACE,qBAAC,WAAD;EACO;EACL,SAAS;EACC;EACV,YAAA;EACA,mBAAkB;EAClB,oBAAoB;GAAE,SAAS;GAAM;GAAU;EAC3B;EACpB,mBAAmB;EACnB,oBAAoB;EACpB,GAAI;EACJ,OAAO;YAXT;GAaG,kBAAkB,WAAW;GAE9B,oBAAC,SAAS,MAAV;IAAe,OAAO;IAAY,2BAA0B;cAC1D,qBAAC,SAAS,MAAV;KAAe,OAAO;eAAtB,CACG,UAAU,QACT,oBAAC,SAAS,MAAV;MAAe,OAAO,mBAAmB;gBACvC,oBAAC,UAAD;OACE,MAAM;OACN,SAAQ;OACR,oBAAoB;OACpB,kBAAkB;OAClB,OAAO;QACL,qBAAqB;QACrB,mBAAmB;QACnB,yBAAyB,KAAA,IACrB,KAAA,IACA;SACE,UAAU;SACV,YAAY,gBAAgB,qBAAqB;SAClD;QACN;OACD,CAAA;MACY,CAAA,EAEjB,WAAW,CAAC,QACX,oBAAC,SAAS,MAAV;MAAe,OAAO,mBAAmB;gBACvC,oBAAC,UAAD;OACE,MAAM;OACN,SAAQ;OACR,oBAAoB;OACpB,kBAAkB;OAClB,OAAO;QACL,qBAAqB;QACrB,mBAAmB;QACnB,yBAAyB,KAAA,IACrB,KAAA,IACA;SACE,UAAU;SACV,YAAY,gBAAgB,qBAAqB;SAClD;QACN;OACD,CAAA;MACY,CAAA,CAEJ;;IACF,CAAA;GAEf,kBAAkB,SAAS;GAClB;;EAEd;AAEF,OAAO,cAAc;AAErB,MAAM,qBAAqBA,aAAW,QAAQ,WAAW;CACvD,QAAQ;EACN,cAAc,MAAM,aAAa;EACjC,YAAY;EACZ,gBAAgB;EACjB;CACD,eAAe;EACb,UAAU;EACV,YAAY;EACZ,gBAAgB;EACjB;CACD,OAAO;EACL,gBAAgB;EAChB,cAAc,MAAM,aAAa;EAClC;CACD,OAAO,EAAE,gBAAuC;EAC9C,eAAe;EACf,YAAY;EACZ,WAAW;EACX,SAAS,WAAW,KAAM;EAC3B;CACF,EAAE"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
require("../../_virtual/_rolldown/runtime.cjs");
|
|
4
|
+
const require_fontScaling_FontScalingContext = require("../../fontScaling/FontScalingContext.cjs");
|
|
5
|
+
const require_fontScaling_useFontScale = require("../../fontScaling/useFontScale.cjs");
|
|
4
6
|
const require_fontScaling_useMaxFontSizeMultiplier = require("../../fontScaling/useMaxFontSizeMultiplier.cjs");
|
|
5
7
|
const require_components_IconSlot = require("../IconSlot.cjs");
|
|
6
|
-
const require_fontScaling_useFontScale = require("../../fontScaling/useFontScale.cjs");
|
|
7
8
|
const require_components_Pressable = require("../Pressable.cjs");
|
|
8
9
|
const require_components_Tabs_tabsContexts = require("./tabsContexts.cjs");
|
|
9
10
|
const require_components_Tabs_tabTheme = require("./tabTheme.cjs");
|
|
@@ -27,7 +28,10 @@ function TabLabel({ style, maxFontSizeMultiplier, children }) {
|
|
|
27
28
|
maxFontSizeMultiplier,
|
|
28
29
|
children
|
|
29
30
|
});
|
|
30
|
-
return
|
|
31
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_fontScaling_FontScalingContext.ResolvedControlFontScalingProvider, {
|
|
32
|
+
maxFontSizeMultiplier,
|
|
33
|
+
children
|
|
34
|
+
});
|
|
31
35
|
}
|
|
32
36
|
/**
|
|
33
37
|
* **⚙️ Tab**
|
|
@@ -45,8 +49,7 @@ const Tab = (0, react.memo)(function Tab({ value, children, startIcon, endIcon,
|
|
|
45
49
|
const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } = require_components_Tabs_tabsContexts.useTabSelectionContext();
|
|
46
50
|
const { theme } = (0, react_native_unistyles.useUnistyles)();
|
|
47
51
|
const [pressed, setPressed] = (0, react.useState)(false);
|
|
48
|
-
const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier)
|
|
49
|
-
const fontScaleFactor = require_fontScaling_useFontScale.useFontScale(resolvedMaxFontSizeMultiplier);
|
|
52
|
+
const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
|
|
50
53
|
const selected = !disabled && selectedId === uid;
|
|
51
54
|
const active = selected ? "on" : "off";
|
|
52
55
|
const interaction = pressed ? "pressed" : "rest";
|
|
@@ -72,6 +75,7 @@ const Tab = (0, react.memo)(function Tab({ value, children, startIcon, endIcon,
|
|
|
72
75
|
active,
|
|
73
76
|
interaction
|
|
74
77
|
]);
|
|
78
|
+
const fontScaleFactor = require_fontScaling_useFontScale.useComponentFontScale(resolvedMaxFontSizeMultiplier, (typeof textStyle.lineHeight === "number" ? textStyle.lineHeight : void 0) ?? (typeof textStyle.fontSize === "number" ? textStyle.fontSize : void 0));
|
|
75
79
|
const iconStyle = (0, react.useMemo)(() => require_components_Tabs_tabTheme.getMergedTabLayerStyle(theme, visualVariant, active, "icon", interaction), [
|
|
76
80
|
theme,
|
|
77
81
|
visualVariant,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tab.d.cts","names":[],"sources":["../../../src/components/Tabs/Tab.tsx"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Tab.d.cts","names":[],"sources":["../../../src/components/Tabs/Tab.tsx"],"mappings":";;;;;;;UAoBU,QAAA,SAEN,IAAA,CAAK,cAAA,kDACL,IAAA,CAAK,iBAAA;EACP,QAAA,EAAU,iBAAA;EACV,SAAA,GAAY,YAAA;EACZ,OAAA,GAAU,YAAA;EACV,KAAA,GAAQ,SAAA;AAAA;;;;;;;;;;cA4CJ,GAAA,EAAG,OAAA,CAAA,oBAAA,CAAA,QAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tab.d.ts","names":[],"sources":["../../../src/components/Tabs/Tab.tsx"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Tab.d.ts","names":[],"sources":["../../../src/components/Tabs/Tab.tsx"],"mappings":";;;;;;;UAoBU,QAAA,SAEN,IAAA,CAAK,cAAA,kDACL,IAAA,CAAK,iBAAA;EACP,QAAA,EAAU,iBAAA;EACV,SAAA,GAAY,YAAA;EACZ,OAAA,GAAU,YAAA;EACV,KAAA,GAAQ,SAAA;AAAA;;;;;;;;;;cA4CJ,GAAA,EAAG,OAAA,CAAA,oBAAA,CAAA,QAAA"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
+
import { ResolvedControlFontScalingProvider } from "../../fontScaling/FontScalingContext.js";
|
|
3
|
+
import { useComponentFontScale } from "../../fontScaling/useFontScale.js";
|
|
2
4
|
import { useMaxFontSizeMultiplier } from "../../fontScaling/useMaxFontSizeMultiplier.js";
|
|
3
5
|
import { IconSlot } from "../IconSlot.js";
|
|
4
|
-
import { useFontScale } from "../../fontScaling/useFontScale.js";
|
|
5
6
|
import { Pressable as Pressable$1 } from "../Pressable.js";
|
|
6
7
|
import { useTabSelectionContext, useTabsVisualContext } from "./tabsContexts.js";
|
|
7
8
|
import { getMergedTabLayerStyle, getTabLayerStyle } from "./tabTheme.js";
|
|
@@ -25,7 +26,10 @@ function TabLabel({ style, maxFontSizeMultiplier, children }) {
|
|
|
25
26
|
maxFontSizeMultiplier,
|
|
26
27
|
children
|
|
27
28
|
});
|
|
28
|
-
return
|
|
29
|
+
return /* @__PURE__ */ jsx(ResolvedControlFontScalingProvider, {
|
|
30
|
+
maxFontSizeMultiplier,
|
|
31
|
+
children
|
|
32
|
+
});
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
35
|
* **⚙️ Tab**
|
|
@@ -43,8 +47,7 @@ const Tab = memo(function Tab({ value, children, startIcon, endIcon, disabled, s
|
|
|
43
47
|
const { selectedId, setSelectedId, registerTab, unregisterTab, setTabLayout } = useTabSelectionContext();
|
|
44
48
|
const { theme } = useUnistyles();
|
|
45
49
|
const [pressed, setPressed] = useState(false);
|
|
46
|
-
const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier)
|
|
47
|
-
const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);
|
|
50
|
+
const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier("control", maxFontSizeMultiplier);
|
|
48
51
|
const selected = !disabled && selectedId === uid;
|
|
49
52
|
const active = selected ? "on" : "off";
|
|
50
53
|
const interaction = pressed ? "pressed" : "rest";
|
|
@@ -70,6 +73,7 @@ const Tab = memo(function Tab({ value, children, startIcon, endIcon, disabled, s
|
|
|
70
73
|
active,
|
|
71
74
|
interaction
|
|
72
75
|
]);
|
|
76
|
+
const fontScaleFactor = useComponentFontScale(resolvedMaxFontSizeMultiplier, (typeof textStyle.lineHeight === "number" ? textStyle.lineHeight : void 0) ?? (typeof textStyle.fontSize === "number" ? textStyle.fontSize : void 0));
|
|
73
77
|
const iconStyle = useMemo(() => getMergedTabLayerStyle(theme, visualVariant, active, "icon", interaction), [
|
|
74
78
|
theme,
|
|
75
79
|
visualVariant,
|
|
@@ -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 { 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 children as ReactElement;\n}\n\n/**\n * **⚙️ Tab**\n *\n * @description\n * A single selectable tab. Must be used inside {@link TabList} within {@link Tabs}.\n *\n * @category Navigation\n * @platform mobile\n */\nconst Tab = memo(function Tab({\n value,\n children,\n startIcon,\n endIcon,\n disabled,\n style,\n ...pressableRest\n}: TabProps) {\n const generatedId = useId();\n const uid = value ?? `uds-tab-${generatedId}`;\n const { variant: visualVariant, reduceMotion, 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 =\n useMaxFontSizeMultiplier('control', maxFontSizeMultiplier) ?? 0;\n const fontScaleFactor = useFontScale(resolvedMaxFontSizeMultiplier);\n\n const selected = !disabled && selectedId === uid;\n const active: 'on' | 'off' = selected ? 'on' : 'off';\n const interaction: 'rest' | 'pressed' = pressed ? 'pressed' : 'rest';\n\n useEffect(() => {\n registerTab(uid);\n return () => {\n unregisterTab(uid);\n };\n }, [uid, registerTab, unregisterTab]);\n\n const rootBase = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'root', interaction) as ViewStyle,\n [theme, visualVariant, active, interaction],\n );\n const textStyle = useMemo(\n () =>\n getMergedTabLayerStyle(theme, visualVariant, active, 'rootText', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n const iconStyle = useMemo(\n () => getMergedTabLayerStyle(theme, visualVariant, active, 'icon', interaction) as TextStyle,\n [theme, visualVariant, active, interaction],\n );\n\n const iconColor = ((): StyleProps['color'] | undefined => {\n const c = iconStyle?.color;\n if (c === undefined || c === null) {\n return undefined;\n }\n return c as StyleProps['color'];\n })();\n\n /** Inactive primary tabs use transparent underline tokens on web; RN has no CSS vars for that layer. */\n const showPrimaryPerTabUnderline = visualVariant === 'primary' && !(selected && !reduceMotion);\n\n const primaryUnderlineColor = useMemo(() => {\n if (visualVariant !== 'primary') {\n return undefined;\n }\n if (selected && reduceMotion) {\n const onText = getTabLayerStyle(theme, 'primary', 'on', 'rootText', 'rest') as TextStyle;\n const c = onText.color;\n if (typeof c === 'string') {\n return c;\n }\n }\n return 'transparent';\n }, [visualVariant, selected, reduceMotion, theme]);\n\n const rootStyle = useMemo((): ViewStyle => {\n const base: ViewStyle = {\n ...rootBase,\n flexDirection: 'row',\n alignItems: 'center',\n flexShrink: 0,\n zIndex: 1,\n position: 'relative',\n };\n // 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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"}
|
package/dist/components/Text.cjs
CHANGED
|
@@ -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_FontScalingContext = require("../fontScaling/FontScalingContext.cjs");
|
|
5
|
+
const require_fontScaling_constants = require("../fontScaling/constants.cjs");
|
|
4
6
|
const require_fontScaling_useMaxFontSizeMultiplier = require("../fontScaling/useMaxFontSizeMultiplier.cjs");
|
|
5
7
|
let react = require("react");
|
|
6
8
|
let react_native = require("react-native");
|
|
@@ -55,6 +57,8 @@ const Text = (0, react.memo)(function Text({ color = "primary", variant = "body1
|
|
|
55
57
|
const resolvedFontSize = fontSize ?? resolvedVariant;
|
|
56
58
|
const resolvedLineHeight = lineHeight === "none" ? void 0 : lineHeight ?? (hasCJKContent(children) ? void 0 : resolvedVariant);
|
|
57
59
|
const resolvedLetterSpacing = letterSpacing ?? resolvedVariant;
|
|
60
|
+
const baseVariant = resolvedVariant?.split("/")[0];
|
|
61
|
+
const defaultDynamicTypeRamp = require_fontScaling_FontScalingContext.useDynamicTypeRampEnabled() && baseVariant ? require_fontScaling_constants.DEFAULT_DYNAMIC_TYPE_RAMPS[baseVariant] : void 0;
|
|
58
62
|
const resolvedMaxFontSizeMultiplier = require_fontScaling_useMaxFontSizeMultiplier.useMaxFontSizeMultiplier(resolvedVariant, maxFontSizeMultiplier);
|
|
59
63
|
generated_styles.styles.useVariants({
|
|
60
64
|
color: resolvedColor,
|
|
@@ -127,6 +131,7 @@ const Text = (0, react.memo)(function Text({ color = "primary", variant = "body1
|
|
|
127
131
|
generated_styles.styles.foundation
|
|
128
132
|
]),
|
|
129
133
|
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
134
|
+
dynamicTypeRamp: defaultDynamicTypeRamp,
|
|
130
135
|
...props,
|
|
131
136
|
children
|
|
132
137
|
});
|
|
@@ -16,11 +16,12 @@ interface TextProps extends TextProps$1 {
|
|
|
16
16
|
/** Typography variant - sets fontSize, lineHeight, letterSpacing, and fontFamily together */
|
|
17
17
|
variant?: TextVariantProp;
|
|
18
18
|
/**
|
|
19
|
-
* Caps how far this text grows with the OS text-size setting.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* Native's 0, which also overrides
|
|
23
|
-
* inherits its parent's cap.
|
|
19
|
+
* Caps how far this text grows with the OS text-size setting. Every text
|
|
20
|
+
* variant is capped at 2x or below by default, with the largest display and
|
|
21
|
+
* title variants tapering further (see DEFAULT_MAX_FONT_SIZE_MULTIPLIERS).
|
|
22
|
+
* Set null to remove the cap (maps to React Native's 0, which also overrides
|
|
23
|
+
* an inherited cap); inherit-variant text inherits its parent's cap.
|
|
24
|
+
* Override app-wide via UDSFontScalingProvider.
|
|
24
25
|
*/
|
|
25
26
|
maxFontSizeMultiplier?: number | null;
|
|
26
27
|
/** Override the fontFamily independently */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Text.d.cts","names":[],"sources":["../../src/components/Text.tsx"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Text.d.cts","names":[],"sources":["../../src/components/Text.tsx"],"mappings":";;;;;;;KAYK,WAAA,GAAc,OAAA,CACjB,WAAA,CAAY,UAAA;AAAA,KAGT,eAAA,GAAkB,WAAA;AAAA,KAIlB,kBAAA;AAAA,UAuBK,SAAA,SAAkB,WAAA;;EAE1B,GAAA,GAAM,GAAA,CAAI,MAAA;EAhCV;EAkCA,KAAA,GAAQ,UAAA;EAnCgB;EAqCxB,OAAA,GAAU,eAAA;EArCO;;;;;AACK;;;EA6CtB,qBAAA;EA1CgC;EA4ChC,UAAA,GAAa,UAAA;EAxCQ;EA0CrB,QAAA,GAAW,UAAA;EA1CU;EA4CrB,UAAA,GAAa,UAAA;EArBL;EAuBR,UAAA,GAAa,UAAA;;EAEb,aAAA,GAAgB,UAAA;EAvBV;EAyBN,SAAA,GAAY,UAAA;EArBF;EAuBV,aAAA,GAAgB,UAAA;EAVL;EAYX,kBAAA,GAAqB,kBAAA;EAErB,eAAA,GAAkB,UAAA;EAElB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EAEpB,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EAEb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EAEZ,UAAA,GAAa,UAAA;EAEb,aAAA,GAAgB,SAAA;EAEhB,MAAA;EACA,KAAA;EACA,SAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA;EAEA,mBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiCI,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
|
|
@@ -16,11 +16,12 @@ interface TextProps extends TextProps$1 {
|
|
|
16
16
|
/** Typography variant - sets fontSize, lineHeight, letterSpacing, and fontFamily together */
|
|
17
17
|
variant?: TextVariantProp;
|
|
18
18
|
/**
|
|
19
|
-
* Caps how far this text grows with the OS text-size setting.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* Native's 0, which also overrides
|
|
23
|
-
* inherits its parent's cap.
|
|
19
|
+
* Caps how far this text grows with the OS text-size setting. Every text
|
|
20
|
+
* variant is capped at 2x or below by default, with the largest display and
|
|
21
|
+
* title variants tapering further (see DEFAULT_MAX_FONT_SIZE_MULTIPLIERS).
|
|
22
|
+
* Set null to remove the cap (maps to React Native's 0, which also overrides
|
|
23
|
+
* an inherited cap); inherit-variant text inherits its parent's cap.
|
|
24
|
+
* Override app-wide via UDSFontScalingProvider.
|
|
24
25
|
*/
|
|
25
26
|
maxFontSizeMultiplier?: number | null;
|
|
26
27
|
/** Override the fontFamily independently */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Text.d.ts","names":[],"sources":["../../src/components/Text.tsx"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Text.d.ts","names":[],"sources":["../../src/components/Text.tsx"],"mappings":";;;;;;;KAYK,WAAA,GAAc,OAAA,CACjB,WAAA,CAAY,UAAA;AAAA,KAGT,eAAA,GAAkB,WAAA;AAAA,KAIlB,kBAAA;AAAA,UAuBK,SAAA,SAAkB,WAAA;;EAE1B,GAAA,GAAM,GAAA,CAAI,MAAA;EAhCV;EAkCA,KAAA,GAAQ,UAAA;EAnCgB;EAqCxB,OAAA,GAAU,eAAA;EArCO;;;;;AACK;;;EA6CtB,qBAAA;EA1CgC;EA4ChC,UAAA,GAAa,UAAA;EAxCQ;EA0CrB,QAAA,GAAW,UAAA;EA1CU;EA4CrB,UAAA,GAAa,UAAA;EArBL;EAuBR,UAAA,GAAa,UAAA;;EAEb,aAAA,GAAgB,UAAA;EAvBV;EAyBN,SAAA,GAAY,UAAA;EArBF;EAuBV,aAAA,GAAgB,UAAA;EAVL;EAYX,kBAAA,GAAqB,kBAAA;EAErB,eAAA,GAAkB,UAAA;EAElB,YAAA,GAAe,UAAA;EACf,oBAAA,GAAuB,UAAA;EACvB,kBAAA,GAAqB,UAAA;EACrB,uBAAA,GAA0B,UAAA;EAC1B,qBAAA,GAAwB,UAAA;EACxB,WAAA,GAAc,UAAA;EACd,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EACpB,WAAA,GAAc,UAAA;EACd,mBAAA,GAAsB,UAAA;EACtB,qBAAA,GAAwB,UAAA;EACxB,gBAAA,GAAmB,UAAA;EACnB,cAAA,GAAiB,UAAA;EACjB,cAAA,GAAiB,UAAA;EACjB,iBAAA,GAAoB,UAAA;EAEpB,OAAA,GAAU,UAAA;EACV,iBAAA,GAAoB,UAAA;EACpB,eAAA,GAAkB,UAAA;EAClB,aAAA,GAAgB,UAAA;EAChB,UAAA,GAAa,UAAA;EACb,YAAA,GAAe,UAAA;EACf,UAAA,GAAa,UAAA;EAEb,MAAA,GAAS,UAAA;EACT,cAAA,GAAiB,UAAA;EACjB,gBAAA,GAAmB,UAAA;EACnB,YAAA,GAAe,UAAA;EACf,SAAA,GAAY,UAAA;EACZ,WAAA,GAAc,UAAA;EACd,SAAA,GAAY,UAAA;EAEZ,UAAA,GAAa,UAAA;EAEb,aAAA,GAAgB,SAAA;EAEhB,MAAA;EACA,KAAA;EACA,SAAA;EACA,SAAA;EACA,QAAA;EACA,QAAA;EAEA,mBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAiCI,IAAA,EAAI,OAAA,CAAA,oBAAA,CAAA,SAAA"}
|
package/dist/components/Text.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/*! © 2026 Yahoo, Inc. UDS Mobile v0.0.0-development */
|
|
2
|
+
import { useDynamicTypeRampEnabled } from "../fontScaling/FontScalingContext.js";
|
|
3
|
+
import { DEFAULT_DYNAMIC_TYPE_RAMPS } from "../fontScaling/constants.js";
|
|
2
4
|
import { useMaxFontSizeMultiplier } from "../fontScaling/useMaxFontSizeMultiplier.js";
|
|
3
5
|
import { memo, useMemo } from "react";
|
|
4
6
|
import { Text as Text$1 } from "react-native";
|
|
@@ -53,6 +55,8 @@ const Text = memo(function Text({ color = "primary", variant = "body1", fontFami
|
|
|
53
55
|
const resolvedFontSize = fontSize ?? resolvedVariant;
|
|
54
56
|
const resolvedLineHeight = lineHeight === "none" ? void 0 : lineHeight ?? (hasCJKContent(children) ? void 0 : resolvedVariant);
|
|
55
57
|
const resolvedLetterSpacing = letterSpacing ?? resolvedVariant;
|
|
58
|
+
const baseVariant = resolvedVariant?.split("/")[0];
|
|
59
|
+
const defaultDynamicTypeRamp = useDynamicTypeRampEnabled() && baseVariant ? DEFAULT_DYNAMIC_TYPE_RAMPS[baseVariant] : void 0;
|
|
56
60
|
const resolvedMaxFontSizeMultiplier = useMaxFontSizeMultiplier(resolvedVariant, maxFontSizeMultiplier);
|
|
57
61
|
styles.useVariants({
|
|
58
62
|
color: resolvedColor,
|
|
@@ -125,6 +129,7 @@ const Text = memo(function Text({ color = "primary", variant = "body1", fontFami
|
|
|
125
129
|
styles.foundation
|
|
126
130
|
]),
|
|
127
131
|
maxFontSizeMultiplier: resolvedMaxFontSizeMultiplier,
|
|
132
|
+
dynamicTypeRamp: defaultDynamicTypeRamp,
|
|
128
133
|
...props,
|
|
129
134
|
children
|
|
130
135
|
});
|