jfs-components 0.0.62 → 0.0.64
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 +59 -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 +109 -48
- 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 +500 -166
- 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 +109 -48
- 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 +503 -169
- 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 +43 -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 +124 -58
- 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 +672 -176
- 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
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
import React, { useState } from 'react'
|
|
1
|
+
import React, { useCallback, useMemo, useRef, useState } from 'react'
|
|
2
2
|
import {
|
|
3
|
+
Platform,
|
|
3
4
|
Pressable,
|
|
4
5
|
type AccessibilityState,
|
|
6
|
+
type PressableStateCallbackType,
|
|
5
7
|
type StyleProp,
|
|
6
8
|
type ViewStyle,
|
|
7
9
|
} from 'react-native'
|
|
8
10
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
9
11
|
import Icon from '../../icons/Icon'
|
|
10
12
|
import { usePressableWebSupport, type SafePressableProps, type WebAccessibilityProps } from '../../utils/web-platform-utils'
|
|
13
|
+
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
11
14
|
|
|
12
15
|
type IconButtonProps = SafePressableProps & {
|
|
13
16
|
iconName?: string;
|
|
@@ -29,7 +32,7 @@ type IconButtonProps = SafePressableProps & {
|
|
|
29
32
|
/**
|
|
30
33
|
* Icon to display when isToggle is true and isActive is false
|
|
31
34
|
*/
|
|
32
|
-
inactiveIcon?: string;
|
|
35
|
+
inactiveIcon?: string;
|
|
33
36
|
/**
|
|
34
37
|
* Whether the toggle button is in active state (only used when isToggle is true)
|
|
35
38
|
*/
|
|
@@ -40,41 +43,75 @@ type IconButtonProps = SafePressableProps & {
|
|
|
40
43
|
webAccessibilityProps?: WebAccessibilityProps;
|
|
41
44
|
};
|
|
42
45
|
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Module-scope constants
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
const IS_WEB = Platform.OS === 'web'
|
|
51
|
+
const IS_IOS = Platform.OS === 'ios'
|
|
52
|
+
const PRESS_DELAY = IS_IOS ? 130 : 0
|
|
53
|
+
|
|
54
|
+
// Pressed visual is applied through Pressable's style callback so the host
|
|
55
|
+
// view updates without scheduling a React render. Hover/focus stay mirrored
|
|
56
|
+
// in React state because they're sustained visual states (web only).
|
|
57
|
+
const pressedOverlayStyle: ViewStyle = { opacity: 0.7 }
|
|
58
|
+
const hoverOverlayStyle: ViewStyle = { opacity: 0.85 }
|
|
59
|
+
const focusOverlayStyle: ViewStyle = { borderWidth: 1, borderColor: '#222' }
|
|
60
|
+
|
|
61
|
+
interface IconButtonTokens {
|
|
62
|
+
baseContainerStyle: ViewStyle;
|
|
63
|
+
iconColor: string;
|
|
64
|
+
iconSize: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function resolveIconButtonTokens(modes: Record<string, any>, disabled: boolean): IconButtonTokens {
|
|
68
|
+
const radiusRaw = (getVariableByName('iconButton/radius', modes) ?? 9999) as number
|
|
69
|
+
const padding = (getVariableByName('iconButton/padding', modes) ?? 12) as number
|
|
70
|
+
const backgroundColor = (getVariableByName('iconButton/background', modes) ?? '#cfa159') as string
|
|
71
|
+
const borderColor = (getVariableByName('iconButton/border/color', modes) ?? '#ffffff00') as string
|
|
72
|
+
const borderSize = (getVariableByName('iconButton/border/size', modes) ?? 1) as number
|
|
73
|
+
const iconColor = (getVariableByName('iconButton/icon/color', modes) ?? '#0f0d0a') as string
|
|
74
|
+
const iconSize = (getVariableByName('iconButton/icon/size', modes) ?? 18) as number
|
|
75
|
+
|
|
76
|
+
// 9999 is the design-token sentinel for "perfect circle"
|
|
77
|
+
const buttonSize = padding * 2 + iconSize
|
|
78
|
+
const borderRadius = radiusRaw === 9999 ? buttonSize / 2 : radiusRaw
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
baseContainerStyle: {
|
|
82
|
+
width: buttonSize,
|
|
83
|
+
height: buttonSize,
|
|
84
|
+
borderRadius,
|
|
85
|
+
borderWidth: borderSize,
|
|
86
|
+
borderColor,
|
|
87
|
+
backgroundColor,
|
|
88
|
+
overflow: 'hidden',
|
|
89
|
+
alignItems: 'center',
|
|
90
|
+
justifyContent: 'center',
|
|
91
|
+
padding,
|
|
92
|
+
opacity: disabled ? 0.5 : 1,
|
|
93
|
+
},
|
|
94
|
+
iconColor,
|
|
95
|
+
iconSize,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
43
99
|
/**
|
|
44
100
|
* IconButton component that displays an icon within a pressable button container.
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* @param {Object} [props.style] - Additional styles for the container
|
|
56
|
-
* @param {string} [props.accessibilityLabel] - Accessibility label for screen readers. If not provided, defaults to iconName
|
|
57
|
-
* @param {string} [props.accessibilityHint] - Additional accessibility hint for screen readers
|
|
58
|
-
* @param {Object} [props.accessibilityState] - Additional accessibility state information
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```jsx
|
|
62
|
-
* // Default icon button
|
|
63
|
-
* <IconButton modes={{}} />
|
|
64
|
-
*
|
|
65
|
-
* // Custom icon with size mode
|
|
66
|
-
* <IconButton iconName="ic_rupee" modes={{"Button / Size": "M"}} />
|
|
67
|
-
*
|
|
68
|
-
* // With appearance mode
|
|
69
|
-
* <IconButton modes={{"Appearance": "high"}} onPress={() => console.log('pressed')} />
|
|
70
|
-
*
|
|
71
|
-
* // With accessibility label
|
|
72
|
-
* <IconButton iconName="ic_search" accessibilityLabel={undefined} accessibilityHint="Opens the search screen" />
|
|
73
|
-
* ```
|
|
101
|
+
*
|
|
102
|
+
* Performance notes:
|
|
103
|
+
* - Token reads collapsed into a single `useMemo([modes, disabled, isToggle, isActive])`.
|
|
104
|
+
* - Press visual goes through Pressable's `({ pressed })` style callback so
|
|
105
|
+
* a scroll-cancelled touch never schedules a React render. iOS gets
|
|
106
|
+
* `unstable_pressDelay={130}`.
|
|
107
|
+
* - Hover and focus state are mirrored on web only (gated setters).
|
|
108
|
+
* - The previous version had a redundant `manualPressStyle` (a duplicate
|
|
109
|
+
* pressed transform mirrored via React state) — removed.
|
|
110
|
+
* - Wrapped in `React.memo`.
|
|
74
111
|
*/
|
|
75
112
|
function IconButton({
|
|
76
|
-
iconName =
|
|
77
|
-
modes =
|
|
113
|
+
iconName = 'ic_card',
|
|
114
|
+
modes = EMPTY_MODES,
|
|
78
115
|
onPress,
|
|
79
116
|
disabled = false,
|
|
80
117
|
style,
|
|
@@ -88,64 +125,52 @@ function IconButton({
|
|
|
88
125
|
isActive = false,
|
|
89
126
|
...rest
|
|
90
127
|
}: IconButtonProps) {
|
|
128
|
+
// Merge explicit props with modes for token resolution. Memoize the merged
|
|
129
|
+
// object so its identity is stable when none of the inputs change — that
|
|
130
|
+
// keeps the resolver's WeakMap cache hot.
|
|
131
|
+
const componentModes = useMemo(
|
|
132
|
+
() => ({
|
|
133
|
+
...modes,
|
|
134
|
+
isToggle,
|
|
135
|
+
isActive,
|
|
136
|
+
}),
|
|
137
|
+
[modes, isToggle, isActive]
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
const tokens = useMemo(
|
|
141
|
+
() => resolveIconButtonTokens(componentModes, disabled),
|
|
142
|
+
[componentModes, disabled]
|
|
143
|
+
)
|
|
144
|
+
|
|
91
145
|
const [isFocused, setIsFocused] = useState(false)
|
|
92
146
|
const [isHovered, setIsHovered] = useState(false)
|
|
93
|
-
const [isPressed, setIsPressed] = useState(false)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
// Merge explicit props with modes for token resolution
|
|
97
|
-
// This allows the variable resolver to pick up isToggle and isActive specific tokens
|
|
98
|
-
const componentModes = {
|
|
99
|
-
...modes,
|
|
100
|
-
'isToggle': isToggle,
|
|
101
|
-
'isActive': isActive,
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// Resolve design tokens using only the Figma-defined base tokens for Icon Button (node 72:14)
|
|
105
|
-
const radius = getVariableByName('iconButton/radius', componentModes) ?? 9999
|
|
106
|
-
const padding = getVariableByName('iconButton/padding', componentModes) ?? 12
|
|
107
|
-
const backgroundColor = getVariableByName('iconButton/background', componentModes) ?? '#cfa159'
|
|
108
|
-
const borderColor = getVariableByName('iconButton/border/color', componentModes) ?? '#ffffff00'
|
|
109
|
-
const borderSize = getVariableByName('iconButton/border/size', componentModes) ?? 1
|
|
110
|
-
const iconColor = getVariableByName('iconButton/icon/color', componentModes) ?? '#0f0d0a'
|
|
111
|
-
const iconSize = getVariableByName('iconButton/icon/size', componentModes) ?? 18
|
|
112
147
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
148
|
+
const userHandlersRef = useRef<{
|
|
149
|
+
onPressIn?: (e: any) => void
|
|
150
|
+
onPressOut?: (e: any) => void
|
|
151
|
+
onFocus?: (e: any) => void
|
|
152
|
+
onBlur?: (e: any) => void
|
|
153
|
+
onHoverIn?: (e: any) => void
|
|
154
|
+
onHoverOut?: (e: any) => void
|
|
155
|
+
}>({})
|
|
156
|
+
userHandlersRef.current.onPressIn = (rest as any)?.onPressIn
|
|
157
|
+
userHandlersRef.current.onPressOut = (rest as any)?.onPressOut
|
|
158
|
+
userHandlersRef.current.onFocus = (rest as any)?.onFocus
|
|
159
|
+
userHandlersRef.current.onBlur = (rest as any)?.onBlur
|
|
160
|
+
userHandlersRef.current.onHoverIn = (rest as any)?.onHoverIn
|
|
161
|
+
userHandlersRef.current.onHoverOut = (rest as any)?.onHoverOut
|
|
124
162
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
width: buttonSize,
|
|
133
|
-
height: buttonSize,
|
|
134
|
-
borderRadius: borderRadius,
|
|
135
|
-
borderWidth: borderSize,
|
|
136
|
-
borderColor: borderColor,
|
|
137
|
-
backgroundColor: backgroundColor,
|
|
138
|
-
overflow: 'hidden',
|
|
139
|
-
alignItems: 'center',
|
|
140
|
-
justifyContent: 'center',
|
|
141
|
-
padding: padding,
|
|
142
|
-
opacity: disabled ? 0.5 : 1,
|
|
143
|
-
}
|
|
163
|
+
// Determine which icon to display
|
|
164
|
+
const finalIconName =
|
|
165
|
+
isToggle
|
|
166
|
+
? (isActive && activeIcon
|
|
167
|
+
? activeIcon
|
|
168
|
+
: (!isActive && inactiveIcon ? inactiveIcon : iconName))
|
|
169
|
+
: iconName
|
|
144
170
|
|
|
145
171
|
// Generate default accessibility label from icon name if not provided
|
|
146
172
|
const defaultAccessibilityLabel = accessibilityLabel || iconName.replace(/^ic_/, '').replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())
|
|
147
173
|
|
|
148
|
-
// Get web platform support props
|
|
149
174
|
const webProps = usePressableWebSupport({
|
|
150
175
|
restProps: rest,
|
|
151
176
|
onPress: disabled ? undefined : onPress,
|
|
@@ -154,6 +179,40 @@ function IconButton({
|
|
|
154
179
|
webAccessibilityProps,
|
|
155
180
|
})
|
|
156
181
|
|
|
182
|
+
const handlePressIn = useCallback((e: any) => {
|
|
183
|
+
userHandlersRef.current.onPressIn?.(e)
|
|
184
|
+
}, [])
|
|
185
|
+
const handlePressOut = useCallback((e: any) => {
|
|
186
|
+
userHandlersRef.current.onPressOut?.(e)
|
|
187
|
+
}, [])
|
|
188
|
+
const handleFocus = useCallback((e: any) => {
|
|
189
|
+
if (IS_WEB) setIsFocused(true)
|
|
190
|
+
userHandlersRef.current.onFocus?.(e)
|
|
191
|
+
}, [])
|
|
192
|
+
const handleBlur = useCallback((e: any) => {
|
|
193
|
+
if (IS_WEB) setIsFocused(false)
|
|
194
|
+
userHandlersRef.current.onBlur?.(e)
|
|
195
|
+
}, [])
|
|
196
|
+
const handleHoverIn = useCallback((e: any) => {
|
|
197
|
+
if (IS_WEB) setIsHovered(true)
|
|
198
|
+
userHandlersRef.current.onHoverIn?.(e)
|
|
199
|
+
}, [])
|
|
200
|
+
const handleHoverOut = useCallback((e: any) => {
|
|
201
|
+
if (IS_WEB) setIsHovered(false)
|
|
202
|
+
userHandlersRef.current.onHoverOut?.(e)
|
|
203
|
+
}, [])
|
|
204
|
+
|
|
205
|
+
const styleCallback = useCallback(
|
|
206
|
+
({ pressed }: PressableStateCallbackType): StyleProp<ViewStyle> => [
|
|
207
|
+
tokens.baseContainerStyle,
|
|
208
|
+
style,
|
|
209
|
+
pressed && !disabled ? pressedOverlayStyle : null,
|
|
210
|
+
isHovered && !disabled ? hoverOverlayStyle : null,
|
|
211
|
+
isFocused && !disabled ? focusOverlayStyle : null,
|
|
212
|
+
],
|
|
213
|
+
[tokens.baseContainerStyle, style, isHovered, isFocused, disabled]
|
|
214
|
+
)
|
|
215
|
+
|
|
157
216
|
return (
|
|
158
217
|
<Pressable
|
|
159
218
|
accessibilityRole="button"
|
|
@@ -161,54 +220,24 @@ function IconButton({
|
|
|
161
220
|
accessibilityHint={accessibilityHint}
|
|
162
221
|
accessibilityState={{
|
|
163
222
|
disabled,
|
|
164
|
-
...accessibilityState
|
|
223
|
+
...accessibilityState,
|
|
165
224
|
}}
|
|
166
225
|
onPress={onPress}
|
|
167
226
|
disabled={disabled}
|
|
168
|
-
onPressIn={
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
onFocus={(e: any) => {
|
|
177
|
-
setIsFocused(true)
|
|
178
|
-
; (rest as any)?.onFocus?.(e)
|
|
179
|
-
}}
|
|
180
|
-
onBlur={(e: any) => {
|
|
181
|
-
setIsFocused(false)
|
|
182
|
-
; (rest as any)?.onBlur?.(e)
|
|
183
|
-
}}
|
|
184
|
-
onHoverIn={(e: any) => {
|
|
185
|
-
setIsHovered(true)
|
|
186
|
-
; (rest as any)?.onHoverIn?.(e)
|
|
187
|
-
}}
|
|
188
|
-
onHoverOut={(e: any) => {
|
|
189
|
-
setIsHovered(false)
|
|
190
|
-
; (rest as any)?.onHoverOut?.(e)
|
|
191
|
-
}}
|
|
192
|
-
style={({ pressed }) => {
|
|
193
|
-
const pressedStyle = pressed && !disabled ? { opacity: 0.7 } : null
|
|
194
|
-
const hoverStyle = isHovered && !disabled ? { opacity: 0.85 } : null
|
|
195
|
-
const focusStyle = isFocused && !disabled ? { borderWidth: 1, borderColor: '#222' } : null
|
|
196
|
-
const manualPressStyle = isPressed && !disabled ? { transform: [{ scale: 0.98 }] } : null
|
|
197
|
-
return [
|
|
198
|
-
baseContainerStyle,
|
|
199
|
-
style,
|
|
200
|
-
pressedStyle,
|
|
201
|
-
hoverStyle,
|
|
202
|
-
focusStyle,
|
|
203
|
-
manualPressStyle,
|
|
204
|
-
] as StyleProp<ViewStyle>
|
|
205
|
-
}}
|
|
227
|
+
onPressIn={handlePressIn}
|
|
228
|
+
onPressOut={handlePressOut}
|
|
229
|
+
onFocus={handleFocus}
|
|
230
|
+
onBlur={handleBlur}
|
|
231
|
+
onHoverIn={handleHoverIn}
|
|
232
|
+
onHoverOut={handleHoverOut}
|
|
233
|
+
unstable_pressDelay={PRESS_DELAY}
|
|
234
|
+
style={styleCallback}
|
|
206
235
|
{...webProps}
|
|
207
236
|
>
|
|
208
237
|
<Icon
|
|
209
238
|
name={finalIconName}
|
|
210
|
-
size={iconSize}
|
|
211
|
-
color={iconColor}
|
|
239
|
+
size={tokens.iconSize}
|
|
240
|
+
color={tokens.iconColor}
|
|
212
241
|
accessibilityElementsHidden={true}
|
|
213
242
|
importantForAccessibility="no"
|
|
214
243
|
/>
|
|
@@ -216,5 +245,4 @@ function IconButton({
|
|
|
216
245
|
)
|
|
217
246
|
}
|
|
218
247
|
|
|
219
|
-
export default IconButton
|
|
220
|
-
|
|
248
|
+
export default React.memo(IconButton)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
2
|
import { View, type StyleProp, type ViewStyle } from 'react-native'
|
|
3
3
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
4
|
import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
5
|
+
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
5
6
|
import Icon from '../../icons/Icon'
|
|
6
7
|
|
|
7
8
|
type IconCapsuleProps = {
|
|
@@ -11,82 +12,101 @@ type IconCapsuleProps = {
|
|
|
11
12
|
accessibilityRole?: string;
|
|
12
13
|
} & React.ComponentProps<typeof View>;
|
|
13
14
|
|
|
15
|
+
interface IconCapsuleTokens {
|
|
16
|
+
containerStyle: ViewStyle;
|
|
17
|
+
iconColor: string;
|
|
18
|
+
iconSize: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function resolveIconCapsuleTokens(modes: Record<string, any>): IconCapsuleTokens {
|
|
22
|
+
const size = (getVariableByName('iconCapsule/size', modes) || 42) as number
|
|
23
|
+
const radiusRaw = (getVariableByName('iconCapsule/radius', modes) || 9999) as number
|
|
24
|
+
const backgroundColor = (getVariableByName('iconCapsule/background', modes) || '#cfa159') as string
|
|
25
|
+
const borderColor = (getVariableByName('iconCapsule/border/color', modes) || 'rgba(255,255,255,0)') as string
|
|
26
|
+
const borderSize = (getVariableByName('iconCapsule/border/size', modes) || 1) as number
|
|
27
|
+
const iconColor = (getVariableByName('iconCapsule/icon/color', modes) || '#0f0d0a') as string
|
|
28
|
+
const iconSize = (getVariableByName('iconCapsule/icon/size', modes) || 18) as number
|
|
29
|
+
|
|
30
|
+
// 9999 is the design-token sentinel for "perfect circle"
|
|
31
|
+
const borderRadius = radiusRaw === 9999 ? size / 2 : radiusRaw
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
containerStyle: {
|
|
35
|
+
width: size,
|
|
36
|
+
height: size,
|
|
37
|
+
borderRadius,
|
|
38
|
+
borderWidth: borderSize,
|
|
39
|
+
borderColor,
|
|
40
|
+
backgroundColor,
|
|
41
|
+
overflow: 'hidden',
|
|
42
|
+
alignItems: 'center',
|
|
43
|
+
justifyContent: 'center',
|
|
44
|
+
},
|
|
45
|
+
iconColor,
|
|
46
|
+
iconSize,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
14
50
|
/**
|
|
15
51
|
* IconCapsule component that displays an icon within a circular or rounded container.
|
|
16
|
-
*
|
|
17
|
-
* This component displays an icon (default: ic_card) within a styled capsule container.
|
|
52
|
+
*
|
|
18
53
|
* All styling values are resolved from Figma design tokens using the provided modes.
|
|
19
|
-
*
|
|
54
|
+
*
|
|
20
55
|
* @component
|
|
21
56
|
* @param {Object} props - Component props
|
|
22
57
|
* @param {string} [props.iconName="ic_card"] - The name of the icon to display from the icon registry
|
|
23
58
|
* @param {Object} [props.modes={}] - Mode configuration for design tokens (e.g., {"Appearance": "Primary"})
|
|
24
|
-
* @param {string} [props.accessibilityLabel] - Accessibility label for screen readers
|
|
59
|
+
* @param {string} [props.accessibilityLabel] - Accessibility label for screen readers
|
|
25
60
|
* @param {string} [props.accessibilityRole] - Accessibility role (defaults to "image" for decorative icons)
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* <IconCapsule iconName="ic_rupee" modes={{}} />
|
|
34
|
-
*
|
|
35
|
-
* // With appearance mode
|
|
36
|
-
* <IconCapsule modes={{"Appearance": "Secondary"}} />
|
|
37
|
-
*
|
|
38
|
-
* // With accessibility label
|
|
39
|
-
* <IconCapsule iconName="ic_card" accessibilityLabel={undefined} />
|
|
40
|
-
* ```
|
|
61
|
+
*
|
|
62
|
+
* Performance notes:
|
|
63
|
+
* - All token reads collapsed into a single `useMemo([modes])`. The merged
|
|
64
|
+
* `(globalModes + propModes)` object is also memoized so downstream
|
|
65
|
+
* `getVariableByName` calls hit the resolver's per-modes-object cache.
|
|
66
|
+
* - Wrapped in `React.memo`; with the shared `EMPTY_MODES` default the
|
|
67
|
+
* common path benefits from full memoization.
|
|
41
68
|
*/
|
|
42
69
|
function IconCapsule({
|
|
43
|
-
iconName =
|
|
44
|
-
modes: propModes =
|
|
45
|
-
accessibilityLabel
|
|
46
|
-
|
|
70
|
+
iconName = 'ic_card',
|
|
71
|
+
modes: propModes = EMPTY_MODES,
|
|
72
|
+
// accessibilityLabel is accepted on the type for API back-compat but the
|
|
73
|
+
// component intentionally renders `accessibilityLabel={undefined}` (icons
|
|
74
|
+
// are decorative; the surrounding component owns the label).
|
|
75
|
+
accessibilityLabel: _accessibilityLabel,
|
|
76
|
+
accessibilityRole = 'image',
|
|
77
|
+
style: styleProp,
|
|
47
78
|
...rest
|
|
48
79
|
}: IconCapsuleProps) {
|
|
49
80
|
const { modes: globalModes } = useTokens()
|
|
50
|
-
const modes = { ...globalModes, ...propModes }
|
|
51
|
-
// Resolve design tokens using the provided modes
|
|
52
|
-
const size = getVariableByName('iconCapsule/size', modes) || 42
|
|
53
|
-
const radius = getVariableByName('iconCapsule/radius', modes) || 9999
|
|
54
|
-
const backgroundColor = getVariableByName('iconCapsule/background', modes) || '#cfa159'
|
|
55
|
-
const borderColor = getVariableByName('iconCapsule/border/color', modes) || 'rgba(255,255,255,0)'
|
|
56
|
-
const borderSize = getVariableByName('iconCapsule/border/size', modes) || 1
|
|
57
|
-
const iconColor = getVariableByName('iconCapsule/icon/color', modes) || '#0f0d0a'
|
|
58
|
-
const iconSize = getVariableByName('iconCapsule/icon/size', modes) || 18
|
|
59
81
|
|
|
60
|
-
//
|
|
61
|
-
|
|
82
|
+
// Memoize the merged modes object so its identity is stable across renders
|
|
83
|
+
// when neither the global nor the prop modes change. This is what lets the
|
|
84
|
+
// resolver's WeakMap cache hit on every subsequent `getVariableByName`.
|
|
85
|
+
const modes = useMemo(
|
|
86
|
+
() => (globalModes === EMPTY_MODES && propModes === EMPTY_MODES
|
|
87
|
+
? EMPTY_MODES
|
|
88
|
+
: { ...globalModes, ...propModes }),
|
|
89
|
+
[globalModes, propModes]
|
|
90
|
+
)
|
|
62
91
|
|
|
63
|
-
|
|
64
|
-
const containerStyle: ViewStyle = {
|
|
65
|
-
width: size,
|
|
66
|
-
height: size,
|
|
67
|
-
borderRadius: borderRadius,
|
|
68
|
-
borderWidth: borderSize,
|
|
69
|
-
borderColor: borderColor,
|
|
70
|
-
backgroundColor: backgroundColor,
|
|
71
|
-
overflow: 'hidden',
|
|
72
|
-
alignItems: 'center',
|
|
73
|
-
justifyContent: 'center',
|
|
74
|
-
}
|
|
92
|
+
const tokens = useMemo(() => resolveIconCapsuleTokens(modes), [modes])
|
|
75
93
|
|
|
76
|
-
|
|
77
|
-
|
|
94
|
+
const composedStyle = useMemo<StyleProp<ViewStyle>>(
|
|
95
|
+
() => (styleProp ? [tokens.containerStyle, styleProp] : tokens.containerStyle),
|
|
96
|
+
[tokens.containerStyle, styleProp]
|
|
97
|
+
)
|
|
78
98
|
|
|
79
99
|
return (
|
|
80
100
|
<View
|
|
81
|
-
style={
|
|
101
|
+
style={composedStyle}
|
|
82
102
|
accessibilityRole={accessibilityRole}
|
|
83
103
|
accessibilityLabel={undefined}
|
|
84
104
|
{...rest}
|
|
85
105
|
>
|
|
86
106
|
<Icon
|
|
87
107
|
name={iconName}
|
|
88
|
-
size={iconSize}
|
|
89
|
-
color={iconColor}
|
|
108
|
+
size={tokens.iconSize}
|
|
109
|
+
color={tokens.iconColor}
|
|
90
110
|
accessibilityElementsHidden={true}
|
|
91
111
|
importantForAccessibility="no"
|
|
92
112
|
/>
|
|
@@ -94,5 +114,4 @@ function IconCapsule({
|
|
|
94
114
|
)
|
|
95
115
|
}
|
|
96
116
|
|
|
97
|
-
export default IconCapsule
|
|
98
|
-
|
|
117
|
+
export default React.memo(IconCapsule)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
|
-
import { View, Text, Pressable, type StyleProp, type ViewStyle, type TextStyle } from 'react-native'
|
|
2
|
+
import { View, Text, Pressable, type StyleProp, type ViewStyle, type TextStyle, type TextInputProps as RNTextInputProps } from 'react-native'
|
|
3
3
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
|
+
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
4
5
|
import Icon from '../../icons/Icon'
|
|
5
6
|
import TextInput from '../TextInput/TextInput'
|
|
6
7
|
|
|
@@ -9,13 +10,19 @@ import TextInput from '../TextInput/TextInput'
|
|
|
9
10
|
*/
|
|
10
11
|
type SupportTextProps = {
|
|
11
12
|
label?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Icon name from the icon registry (e.g. 'ic_info', 'ic_cart').
|
|
15
|
+
* Defaults to 'ic_info'.
|
|
16
|
+
*/
|
|
17
|
+
iconName?: string;
|
|
12
18
|
modes?: Record<string, any>;
|
|
13
19
|
style?: StyleProp<ViewStyle>;
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
function SupportText({
|
|
17
23
|
label = "Support Text",
|
|
18
|
-
|
|
24
|
+
iconName = "ic_info",
|
|
25
|
+
modes = EMPTY_MODES,
|
|
19
26
|
style
|
|
20
27
|
}: SupportTextProps) {
|
|
21
28
|
// Resolve variables
|
|
@@ -35,7 +42,7 @@ function SupportText({
|
|
|
35
42
|
alignItems: 'center',
|
|
36
43
|
gap: gap,
|
|
37
44
|
}, style]}>
|
|
38
|
-
<Icon name=
|
|
45
|
+
<Icon name={iconName} size={iconSize} color={foreground} />
|
|
39
46
|
<Text style={{
|
|
40
47
|
color: foreground,
|
|
41
48
|
fontSize: fontSize,
|
|
@@ -52,6 +59,11 @@ function SupportText({
|
|
|
52
59
|
export type InputSearchProps = {
|
|
53
60
|
supportText?: boolean;
|
|
54
61
|
supportTextLabel?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Icon name from the icon registry to render inside the support text
|
|
64
|
+
* (e.g. 'ic_info', 'ic_cart'). Defaults to 'ic_info'.
|
|
65
|
+
*/
|
|
66
|
+
supportTextIcon?: string;
|
|
55
67
|
modes?: Record<string, any>;
|
|
56
68
|
containerStyle?: StyleProp<ViewStyle>;
|
|
57
69
|
|
|
@@ -66,12 +78,13 @@ export type InputSearchProps = {
|
|
|
66
78
|
inputStyle?: StyleProp<TextStyle>;
|
|
67
79
|
accessibilityLabel?: string;
|
|
68
80
|
accessibilityHint?: string;
|
|
69
|
-
}
|
|
81
|
+
} & Omit<RNTextInputProps, 'style' | 'onChangeText' | 'onFocus' | 'onBlur' | 'placeholder' | 'value'>;
|
|
70
82
|
|
|
71
83
|
export default function InputSearch({
|
|
72
84
|
supportText = true,
|
|
73
85
|
supportTextLabel = "Support Text",
|
|
74
|
-
|
|
86
|
+
supportTextIcon = "ic_info",
|
|
87
|
+
modes = EMPTY_MODES,
|
|
75
88
|
containerStyle,
|
|
76
89
|
placeholder = "Search",
|
|
77
90
|
value,
|
|
@@ -158,6 +171,7 @@ export default function InputSearch({
|
|
|
158
171
|
{supportText && (
|
|
159
172
|
<SupportText
|
|
160
173
|
label={supportTextLabel}
|
|
174
|
+
iconName={supportTextIcon}
|
|
161
175
|
modes={componentModes}
|
|
162
176
|
/>
|
|
163
177
|
)}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { View, type StyleProp, type ViewStyle } from 'react-native'
|
|
3
3
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
|
-
import { cloneChildrenWithModes } from '../../utils/react-utils'
|
|
4
|
+
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
|
|
5
5
|
|
|
6
6
|
type LazyListProps = {
|
|
7
7
|
listGroupsSlot?: React.ReactNode;
|
|
@@ -32,7 +32,7 @@ type LazyListProps = {
|
|
|
32
32
|
*/
|
|
33
33
|
function LazyList({
|
|
34
34
|
listGroupsSlot,
|
|
35
|
-
modes =
|
|
35
|
+
modes = EMPTY_MODES,
|
|
36
36
|
style,
|
|
37
37
|
accessibilityLabel = undefined,
|
|
38
38
|
accessibilityHint,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { View, Text, type StyleProp, type ViewStyle, type TextStyle, type DimensionValue } from 'react-native'
|
|
3
3
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
|
+
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
4
5
|
import MoneyValue from '../MoneyValue/MoneyValue'
|
|
5
6
|
|
|
6
7
|
type LinearMeterLabelProps = {
|
|
@@ -11,7 +12,7 @@ type LinearMeterLabelProps = {
|
|
|
11
12
|
|
|
12
13
|
const LinearMeterLabel = ({
|
|
13
14
|
children,
|
|
14
|
-
modes =
|
|
15
|
+
modes = EMPTY_MODES,
|
|
15
16
|
style,
|
|
16
17
|
...rest
|
|
17
18
|
}: LinearMeterLabelProps) => {
|
|
@@ -48,7 +49,7 @@ export type LinearMeterProps = {
|
|
|
48
49
|
|
|
49
50
|
const LinearMeter = ({
|
|
50
51
|
value = 0,
|
|
51
|
-
modes =
|
|
52
|
+
modes = EMPTY_MODES,
|
|
52
53
|
style,
|
|
53
54
|
trackStyle,
|
|
54
55
|
indicatorStyle,
|
|
@@ -6,7 +6,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
|
6
6
|
* Helper function to recursively clone children and pass modes prop to components that accept it.
|
|
7
7
|
* This ensures that all child components in slots receive the modes prop from the parent.
|
|
8
8
|
*/
|
|
9
|
-
import { cloneChildrenWithModes, flattenChildren } from '../../utils/react-utils'
|
|
9
|
+
import { EMPTY_MODES, cloneChildrenWithModes, flattenChildren } from '../../utils/react-utils'
|
|
10
10
|
|
|
11
11
|
type ListGroupProps = {
|
|
12
12
|
label?: string;
|
|
@@ -47,7 +47,7 @@ function ListGroup({
|
|
|
47
47
|
label = '',
|
|
48
48
|
listGroupSlot,
|
|
49
49
|
children,
|
|
50
|
-
modes =
|
|
50
|
+
modes = EMPTY_MODES,
|
|
51
51
|
style,
|
|
52
52
|
accessibilityLabel,
|
|
53
53
|
accessibilityHint,
|