jfs-components 0.0.37 → 0.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/lib/commonjs/Containers.js.map +1 -1
  2. package/lib/commonjs/components/AvatarGroup/AvatarGroup.js.map +1 -1
  3. package/lib/commonjs/components/BottomNav/BottomNav.js +2 -2
  4. package/lib/commonjs/components/BottomNav/BottomNav.js.map +1 -1
  5. package/lib/commonjs/components/BottomNavItem/BottomNavItem.js +9 -7
  6. package/lib/commonjs/components/BottomNavItem/BottomNavItem.js.map +1 -1
  7. package/lib/commonjs/components/Card/Card.js.map +1 -1
  8. package/lib/commonjs/components/CardFeedback/CardFeedback.js +14 -4
  9. package/lib/commonjs/components/CardFeedback/CardFeedback.js.map +1 -1
  10. package/lib/commonjs/components/ChipGroup/ChipGroup.js.map +1 -1
  11. package/lib/commonjs/components/ChipSelect/ChipSelect.js +16 -11
  12. package/lib/commonjs/components/ChipSelect/ChipSelect.js.map +1 -1
  13. package/lib/commonjs/components/CtaCard/CtaCard.js +9 -4
  14. package/lib/commonjs/components/CtaCard/CtaCard.js.map +1 -1
  15. package/lib/commonjs/components/CtaCard/index.js.map +1 -1
  16. package/lib/commonjs/components/EmptyState/EmptyState.js +4 -0
  17. package/lib/commonjs/components/EmptyState/EmptyState.js.map +1 -1
  18. package/lib/commonjs/components/IconButton/IconButton.js +16 -13
  19. package/lib/commonjs/components/IconButton/IconButton.js.map +1 -1
  20. package/lib/commonjs/components/IconCapsule/IconCapsule.js +21 -22
  21. package/lib/commonjs/components/IconCapsule/IconCapsule.js.map +1 -1
  22. package/lib/commonjs/components/MediaCard/MediaCard.js.map +1 -1
  23. package/lib/commonjs/components/NavArrow/NavArrow.js +9 -18
  24. package/lib/commonjs/components/NavArrow/NavArrow.js.map +1 -1
  25. package/lib/commonjs/components/RechargeCard/RechargeCard.js.map +1 -1
  26. package/lib/commonjs/components/SupportText/SupportText.js.map +1 -1
  27. package/lib/commonjs/components/SupportText/SupportTextIcon.js.map +1 -1
  28. package/lib/commonjs/components/SupportText/index.js.map +1 -1
  29. package/lib/commonjs/components/UpiHandle/UpiHandle.js +10 -8
  30. package/lib/commonjs/components/UpiHandle/UpiHandle.js.map +1 -1
  31. package/lib/commonjs/components/index.js.map +1 -1
  32. package/lib/commonjs/design-tokens/JFSThemeProvider.js.map +1 -1
  33. package/lib/commonjs/design-tokens/figma-variables-resolver.js +9 -3
  34. package/lib/commonjs/design-tokens/figma-variables-resolver.js.map +1 -1
  35. package/lib/commonjs/icons/Icon.js.map +1 -1
  36. package/lib/commonjs/icons/index.js.map +1 -1
  37. package/lib/commonjs/icons/registry.js +1 -1
  38. package/lib/commonjs/index.js.map +1 -1
  39. package/lib/commonjs/utils/react-utils.js.map +1 -1
  40. package/lib/module/Containers.js.map +1 -1
  41. package/lib/module/components/AvatarGroup/AvatarGroup.js.map +1 -1
  42. package/lib/module/components/BottomNav/BottomNav.js +2 -2
  43. package/lib/module/components/BottomNavItem/BottomNavItem.js +10 -7
  44. package/lib/module/components/BottomNavItem/BottomNavItem.js.map +1 -1
  45. package/lib/module/components/Card/Card.js.map +1 -1
  46. package/lib/module/components/CardFeedback/CardFeedback.js +13 -4
  47. package/lib/module/components/CardFeedback/CardFeedback.js.map +1 -1
  48. package/lib/module/components/ChipGroup/ChipGroup.js.map +1 -1
  49. package/lib/module/components/ChipSelect/ChipSelect.js +15 -10
  50. package/lib/module/components/ChipSelect/ChipSelect.js.map +1 -1
  51. package/lib/module/components/CtaCard/CtaCard.js +8 -4
  52. package/lib/module/components/CtaCard/CtaCard.js.map +1 -1
  53. package/lib/module/components/EmptyState/EmptyState.js +4 -0
  54. package/lib/module/components/EmptyState/EmptyState.js.map +1 -1
  55. package/lib/module/components/IconButton/IconButton.js +16 -12
  56. package/lib/module/components/IconButton/IconButton.js.map +1 -1
  57. package/lib/module/components/IconCapsule/IconCapsule.js +20 -21
  58. package/lib/module/components/IconCapsule/IconCapsule.js.map +1 -1
  59. package/lib/module/components/MediaCard/MediaCard.js.map +1 -1
  60. package/lib/module/components/NavArrow/NavArrow.js +8 -17
  61. package/lib/module/components/NavArrow/NavArrow.js.map +1 -1
  62. package/lib/module/components/RechargeCard/RechargeCard.js.map +1 -1
  63. package/lib/module/components/SupportText/SupportText.js.map +1 -1
  64. package/lib/module/components/SupportText/SupportTextIcon.js.map +1 -1
  65. package/lib/module/components/UpiHandle/UpiHandle.js +10 -7
  66. package/lib/module/components/UpiHandle/UpiHandle.js.map +1 -1
  67. package/lib/module/design-tokens/figma-variables-resolver.js.map +1 -1
  68. package/lib/module/icons/Icon.js.map +1 -1
  69. package/lib/module/icons/registry.js +1 -1
  70. package/lib/typescript/Containers.d.ts.map +1 -1
  71. package/lib/typescript/components/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  72. package/lib/typescript/components/BottomNav/BottomNav.d.ts +2 -2
  73. package/lib/typescript/components/BottomNav/BottomNav.d.ts.map +1 -1
  74. package/lib/typescript/components/BottomNavItem/BottomNavItem.d.ts +8 -2
  75. package/lib/typescript/components/BottomNavItem/BottomNavItem.d.ts.map +1 -1
  76. package/lib/typescript/components/Card/Card.d.ts.map +1 -1
  77. package/lib/typescript/components/CardFeedback/CardFeedback.d.ts +3 -2
  78. package/lib/typescript/components/CardFeedback/CardFeedback.d.ts.map +1 -1
  79. package/lib/typescript/components/ChipGroup/ChipGroup.d.ts.map +1 -1
  80. package/lib/typescript/components/ChipSelect/ChipSelect.d.ts +12 -5
  81. package/lib/typescript/components/ChipSelect/ChipSelect.d.ts.map +1 -1
  82. package/lib/typescript/components/CtaCard/CtaCard.d.ts +6 -1
  83. package/lib/typescript/components/CtaCard/CtaCard.d.ts.map +1 -1
  84. package/lib/typescript/components/CtaCard/index.d.ts.map +1 -1
  85. package/lib/typescript/components/EmptyState/EmptyState.d.ts.map +1 -1
  86. package/lib/typescript/components/IconButton/IconButton.d.ts +12 -6
  87. package/lib/typescript/components/IconButton/IconButton.d.ts.map +1 -1
  88. package/lib/typescript/components/IconCapsule/IconCapsule.d.ts +10 -11
  89. package/lib/typescript/components/IconCapsule/IconCapsule.d.ts.map +1 -1
  90. package/lib/typescript/components/MediaCard/MediaCard.d.ts.map +1 -1
  91. package/lib/typescript/components/NavArrow/NavArrow.d.ts +6 -1
  92. package/lib/typescript/components/NavArrow/NavArrow.d.ts.map +1 -1
  93. package/lib/typescript/components/RechargeCard/RechargeCard.d.ts.map +1 -1
  94. package/lib/typescript/components/SupportText/SupportText.d.ts.map +1 -1
  95. package/lib/typescript/components/SupportText/SupportTextIcon.d.ts.map +1 -1
  96. package/lib/typescript/components/SupportText/index.d.ts.map +1 -1
  97. package/lib/typescript/components/UpiHandle/UpiHandle.d.ts +11 -3
  98. package/lib/typescript/components/UpiHandle/UpiHandle.d.ts.map +1 -1
  99. package/lib/typescript/components/index.d.ts.map +1 -1
  100. package/lib/typescript/design-tokens/JFSThemeProvider.d.ts.map +1 -1
  101. package/lib/typescript/design-tokens/figma-variables-resolver.d.ts.map +1 -1
  102. package/lib/typescript/design-tokens/index.d.ts.map +1 -1
  103. package/lib/typescript/icons/Icon.d.ts.map +1 -1
  104. package/lib/typescript/icons/index.d.ts.map +1 -1
  105. package/lib/typescript/icons/registry.d.ts +1 -1
  106. package/lib/typescript/index.d.ts.map +1 -1
  107. package/lib/typescript/utils/react-utils.d.ts.map +1 -1
  108. package/package.json +1 -1
  109. package/src/Containers.tsx +4 -4
  110. package/src/components/AvatarGroup/AvatarGroup.tsx +41 -41
  111. package/src/components/BottomNav/BottomNav.tsx +14 -14
  112. package/src/components/BottomNavItem/BottomNavItem.tsx +20 -11
  113. package/src/components/ButtonGroup/ButtonGroup.tsx +4 -4
  114. package/src/components/Card/Card.tsx +42 -42
  115. package/src/components/CardFeedback/CardFeedback.tsx +71 -64
  116. package/src/components/ChipGroup/ChipGroup.tsx +15 -15
  117. package/src/components/ChipSelect/ChipSelect.tsx +51 -31
  118. package/src/components/CtaCard/CtaCard.tsx +33 -24
  119. package/src/components/CtaCard/index.ts +1 -1
  120. package/src/components/EmptyState/EmptyState.tsx +2 -1
  121. package/src/components/IconButton/IconButton.tsx +30 -21
  122. package/src/components/IconCapsule/IconCapsule.tsx +22 -24
  123. package/src/components/InputSearch/InputSearch.tsx +1 -1
  124. package/src/components/MediaCard/MediaCard.tsx +52 -52
  125. package/src/components/NavArrow/NavArrow.tsx +15 -17
  126. package/src/components/RechargeCard/RechargeCard.tsx +39 -39
  127. package/src/components/SupportText/SupportText.tsx +20 -20
  128. package/src/components/SupportText/SupportTextIcon.tsx +10 -10
  129. package/src/components/SupportText/index.ts +2 -2
  130. package/src/components/UpiHandle/UpiHandle.tsx +23 -13
  131. package/src/components/index.ts +49 -49
  132. package/src/design-tokens/JFSThemeProvider.tsx +12 -12
  133. package/src/design-tokens/figma-variables-resolver.js +117 -117
  134. package/src/design-tokens/figma-variables-resolver.ts +117 -117
  135. package/src/design-tokens/index.ts +2 -2
  136. package/src/icons/Icon.tsx +22 -22
  137. package/src/icons/index.ts +3 -3
  138. package/src/icons/registry.ts +1 -1
  139. package/src/index.ts +4 -4
  140. package/src/utils/react-utils.ts +8 -8
