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