jfs-components 0.0.62 → 0.0.63
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/CHANGELOG.md +36 -0
- package/lib/commonjs/components/Accordion/Accordion.js +1 -1
- package/lib/commonjs/components/ActionFooter/ActionFooter.js +1 -1
- package/lib/commonjs/components/ActionTile/ActionTile.js +2 -1
- package/lib/commonjs/components/AmountInput/AmountInput.js +2 -1
- package/lib/commonjs/components/AppBar/AppBar.js +1 -1
- package/lib/commonjs/components/Avatar/Avatar.js +184 -162
- package/lib/commonjs/components/AvatarGroup/AvatarGroup.js +1 -1
- package/lib/commonjs/components/Badge/Badge.js +2 -1
- package/lib/commonjs/components/Balance/Balance.js +2 -1
- package/lib/commonjs/components/BottomNav/BottomNav.js +2 -1
- package/lib/commonjs/components/BottomNavItem/BottomNavItem.js +106 -86
- package/lib/commonjs/components/Button/Button.js +190 -93
- package/lib/commonjs/components/ButtonGroup/ButtonGroup.js +1 -1
- package/lib/commonjs/components/Card/Card.js +2 -1
- package/lib/commonjs/components/CardCTA/CardCTA.js +1 -1
- package/lib/commonjs/components/CardProviderInfo/CardProviderInfo.js +1 -1
- package/lib/commonjs/components/Carousel/Carousel.js +3 -2
- package/lib/commonjs/components/Checkbox/Checkbox.js +2 -1
- package/lib/commonjs/components/ChipGroup/ChipGroup.js +1 -1
- package/lib/commonjs/components/ChipSelect/ChipSelect.js +2 -1
- package/lib/commonjs/components/DebitCard/DebitCard.js +1 -1
- package/lib/commonjs/components/Disclaimer/Disclaimer.js +2 -1
- package/lib/commonjs/components/Divider/Divider.js +2 -1
- package/lib/commonjs/components/Drawer/Drawer.js +2 -1
- package/lib/commonjs/components/EmptyState/EmptyState.js +2 -1
- package/lib/commonjs/components/FilterBar/FilterBar.js +1 -1
- package/lib/commonjs/components/Form/Form.js +2 -1
- package/lib/commonjs/components/FormField/FormField.js +3 -2
- package/lib/commonjs/components/HStack/HStack.js +1 -1
- package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +2 -1
- package/lib/commonjs/components/IconButton/IconButton.js +118 -128
- package/lib/commonjs/components/IconCapsule/IconCapsule.js +61 -57
- package/lib/commonjs/components/InputSearch/InputSearch.js +7 -3
- package/lib/commonjs/components/LazyList/LazyList.js +1 -1
- package/lib/commonjs/components/LinearMeter/LinearMeter.js +3 -2
- package/lib/commonjs/components/ListGroup/ListGroup.js +1 -1
- package/lib/commonjs/components/ListItem/ListItem.js +190 -142
- package/lib/commonjs/components/MediaCard/MediaCard.js +3 -3
- package/lib/commonjs/components/MerchantProfile/MerchantProfile.js +2 -1
- package/lib/commonjs/components/MoneyValue/MoneyValue.js +2 -1
- package/lib/commonjs/components/NavArrow/NavArrow.js +82 -59
- package/lib/commonjs/components/NoteInput/NoteInput.js +2 -1
- package/lib/commonjs/components/Nudge/Nudge.js +1 -1
- package/lib/commonjs/components/Numpad/Numpad.js +2 -1
- package/lib/commonjs/components/OTP/OTP.js +1 -1
- package/lib/commonjs/components/PaymentFeedback/PaymentFeedback.js +2 -1
- package/lib/commonjs/components/Popup/Popup.js +2 -1
- package/lib/commonjs/components/ProductLabel/ProductLabel.js +2 -1
- package/lib/commonjs/components/ProgressBadge/ProgressBadge.js +2 -1
- package/lib/commonjs/components/RadioButton/RadioButton.js +2 -1
- package/lib/commonjs/components/RechargeCard/RechargeCard.js +2 -1
- package/lib/commonjs/components/Screen/Screen.js +1 -1
- package/lib/commonjs/components/Section/Section.js +268 -156
- package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +3 -2
- package/lib/commonjs/components/StatItem/StatItem.js +2 -1
- package/lib/commonjs/components/StatusHero/StatusHero.js +2 -1
- package/lib/commonjs/components/Stepper/Step.js +2 -1
- package/lib/commonjs/components/Stepper/StepLabel.js +2 -1
- package/lib/commonjs/components/Stepper/Stepper.js +2 -1
- package/lib/commonjs/components/SupportText/SupportText.js +2 -1
- package/lib/commonjs/components/SupportText/SupportTextIcon.js +2 -1
- package/lib/commonjs/components/SwappableAmount/SwappableAmount.js +2 -1
- package/lib/commonjs/components/Tabs/TabItem.js +2 -1
- package/lib/commonjs/components/Tabs/Tabs.js +2 -1
- package/lib/commonjs/components/Text/Text.js +2 -1
- package/lib/commonjs/components/TextInput/TextInput.js +2 -2
- package/lib/commonjs/components/ThreadHero/ThreadHero.js +2 -1
- package/lib/commonjs/components/Title/Title.js +2 -1
- package/lib/commonjs/components/Toast/Toast.js +2 -1
- package/lib/commonjs/components/Toggle/Toggle.js +2 -1
- package/lib/commonjs/components/Tooltip/Tooltip.js +2 -1
- package/lib/commonjs/components/TransactionBubble/TransactionBubble.js +1 -1
- package/lib/commonjs/components/TransactionDetails/TransactionDetails.js +2 -2
- package/lib/commonjs/components/TransactionStatus/TransactionStatus.js +3 -2
- package/lib/commonjs/components/UpiHandle/UpiHandle.js +144 -110
- package/lib/commonjs/components/VStack/VStack.js +1 -1
- package/lib/commonjs/design-tokens/figma-variables-resolver.js +21 -3
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/commonjs/utils/react-utils.js +17 -0
- package/lib/module/components/Accordion/Accordion.js +2 -2
- package/lib/module/components/ActionFooter/ActionFooter.js +2 -2
- package/lib/module/components/ActionTile/ActionTile.js +2 -1
- package/lib/module/components/AmountInput/AmountInput.js +2 -1
- package/lib/module/components/AppBar/AppBar.js +2 -2
- package/lib/module/components/Avatar/Avatar.js +184 -162
- package/lib/module/components/AvatarGroup/AvatarGroup.js +2 -2
- package/lib/module/components/Badge/Badge.js +2 -1
- package/lib/module/components/Balance/Balance.js +2 -1
- package/lib/module/components/BottomNav/BottomNav.js +2 -1
- package/lib/module/components/BottomNavItem/BottomNavItem.js +108 -88
- package/lib/module/components/Button/Button.js +192 -95
- package/lib/module/components/ButtonGroup/ButtonGroup.js +2 -2
- package/lib/module/components/Card/Card.js +2 -1
- package/lib/module/components/CardCTA/CardCTA.js +2 -2
- package/lib/module/components/CardProviderInfo/CardProviderInfo.js +2 -2
- package/lib/module/components/Carousel/Carousel.js +3 -2
- package/lib/module/components/Checkbox/Checkbox.js +2 -1
- package/lib/module/components/ChipGroup/ChipGroup.js +2 -2
- package/lib/module/components/ChipSelect/ChipSelect.js +2 -1
- package/lib/module/components/DebitCard/DebitCard.js +2 -2
- package/lib/module/components/Disclaimer/Disclaimer.js +2 -1
- package/lib/module/components/Divider/Divider.js +2 -1
- package/lib/module/components/Drawer/Drawer.js +2 -1
- package/lib/module/components/EmptyState/EmptyState.js +2 -1
- package/lib/module/components/FilterBar/FilterBar.js +2 -2
- package/lib/module/components/Form/Form.js +2 -1
- package/lib/module/components/FormField/FormField.js +3 -2
- package/lib/module/components/HStack/HStack.js +2 -2
- package/lib/module/components/HoldingsCard/HoldingsCard.js +2 -1
- package/lib/module/components/IconButton/IconButton.js +120 -130
- package/lib/module/components/IconCapsule/IconCapsule.js +60 -57
- package/lib/module/components/InputSearch/InputSearch.js +7 -3
- package/lib/module/components/LazyList/LazyList.js +2 -2
- package/lib/module/components/LinearMeter/LinearMeter.js +3 -2
- package/lib/module/components/ListGroup/ListGroup.js +2 -2
- package/lib/module/components/ListItem/ListItem.js +194 -146
- package/lib/module/components/MediaCard/MediaCard.js +4 -2
- package/lib/module/components/MerchantProfile/MerchantProfile.js +2 -1
- package/lib/module/components/MoneyValue/MoneyValue.js +2 -1
- package/lib/module/components/NavArrow/NavArrow.js +82 -58
- package/lib/module/components/NoteInput/NoteInput.js +2 -1
- package/lib/module/components/Nudge/Nudge.js +2 -2
- package/lib/module/components/Numpad/Numpad.js +2 -1
- package/lib/module/components/OTP/OTP.js +2 -2
- package/lib/module/components/PaymentFeedback/PaymentFeedback.js +2 -1
- package/lib/module/components/Popup/Popup.js +2 -1
- package/lib/module/components/ProductLabel/ProductLabel.js +2 -1
- package/lib/module/components/ProgressBadge/ProgressBadge.js +2 -1
- package/lib/module/components/RadioButton/RadioButton.js +2 -1
- package/lib/module/components/RechargeCard/RechargeCard.js +2 -1
- package/lib/module/components/Screen/Screen.js +2 -2
- package/lib/module/components/Section/Section.js +271 -159
- package/lib/module/components/SegmentedControl/SegmentedControl.js +3 -2
- package/lib/module/components/StatItem/StatItem.js +2 -1
- package/lib/module/components/StatusHero/StatusHero.js +2 -1
- package/lib/module/components/Stepper/Step.js +2 -1
- package/lib/module/components/Stepper/StepLabel.js +2 -1
- package/lib/module/components/Stepper/Stepper.js +2 -1
- package/lib/module/components/SupportText/SupportText.js +2 -1
- package/lib/module/components/SupportText/SupportTextIcon.js +2 -1
- package/lib/module/components/SwappableAmount/SwappableAmount.js +2 -1
- package/lib/module/components/Tabs/TabItem.js +2 -1
- package/lib/module/components/Tabs/Tabs.js +2 -1
- package/lib/module/components/Text/Text.js +2 -1
- package/lib/module/components/TextInput/TextInput.js +3 -3
- package/lib/module/components/ThreadHero/ThreadHero.js +2 -1
- package/lib/module/components/Title/Title.js +2 -1
- package/lib/module/components/Toast/Toast.js +2 -1
- package/lib/module/components/Toggle/Toggle.js +2 -1
- package/lib/module/components/Tooltip/Tooltip.js +2 -1
- package/lib/module/components/TransactionBubble/TransactionBubble.js +2 -2
- package/lib/module/components/TransactionDetails/TransactionDetails.js +3 -3
- package/lib/module/components/TransactionStatus/TransactionStatus.js +3 -2
- package/lib/module/components/UpiHandle/UpiHandle.js +147 -113
- package/lib/module/components/VStack/VStack.js +2 -2
- package/lib/module/design-tokens/figma-variables-resolver.js +21 -3
- package/lib/module/icons/registry.js +1 -1
- package/lib/module/utils/react-utils.js +16 -0
- package/lib/typescript/src/components/Avatar/Avatar.d.ts +11 -17
- package/lib/typescript/src/components/BottomNavItem/BottomNavItem.d.ts +12 -8
- package/lib/typescript/src/components/Button/Button.d.ts +18 -1
- package/lib/typescript/src/components/IconButton/IconButton.d.ts +12 -29
- package/lib/typescript/src/components/IconCapsule/IconCapsule.d.ts +10 -18
- package/lib/typescript/src/components/InputSearch/InputSearch.d.ts +8 -3
- package/lib/typescript/src/components/ListItem/ListItem.d.ts +14 -1
- package/lib/typescript/src/components/NavArrow/NavArrow.d.ts +12 -11
- package/lib/typescript/src/components/Section/Section.d.ts +2 -48
- package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +13 -12
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/lib/typescript/src/utils/react-utils.d.ts +15 -0
- package/package.json +4 -6
- package/src/components/Accordion/Accordion.tsx +2 -2
- package/src/components/ActionFooter/ActionFooter.tsx +2 -2
- package/src/components/ActionTile/ActionTile.tsx +2 -1
- package/src/components/AmountInput/AmountInput.tsx +2 -1
- package/src/components/AppBar/AppBar.tsx +2 -2
- package/src/components/Avatar/Avatar.tsx +229 -158
- package/src/components/AvatarGroup/AvatarGroup.tsx +2 -2
- package/src/components/Badge/Badge.tsx +2 -1
- package/src/components/Balance/Balance.tsx +2 -1
- package/src/components/BottomNav/BottomNav.tsx +2 -1
- package/src/components/BottomNavItem/BottomNavItem.tsx +159 -88
- package/src/components/Button/Button.tsx +228 -101
- package/src/components/ButtonGroup/ButtonGroup.tsx +2 -2
- package/src/components/Card/Card.tsx +2 -1
- package/src/components/CardCTA/CardCTA.tsx +2 -2
- package/src/components/CardProviderInfo/CardProviderInfo.tsx +2 -2
- package/src/components/Carousel/Carousel.tsx +3 -2
- package/src/components/Checkbox/Checkbox.tsx +2 -1
- package/src/components/ChipGroup/ChipGroup.tsx +2 -2
- package/src/components/ChipSelect/ChipSelect.tsx +2 -1
- package/src/components/DebitCard/DebitCard.tsx +2 -2
- package/src/components/Disclaimer/Disclaimer.tsx +2 -1
- package/src/components/Divider/Divider.tsx +2 -1
- package/src/components/Drawer/Drawer.tsx +2 -1
- package/src/components/EmptyState/EmptyState.tsx +2 -1
- package/src/components/FilterBar/FilterBar.tsx +2 -2
- package/src/components/Form/Form.tsx +2 -1
- package/src/components/FormField/FormField.tsx +3 -2
- package/src/components/HStack/HStack.tsx +2 -2
- package/src/components/HoldingsCard/HoldingsCard.tsx +2 -1
- package/src/components/IconButton/IconButton.tsx +154 -126
- package/src/components/IconCapsule/IconCapsule.tsx +73 -54
- package/src/components/InputSearch/InputSearch.tsx +19 -5
- package/src/components/LazyList/LazyList.tsx +2 -2
- package/src/components/LinearMeter/LinearMeter.tsx +3 -2
- package/src/components/ListGroup/ListGroup.tsx +2 -2
- package/src/components/ListItem/ListItem.tsx +257 -187
- package/src/components/MediaCard/MediaCard.tsx +2 -1
- package/src/components/MerchantProfile/MerchantProfile.tsx +2 -1
- package/src/components/MoneyValue/MoneyValue.tsx +2 -1
- package/src/components/NavArrow/NavArrow.tsx +91 -58
- package/src/components/NoteInput/NoteInput.tsx +2 -1
- package/src/components/Nudge/Nudge.tsx +2 -2
- package/src/components/Numpad/Numpad.tsx +2 -1
- package/src/components/OTP/OTP.tsx +2 -2
- package/src/components/PaymentFeedback/PaymentFeedback.tsx +2 -1
- package/src/components/Popup/Popup.tsx +2 -1
- package/src/components/ProductLabel/ProductLabel.tsx +2 -1
- package/src/components/ProgressBadge/ProgressBadge.tsx +2 -2
- package/src/components/RadioButton/RadioButton.tsx +2 -1
- package/src/components/RechargeCard/RechargeCard.tsx +2 -1
- package/src/components/Screen/Screen.tsx +2 -2
- package/src/components/Section/Section.tsx +323 -167
- package/src/components/SegmentedControl/SegmentedControl.tsx +3 -2
- package/src/components/StatItem/StatItem.tsx +2 -1
- package/src/components/StatusHero/StatusHero.tsx +2 -1
- package/src/components/Stepper/Step.tsx +2 -1
- package/src/components/Stepper/StepLabel.tsx +2 -1
- package/src/components/Stepper/Stepper.tsx +2 -1
- package/src/components/SupportText/SupportText.tsx +2 -1
- package/src/components/SupportText/SupportTextIcon.tsx +2 -1
- package/src/components/SwappableAmount/SwappableAmount.tsx +2 -1
- package/src/components/Tabs/TabItem.tsx +2 -1
- package/src/components/Tabs/Tabs.tsx +2 -1
- package/src/components/Text/Text.tsx +2 -1
- package/src/components/TextInput/TextInput.tsx +3 -3
- package/src/components/ThreadHero/ThreadHero.tsx +2 -1
- package/src/components/Title/Title.tsx +2 -1
- package/src/components/Toast/Toast.tsx +2 -1
- package/src/components/Toggle/Toggle.tsx +2 -1
- package/src/components/Tooltip/Tooltip.tsx +2 -1
- package/src/components/TransactionBubble/TransactionBubble.tsx +2 -2
- package/src/components/TransactionDetails/TransactionDetails.tsx +3 -3
- package/src/components/TransactionStatus/TransactionStatus.tsx +3 -2
- package/src/components/UpiHandle/UpiHandle.tsx +193 -125
- package/src/components/VStack/VStack.tsx +2 -2
- package/src/design-tokens/figma-variables-resolver.ts +21 -3
- package/src/icons/registry.ts +1 -1
- package/src/utils/react-utils.ts +16 -0
- package/lib/typescript/App.d.ts +0 -2
- package/lib/typescript/index.d.ts +0 -2
- package/lib/typescript/metro.config.d.ts +0 -78
- package/lib/typescript/react-native.config.d.ts +0 -4
|
@@ -10,24 +10,69 @@ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resol
|
|
|
10
10
|
var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
|
|
11
11
|
var _Icon = _interopRequireDefault(require("../../icons/Icon"));
|
|
12
12
|
var _webPlatformUtils = require("../../utils/web-platform-utils");
|
|
13
|
+
var _reactUtils = require("../../utils/react-utils");
|
|
13
14
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
16
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
17
|
+
const IS_WEB = _reactNative.Platform.OS === 'web';
|
|
18
|
+
const IS_IOS = _reactNative.Platform.OS === 'ios';
|
|
19
|
+
const PRESS_DELAY = IS_IOS ? 130 : 0;
|
|
20
|
+
const pressedOverlayStyle = {
|
|
21
|
+
opacity: 0.7
|
|
22
|
+
};
|
|
23
|
+
const hoverOverlayStyle = {
|
|
24
|
+
opacity: 0.85
|
|
25
|
+
};
|
|
26
|
+
const focusOverlayStyle = {
|
|
27
|
+
borderBottomWidth: 2,
|
|
28
|
+
borderBottomColor: '#222'
|
|
29
|
+
};
|
|
30
|
+
function resolveBottomNavItemTokens(modes, disabled, iconColorOverride, iconSizeOverride) {
|
|
31
|
+
const gap = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/gap', modes) ?? 6;
|
|
32
|
+
const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/fontFamily', modes) || 'JioType_Var:Medium';
|
|
33
|
+
const fontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/fontWeight', modes) ?? 500;
|
|
34
|
+
const fontWeight = typeof fontWeightRaw === 'number' ? fontWeightRaw.toString() : fontWeightRaw;
|
|
35
|
+
const fontSize = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/fontSize', modes) ?? 11;
|
|
36
|
+
const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/lineHeight', modes) ?? 14;
|
|
37
|
+
const labelColor = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/label/color', modes) || '#0d0d0f';
|
|
38
|
+
const resolvedIconColor = iconColorOverride || (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/icon/color', modes) || '#ad8545';
|
|
39
|
+
const resolvedIconSize = iconSizeOverride ?? (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/icon/size', modes) ?? 24;
|
|
40
|
+
return {
|
|
41
|
+
baseContainerStyle: {
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
opacity: disabled ? 0.5 : 1
|
|
44
|
+
},
|
|
45
|
+
textStyle: {
|
|
46
|
+
color: labelColor,
|
|
47
|
+
fontFamily,
|
|
48
|
+
fontWeight: fontWeight,
|
|
49
|
+
fontSize,
|
|
50
|
+
lineHeight,
|
|
51
|
+
textAlign: 'center',
|
|
52
|
+
marginTop: gap
|
|
53
|
+
},
|
|
54
|
+
iconColor: resolvedIconColor,
|
|
55
|
+
iconSize: resolvedIconSize
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
16
59
|
/**
|
|
17
60
|
* Bottom navigation item with icon and label stacked vertically.
|
|
18
61
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
62
|
+
* Performance notes:
|
|
63
|
+
* - Token reads collapsed into a single `useMemo([modes, disabled, iconColor, iconSize])`.
|
|
64
|
+
* - Press visual via Pressable's `({ pressed })` style callback.
|
|
65
|
+
* - Hover and focus state are mirrored on web only (gated setters).
|
|
66
|
+
* - The previous version had no-op `onPressIn`/`onPressOut` handlers that
|
|
67
|
+
* forwarded to user callbacks but did nothing else — they were still
|
|
68
|
+
* creating fresh closures every render and forcing Pressable to re-bind.
|
|
69
|
+
* Now stable via a ref-backed wrapper.
|
|
70
|
+
* - Wrapped in `React.memo`.
|
|
26
71
|
*/
|
|
27
72
|
function BottomNavItem({
|
|
28
73
|
iconName = 'ic_home',
|
|
29
74
|
label = 'Home',
|
|
30
|
-
modes: propModes =
|
|
75
|
+
modes: propModes = _reactUtils.EMPTY_MODES,
|
|
31
76
|
onPress,
|
|
32
77
|
disabled = false,
|
|
33
78
|
style,
|
|
@@ -43,54 +88,21 @@ function BottomNavItem({
|
|
|
43
88
|
const {
|
|
44
89
|
modes: globalModes
|
|
45
90
|
} = (0, _JFSThemeProvider.useTokens)();
|
|
46
|
-
const modes = {
|
|
91
|
+
const modes = (0, _react.useMemo)(() => globalModes === _reactUtils.EMPTY_MODES && propModes === _reactUtils.EMPTY_MODES ? _reactUtils.EMPTY_MODES : {
|
|
47
92
|
...globalModes,
|
|
48
93
|
...propModes
|
|
49
|
-
};
|
|
94
|
+
}, [globalModes, propModes]);
|
|
95
|
+
const tokens = (0, _react.useMemo)(() => resolveBottomNavItemTokens(modes, disabled, iconColorOverride, iconSizeOverride), [modes, disabled, iconColorOverride, iconSizeOverride]);
|
|
50
96
|
const [isFocused, setIsFocused] = (0, _react.useState)(false);
|
|
51
97
|
const [isHovered, setIsHovered] = (0, _react.useState)(false);
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const hoverStyle = {
|
|
60
|
-
opacity: 0.85
|
|
61
|
-
};
|
|
62
|
-
// Resolve spacing and typography
|
|
63
|
-
const gap = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/gap', modes) ?? 6;
|
|
64
|
-
const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/fontFamily', modes) || 'JioType_Var:Medium';
|
|
65
|
-
const fontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/fontWeight', modes) ?? 500;
|
|
66
|
-
const fontWeight = typeof fontWeightRaw === 'number' ? fontWeightRaw.toString() : fontWeightRaw;
|
|
67
|
-
const fontSize = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/fontSize', modes) ?? 11;
|
|
68
|
-
const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/lineHeight', modes) ?? 14;
|
|
69
|
-
|
|
70
|
-
// Resolve Label Color
|
|
71
|
-
const labelColor = (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/label/color', modes) || '#0d0d0f';
|
|
72
|
-
|
|
73
|
-
// Resolve icon appearance
|
|
74
|
-
const resolvedIconColor = iconColorOverride || (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/icon/color', modes) || '#ad8545';
|
|
75
|
-
const resolvedIconSize = iconSizeOverride ?? (0, _figmaVariablesResolver.getVariableByName)('bottomNavItem/icon/size', modes) ?? 24;
|
|
76
|
-
const baseContainerStyle = {
|
|
77
|
-
alignItems: 'center',
|
|
78
|
-
opacity: disabled ? 0.5 : 1
|
|
79
|
-
};
|
|
80
|
-
const textStyle = {
|
|
81
|
-
color: labelColor,
|
|
82
|
-
fontFamily,
|
|
83
|
-
fontWeight,
|
|
84
|
-
fontSize,
|
|
85
|
-
lineHeight,
|
|
86
|
-
textAlign: 'center',
|
|
87
|
-
marginTop: gap
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
// Use provided accessibilityLabel or fall back to label
|
|
98
|
+
const userHandlersRef = (0, _react.useRef)({});
|
|
99
|
+
userHandlersRef.current.onPressIn = rest?.onPressIn;
|
|
100
|
+
userHandlersRef.current.onPressOut = rest?.onPressOut;
|
|
101
|
+
userHandlersRef.current.onFocus = rest?.onFocus;
|
|
102
|
+
userHandlersRef.current.onBlur = rest?.onBlur;
|
|
103
|
+
userHandlersRef.current.onHoverIn = rest?.onHoverIn;
|
|
104
|
+
userHandlersRef.current.onHoverOut = rest?.onHoverOut;
|
|
91
105
|
const defaultAccessibilityLabel = accessibilityLabel || label;
|
|
92
|
-
|
|
93
|
-
// Get web platform support props (only used when onPress is defined)
|
|
94
106
|
const webProps = (0, _webPlatformUtils.usePressableWebSupport)({
|
|
95
107
|
restProps: rest,
|
|
96
108
|
onPress: disabled ? undefined : onPress,
|
|
@@ -98,23 +110,50 @@ function BottomNavItem({
|
|
|
98
110
|
accessibilityLabel: defaultAccessibilityLabel,
|
|
99
111
|
webAccessibilityProps
|
|
100
112
|
});
|
|
101
|
-
const
|
|
113
|
+
const composedTextStyle = (0, _react.useMemo)(() => labelStyle ? [tokens.textStyle, labelStyle] : tokens.textStyle, [tokens.textStyle, labelStyle]);
|
|
114
|
+
const renderContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
102
115
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
|
|
103
116
|
name: iconName,
|
|
104
|
-
size:
|
|
105
|
-
color:
|
|
117
|
+
size: tokens.iconSize,
|
|
118
|
+
color: tokens.iconColor,
|
|
106
119
|
accessibilityElementsHidden: true,
|
|
107
120
|
importantForAccessibility: "no"
|
|
108
121
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
109
|
-
style:
|
|
122
|
+
style: composedTextStyle,
|
|
110
123
|
accessibilityElementsHidden: true,
|
|
111
124
|
importantForAccessibility: "no",
|
|
112
125
|
children: label
|
|
113
126
|
})]
|
|
114
127
|
});
|
|
128
|
+
const staticContainerStyle = (0, _react.useMemo)(() => style ? [tokens.baseContainerStyle, style] : tokens.baseContainerStyle, [tokens.baseContainerStyle, style]);
|
|
129
|
+
const handlePressIn = (0, _react.useCallback)(e => {
|
|
130
|
+
userHandlersRef.current.onPressIn?.(e);
|
|
131
|
+
}, []);
|
|
132
|
+
const handlePressOut = (0, _react.useCallback)(e => {
|
|
133
|
+
userHandlersRef.current.onPressOut?.(e);
|
|
134
|
+
}, []);
|
|
135
|
+
const handleFocus = (0, _react.useCallback)(e => {
|
|
136
|
+
if (IS_WEB) setIsFocused(true);
|
|
137
|
+
userHandlersRef.current.onFocus?.(e);
|
|
138
|
+
}, []);
|
|
139
|
+
const handleBlur = (0, _react.useCallback)(e => {
|
|
140
|
+
if (IS_WEB) setIsFocused(false);
|
|
141
|
+
userHandlersRef.current.onBlur?.(e);
|
|
142
|
+
}, []);
|
|
143
|
+
const handleHoverIn = (0, _react.useCallback)(e => {
|
|
144
|
+
if (IS_WEB) setIsHovered(true);
|
|
145
|
+
userHandlersRef.current.onHoverIn?.(e);
|
|
146
|
+
}, []);
|
|
147
|
+
const handleHoverOut = (0, _react.useCallback)(e => {
|
|
148
|
+
if (IS_WEB) setIsHovered(false);
|
|
149
|
+
userHandlersRef.current.onHoverOut?.(e);
|
|
150
|
+
}, []);
|
|
151
|
+
const pressableStyle = (0, _react.useCallback)(({
|
|
152
|
+
pressed
|
|
153
|
+
}) => [tokens.baseContainerStyle, style, pressed && !disabled ? pressedOverlayStyle : null, isHovered && !disabled ? hoverOverlayStyle : null, isFocused && !disabled ? focusOverlayStyle : null], [tokens.baseContainerStyle, style, isHovered, isFocused, disabled]);
|
|
115
154
|
if (!onPress) {
|
|
116
155
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
117
|
-
style:
|
|
156
|
+
style: staticContainerStyle,
|
|
118
157
|
accessibilityRole: "tab",
|
|
119
158
|
accessibilityLabel: undefined,
|
|
120
159
|
accessibilityHint: accessibilityHint,
|
|
@@ -123,7 +162,7 @@ function BottomNavItem({
|
|
|
123
162
|
...accessibilityState
|
|
124
163
|
},
|
|
125
164
|
...rest,
|
|
126
|
-
children: renderContent
|
|
165
|
+
children: renderContent
|
|
127
166
|
});
|
|
128
167
|
}
|
|
129
168
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
|
|
@@ -137,35 +176,16 @@ function BottomNavItem({
|
|
|
137
176
|
},
|
|
138
177
|
onPress: onPress,
|
|
139
178
|
disabled: disabled,
|
|
140
|
-
onPressIn:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
onFocus: e => {
|
|
149
|
-
setIsFocused(true);
|
|
150
|
-
rest?.onFocus?.(e);
|
|
151
|
-
},
|
|
152
|
-
onBlur: e => {
|
|
153
|
-
setIsFocused(false);
|
|
154
|
-
rest?.onBlur?.(e);
|
|
155
|
-
},
|
|
156
|
-
onHoverIn: e => {
|
|
157
|
-
setIsHovered(true);
|
|
158
|
-
rest?.onHoverIn?.(e);
|
|
159
|
-
},
|
|
160
|
-
onHoverOut: e => {
|
|
161
|
-
setIsHovered(false);
|
|
162
|
-
rest?.onHoverOut?.(e);
|
|
163
|
-
},
|
|
164
|
-
style: ({
|
|
165
|
-
pressed
|
|
166
|
-
}) => [baseContainerStyle, style, pressed && !disabled ? pressedStyle : null, isHovered && !disabled ? hoverStyle : null, isFocused && !disabled ? focusStyle : null],
|
|
179
|
+
onPressIn: handlePressIn,
|
|
180
|
+
onPressOut: handlePressOut,
|
|
181
|
+
onFocus: handleFocus,
|
|
182
|
+
onBlur: handleBlur,
|
|
183
|
+
onHoverIn: handleHoverIn,
|
|
184
|
+
onHoverOut: handleHoverOut,
|
|
185
|
+
unstable_pressDelay: PRESS_DELAY,
|
|
186
|
+
style: pressableStyle,
|
|
167
187
|
...webProps,
|
|
168
|
-
children: renderContent
|
|
188
|
+
children: renderContent
|
|
169
189
|
});
|
|
170
190
|
}
|
|
171
|
-
var _default = exports.default = BottomNavItem;
|
|
191
|
+
var _default = exports.default = /*#__PURE__*/_react.default.memo(BottomNavItem);
|
|
@@ -8,10 +8,120 @@ var _react = _interopRequireWildcard(require("react"));
|
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
|
|
10
10
|
var _webPlatformUtils = require("../../utils/web-platform-utils");
|
|
11
|
+
var _reactUtils = require("../../utils/react-utils");
|
|
11
12
|
var _Icon = _interopRequireDefault(require("../../icons/Icon"));
|
|
12
13
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
14
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
15
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Module-scope constants — never re-allocated per render.
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
const IS_WEB = _reactNative.Platform.OS === 'web';
|
|
21
|
+
const IS_IOS = _reactNative.Platform.OS === 'ios';
|
|
22
|
+
|
|
23
|
+
// iOS Pressable inside a ScrollView fires onPressIn on touchstart by default,
|
|
24
|
+
// which causes a visible "press" flash that snaps back when ScrollView claims
|
|
25
|
+
// the gesture. Delaying press by ~130ms lets the scroll responder cancel the
|
|
26
|
+
// gesture before the pressed visual is ever applied.
|
|
27
|
+
//
|
|
28
|
+
// Android uses the responder system + the touchable cancellation pipeline and
|
|
29
|
+
// does not need an extra delay; setting it to 0 keeps tap latency identical
|
|
30
|
+
// to today's behavior on Android.
|
|
31
|
+
const PRESS_DELAY = IS_IOS ? 130 : 0;
|
|
32
|
+
const containerLayoutStyle = {
|
|
33
|
+
flexDirection: 'row',
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
justifyContent: 'center'
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Token resolution
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
//
|
|
42
|
+
// Memoizing all token reads in a single useMemo keyed on (modes, disabled)
|
|
43
|
+
// turns the previous ~21 cache lookups + arithmetic per render into a single
|
|
44
|
+
// resolve per (modes, disabled) tuple. With `EMPTY_MODES` as the default,
|
|
45
|
+
// the most common path (no modes prop) is resolved once for the whole app.
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
function resolveButtonTokens(modes, disabled) {
|
|
49
|
+
const backgroundColor = (0, _figmaVariablesResolver.getVariableByName)('button/background', modes) || '#cfa159';
|
|
50
|
+
const borderColor = (0, _figmaVariablesResolver.getVariableByName)('button/border/color', modes) || 'rgba(255,255,255,0)';
|
|
51
|
+
const borderWidth = (0, _figmaVariablesResolver.getVariableByName)('button/border/size', modes);
|
|
52
|
+
const radius = (0, _figmaVariablesResolver.getVariableByName)('button/radius', modes) || 9999;
|
|
53
|
+
const paddingHorizontal = (0, _figmaVariablesResolver.getVariableByName)('button/padding/horizontal', modes) || 20;
|
|
54
|
+
const paddingVertical = (0, _figmaVariablesResolver.getVariableByName)('button/padding/vertical', modes) || 12;
|
|
55
|
+
const gap = (0, _figmaVariablesResolver.getVariableByName)('button/gap', modes) || 8;
|
|
56
|
+
const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('button/fontFamily', modes) || 'System';
|
|
57
|
+
const fontWeightValue = (0, _figmaVariablesResolver.getVariableByName)('button/fontWeight', modes) || 700;
|
|
58
|
+
const fontWeight = typeof fontWeightValue === 'number' ? fontWeightValue.toString() : fontWeightValue;
|
|
59
|
+
const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('button/lineHeight', modes) || 19;
|
|
60
|
+
const fontSize = (0, _figmaVariablesResolver.getVariableByName)('button/fontSize', modes) || 16;
|
|
61
|
+
const textColor = (0, _figmaVariablesResolver.getVariableByName)('button/foreground', modes) || '#0f0d0a';
|
|
62
|
+
const iconSize = (0, _figmaVariablesResolver.getVariableByName)('button/icon/size', modes) ?? 18;
|
|
63
|
+
|
|
64
|
+
// Pressed tokens are always resolved so the Pressable `style` callback can
|
|
65
|
+
// apply the pressed visual without scheduling a React render.
|
|
66
|
+
const pressedModes = {
|
|
67
|
+
...modes,
|
|
68
|
+
'Button / State': 'Pressed'
|
|
69
|
+
};
|
|
70
|
+
const pressedBg = (0, _figmaVariablesResolver.getVariableByName)('button/background', pressedModes) || backgroundColor;
|
|
71
|
+
const pressedBorderColor = (0, _figmaVariablesResolver.getVariableByName)('button/border/color', pressedModes) || borderColor;
|
|
72
|
+
const pressedTextColor = (0, _figmaVariablesResolver.getVariableByName)('button/foreground', pressedModes) || textColor;
|
|
73
|
+
|
|
74
|
+
// Hover tokens are only meaningful on web. Skipping them on native saves
|
|
75
|
+
// ~3 token lookups + an object spread per render on every Button.
|
|
76
|
+
let hoverContainer = null;
|
|
77
|
+
let hoverTextColor = null;
|
|
78
|
+
if (IS_WEB) {
|
|
79
|
+
const hoverModes = {
|
|
80
|
+
...modes,
|
|
81
|
+
'Button / State': 'Hover'
|
|
82
|
+
};
|
|
83
|
+
const hoverBg = (0, _figmaVariablesResolver.getVariableByName)('button/background', hoverModes) || backgroundColor;
|
|
84
|
+
const hoverBorderColor = (0, _figmaVariablesResolver.getVariableByName)('button/border/color', hoverModes) || borderColor;
|
|
85
|
+
hoverTextColor = (0, _figmaVariablesResolver.getVariableByName)('button/foreground', hoverModes) || textColor;
|
|
86
|
+
hoverContainer = {
|
|
87
|
+
backgroundColor: hoverBg,
|
|
88
|
+
borderColor: hoverBorderColor
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
container: {
|
|
93
|
+
...containerLayoutStyle,
|
|
94
|
+
paddingHorizontal: paddingHorizontal,
|
|
95
|
+
paddingVertical: paddingVertical,
|
|
96
|
+
borderRadius: radius,
|
|
97
|
+
borderWidth: borderWidth ?? 1,
|
|
98
|
+
borderColor: borderColor,
|
|
99
|
+
backgroundColor: backgroundColor,
|
|
100
|
+
gap: gap,
|
|
101
|
+
opacity: disabled ? 0.5 : 1
|
|
102
|
+
},
|
|
103
|
+
baseLabel: {
|
|
104
|
+
color: textColor,
|
|
105
|
+
fontFamily: fontFamily,
|
|
106
|
+
fontWeight: fontWeight,
|
|
107
|
+
fontSize: fontSize,
|
|
108
|
+
lineHeight: lineHeight
|
|
109
|
+
},
|
|
110
|
+
hoverContainer,
|
|
111
|
+
pressedContainer: {
|
|
112
|
+
backgroundColor: pressedBg,
|
|
113
|
+
borderColor: pressedBorderColor
|
|
114
|
+
},
|
|
115
|
+
hoverTextColor,
|
|
116
|
+
pressedTextColor,
|
|
117
|
+
baseIconColor: textColor,
|
|
118
|
+
hoverIconColor: hoverTextColor,
|
|
119
|
+
pressedIconColor: pressedTextColor,
|
|
120
|
+
iconSize,
|
|
121
|
+
accessoryOffset: gap / 2
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
15
125
|
/**
|
|
16
126
|
* Button component that maps directly to the Figma design using design tokens.
|
|
17
127
|
*
|
|
@@ -30,15 +140,31 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
30
140
|
* @param {string} [props.accessibilityLabel] - Accessibility label for screen readers. If not provided, uses label or children text
|
|
31
141
|
* @param {string} [props.accessibilityHint] - Additional accessibility hint for screen readers
|
|
32
142
|
* @param {Object} [props.accessibilityState] - Additional accessibility state information
|
|
143
|
+
*
|
|
144
|
+
* Performance notes:
|
|
145
|
+
* - The pressed visual (background/border swap) is applied through the
|
|
146
|
+
* Pressable `style` callback, NOT a mirrored React state. This avoids the
|
|
147
|
+
* flicker that scrolling parents previously caused: when a ScrollView
|
|
148
|
+
* cancels a touch the host view simply reverts its style without React
|
|
149
|
+
* rendering. On iOS we additionally use `unstable_pressDelay` so the
|
|
150
|
+
* pressed visual is never even applied during a scroll-cancelled touch.
|
|
151
|
+
* - Hover state is only mirrored into React state on web (where hover events
|
|
152
|
+
* fire). On native the setter call is gated out so the component never
|
|
153
|
+
* re-renders due to hover.
|
|
154
|
+
* - All design-token reads are folded into a single `useMemo` keyed on
|
|
155
|
+
* `(modes, disabled)`.
|
|
156
|
+
* - The component is wrapped in `React.memo`. Callers that want to take
|
|
157
|
+
* advantage of this should pass stable `modes` (the default `EMPTY_MODES`
|
|
158
|
+
* is already stable) and stable callback props.
|
|
33
159
|
*/
|
|
34
|
-
function
|
|
160
|
+
function ButtonImpl({
|
|
35
161
|
label = 'Button',
|
|
36
162
|
children,
|
|
37
163
|
renderContent,
|
|
38
164
|
leading,
|
|
39
165
|
trailing,
|
|
40
166
|
icon,
|
|
41
|
-
modes =
|
|
167
|
+
modes = _reactUtils.EMPTY_MODES,
|
|
42
168
|
onPress,
|
|
43
169
|
disabled = false,
|
|
44
170
|
style,
|
|
@@ -49,85 +175,50 @@ function Button({
|
|
|
49
175
|
webAccessibilityProps,
|
|
50
176
|
...rest
|
|
51
177
|
}) {
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
const borderColor = (0, _figmaVariablesResolver.getVariableByName)('button/border/color', modes) || 'rgba(255,255,255,0)';
|
|
55
|
-
const borderWidth = (0, _figmaVariablesResolver.getVariableByName)('button/border/size', modes);
|
|
56
|
-
const radius = (0, _figmaVariablesResolver.getVariableByName)('button/radius', modes) || 9999;
|
|
57
|
-
const paddingHorizontal = (0, _figmaVariablesResolver.getVariableByName)('button/padding/horizontal', modes) || 20;
|
|
58
|
-
const paddingVertical = (0, _figmaVariablesResolver.getVariableByName)('button/padding/vertical', modes) || 12;
|
|
59
|
-
const gap = (0, _figmaVariablesResolver.getVariableByName)('button/gap', modes) || 8;
|
|
60
|
-
const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('button/fontFamily', modes) || 'System';
|
|
61
|
-
const fontWeightValue = (0, _figmaVariablesResolver.getVariableByName)('button/fontWeight', modes) || 700;
|
|
62
|
-
const fontWeight = typeof fontWeightValue === 'number' ? fontWeightValue.toString() : fontWeightValue;
|
|
63
|
-
const lineHeight = (0, _figmaVariablesResolver.getVariableByName)('button/lineHeight', modes) || 19;
|
|
64
|
-
const fontSize = (0, _figmaVariablesResolver.getVariableByName)('button/fontSize', modes) || 16;
|
|
65
|
-
const textColor = (0, _figmaVariablesResolver.getVariableByName)('button/foreground', modes) || '#0f0d0a';
|
|
66
|
-
const iconColor = textColor;
|
|
67
|
-
const iconSize = (0, _figmaVariablesResolver.getVariableByName)('button/icon/size', modes) ?? 18;
|
|
178
|
+
// Hover state is web-only in practice; the setter is gated so native taps
|
|
179
|
+
// never schedule a re-render through this hook.
|
|
68
180
|
const [isHovered, setIsHovered] = (0, _react.useState)(false);
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
color: activeTextColor,
|
|
90
|
-
fontFamily,
|
|
91
|
-
fontWeight,
|
|
92
|
-
fontSize,
|
|
93
|
-
lineHeight
|
|
94
|
-
};
|
|
95
|
-
const mergedLabelTextStyle = [baseLabelTextStyle, labelStyle];
|
|
181
|
+
|
|
182
|
+
// Mirror user-supplied handlers in a ref so our wrapper handlers can stay
|
|
183
|
+
// referentially stable (otherwise Pressable would re-bind every render).
|
|
184
|
+
const userHandlersRef = (0, _react.useRef)({});
|
|
185
|
+
userHandlersRef.current.onPressIn = rest?.onPressIn;
|
|
186
|
+
userHandlersRef.current.onPressOut = rest?.onPressOut;
|
|
187
|
+
userHandlersRef.current.onHoverIn = rest?.onHoverIn;
|
|
188
|
+
userHandlersRef.current.onHoverOut = rest?.onHoverOut;
|
|
189
|
+
const tokens = (0, _react.useMemo)(() => resolveButtonTokens(modes, disabled), [modes, disabled]);
|
|
190
|
+
|
|
191
|
+
// Active label color: base by default; hover override (web-only) when hovered.
|
|
192
|
+
// Press color is intentionally NOT applied to the label on native — applying
|
|
193
|
+
// it would require a React render per touch and re-introduce the flicker.
|
|
194
|
+
const activeLabelStyle = (0, _react.useMemo)(() => {
|
|
195
|
+
const hoverOverride = isHovered && !disabled && tokens.hoverTextColor ? {
|
|
196
|
+
color: tokens.hoverTextColor
|
|
197
|
+
} : null;
|
|
198
|
+
return [tokens.baseLabel, hoverOverride, labelStyle];
|
|
199
|
+
}, [tokens.baseLabel, tokens.hoverTextColor, isHovered, disabled, labelStyle]);
|
|
200
|
+
const activeIconColor = isHovered && !disabled && tokens.hoverIconColor ? tokens.hoverIconColor : tokens.baseIconColor;
|
|
96
201
|
let content;
|
|
97
202
|
if (renderContent) {
|
|
98
203
|
// Preferred extension point: caller fully controls the inner node but we
|
|
99
204
|
// still provide the token-derived text styles.
|
|
100
|
-
content = renderContent(
|
|
205
|
+
content = renderContent(activeLabelStyle);
|
|
101
206
|
} else if (children !== undefined && children !== null) {
|
|
102
207
|
// Full-content override: label and labelStyle are intentionally ignored.
|
|
103
208
|
content = children;
|
|
104
209
|
} else {
|
|
105
210
|
content = /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
106
|
-
style:
|
|
211
|
+
style: activeLabelStyle,
|
|
107
212
|
numberOfLines: 1,
|
|
108
213
|
children: label
|
|
109
214
|
});
|
|
110
215
|
}
|
|
111
|
-
const containerBaseStyle = {
|
|
112
|
-
flexDirection: 'row',
|
|
113
|
-
alignItems: 'center',
|
|
114
|
-
justifyContent: 'center',
|
|
115
|
-
paddingHorizontal,
|
|
116
|
-
paddingVertical,
|
|
117
|
-
borderRadius: radius,
|
|
118
|
-
borderWidth: borderWidth ?? 1,
|
|
119
|
-
borderColor,
|
|
120
|
-
backgroundColor,
|
|
121
|
-
gap,
|
|
122
|
-
opacity: disabled ? 0.5 : 1
|
|
123
|
-
};
|
|
124
|
-
const accessoryOffset = gap / 2;
|
|
125
216
|
const leadingAccessoryStyle = (0, _react.useMemo)(() => ({
|
|
126
|
-
marginRight: accessoryOffset
|
|
127
|
-
}), [accessoryOffset]);
|
|
217
|
+
marginRight: tokens.accessoryOffset
|
|
218
|
+
}), [tokens.accessoryOffset]);
|
|
128
219
|
const trailingAccessoryStyle = (0, _react.useMemo)(() => ({
|
|
129
|
-
marginLeft: accessoryOffset
|
|
130
|
-
}), [accessoryOffset]);
|
|
220
|
+
marginLeft: tokens.accessoryOffset
|
|
221
|
+
}), [tokens.accessoryOffset]);
|
|
131
222
|
|
|
132
223
|
// Use provided accessibilityLabel, or fall back to label text
|
|
133
224
|
const defaultAccessibilityLabel = accessibilityLabel || (typeof label === 'string' ? label : undefined);
|
|
@@ -140,14 +231,32 @@ function Button({
|
|
|
140
231
|
accessibilityLabel: defaultAccessibilityLabel,
|
|
141
232
|
webAccessibilityProps
|
|
142
233
|
});
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
234
|
+
|
|
235
|
+
// Stable handler identities. The user's handlers are read through a ref so
|
|
236
|
+
// these wrappers do not need to be re-created when the user passes inline
|
|
237
|
+
// closures, which would defeat React.memo on Pressable.
|
|
238
|
+
const handlePressIn = (0, _react.useCallback)(e => {
|
|
239
|
+
userHandlersRef.current.onPressIn?.(e);
|
|
240
|
+
}, []);
|
|
241
|
+
const handlePressOut = (0, _react.useCallback)(e => {
|
|
242
|
+
userHandlersRef.current.onPressOut?.(e);
|
|
243
|
+
}, []);
|
|
244
|
+
const handleHoverIn = (0, _react.useCallback)(e => {
|
|
245
|
+
if (IS_WEB) setIsHovered(true);
|
|
246
|
+
userHandlersRef.current.onHoverIn?.(e);
|
|
247
|
+
}, []);
|
|
248
|
+
const handleHoverOut = (0, _react.useCallback)(e => {
|
|
249
|
+
if (IS_WEB) setIsHovered(false);
|
|
250
|
+
userHandlersRef.current.onHoverOut?.(e);
|
|
251
|
+
}, []);
|
|
252
|
+
|
|
253
|
+
// The Pressable style callback receives `pressed` from RN's gesture
|
|
254
|
+
// pipeline and applies the pressed visual to the host view directly,
|
|
255
|
+
// without going through React. This is the key to flicker-free behavior:
|
|
256
|
+
// a scroll-cancelled touch reverts the style on the native side only.
|
|
257
|
+
const styleCallback = (0, _react.useCallback)(({
|
|
258
|
+
pressed
|
|
259
|
+
}) => [tokens.container, isHovered && !disabled ? tokens.hoverContainer : null, pressed && !disabled ? tokens.pressedContainer : null, style], [tokens.container, tokens.hoverContainer, tokens.pressedContainer, isHovered, disabled, style]);
|
|
151
260
|
if (__DEV__) {
|
|
152
261
|
if (children && labelStyle) {
|
|
153
262
|
console.warn('[Button] `children` was provided; `labelStyle` will be ignored. ' + 'Use `renderContent` if you need custom content that still reuses the label styles.');
|
|
@@ -170,25 +279,12 @@ function Button({
|
|
|
170
279
|
...(onPress !== undefined ? {
|
|
171
280
|
onPress
|
|
172
281
|
} : {}),
|
|
173
|
-
onPressIn:
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
rest?.onPressOut?.(e);
|
|
180
|
-
},
|
|
181
|
-
onHoverIn: e => {
|
|
182
|
-
setIsHovered(true);
|
|
183
|
-
rest?.onHoverIn?.(e);
|
|
184
|
-
},
|
|
185
|
-
onHoverOut: e => {
|
|
186
|
-
setIsHovered(false);
|
|
187
|
-
rest?.onHoverOut?.(e);
|
|
188
|
-
},
|
|
189
|
-
style: ({
|
|
190
|
-
pressed
|
|
191
|
-
}) => [containerBaseStyle, isHovered && !disabled ? hoverStyle : null, (pressed || isPressed) && !disabled ? pressedStyle : null, style],
|
|
282
|
+
onPressIn: handlePressIn,
|
|
283
|
+
onPressOut: handlePressOut,
|
|
284
|
+
onHoverIn: handleHoverIn,
|
|
285
|
+
onHoverOut: handleHoverOut,
|
|
286
|
+
unstable_pressDelay: PRESS_DELAY,
|
|
287
|
+
style: styleCallback,
|
|
192
288
|
...webProps,
|
|
193
289
|
children: [leading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
194
290
|
style: leadingAccessoryStyle,
|
|
@@ -197,7 +293,7 @@ function Button({
|
|
|
197
293
|
style: trailingAccessoryStyle,
|
|
198
294
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
|
|
199
295
|
name: icon,
|
|
200
|
-
size: iconSize,
|
|
296
|
+
size: tokens.iconSize,
|
|
201
297
|
color: activeIconColor,
|
|
202
298
|
accessibilityElementsHidden: true,
|
|
203
299
|
importantForAccessibility: "no"
|
|
@@ -208,4 +304,5 @@ function Button({
|
|
|
208
304
|
}) : null]
|
|
209
305
|
});
|
|
210
306
|
}
|
|
307
|
+
const Button = /*#__PURE__*/_react.default.memo(ButtonImpl);
|
|
211
308
|
var _default = exports.default = Button;
|
|
@@ -8,6 +8,7 @@ exports.default = void 0;
|
|
|
8
8
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
9
|
var _reactNative = require("react-native");
|
|
10
10
|
var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
|
|
11
|
+
var _reactUtils = require("../../utils/react-utils");
|
|
11
12
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
13
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
13
14
|
/**
|
|
@@ -31,7 +32,7 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
|
|
|
31
32
|
function Card({
|
|
32
33
|
media,
|
|
33
34
|
children,
|
|
34
|
-
modes =
|
|
35
|
+
modes = _reactUtils.EMPTY_MODES,
|
|
35
36
|
mediaAspectRatio = 154 / 116,
|
|
36
37
|
style
|
|
37
38
|
}) {
|
|
@@ -22,7 +22,7 @@ function CardProviderInfo({
|
|
|
22
22
|
label = 'Gold',
|
|
23
23
|
imageSource,
|
|
24
24
|
children,
|
|
25
|
-
modes =
|
|
25
|
+
modes = _reactUtils.EMPTY_MODES,
|
|
26
26
|
style
|
|
27
27
|
}) {
|
|
28
28
|
const background = (0, _figmaVariablesResolver.getVariableByName)('card/providerInfo/background', modes) ?? '#fef4e5';
|