jfs-components 0.0.44 → 0.0.45

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 (73) hide show
  1. package/lib/commonjs/components/AmountInput/AmountInput.js +82 -0
  2. package/lib/commonjs/components/AmountInput/index.js +13 -0
  3. package/lib/commonjs/components/Button/Button.js +31 -28
  4. package/lib/commonjs/components/CardProviderInfo/CardProviderInfo.js +76 -0
  5. package/lib/commonjs/components/EmptyState/EmptyState.js +2 -1
  6. package/lib/commonjs/components/OTP/OTP.js +242 -0
  7. package/lib/commonjs/components/PortfolioHero/PortfolioHero.js +78 -0
  8. package/lib/commonjs/components/ProductLabel/ProductLabel.js +50 -0
  9. package/lib/commonjs/components/ProgressBadge/ProgressBadge.js +130 -0
  10. package/lib/commonjs/components/ProgressBadge/index.js +25 -0
  11. package/lib/commonjs/components/StatItem/StatItem.js +61 -0
  12. package/lib/commonjs/components/SwappableAmount/SwappableAmount.js +71 -0
  13. package/lib/commonjs/components/Text/Text.js +38 -0
  14. package/lib/commonjs/components/Toggle/Toggle.js +102 -0
  15. package/lib/commonjs/components/index.js +63 -0
  16. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -0
  17. package/lib/commonjs/design-tokens/figma-variables-resolver.js +1 -1
  18. package/lib/commonjs/icons/registry.js +1 -1
  19. package/lib/module/components/AmountInput/AmountInput.js +77 -0
  20. package/lib/module/components/AmountInput/index.js +3 -0
  21. package/lib/module/components/Button/Button.js +31 -28
  22. package/lib/module/components/CardProviderInfo/CardProviderInfo.js +71 -0
  23. package/lib/module/components/EmptyState/EmptyState.js +2 -1
  24. package/lib/module/components/OTP/OTP.js +236 -0
  25. package/lib/module/components/PortfolioHero/PortfolioHero.js +73 -0
  26. package/lib/module/components/ProductLabel/ProductLabel.js +45 -0
  27. package/lib/module/components/ProgressBadge/ProgressBadge.js +125 -0
  28. package/lib/module/components/ProgressBadge/index.js +4 -0
  29. package/lib/module/components/StatItem/StatItem.js +56 -0
  30. package/lib/module/components/SwappableAmount/SwappableAmount.js +66 -0
  31. package/lib/module/components/Text/Text.js +33 -0
  32. package/lib/module/components/Toggle/Toggle.js +97 -0
  33. package/lib/module/components/index.js +10 -1
  34. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -0
  35. package/lib/module/design-tokens/figma-variables-resolver.js +1 -1
  36. package/lib/module/icons/registry.js +1 -1
  37. package/lib/typescript/src/components/AmountInput/AmountInput.d.ts +23 -0
  38. package/lib/typescript/src/components/AmountInput/index.d.ts +3 -0
  39. package/lib/typescript/src/components/CardProviderInfo/CardProviderInfo.d.ts +24 -0
  40. package/lib/typescript/src/components/EmptyState/EmptyState.d.ts +6 -1
  41. package/lib/typescript/src/components/OTP/OTP.d.ts +36 -0
  42. package/lib/typescript/src/components/PortfolioHero/PortfolioHero.d.ts +21 -0
  43. package/lib/typescript/src/components/ProductLabel/ProductLabel.d.ts +14 -0
  44. package/lib/typescript/src/components/ProgressBadge/ProgressBadge.d.ts +36 -0
  45. package/lib/typescript/src/components/ProgressBadge/index.d.ts +3 -0
  46. package/lib/typescript/src/components/StatItem/StatItem.d.ts +21 -0
  47. package/lib/typescript/src/components/SwappableAmount/SwappableAmount.d.ts +22 -0
  48. package/lib/typescript/src/components/Text/Text.d.ts +14 -0
  49. package/lib/typescript/src/components/Toggle/Toggle.d.ts +29 -0
  50. package/lib/typescript/src/components/index.d.ts +9 -0
  51. package/lib/typescript/src/icons/registry.d.ts +1 -1
  52. package/package.json +1 -1
  53. package/src/components/AmountInput/AmountInput.tsx +81 -0
  54. package/src/components/AmountInput/index.ts +2 -0
  55. package/src/components/Button/Button.tsx +27 -20
  56. package/src/components/CardProviderInfo/CardProviderInfo.tsx +81 -0
  57. package/src/components/EmptyState/EmptyState.tsx +7 -1
  58. package/src/components/OTP/OTP.tsx +275 -0
  59. package/src/components/PortfolioHero/PortfolioHero.tsx +91 -0
  60. package/src/components/ProductLabel/ProductLabel.tsx +58 -0
  61. package/src/components/ProgressBadge/ProgressBadge.tsx +172 -0
  62. package/src/components/ProgressBadge/index.ts +2 -0
  63. package/src/components/StatItem/StatItem.tsx +71 -0
  64. package/src/components/SwappableAmount/SwappableAmount.tsx +92 -0
  65. package/src/components/Text/Text.tsx +48 -0
  66. package/src/components/Toggle/Toggle.tsx +122 -0
  67. package/src/components/index.ts +9 -0
  68. package/src/design-tokens/Coin Variables-variables-full.json +1 -0
  69. package/src/design-tokens/figma-variables-resolver.ts +1 -1
  70. package/src/icons/registry.ts +1 -1
  71. package/lib/commonjs/design-tokens/JFS Variables-variables-full.json +0 -1
  72. package/lib/module/design-tokens/JFS Variables-variables-full.json +0 -1
  73. package/src/design-tokens/JFS Variables-variables-full.json +0 -1
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { View } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { useTokens } from '../../design-tokens/JFSThemeProvider';
7
+ import MoneyValue from '../MoneyValue/MoneyValue';
8
+ import NoteInput from '../NoteInput/NoteInput';
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ /**
11
+ * AmountInput component that combines MoneyValue and NoteInput from Figma design.
12
+ *
13
+ * @component
14
+ */
15
+ export default function AmountInput({
16
+ moneyValueSlot,
17
+ noteInputSlot,
18
+ modes: propModes = {},
19
+ style
20
+ }) {
21
+ const {
22
+ modes: globalModes
23
+ } = useTokens();
24
+ const modes = {
25
+ ...globalModes,
26
+ ...propModes
27
+ };
28
+
29
+ // Resolve tokens
30
+ const gap = Number(getVariableByName('amountInput/gap', modes)) || 16;
31
+ const paddingHorizontal = Number(getVariableByName('amountInput/padding/horizontal', modes)) || 0;
32
+ const paddingVertical = Number(getVariableByName('amountInput/padding/vertical', modes)) || 0;
33
+ const containerStyle = {
34
+ flexDirection: 'column',
35
+ alignItems: 'center',
36
+ gap,
37
+ paddingHorizontal,
38
+ paddingVertical,
39
+ ...style
40
+ };
41
+
42
+ // Handle MoneyValue Slot
43
+ const renderMoneyValueSlot = () => {
44
+ if (/*#__PURE__*/React.isValidElement(moneyValueSlot)) {
45
+ return /*#__PURE__*/React.cloneElement(moneyValueSlot, {
46
+ modes
47
+ });
48
+ }
49
+ // Default fallback if no slot prop is provided
50
+ if (!moneyValueSlot) {
51
+ return /*#__PURE__*/_jsx(MoneyValue, {
52
+ modes: modes
53
+ });
54
+ }
55
+ return moneyValueSlot;
56
+ };
57
+
58
+ // Handle NoteInput Slot
59
+ const renderNoteInputSlot = () => {
60
+ if (/*#__PURE__*/React.isValidElement(noteInputSlot)) {
61
+ return /*#__PURE__*/React.cloneElement(noteInputSlot, {
62
+ modes
63
+ });
64
+ }
65
+ // Default fallback if no slot prop is provided
66
+ if (!noteInputSlot) {
67
+ return /*#__PURE__*/_jsx(NoteInput, {
68
+ modes: modes
69
+ });
70
+ }
71
+ return noteInputSlot;
72
+ };
73
+ return /*#__PURE__*/_jsxs(View, {
74
+ style: containerStyle,
75
+ children: [renderMoneyValueSlot(), renderNoteInputSlot()]
76
+ });
77
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+
3
+ export { default } from './AmountInput';
@@ -59,8 +59,28 @@ function Button({
59
59
  const textColor = getVariableByName('button/foreground', modes) || '#0f0d0a';
60
60
  const iconColor = getVariableByName('button/icon/color', modes) ?? textColor;
61
61
  const iconSize = getVariableByName('button/icon/size', modes) ?? 18;
62
+ const [isHovered, setIsHovered] = useState(false);
63
+ const [isPressed, setIsPressed] = useState(false);
64
+ const hoverModes = {
65
+ ...modes,
66
+ "Button / State": "Hover"
67
+ };
68
+ const hoverBg = getVariableByName('button/background', hoverModes) || backgroundColor;
69
+ const hoverBorderColor = getVariableByName('button/border/color', hoverModes) || borderColor;
70
+ const hoverTextColor = getVariableByName('button/foreground', hoverModes) || textColor;
71
+ const hoverIconColor = getVariableByName('button/icon/color', hoverModes) ?? hoverTextColor;
72
+ const pressedModes = {
73
+ ...modes,
74
+ "Button / State": "Pressed"
75
+ };
76
+ const pressedBg = getVariableByName('button/background', pressedModes) || backgroundColor;
77
+ const pressedBorderColor = getVariableByName('button/border/color', pressedModes) || borderColor;
78
+ const pressedTextColor = getVariableByName('button/foreground', pressedModes) || textColor;
79
+ const pressedIconColor = getVariableByName('button/icon/color', pressedModes) ?? pressedTextColor;
80
+ const activeTextColor = isPressed && !disabled ? pressedTextColor : isHovered && !disabled ? hoverTextColor : textColor;
81
+ const activeIconColor = isPressed && !disabled ? pressedIconColor : isHovered && !disabled ? hoverIconColor : iconColor;
62
82
  const baseLabelTextStyle = {
63
- color: textColor,
83
+ color: activeTextColor,
64
84
  fontFamily,
65
85
  fontWeight,
66
86
  fontSize,
@@ -114,22 +134,13 @@ function Button({
114
134
  accessibilityLabel: defaultAccessibilityLabel,
115
135
  webAccessibilityProps
116
136
  });
117
-
118
- // Interaction states (placeholders for visuals; tweak later)
119
- const [isFocused, setIsFocused] = useState(false);
120
- const [isHovered, setIsHovered] = useState(false);
121
- const pressedStyle = {
122
- transform: [{
123
- scale: 0.995
124
- }],
125
- backgroundColor: '#b88940'
126
- };
127
- const focusStyle = {
128
- borderWidth: 1,
129
- borderColor: '#222'
130
- };
131
137
  const hoverStyle = {
132
- opacity: 0.95
138
+ backgroundColor: hoverBg,
139
+ borderColor: hoverBorderColor
140
+ };
141
+ const pressedStyle = {
142
+ backgroundColor: pressedBg,
143
+ borderColor: pressedBorderColor
133
144
  };
134
145
  if (__DEV__) {
135
146
  if (children && labelStyle) {
@@ -154,21 +165,13 @@ function Button({
154
165
  onPress
155
166
  } : {}),
156
167
  onPressIn: e => {
157
- ;
168
+ setIsPressed(true);
158
169
  rest?.onPressIn?.(e);
159
170
  },
160
171
  onPressOut: e => {
161
- ;
172
+ setIsPressed(false);
162
173
  rest?.onPressOut?.(e);
163
174
  },
164
- onFocus: e => {
165
- setIsFocused(true);
166
- rest?.onFocus?.(e);
167
- },
168
- onBlur: e => {
169
- setIsFocused(false);
170
- rest?.onBlur?.(e);
171
- },
172
175
  onHoverIn: e => {
173
176
  setIsHovered(true);
174
177
  rest?.onHoverIn?.(e);
@@ -179,7 +182,7 @@ function Button({
179
182
  },
180
183
  style: ({
181
184
  pressed
182
- }) => [containerBaseStyle, pressed && !disabled ? pressedStyle : null, isHovered && !disabled ? hoverStyle : null, isFocused && !disabled ? focusStyle : null, style],
185
+ }) => [containerBaseStyle, isHovered && !disabled ? hoverStyle : null, (pressed || isPressed) && !disabled ? pressedStyle : null, style],
183
186
  ...webProps,
184
187
  children: [leading ? /*#__PURE__*/_jsx(View, {
185
188
  style: leadingAccessoryStyle,
@@ -189,7 +192,7 @@ function Button({
189
192
  children: /*#__PURE__*/_jsx(Icon, {
190
193
  name: icon,
191
194
  size: iconSize,
192
- color: iconColor,
195
+ color: activeIconColor,
193
196
  accessibilityElementsHidden: true,
194
197
  importantForAccessibility: "no"
195
198
  })
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { View } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import ProductLabel from '../ProductLabel/ProductLabel';
7
+ import { cloneChildrenWithModes } from '../../utils/react-utils';
8
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
+ /**
10
+ * CardProviderInfo displays a product header (ProductLabel) followed by a
11
+ * 2-column grid of children (typically StatItem instances).
12
+ *
13
+ * @component
14
+ * @param {CardProviderInfoProps} props
15
+ */
16
+ function CardProviderInfo({
17
+ label = 'Gold',
18
+ imageSource,
19
+ children,
20
+ modes = {},
21
+ style
22
+ }) {
23
+ const background = getVariableByName('card/providerInfo/background', modes) ?? '#fef4e5';
24
+ const border = getVariableByName('card/providerInfo/border', modes) ?? '#fef4e5';
25
+ const borderWidthVal = getVariableByName('card/providerInfo/borderWidth', modes) ?? 1;
26
+ const padding = getVariableByName('card/providerInfo/padding', modes) ?? 20;
27
+ const gap = getVariableByName('card/providerInfo/gap', modes) ?? 20;
28
+ const radius = getVariableByName('card/providerInfo/radius', modes) ?? 16;
29
+ const gridGap = getVariableByName('card/providerInfo/grid/gap', modes) ?? 8;
30
+ const containerStyle = {
31
+ backgroundColor: background,
32
+ borderColor: border,
33
+ borderWidth: borderWidthVal,
34
+ borderStyle: 'solid',
35
+ padding: padding,
36
+ gap: gap,
37
+ borderRadius: radius
38
+ };
39
+ const gridGapNum = gridGap;
40
+ const clonedChildren = children ? cloneChildrenWithModes(children, modes) : [];
41
+ const childArray = React.Children.toArray(clonedChildren);
42
+ const rows = [];
43
+ for (let i = 0; i < childArray.length; i += 2) {
44
+ rows.push(childArray.slice(i, i + 2));
45
+ }
46
+ return /*#__PURE__*/_jsxs(View, {
47
+ style: [containerStyle, style],
48
+ children: [/*#__PURE__*/_jsx(ProductLabel, {
49
+ label: label,
50
+ imageSource: imageSource,
51
+ modes: modes
52
+ }), childArray.length > 0 && /*#__PURE__*/_jsx(View, {
53
+ style: {
54
+ rowGap: gridGapNum
55
+ },
56
+ children: rows.map((row, i) => /*#__PURE__*/_jsx(View, {
57
+ style: {
58
+ flexDirection: 'row',
59
+ columnGap: gridGapNum
60
+ },
61
+ children: row.map((child, j) => /*#__PURE__*/_jsx(View, {
62
+ style: {
63
+ flex: 1
64
+ },
65
+ children: child
66
+ }, j))
67
+ }, i))
68
+ })]
69
+ });
70
+ }
71
+ export default CardProviderInfo;
@@ -15,6 +15,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
15
  function EmptyState({
16
16
  title = "No payments to show",
17
17
  description = "Start by paying bills, recharge or your friends",
18
+ showDescription = true,
18
19
  iconSlot,
19
20
  buttonSlot,
20
21
  modes: propModes = {},
@@ -110,7 +111,7 @@ function EmptyState({
110
111
  children: [iconContent, /*#__PURE__*/_jsx(Text, {
111
112
  style: titleStyle,
112
113
  children: title
113
- }), description ? /*#__PURE__*/_jsx(Text, {
114
+ }), showDescription && description ? /*#__PURE__*/_jsx(Text, {
114
115
  style: bodyStyle,
115
116
  children: description
116
117
  }) : null]
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+
3
+ import React, { useState, useRef, useCallback, useEffect } from 'react';
4
+ import { View, Text, TextInput as RNTextInput, Pressable, Animated } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { useTokens } from '../../design-tokens/JFSThemeProvider';
7
+ import SupportText from '../SupportText/SupportText';
8
+ import { cloneChildrenWithModes } from '../../utils/react-utils';
9
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
10
+ const DIGITS_ONLY = /^\d*$/;
11
+ function OTP({
12
+ length = 6,
13
+ value: controlledValue,
14
+ defaultValue = '',
15
+ onChange,
16
+ onValueChange,
17
+ onComplete,
18
+ isDisabled = false,
19
+ isInvalid = false,
20
+ allowedPattern = DIGITS_ONLY,
21
+ autoFocus = false,
22
+ modes: propModes = {},
23
+ style,
24
+ supportText,
25
+ supportTextStatus
26
+ }) {
27
+ const {
28
+ modes: globalModes
29
+ } = useTokens();
30
+ const modes = {
31
+ ...globalModes,
32
+ ...propModes
33
+ };
34
+ const isControlled = controlledValue !== undefined;
35
+ const [internalValue, setInternalValue] = useState(defaultValue);
36
+ const currentValue = isControlled ? controlledValue : internalValue;
37
+ const inputRef = useRef(null);
38
+ const [isFocused, setIsFocused] = useState(false);
39
+ const caretAnim = useRef(new Animated.Value(1)).current;
40
+ useEffect(() => {
41
+ if (!isFocused) return;
42
+ const blink = Animated.loop(Animated.sequence([Animated.timing(caretAnim, {
43
+ toValue: 0,
44
+ duration: 400,
45
+ useNativeDriver: true
46
+ }), Animated.timing(caretAnim, {
47
+ toValue: 1,
48
+ duration: 400,
49
+ useNativeDriver: true
50
+ })]));
51
+ blink.start();
52
+ return () => blink.stop();
53
+ }, [isFocused, caretAnim]);
54
+ const prevCompleteRef = useRef(false);
55
+ const setValue = useCallback(next => {
56
+ const clamped = next.slice(0, length);
57
+ if (!isControlled) setInternalValue(clamped);
58
+ onChange?.(clamped);
59
+ onValueChange?.(clamped);
60
+ if (clamped.length === length && !prevCompleteRef.current) {
61
+ prevCompleteRef.current = true;
62
+ onComplete?.(clamped);
63
+ }
64
+ if (clamped.length < length) {
65
+ prevCompleteRef.current = false;
66
+ }
67
+ }, [length, isControlled, onChange, onValueChange, onComplete]);
68
+ const handleChangeText = useCallback(text => {
69
+ if (isDisabled) return;
70
+ if (!allowedPattern.test(text)) return;
71
+ setValue(text);
72
+ }, [isDisabled, allowedPattern, setValue]);
73
+ const handlePress = useCallback(() => {
74
+ if (isDisabled) return;
75
+ inputRef.current?.focus();
76
+ }, [isDisabled]);
77
+
78
+ // --- Token resolution (state-independent tokens resolved once) ---
79
+ const otpGap = Number(getVariableByName('otp/gap', modes)) || 36;
80
+ const otpPaddingH = Number(getVariableByName('otp/padding/horizontal', modes)) || 8;
81
+ const otpPaddingV = Number(getVariableByName('otp/padding/vertical', modes)) || 8;
82
+ const slotWidth = Number(getVariableByName('pinSlot/width', modes)) || 48;
83
+ const slotGap = Number(getVariableByName('pinSlot/gap', modes)) || 8;
84
+ // digit/color has no state variants in Figma — resolved once from the Output collection
85
+ const digitColor = getVariableByName('pinSlot/digit/color', modes) || '#000000';
86
+ const digitFontSize = Number(getVariableByName('pinSlot/digit/fontSize', modes)) || 24;
87
+ const digitFontFamily = getVariableByName('pinSlot/digit/fontFamily', modes) || 'JioType Var';
88
+ const digitLineHeight = Number(getVariableByName('pinSlot/digit/lineHeight', modes)) || 29;
89
+ const digitFontWeight = getVariableByName('pinSlot/digit/fontWeight', modes) || '500';
90
+ const underlineHeight = Number(getVariableByName('pinSlot/underline/height', modes)) || 2;
91
+ const underlineRadius = Number(getVariableByName('pinSlot/underline/radius', modes)) || 1;
92
+
93
+ // --- State-driven slot modes ---
94
+ // Collection name in Figma is "Input/PINSlot States" (double space before States).
95
+ // Only PinSlot/underline/color (capital P/S) lives in this collection with Idle/Active/Error modes.
96
+ // isInvalid takes priority over active focus; the component maps semantic state → token mode
97
+ // internally so consumers never need to know the collection key name.
98
+ const getSlotModes = isActiveSlot => {
99
+ if (isInvalid) return {
100
+ ...modes,
101
+ 'Input/PINSlot States': 'Error'
102
+ };
103
+ if (isActiveSlot && isFocused) return {
104
+ ...modes,
105
+ 'Input/PINSlot States': 'Active'
106
+ };
107
+ return {
108
+ ...modes,
109
+ 'Input/PINSlot States': 'Idle'
110
+ };
111
+ };
112
+
113
+ // --- Styles ---
114
+ const containerStyle = {
115
+ flexDirection: 'column',
116
+ alignItems: 'flex-end',
117
+ gap: otpGap,
118
+ paddingHorizontal: otpPaddingH,
119
+ paddingVertical: otpPaddingV
120
+ };
121
+ const slotWrapStyle = {
122
+ flexDirection: 'row',
123
+ gap: 8,
124
+ alignItems: 'flex-start',
125
+ alignSelf: 'stretch'
126
+ };
127
+ const renderSlot = index => {
128
+ const char = currentValue[index];
129
+ const isActiveSlot = index === currentValue.length && currentValue.length < length;
130
+ const isFilled = char !== undefined;
131
+
132
+ // Underline color is the only state-sensitive token (lives in "Input/PINSlot States" collection).
133
+ // Note: token name is "PinSlot/underline/color" (capital P/S) — different from the static
134
+ // "pinSlot/underline/color" in the Output collection.
135
+ const slotModes = getSlotModes(isActiveSlot);
136
+ const underlineColor = getVariableByName('PinSlot/underline/color', slotModes) || '#303338';
137
+ const slotStyle = {
138
+ width: slotWidth,
139
+ flexDirection: 'column',
140
+ alignItems: 'center',
141
+ justifyContent: 'flex-end',
142
+ gap: slotGap
143
+ };
144
+ const digitStyle = {
145
+ fontFamily: digitFontFamily,
146
+ fontWeight: digitFontWeight,
147
+ fontSize: digitFontSize,
148
+ lineHeight: digitLineHeight,
149
+ color: digitColor,
150
+ textAlign: 'center',
151
+ minWidth: '100%'
152
+ };
153
+ const underlineStyle = {
154
+ width: slotWidth,
155
+ height: underlineHeight,
156
+ borderRadius: underlineRadius,
157
+ backgroundColor: underlineColor
158
+ };
159
+ return /*#__PURE__*/_jsxs(View, {
160
+ style: slotStyle,
161
+ children: [/*#__PURE__*/_jsx(View, {
162
+ style: {
163
+ minHeight: digitLineHeight,
164
+ justifyContent: 'center',
165
+ alignItems: 'center',
166
+ width: '100%'
167
+ },
168
+ children: isFilled ? /*#__PURE__*/_jsx(Text, {
169
+ style: digitStyle,
170
+ children: char
171
+ }) : isActiveSlot && isFocused ? /*#__PURE__*/_jsx(Animated.View, {
172
+ style: {
173
+ width: 2,
174
+ height: digitFontSize,
175
+ backgroundColor: digitColor,
176
+ opacity: caretAnim
177
+ }
178
+ }) : /*#__PURE__*/_jsx(Text, {
179
+ style: [digitStyle, {
180
+ color: 'transparent'
181
+ }],
182
+ children: '\u00A0'
183
+ })
184
+ }), /*#__PURE__*/_jsx(View, {
185
+ style: underlineStyle
186
+ })]
187
+ }, index);
188
+ };
189
+ const renderSupportText = () => {
190
+ if (!supportText) return null;
191
+ if (typeof supportText === 'string') {
192
+ return /*#__PURE__*/_jsx(SupportText, {
193
+ label: supportText,
194
+ status: supportTextStatus ?? (isInvalid ? 'Error' : 'Neutral'),
195
+ modes: modes
196
+ });
197
+ }
198
+ return /*#__PURE__*/_jsx(_Fragment, {
199
+ children: cloneChildrenWithModes(React.Children.toArray(supportText), modes)
200
+ });
201
+ };
202
+ return /*#__PURE__*/_jsxs(Pressable, {
203
+ style: [containerStyle, isDisabled && {
204
+ opacity: 0.4
205
+ }, style],
206
+ onPress: handlePress,
207
+ disabled: isDisabled,
208
+ accessibilityRole: "none",
209
+ children: [/*#__PURE__*/_jsx(RNTextInput, {
210
+ ref: inputRef,
211
+ value: currentValue,
212
+ onChangeText: handleChangeText,
213
+ maxLength: length,
214
+ keyboardType: "number-pad",
215
+ autoFocus: autoFocus,
216
+ editable: !isDisabled,
217
+ onFocus: () => setIsFocused(true),
218
+ onBlur: () => setIsFocused(false),
219
+ caretHidden: true,
220
+ style: {
221
+ position: 'absolute',
222
+ width: 1,
223
+ height: 1,
224
+ opacity: 0
225
+ },
226
+ accessibilityLabel: `OTP input, ${length} digits`,
227
+ accessibilityHint: "Enter your verification code"
228
+ }), /*#__PURE__*/_jsx(View, {
229
+ style: slotWrapStyle,
230
+ children: Array.from({
231
+ length
232
+ }, (_, i) => renderSlot(i))
233
+ }), renderSupportText()]
234
+ });
235
+ }
236
+ export default OTP;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { View, Text } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import { cloneChildrenWithModes } from '../../utils/react-utils';
7
+ import Avatar from '../Avatar/Avatar';
8
+ import MoneyValue from '../MoneyValue/MoneyValue';
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ function PortfolioHero({
11
+ label = 'Gold',
12
+ imageSource,
13
+ value = '12,000.11',
14
+ currency = '₹',
15
+ modes = {
16
+ Context3: 'Balance'
17
+ },
18
+ children,
19
+ style
20
+ }) {
21
+ const gap = getVariableByName('portfolioHero/gap', modes) ?? 16;
22
+ const padding = getVariableByName('portfolioHero/padding', modes) ?? 8;
23
+ const slotWrapGap = getVariableByName('portfolioHero/slotWrap/gap', modes) ?? 8;
24
+ const containerStyle = {
25
+ flexDirection: 'column',
26
+ alignItems: 'center',
27
+ justifyContent: 'center',
28
+ gap: gap,
29
+ padding: padding
30
+ };
31
+ const productLabelStyle = {
32
+ flexDirection: 'row',
33
+ alignItems: 'center',
34
+ gap: 8
35
+ };
36
+ const labelTextStyle = {
37
+ fontFamily: 'System',
38
+ fontWeight: '700',
39
+ fontSize: 16,
40
+ lineHeight: 16 * 1.3,
41
+ color: '#0d0d0f',
42
+ textAlign: 'center'
43
+ };
44
+ const slotWrapStyle = {
45
+ flexDirection: 'column',
46
+ alignItems: 'center',
47
+ gap: slotWrapGap
48
+ };
49
+ return /*#__PURE__*/_jsxs(View, {
50
+ style: [containerStyle, style],
51
+ children: [/*#__PURE__*/_jsxs(View, {
52
+ style: productLabelStyle,
53
+ children: [/*#__PURE__*/_jsx(Avatar, {
54
+ style: "Image",
55
+ ...(imageSource != null && {
56
+ imageSource
57
+ }),
58
+ modes: modes
59
+ }), /*#__PURE__*/_jsx(Text, {
60
+ style: labelTextStyle,
61
+ children: label
62
+ })]
63
+ }), /*#__PURE__*/_jsx(MoneyValue, {
64
+ value: value,
65
+ currency: currency,
66
+ modes: modes
67
+ }), children && /*#__PURE__*/_jsx(View, {
68
+ style: slotWrapStyle,
69
+ children: cloneChildrenWithModes(children, modes)
70
+ })]
71
+ });
72
+ }
73
+ export default PortfolioHero;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { View, Text } from 'react-native';
5
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
6
+ import Avatar from '../Avatar/Avatar';
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ function ProductLabel({
9
+ label = 'Gold',
10
+ imageSource,
11
+ modes = {},
12
+ style
13
+ }) {
14
+ const gap = getVariableByName('productLabel/gap', modes) ?? 8;
15
+ const textColor = getVariableByName('productLabel/text/color', modes) ?? '#000000';
16
+ const textFontSize = getVariableByName('productLabel/text/fontSize', modes) ?? 16;
17
+ const textFontFamily = getVariableByName('productLabel/text/fontFamily', modes) ?? 'JioType Var';
18
+ const textFontWeight = getVariableByName('productLabel/text/fontWeight', modes) ?? 700;
19
+ const textLineHeight = getVariableByName('productLabel/text/lineHeight', modes) ?? 21;
20
+ const containerStyle = {
21
+ flexDirection: 'row',
22
+ alignItems: 'center',
23
+ gap: gap
24
+ };
25
+ const labelTextStyle = {
26
+ color: textColor,
27
+ fontSize: textFontSize,
28
+ fontFamily: textFontFamily,
29
+ fontWeight: String(textFontWeight),
30
+ lineHeight: textLineHeight,
31
+ textAlign: 'center'
32
+ };
33
+ return /*#__PURE__*/_jsxs(View, {
34
+ style: [containerStyle, style],
35
+ children: [/*#__PURE__*/_jsx(Avatar, {
36
+ style: "Image",
37
+ imageSource: imageSource,
38
+ modes: modes
39
+ }), /*#__PURE__*/_jsx(Text, {
40
+ style: labelTextStyle,
41
+ children: label
42
+ })]
43
+ });
44
+ }
45
+ export default ProductLabel;