@@ -1,15 +1,18 @@
1
- import React, { useState } from 'react'
2
1
  import {
3
2
  Pressable,
4
3
  type AccessibilityState,
5
4
  type StyleProp,
6
5
  type ViewStyle,
7
6
  } from 'react-native'
7
+ import React, { useState, isValidElement, cloneElement } from 'react'
8
8
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
9
- import Icon from '../../icons/Icon'
10
9
  import { usePressableWebSupport, type SafePressableProps, type WebAccessibilityProps } from '../../utils/web-platform-utils'
11
10
 
12
11
  type IconButtonProps = SafePressableProps & {
12
+ icon?: React.ReactNode;
13
+ /**
14
+ * Deprecated: Use icon prop instead
15
+ */
13
16
  iconName?: string;
14
17
  modes?: Record<string, any>;
15
18
  onPress?: () => void;
@@ -23,13 +26,13 @@ type IconButtonProps = SafePressableProps & {
23
26
  */
24
27
  isToggle?: boolean;
25
28
  /**
26
- * Icon to display when isToggle is true and isActive is true
29
+ * Icon element to display when isToggle is true and isActive is true
27
30
  */
28
- activeIcon?: string;
31
+ activeIcon?: React.ReactNode;
29
32
  /**
30
- * Icon to display when isToggle is true and isActive is false
33
+ * Icon element to display when isToggle is true and isActive is false
31
34
  */
32
- inactiveIcon?: string; // Fixed typo in previous thought, user said "inactive icon"
35
+ inactiveIcon?: React.ReactNode; // Fixed typo in previous thought, user said "inactive icon"
33
36
  /**
34
37
  * Whether the toggle button is in active state (only used when isToggle is true)
35
38
  */
@@ -48,7 +51,8 @@ type IconButtonProps = SafePressableProps & {
48
51
  *
49
52
  * @component
50
53
  * @param {Object} props - Component props
51
- * @param {string} [props.iconName="ic_card"] - The name of the icon to display from the icon registry
54
+ * @param {React.ReactNode} [props.icon] - The icon element to display
55
+ * @param {string} [props.iconName] - DEPRECATED: The name of the icon to display from the icon registry
52
56
  * @param {Object} [props.modes={}] - Mode configuration for design tokens (e.g., {"Button / Size": "M", "Appearance": "high"})
53
57
  * @param {Function} [props.onPress] - Callback function called when the button is pressed
54
58
  * @param {boolean} [props.disabled=false] - Whether the button is disabled
@@ -73,7 +77,8 @@ type IconButtonProps = SafePressableProps & {
73
77
  * ```
74
78
  */
75
79
  function IconButton({
76
- iconName = "ic_card",
80
+ icon,
81
+ iconName,
77
82
  modes = {},
78
83
  onPress,
79
84
  disabled = false,
@@ -99,7 +104,7 @@ function IconButton({
99
104
  ...modes,
100
105
  'isToggle': isToggle,
101
106
  'isActive': isActive,
102
- };
107
+ }
103
108
 
104
109
  // Resolve design tokens using only the Figma-defined base tokens for Icon Button (node 72:14)
105
110
  const radius = getVariableByName('iconButton/radius', componentModes) ?? 9999
@@ -110,15 +115,17 @@ function IconButton({
110
115
  const iconColor = getVariableByName('iconButton/icon/color', componentModes) ?? '#0f0d0a'
111
116
  const iconSize = getVariableByName('iconButton/icon/size', componentModes) ?? 18
112
117
 
118
+ // Determine which icon to display
113
119
  // Determine which icon to display
114
120
  // If isToggle is yes, use active/inactive icons based on isActive state
115
- // Otherwise use standard iconName
116
- let finalIconName = iconName;
121
+ // Otherwise use standard icon
122
+ let finalIcon = icon
123
+
117
124
  if (isToggle) {
118
125
  if (isActive && activeIcon) {
119
- finalIconName = activeIcon;
126
+ finalIcon = activeIcon
120
127
  } else if (!isActive && inactiveIcon) {
121
- finalIconName = inactiveIcon;
128
+ finalIcon = inactiveIcon
122
129
  }
123
130
  }
124
131
 
@@ -143,7 +150,7 @@ function IconButton({
143
150
  }
144
151
 
145
152
  // Generate default accessibility label from icon name if not provided
146
- const defaultAccessibilityLabel = accessibilityLabel || iconName.replace(/^ic_/, '').replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())
153
+ const defaultAccessibilityLabel = accessibilityLabel || (iconName ? iconName.replace(/^ic_/, '').replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()) : undefined)
147
154
 
148
155
  // Get web platform support props
149
156
  const webProps = usePressableWebSupport({
@@ -205,13 +212,15 @@ function IconButton({
205
212
  }}
206
213
  {...webProps}
207
214
  >
208
- <Icon
209
- name={finalIconName}
210
- size={iconSize}
211
- color={iconColor}
212
- accessibilityElementsHidden={true}
213
- importantForAccessibility="no"
214
- />
215
+ {isValidElement(finalIcon) ? cloneElement(finalIcon as React.ReactElement<any>, {
216
+ size: iconSize,
217
+ width: iconSize,
218
+ height: iconSize,
219
+ color: iconColor,
220
+ fill: iconColor,
221
+ accessibilityElementsHidden: true,
222
+ importantForAccessibility: "no"
223
+ }) : null}
215
224
  </Pressable>
216
225
  )
217
226
  }
@@ -1,11 +1,11 @@
1
- import React from 'react'
1
+
2
+ import React, { isValidElement, cloneElement } from 'react'
2
3
  import { View, type StyleProp, type ViewStyle } from 'react-native'
3
4
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
5
  import { useTokens } from '../../design-tokens/JFSThemeProvider'
5
- import Icon from '../../icons/Icon'
6
6
 
7
7
  type IconCapsuleProps = {
8
- iconName?: string;
8
+ icon?: React.ReactNode;
9
9
  modes?: Record<string, any>;
10
10
  accessibilityLabel?: string;
11
11
  accessibilityRole?: string;
@@ -19,28 +19,27 @@ type IconCapsuleProps = {
19
19
  *
20
20
  * @component
21
21
  * @param {Object} props - Component props
22
- * @param {string} [props.iconName="ic_card"] - The name of the icon to display from the icon registry
22
+ * @param {React.ReactNode} [props.icon] - The icon element to render (e.g., <IconAdd /> or <Icon name="..." />)
23
23
  * @param {Object} [props.modes={}] - Mode configuration for design tokens (e.g., {"Appearance": "Primary"})
24
- * @param {string} [props.accessibilityLabel] - Accessibility label for screen readers. If not provided, defaults to iconName
24
+ * @param {string} [props.accessibilityLabel] - Accessibility label for screen readers.
25
25
  * @param {string} [props.accessibilityRole] - Accessibility role (defaults to "image" for decorative icons)
26
26
  *
27
27
  * @example
28
- * ```jsx
29
- * // Default icon (ic_card)
30
- * <IconCapsule modes={{}} />
28
+ * // With explicit icon component
29
+ * <IconCapsule icon={<IconAdd />} modes={{}} />
31
30
  *
32
- * // Custom icon
33
- * <IconCapsule iconName="ic_rupee" modes={{}} />
31
+ * // With legacy icon component (if needed)
32
+ * <IconCapsule icon={<Icon name="ic_rupee" />} modes={{}} />
34
33
  *
35
34
  * // With appearance mode
36
- * <IconCapsule modes={{"Appearance": "Secondary"}} />
35
+ * <IconCapsule modes={{"Appearance": "Secondary"}} icon={<IconAdd />} />
37
36
  *
38
37
  * // With accessibility label
39
- * <IconCapsule iconName="ic_card" accessibilityLabel={undefined} />
38
+ * <IconCapsule icon={<IconAdd />} accessibilityLabel="Add Card" />
40
39
  * ```
41
40
  */
42
41
  function IconCapsule({
43
- iconName = "ic_card",
42
+ icon,
44
43
  modes: propModes = {},
45
44
  accessibilityLabel,
46
45
  accessibilityRole = "image",
@@ -73,26 +72,25 @@ function IconCapsule({
73
72
  justifyContent: 'center',
74
73
  }
75
74
 
76
- // Generate default accessibility label from icon name if not provided
77
- const defaultAccessibilityLabel = accessibilityLabel || iconName.replace(/^ic_/, '').replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())
75
+ // Generate default accessibility label if not provided
76
+ const defaultAccessibilityLabel = accessibilityLabel
78
77
 
79
78
  return (
80
79
  <View
81
80
  style={containerStyle}
82
81
  accessibilityRole={accessibilityRole}
83
- accessibilityLabel={undefined}
82
+ accessibilityLabel={defaultAccessibilityLabel}
84
83
  {...rest}
85
84
  >
86
- <Icon
87
- name={iconName}
88
- size={iconSize}
89
- color={iconColor}
90
- accessibilityElementsHidden={true}
91
- importantForAccessibility="no"
92
- />
85
+ {isValidElement(icon) ? cloneElement(icon as React.ReactElement<any>, {
86
+ size: iconSize, // Support legacy Icon component
87
+ width: iconSize,
88
+ height: iconSize,
89
+ fill: iconColor,
90
+ color: iconColor, // Support both fill and color props
91
+ }) : null}
93
92
  </View>
94
93
  )
95
94
  }
96
95
 
97
96
  export default IconCapsule
98
-
@@ -100,7 +100,7 @@ export default function InputSearch({
100
100
  // Actually, usually search inputs show clear button when there is text, regardless of focus, OR only when focused.
101
101
  // Given the user said "when user is focused or typing in the input, then it's active", I will link 'Active' mode to focus.
102
102
  // For the clear button, I'll show it if there is a value.
103
- const hasValue = value && value.length > 0;
103
+ const hasValue = value && value.length > 0
104
104
 
105
105
  const handleClear = () => {
106
106
  if (onChangeText) {
@@ -1,13 +1,13 @@
1
- import React, { createContext, useContext, isValidElement, cloneElement } from 'react';
2
- import { View, Text, StyleSheet, type ViewStyle, type TextStyle, type StyleProp, Platform, Image } from 'react-native';
3
- import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
4
- import Button, { type ButtonProps } from '../Button/Button';
5
- import Avatar, { type AvatarProps } from '../Avatar/Avatar';
1
+ import React, { createContext, useContext, isValidElement, cloneElement } from 'react'
2
+ import { View, Text, StyleSheet, type ViewStyle, type TextStyle, type StyleProp, Platform, Image } from 'react-native'
3
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
+ import Button, { type ButtonProps } from '../Button/Button'
5
+ import Avatar, { type AvatarProps } from '../Avatar/Avatar'
6
6
 
7
7
  /**
8
8
  * Context to share 'modes' with child components.
9
9
  */
10
- const MediaCardContext = createContext<{ modes?: Record<string, any> }>({});
10
+ const MediaCardContext = createContext<{ modes?: Record<string, any> }>({})
11
11
 
12
12
  export interface MediaCardProps {
13
13
  /**
@@ -41,8 +41,8 @@ export function MediaCard({
41
41
  style,
42
42
  }: MediaCardProps) {
43
43
  // Container Tokens
44
- const radius = parseFloat(getVariableByName('cardMedia/radius', modes) || '24');
45
- const gap = parseFloat(getVariableByName('cardMedia/gap', modes) || '0');
44
+ const radius = parseFloat(getVariableByName('cardMedia/radius', modes) || '24')
45
+ const gap = parseFloat(getVariableByName('cardMedia/gap', modes) || '0')
46
46
  // Dimensions from Figma: w=369, h=308. We can make it flexible or default to these?
47
47
  // Usually components should be flexible, but stories will constrain them.
48
48
  // Figma context shows fixed/hug behavior. Let's start with flex container.
@@ -56,11 +56,11 @@ export function MediaCard({
56
56
  // However, to match "Maximize existing component usage", we follow patterns.
57
57
  // We'll trust the parent layout or style prop for width/height.
58
58
  minHeight: 308, // inferred from Figma height as a good default or minimum
59
- };
59
+ }
60
60
 
61
61
  const mediaWithModes = isValidElement(media)
62
62
  ? cloneElement(media as any, { modes: { ...(media.props as any).modes, ...modes } })
63
- : media;
63
+ : media
64
64
 
65
65
  return (
66
66
  <MediaCardContext.Provider value={{ modes }}>
@@ -74,7 +74,7 @@ export function MediaCard({
74
74
  {children}
75
75
  </View>
76
76
  </MediaCardContext.Provider>
77
- );
77
+ )
78
78
  }
79
79
 
80
80
  // ----------------------------------------------------------------------------
@@ -91,7 +91,7 @@ export function Header({ children, style }: { children?: React.ReactNode; style?
91
91
  <View style={[{ padding: 16, flex: 1 }, style]}>
92
92
  {children}
93
93
  </View>
94
- );
94
+ )
95
95
  }
96
96
 
97
97
  /**
@@ -99,14 +99,14 @@ export function Header({ children, style }: { children?: React.ReactNode; style?
99
99
  * Tokens: cardMedia/title/*
100
100
  */
101
101
  export function Title({ children, style, modes: propModes }: { children?: React.ReactNode; style?: StyleProp<TextStyle>; modes?: Record<string, any> }) {
102
- const context = useContext(MediaCardContext);
103
- const modes = propModes || context.modes || {};
102
+ const context = useContext(MediaCardContext)
103
+ const modes = propModes || context.modes || {}
104
104
 
105
- const color = getVariableByName('cardMedia/title/color', modes) || '#ffffff';
106
- const fontSize = parseFloat(getVariableByName('cardMedia/title/fontSize', modes) || '52');
107
- const fontFamily = getVariableByName('cardMedia/title/fontFamily', modes) || 'JioType Var';
108
- const lineHeight = parseFloat(getVariableByName('cardMedia/title/lineHeight', modes) || '68');
109
- const fontWeight = getVariableByName('cardMedia/title/fontWeight', modes) || '900';
105
+ const color = getVariableByName('cardMedia/title/color', modes) || '#ffffff'
106
+ const fontSize = parseFloat(getVariableByName('cardMedia/title/fontSize', modes) || '52')
107
+ const fontFamily = getVariableByName('cardMedia/title/fontFamily', modes) || 'JioType Var'
108
+ const lineHeight = parseFloat(getVariableByName('cardMedia/title/lineHeight', modes) || '68')
109
+ const fontWeight = getVariableByName('cardMedia/title/fontWeight', modes) || '900'
110
110
 
111
111
  const textStyle: TextStyle = {
112
112
  color,
@@ -114,9 +114,9 @@ export function Title({ children, style, modes: propModes }: { children?: React.
114
114
  fontFamily,
115
115
  lineHeight,
116
116
  fontWeight: fontWeight as TextStyle['fontWeight'],
117
- };
117
+ }
118
118
 
119
- return <Text style={[textStyle, style]}>{children}</Text>;
119
+ return <Text style={[textStyle, style]}>{children}</Text>
120
120
  }
121
121
 
122
122
  /**
@@ -124,20 +124,20 @@ export function Title({ children, style, modes: propModes }: { children?: React.
124
124
  * Tokens: cardMedia/footer/*, glass/minimal, blur/minimal
125
125
  */
126
126
  export function Footer({ children, style, modes: propModes }: { children?: React.ReactNode; style?: StyleProp<ViewStyle>; modes?: Record<string, any> }) {
127
- const context = useContext(MediaCardContext);
128
- const modes = propModes || context.modes || {};
127
+ const context = useContext(MediaCardContext)
128
+ const modes = propModes || context.modes || {}
129
129
 
130
130
  // Tokens
131
- const gap = parseFloat(getVariableByName('cardMedia/footer/gap', modes) || '24');
132
- const paddingHorizontal = parseFloat(getVariableByName('cardMedia/footer/padding/horizontal', modes) || '16');
133
- const paddingVertical = parseFloat(getVariableByName('cardMedia/footer/padding/vertical', modes) || '12');
131
+ const gap = parseFloat(getVariableByName('cardMedia/footer/gap', modes) || '24')
132
+ const paddingHorizontal = parseFloat(getVariableByName('cardMedia/footer/padding/horizontal', modes) || '16')
133
+ const paddingVertical = parseFloat(getVariableByName('cardMedia/footer/padding/vertical', modes) || '12')
134
134
 
135
135
  // Glass Effect
136
136
  // Figma:
137
137
  // blur/minimal/background: "#1414174a"
138
138
  // blur/minimal: 29
139
- const glassBgColor = getVariableByName('blur/minimal/background', modes) || '#1414174a';
140
- const blurRadius = parseFloat(getVariableByName('blur/minimal', modes) || '29');
139
+ const glassBgColor = getVariableByName('blur/minimal/background', modes) || '#1414174a'
140
+ const blurRadius = parseFloat(getVariableByName('blur/minimal', modes) || '29')
141
141
 
142
142
  const containerStyle: ViewStyle = {
143
143
  flexDirection: 'row',
@@ -149,13 +149,13 @@ export function Footer({ children, style, modes: propModes }: { children?: React
149
149
  // Web-specific backdrop filter for glass effect
150
150
  // @ts-ignore
151
151
  ...(Platform.OS === 'web' ? { backdropFilter: `blur(${blurRadius}px)` } : {}),
152
- };
152
+ }
153
153
 
154
154
  return (
155
155
  <View style={[containerStyle, style]}>
156
156
  {children}
157
157
  </View>
158
- );
158
+ )
159
159
  }
160
160
 
161
161
  /**
@@ -163,20 +163,20 @@ export function Footer({ children, style, modes: propModes }: { children?: React
163
163
  * Tokens: cardMedia/footer/title/*
164
164
  */
165
165
  export function FooterTitle({ children, style, modes: propModes }: { children?: React.ReactNode; style?: StyleProp<TextStyle>; modes?: Record<string, any> }) {
166
- const context = useContext(MediaCardContext);
167
- const modes = propModes || context.modes || {};
166
+ const context = useContext(MediaCardContext)
167
+ const modes = propModes || context.modes || {}
168
168
 
169
- const color = getVariableByName('cardMedia/footer/title/color', modes) || '#ffffff';
170
- const fontSize = parseFloat(getVariableByName('cardMedia/footer/title/fontSize', modes) || '14');
171
- const fontFamily = getVariableByName('cardMedia/footer/title/fontFamily', modes) || 'JioType Var';
172
- const lineHeight = parseFloat(getVariableByName('cardMedia/footer/title/lineHeight', modes) || '16');
173
- const fontWeight = getVariableByName('cardMedia/footer/title/fontWeight', modes) || '800';
169
+ const color = getVariableByName('cardMedia/footer/title/color', modes) || '#ffffff'
170
+ const fontSize = parseFloat(getVariableByName('cardMedia/footer/title/fontSize', modes) || '14')
171
+ const fontFamily = getVariableByName('cardMedia/footer/title/fontFamily', modes) || 'JioType Var'
172
+ const lineHeight = parseFloat(getVariableByName('cardMedia/footer/title/lineHeight', modes) || '16')
173
+ const fontWeight = getVariableByName('cardMedia/footer/title/fontWeight', modes) || '800'
174
174
 
175
175
  return (
176
176
  <Text style={[{ color, fontSize, fontFamily, lineHeight, fontWeight: fontWeight as any }, style]}>
177
177
  {children}
178
178
  </Text>
179
- );
179
+ )
180
180
  }
181
181
 
182
182
  /**
@@ -184,27 +184,27 @@ export function FooterTitle({ children, style, modes: propModes }: { children?:
184
184
  * Tokens: cardMedia/footer/subtitle/*
185
185
  */
186
186
  export function FooterSubtitle({ children, style, modes: propModes }: { children?: React.ReactNode; style?: StyleProp<TextStyle>; modes?: Record<string, any> }) {
187
- const context = useContext(MediaCardContext);
188
- const modes = propModes || context.modes || {};
187
+ const context = useContext(MediaCardContext)
188
+ const modes = propModes || context.modes || {}
189
189
 
190
- const color = getVariableByName('cardMedia/footer/subtitle/color', modes) || '#f5f7f7a1';
191
- const fontSize = parseFloat(getVariableByName('cardMedia/footer/subtitle/fontSize', modes) || '12');
192
- const fontFamily = getVariableByName('cardMedia/footer/subtitle/fontFamily', modes) || 'JioType Var';
193
- const lineHeight = parseFloat(getVariableByName('cardMedia/footer/subtitle/lineHeight', modes) || '14');
194
- const fontWeight = getVariableByName('cardMedia/footer/subtitle/fontWeight', modes) || '400';
190
+ const color = getVariableByName('cardMedia/footer/subtitle/color', modes) || '#f5f7f7a1'
191
+ const fontSize = parseFloat(getVariableByName('cardMedia/footer/subtitle/fontSize', modes) || '12')
192
+ const fontFamily = getVariableByName('cardMedia/footer/subtitle/fontFamily', modes) || 'JioType Var'
193
+ const lineHeight = parseFloat(getVariableByName('cardMedia/footer/subtitle/lineHeight', modes) || '14')
194
+ const fontWeight = getVariableByName('cardMedia/footer/subtitle/fontWeight', modes) || '400'
195
195
 
196
196
  return (
197
197
  <Text style={[{ color, fontSize, fontFamily, lineHeight, fontWeight: fontWeight as any }, style]}>
198
198
  {children}
199
199
  </Text>
200
- );
200
+ )
201
201
  }
202
202
 
203
203
  // Attach sub-components
204
- MediaCard.Header = Header;
205
- MediaCard.Title = Title;
206
- MediaCard.Footer = Footer;
207
- MediaCard.FooterTitle = FooterTitle;
208
- MediaCard.FooterSubtitle = FooterSubtitle;
204
+ MediaCard.Header = Header
205
+ MediaCard.Title = Title
206
+ MediaCard.Footer = Footer
207
+ MediaCard.FooterTitle = FooterTitle
208
+ MediaCard.FooterSubtitle = FooterSubtitle
209
209
 
210
- export default MediaCard;
210
+ export default MediaCard
@@ -1,7 +1,6 @@
1
- import React from 'react'
1
+ import React, { isValidElement, cloneElement } from 'react'
2
2
  import { View, type ViewStyle } from 'react-native'
3
3
  import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
4
- import Icon from '../../icons/Icon'
5
4
 
6
5
  type NavArrowDirection = 'Back' | 'Forward' | 'Down'
7
6
 
@@ -14,6 +13,11 @@ type NavArrowProps = {
14
13
  style?: ViewStyle
15
14
  /** Accessibility label for the arrow */
16
15
  accessibilityLabel?: string
16
+ /**
17
+ * The icon element to display.
18
+ * Should be a ReactNode (e.g. <IconChevronRight />)
19
+ */
20
+ icon?: React.ReactNode
17
21
  } & Omit<React.ComponentProps<typeof View>, 'style' | 'accessibilityLabel'>
18
22
 
19
23
  /**
@@ -40,6 +44,7 @@ export default function NavArrow({
40
44
  modes = {},
41
45
  style,
42
46
  accessibilityLabel,
47
+ icon,
43
48
  ...rest
44
49
  }: NavArrowProps) {
45
50
  // Resolve design tokens
@@ -92,21 +97,14 @@ export default function NavArrow({
92
97
  accessibilityLabel={undefined}
93
98
  {...rest}
94
99
  >
95
- <Icon
96
- name={iconName}
97
- size={24} // Internal icon size is fixed/clipped by container in design but Icon requires a size
98
- color={iconColor}
99
- style={{
100
- // Center the larger icon within the small container if needed,
101
- // though flex center on container handles this.
102
- // If the container is 6x10 and icon is 24, we might want to ensure it doesn't affect layout
103
- // but Flexbox 'center' centers the content.
104
- // However, if the icon component has its own frame, it might overflow.
105
- // React Native View has overflow: 'hidden' by default if borderRadius is set? No.
106
- // We might want overflow: 'hidden' if strictly following design clip.
107
- // Figma design had "overflow-clip" class.
108
- }}
109
- />
100
+
101
+ {isValidElement(icon) ? cloneElement(icon as React.ReactElement<any>, {
102
+ size: 24,
103
+ width: 24,
104
+ height: 24,
105
+ color: iconColor,
106
+ fill: iconColor,
107
+ }) : null}
110
108
  </View>
111
109
  )
112
110
  }
@@ -1,10 +1,10 @@
1
- import React, { isValidElement, cloneElement } from 'react';
2
- import { View, Text, StyleSheet, type ViewStyle } from 'react-native';
3
- import ButtonGroup from '../ButtonGroup/ButtonGroup';
4
- import AvatarGroup from '../AvatarGroup/AvatarGroup';
5
- import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
- import MoneyValue from '../MoneyValue/MoneyValue';
7
- import Button from '../Button/Button';
1
+ import React, { isValidElement, cloneElement } from 'react'
2
+ import { View, Text, StyleSheet, type ViewStyle } from 'react-native'
3
+ import ButtonGroup from '../ButtonGroup/ButtonGroup'
4
+ import AvatarGroup from '../AvatarGroup/AvatarGroup'
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
6
+ import MoneyValue from '../MoneyValue/MoneyValue'
7
+ import Button from '../Button/Button'
8
8
 
9
9
 
10
10
  type RechargeCardProps = {
@@ -66,55 +66,55 @@ export default function RechargeCard({
66
66
  style,
67
67
  }: RechargeCardProps) {
68
68
  // Container Tokens
69
- const backgroundColor = getVariableByName('rechargeCard/background', modes) || '#f6f3ff';
70
- const paddingHorizontal = parseInt(getVariableByName('rechargeCard/padding/horizontal', modes) || 16, 10);
71
- const paddingVertical = parseInt(getVariableByName('rechargeCard/padding/vertical', modes) || 20, 10);
72
- const gap = parseInt(getVariableByName('rechargeCard/gap', modes) || 20, 10);
73
- const radius = parseInt(getVariableByName('rechargeCard/radius', modes) || 20, 10);
74
- const minWidth = parseInt(getVariableByName('rechargeCard/minWidth', modes) || 328, 10);
69
+ const backgroundColor = getVariableByName('rechargeCard/background', modes) || '#f6f3ff'
70
+ const paddingHorizontal = parseInt(getVariableByName('rechargeCard/padding/horizontal', modes) || 16, 10)
71
+ const paddingVertical = parseInt(getVariableByName('rechargeCard/padding/vertical', modes) || 20, 10)
72
+ const gap = parseInt(getVariableByName('rechargeCard/gap', modes) || 20, 10)
73
+ const radius = parseInt(getVariableByName('rechargeCard/radius', modes) || 20, 10)
74
+ const minWidth = parseInt(getVariableByName('rechargeCard/minWidth', modes) || 328, 10)
75
75
 
76
76
  // Header Tokens
77
- const headerGap = parseInt(getVariableByName('rechargeCard/header/gap', modes) || 4, 10);
78
- const titleColor = getVariableByName('rechargeCard/title/color', modes) || '#13002d';
79
- const titleFontSize = parseInt(getVariableByName('rechargeCard/title/fontSize', modes) || 12, 10);
80
- const titleFontFamily = getVariableByName('rechargeCard/title/fontFamily', modes) || 'JioType Var';
81
- const titleLineHeight = parseInt(getVariableByName('rechargeCard/title/lineHeight', modes) || 14, 10);
82
- const titleFontWeight = getVariableByName('rechargeCard/title/fontWeight', modes) || '700';
77
+ const headerGap = parseInt(getVariableByName('rechargeCard/header/gap', modes) || 4, 10)
78
+ const titleColor = getVariableByName('rechargeCard/title/color', modes) || '#13002d'
79
+ const titleFontSize = parseInt(getVariableByName('rechargeCard/title/fontSize', modes) || 12, 10)
80
+ const titleFontFamily = getVariableByName('rechargeCard/title/fontFamily', modes) || 'JioType Var'
81
+ const titleLineHeight = parseInt(getVariableByName('rechargeCard/title/lineHeight', modes) || 14, 10)
82
+ const titleFontWeight = getVariableByName('rechargeCard/title/fontWeight', modes) || '700'
83
83
 
84
84
  // Specs Tokens
85
- const specsGap = parseInt(getVariableByName('rechargeCard/specs/gap', modes) || 0, 10);
86
- const specItemGap = parseInt(getVariableByName('rechargeCard/specItem/gap', modes) || 4, 10);
85
+ const specsGap = parseInt(getVariableByName('rechargeCard/specs/gap', modes) || 0, 10)
86
+ const specItemGap = parseInt(getVariableByName('rechargeCard/specItem/gap', modes) || 4, 10)
87
87
 
88
88
  // Spec Label Tokens
89
- const specLabelColor = getVariableByName('rechargeCard/specItem/label/color', modes) || '#13002d';
90
- const specLabelFontSize = parseInt(getVariableByName('rechargeCard/specItem/label/fontSize', modes) || 12, 10);
91
- const specLabelFontFamily = getVariableByName('rechargeCard/specItem/label/fontFamily', modes) || 'JioType Var';
92
- const specLabelLineHeight = parseInt(getVariableByName('rechargeCard/specItem/label/lineHeight', modes) || 14, 10);
93
- const specLabelFontWeight = getVariableByName('rechargeCard/specItem/label/fontWeight', modes) || '500';
89
+ const specLabelColor = getVariableByName('rechargeCard/specItem/label/color', modes) || '#13002d'
90
+ const specLabelFontSize = parseInt(getVariableByName('rechargeCard/specItem/label/fontSize', modes) || 12, 10)
91
+ const specLabelFontFamily = getVariableByName('rechargeCard/specItem/label/fontFamily', modes) || 'JioType Var'
92
+ const specLabelLineHeight = parseInt(getVariableByName('rechargeCard/specItem/label/lineHeight', modes) || 14, 10)
93
+ const specLabelFontWeight = getVariableByName('rechargeCard/specItem/label/fontWeight', modes) || '500'
94
94
 
95
95
  // Spec Value Tokens
96
- const specValueColor = getVariableByName('rechargeCard/specItem/value/color', modes) || '#310064';
97
- const specValueFontSize = parseInt(getVariableByName('rechargeCard/specItem/value/fontSize', modes) || 14, 10);
98
- const specValueFontFamily = getVariableByName('rechargeCard/specItem/value/fontFamily', modes) || 'JioType Var';
99
- const specValueLineHeight = parseInt(getVariableByName('rechargeCard/specItem/value/lineHeight', modes) || 17, 10);
100
- const specValueFontWeight = getVariableByName('rechargeCard/specItem/value/fontWeight', modes) || '500';
96
+ const specValueColor = getVariableByName('rechargeCard/specItem/value/color', modes) || '#310064'
97
+ const specValueFontSize = parseInt(getVariableByName('rechargeCard/specItem/value/fontSize', modes) || 14, 10)
98
+ const specValueFontFamily = getVariableByName('rechargeCard/specItem/value/fontFamily', modes) || 'JioType Var'
99
+ const specValueLineHeight = parseInt(getVariableByName('rechargeCard/specItem/value/lineHeight', modes) || 17, 10)
100
+ const specValueFontWeight = getVariableByName('rechargeCard/specItem/value/fontWeight', modes) || '500'
101
101
 
102
102
  // Disclaimer Tokens
103
- const disclaimerColor = getVariableByName('rechargeCard/disclaimer/color', modes) || '#22004a';
104
- const disclaimerFontSize = parseInt(getVariableByName('rechargeCard/disclaimer/fontSize', modes) || 10, 10);
105
- const disclaimerFontFamily = getVariableByName('rechargeCard/disclaimer/fontFamily', modes) || 'JioType Var';
106
- const disclaimerLineHeight = parseInt(getVariableByName('rechargeCard/disclaimer/lineHeight', modes) || 13, 10);
107
- const disclaimerFontWeight = getVariableByName('rechargeCard/disclaimer/fontWeight', modes) || '400';
103
+ const disclaimerColor = getVariableByName('rechargeCard/disclaimer/color', modes) || '#22004a'
104
+ const disclaimerFontSize = parseInt(getVariableByName('rechargeCard/disclaimer/fontSize', modes) || 10, 10)
105
+ const disclaimerFontFamily = getVariableByName('rechargeCard/disclaimer/fontFamily', modes) || 'JioType Var'
106
+ const disclaimerLineHeight = parseInt(getVariableByName('rechargeCard/disclaimer/lineHeight', modes) || 13, 10)
107
+ const disclaimerFontWeight = getVariableByName('rechargeCard/disclaimer/fontWeight', modes) || '400'
108
108
 
109
109
  // Button Group Tokens
110
110
  // Handled by ButtonGroup component directly
111
111
 
112
112
  // Helpers
113
- const resolveFontWeight = (weight: string | number) => typeof weight === 'number' ? weight.toString() : weight;
113
+ const resolveFontWeight = (weight: string | number) => typeof weight === 'number' ? weight.toString() : weight
114
114
 
115
115
  // Pass modes to subscription children (e.g. AvatarGroup)
116
116
  // Now encapsulated, so we just pass children to AvatarGroup
117
- const hasSubscriptions = React.Children.count(subscriptionContent) > 0;
117
+ const hasSubscriptions = React.Children.count(subscriptionContent) > 0
118
118
 
119
119
 
120
120
  return (
@@ -235,5 +235,5 @@ export default function RechargeCard({
235
235
  {actions}
236
236
  </ButtonGroup>
237
237
  </View>
238
- );
238
+ )
239
239
  }