jfs-components 0.0.73 → 0.0.74

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 (63) hide show
  1. package/CHANGELOG.md +23 -6
  2. package/lib/commonjs/components/AccountCard/AccountCard.js +247 -0
  3. package/lib/commonjs/components/AppBar/AppBar.js +17 -11
  4. package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +18 -2
  5. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +40 -25
  6. package/lib/commonjs/components/Dropdown/Dropdown.js +214 -0
  7. package/lib/commonjs/components/DropdownInput/DropdownInput.js +542 -0
  8. package/lib/commonjs/components/FormField/FormField.js +328 -178
  9. package/lib/commonjs/components/LottieIntroBlock/LottieIntroBlock.js +150 -0
  10. package/lib/commonjs/components/PageHero/PageHero.js +153 -0
  11. package/lib/commonjs/components/PoweredByLabel/PoweredByLabel.js +135 -0
  12. package/lib/commonjs/components/PoweredByLabel/finvu.png +0 -0
  13. package/lib/commonjs/components/Text/Text.js +9 -2
  14. package/lib/commonjs/components/Tooltip/Tooltip.js +34 -27
  15. package/lib/commonjs/components/index.js +60 -0
  16. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  17. package/lib/commonjs/icons/registry.js +1 -1
  18. package/lib/module/components/AccountCard/AccountCard.js +241 -0
  19. package/lib/module/components/AppBar/AppBar.js +17 -11
  20. package/lib/module/components/CardBankAccount/CardBankAccount.js +17 -2
  21. package/lib/module/components/CheckboxItem/CheckboxItem.js +41 -26
  22. package/lib/module/components/Dropdown/Dropdown.js +206 -0
  23. package/lib/module/components/DropdownInput/DropdownInput.js +536 -0
  24. package/lib/module/components/FormField/FormField.js +330 -180
  25. package/lib/module/components/LottieIntroBlock/LottieIntroBlock.js +144 -0
  26. package/lib/module/components/PageHero/PageHero.js +147 -0
  27. package/lib/module/components/PoweredByLabel/PoweredByLabel.js +130 -0
  28. package/lib/module/components/PoweredByLabel/finvu.png +0 -0
  29. package/lib/module/components/Text/Text.js +9 -2
  30. package/lib/module/components/Tooltip/Tooltip.js +34 -27
  31. package/lib/module/components/index.js +7 -1
  32. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  33. package/lib/module/icons/registry.js +1 -1
  34. package/lib/typescript/src/components/AccountCard/AccountCard.d.ts +81 -0
  35. package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +9 -2
  36. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +18 -2
  37. package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +62 -0
  38. package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +107 -0
  39. package/lib/typescript/src/components/FormField/FormField.d.ts +76 -19
  40. package/lib/typescript/src/components/LottieIntroBlock/LottieIntroBlock.d.ts +58 -0
  41. package/lib/typescript/src/components/PageHero/PageHero.d.ts +53 -0
  42. package/lib/typescript/src/components/PoweredByLabel/PoweredByLabel.d.ts +70 -0
  43. package/lib/typescript/src/components/Text/Text.d.ts +12 -2
  44. package/lib/typescript/src/components/Tooltip/Tooltip.d.ts +13 -2
  45. package/lib/typescript/src/components/index.d.ts +7 -1
  46. package/lib/typescript/src/icons/registry.d.ts +1 -1
  47. package/package.json +1 -3
  48. package/src/components/AccountCard/AccountCard.tsx +376 -0
  49. package/src/components/AppBar/AppBar.tsx +25 -14
  50. package/src/components/CardBankAccount/CardBankAccount.tsx +29 -3
  51. package/src/components/CheckboxItem/CheckboxItem.tsx +65 -30
  52. package/src/components/Dropdown/Dropdown.tsx +331 -0
  53. package/src/components/DropdownInput/DropdownInput.tsx +819 -0
  54. package/src/components/FormField/FormField.tsx +542 -215
  55. package/src/components/LottieIntroBlock/LottieIntroBlock.tsx +202 -0
  56. package/src/components/PageHero/PageHero.tsx +200 -0
  57. package/src/components/PoweredByLabel/PoweredByLabel.tsx +221 -0
  58. package/src/components/PoweredByLabel/finvu.png +0 -0
  59. package/src/components/Text/Text.tsx +24 -3
  60. package/src/components/Tooltip/Tooltip.tsx +50 -25
  61. package/src/components/index.ts +15 -1
  62. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  63. package/src/icons/registry.ts +1 -1
@@ -0,0 +1,150 @@
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 _Button = _interopRequireDefault(require("../Button/Button"));
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 DEFAULT_MEDIA_SIZE = 117;
17
+ /**
18
+ * LottieIntroBlock displays a centered onboarding/intro block composed of a
19
+ * media slot (typically a Lottie animation or illustration) above a title,
20
+ * an optional supportive paragraph, and an optional action button.
21
+ *
22
+ * All visual values are resolved from Figma design tokens via
23
+ * `getVariableByName`. Slots cascade the active `modes` to their children
24
+ * through `cloneChildrenWithModes`.
25
+ *
26
+ * @component
27
+ * @example
28
+ * ```tsx
29
+ * <LottieIntroBlock
30
+ * title="Let's get to know how your financial health is doing"
31
+ * supportText="From assets to taxes, stay on top of everything in one simple view."
32
+ * buttonLabel="Get started"
33
+ * onButtonPress={() => navigate('NextScreen')}
34
+ * media={<MyLottiePlayer source={animationSource} />}
35
+ * />
36
+ * ```
37
+ */
38
+ function LottieIntroBlock({
39
+ title = "Let's get to know how your financial health is doing",
40
+ showSupportText = true,
41
+ supportText = 'From assets to taxes, stay on top of everything in one simple view.',
42
+ showButton = true,
43
+ buttonLabel = 'Button',
44
+ onButtonPress,
45
+ media,
46
+ buttonSlot,
47
+ modes: propModes = _reactUtils.EMPTY_MODES,
48
+ style,
49
+ testID
50
+ }) {
51
+ const {
52
+ modes: globalModes
53
+ } = (0, _JFSThemeProvider.useTokens)();
54
+ const modes = (0, _react.useMemo)(() => ({
55
+ ...globalModes,
56
+ ...propModes
57
+ }), [globalModes, propModes]);
58
+
59
+ // Container
60
+ const gap = Number((0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/gap', modes)) || 36;
61
+ const paddingHorizontal = Number((0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/padding/horizontal', modes)) || 0;
62
+ const paddingVertical = Number((0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/padding/vertical', modes)) || 16;
63
+
64
+ // Text wrap
65
+ const textWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/textWrap/gap', modes)) || 16;
66
+
67
+ // Title
68
+ const titleColor = (0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/title/foreground', modes) || '#0d0d0f';
69
+ const titleFontSize = Number((0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/title/fontSize', modes)) || 23;
70
+ const titleFontFamily = (0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/title/fontFamily', modes) || 'System';
71
+ const titleLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/title/lineHeight', modes)) || 23;
72
+ const titleFontWeight = (0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/title/fontWeight', modes) || 900;
73
+
74
+ // Support text
75
+ const supportColor = (0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/supportText/foreground', modes) || '#0d0d0f';
76
+ const supportFontSize = Number((0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/supportText/fontSize', modes)) || 14;
77
+ const supportFontFamily = (0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/supportText/fontFamily', modes) || 'System';
78
+ const supportLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/supportText/lineHeight', modes)) || 18;
79
+ const supportFontWeight = (0, _figmaVariablesResolver.getVariableByName)('lottieIntroBlock/supportText/fontWeight', modes) || 400;
80
+ const containerStyle = {
81
+ flexDirection: 'column',
82
+ alignItems: 'center',
83
+ paddingHorizontal,
84
+ paddingVertical,
85
+ gap
86
+ };
87
+ const textWrapStyle = {
88
+ flexDirection: 'column',
89
+ alignItems: 'center',
90
+ gap: textWrapGap,
91
+ width: '100%'
92
+ };
93
+ const titleStyle = {
94
+ color: titleColor,
95
+ fontSize: titleFontSize,
96
+ fontFamily: titleFontFamily,
97
+ lineHeight: titleLineHeight,
98
+ fontWeight: String(titleFontWeight),
99
+ textAlign: 'center'
100
+ };
101
+ const supportTextStyle = {
102
+ color: supportColor,
103
+ fontSize: supportFontSize,
104
+ fontFamily: supportFontFamily,
105
+ lineHeight: supportLineHeight,
106
+ fontWeight: String(supportFontWeight),
107
+ textAlign: 'center'
108
+ };
109
+ const mediaContent = (0, _react.useMemo)(() => {
110
+ if (media === undefined || media === null) {
111
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
112
+ style: {
113
+ width: DEFAULT_MEDIA_SIZE,
114
+ height: DEFAULT_MEDIA_SIZE
115
+ },
116
+ accessibilityElementsHidden: true,
117
+ importantForAccessibility: "no-hide-descendants"
118
+ });
119
+ }
120
+ return (0, _reactUtils.cloneChildrenWithModes)(media, modes);
121
+ }, [media, modes]);
122
+ const buttonContent = (0, _react.useMemo)(() => {
123
+ if (buttonSlot !== undefined && buttonSlot !== null) {
124
+ return (0, _reactUtils.cloneChildrenWithModes)(buttonSlot, modes);
125
+ }
126
+ if (!showButton) {
127
+ return null;
128
+ }
129
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
130
+ label: buttonLabel,
131
+ onPress: onButtonPress,
132
+ modes: modes
133
+ });
134
+ }, [buttonSlot, showButton, buttonLabel, onButtonPress, modes]);
135
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
136
+ style: [containerStyle, style],
137
+ testID: testID,
138
+ children: [mediaContent, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
139
+ style: textWrapStyle,
140
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
141
+ style: titleStyle,
142
+ children: title
143
+ }), showSupportText && supportText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
144
+ style: supportTextStyle,
145
+ children: supportText
146
+ }) : null, buttonContent]
147
+ })]
148
+ });
149
+ }
150
+ var _default = exports.default = LottieIntroBlock;
@@ -0,0 +1,153 @@
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 _Button = _interopRequireDefault(require("../Button/Button"));
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
+ /**
17
+ * PageHero displays a centered hero block typically used at the top of a page
18
+ * or feature screen. It contains an eyebrow line, a large headline, an optional
19
+ * supporting line (e.g. price/timeline), and an optional action button.
20
+ *
21
+ * All visual values are resolved from Figma design tokens via
22
+ * `getVariableByName`. The button slot cascades the active `modes` to its
23
+ * children through `cloneChildrenWithModes`.
24
+ *
25
+ * @component
26
+ * @example
27
+ * ```tsx
28
+ * <PageHero
29
+ * eyebrow="Upgrade to JioFinance+"
30
+ * headline="Resume earning cashback, extra points, and 1% gold"
31
+ * supportingText="₹999/year · ₹0 until 2027"
32
+ * buttonLabel="Renew for free"
33
+ * onButtonPress={() => navigate('Upgrade')}
34
+ * />
35
+ * ```
36
+ */
37
+ function PageHero({
38
+ eyebrow = 'Upgrade to JioFinance+',
39
+ headline = 'Resume earning cashback, extra points, and 1% gold',
40
+ supportingText = '₹999/year · ₹0 until 2027',
41
+ showSupportingText = true,
42
+ buttonLabel = 'Renew for free',
43
+ onButtonPress,
44
+ showButton = true,
45
+ buttonSlot,
46
+ modes: propModes = _reactUtils.EMPTY_MODES,
47
+ style,
48
+ testID
49
+ }) {
50
+ const {
51
+ modes: globalModes
52
+ } = (0, _JFSThemeProvider.useTokens)();
53
+ const modes = (0, _react.useMemo)(() => ({
54
+ ...globalModes,
55
+ ...propModes
56
+ }), [globalModes, propModes]);
57
+ const gap = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/gap', modes)) || 16;
58
+ const paddingHorizontal = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/padding/horizontal', modes)) || 0;
59
+ const textWrapGap = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/textWrap/gap', modes)) || 8;
60
+ const eyebrowColor = (0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/color', modes) || '#ffffff';
61
+ const eyebrowFontFamily = (0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/fontFamily', modes) || 'System';
62
+ const eyebrowFontSize = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/fontSize', modes)) || 18;
63
+ const eyebrowFontWeight = (0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/fontWeight', modes) || 700;
64
+ const eyebrowLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/eyebrow/lineHeight', modes)) || 20;
65
+ const headlineColor = (0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/color', modes) || '#ffffff';
66
+ const headlineFontFamily = (0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/fontFamily', modes) || 'System';
67
+ const headlineFontSize = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/fontSize', modes)) || 29;
68
+ const headlineFontWeight = (0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/fontWeight', modes) || 900;
69
+ const headlineLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/headline/lineHeight', modes)) || 29;
70
+
71
+ // Only `lineHeight` is tokenized for the supporting text in the Figma source.
72
+ // Color, font size and weight are inline literals in the design (12px medium
73
+ // white) — we mirror that here so the visual stays faithful when no token
74
+ // exists.
75
+ const supportingTextLineHeight = Number((0, _figmaVariablesResolver.getVariableByName)('PageHero/supportingText/lineHeight', modes)) || 16;
76
+ const containerStyle = {
77
+ flexDirection: 'column',
78
+ alignItems: 'center',
79
+ paddingHorizontal,
80
+ gap,
81
+ width: '100%'
82
+ };
83
+ const textWrapStyle = {
84
+ flexDirection: 'column',
85
+ alignItems: 'center',
86
+ gap: textWrapGap,
87
+ width: '100%'
88
+ };
89
+ const eyebrowStyle = {
90
+ color: eyebrowColor,
91
+ fontFamily: eyebrowFontFamily,
92
+ fontSize: eyebrowFontSize,
93
+ fontWeight: String(eyebrowFontWeight),
94
+ lineHeight: eyebrowLineHeight,
95
+ textAlign: 'center'
96
+ };
97
+ const headlineStyle = {
98
+ color: headlineColor,
99
+ fontFamily: headlineFontFamily,
100
+ fontSize: headlineFontSize,
101
+ fontWeight: String(headlineFontWeight),
102
+ lineHeight: headlineLineHeight,
103
+ textAlign: 'center',
104
+ width: '100%'
105
+ };
106
+ const supportingTextStyle = {
107
+ color: '#ffffff',
108
+ fontFamily: 'System',
109
+ fontSize: 12,
110
+ fontWeight: '500',
111
+ lineHeight: supportingTextLineHeight,
112
+ textAlign: 'center'
113
+ };
114
+ const buttonWrapStyle = {
115
+ width: '100%'
116
+ };
117
+ const buttonContent = (0, _react.useMemo)(() => {
118
+ if (buttonSlot !== undefined && buttonSlot !== null) {
119
+ return (0, _reactUtils.cloneChildrenWithModes)(buttonSlot, modes);
120
+ }
121
+ if (!showButton) {
122
+ return null;
123
+ }
124
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
125
+ label: buttonLabel,
126
+ onPress: onButtonPress,
127
+ modes: modes,
128
+ style: buttonWrapStyle
129
+ });
130
+ // buttonWrapStyle is a literal object created above; it is intentionally
131
+ // omitted from deps because its identity changes on every render but its
132
+ // shape never does.
133
+ // eslint-disable-next-line react-hooks/exhaustive-deps
134
+ }, [buttonSlot, showButton, buttonLabel, onButtonPress, modes]);
135
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
136
+ style: [containerStyle, style],
137
+ testID: testID,
138
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
139
+ style: textWrapStyle,
140
+ children: [eyebrow ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
141
+ style: eyebrowStyle,
142
+ children: eyebrow
143
+ }) : null, headline ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
144
+ style: headlineStyle,
145
+ children: headline
146
+ }) : null]
147
+ }), showSupportingText && supportingText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
148
+ style: supportingTextStyle,
149
+ children: supportingText
150
+ }) : null, buttonContent]
151
+ });
152
+ }
153
+ var _default = exports.default = PageHero;
@@ -0,0 +1,135 @@
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 _reactUtils = require("../../utils/react-utils");
12
+ var _MediaSource = _interopRequireDefault(require("../../utils/MediaSource"));
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
+ // Default bundled FINVU brand logo, matching the Figma reference so the
17
+ // component renders correctly out of the box without any image prop.
18
+ const DEFAULT_LOGO = require('./finvu.png');
19
+ const DEFAULT_LABEL = 'Powered by RBI-regulated account aggregator';
20
+ const DEFAULT_IMAGE_WIDTH = 33;
21
+ const DEFAULT_IMAGE_HEIGHT = 12;
22
+ const toNumber = (value, fallback) => {
23
+ if (typeof value === 'number') return Number.isFinite(value) ? value : fallback;
24
+ if (typeof value === 'string') {
25
+ const parsed = Number(value);
26
+ return Number.isFinite(parsed) ? parsed : fallback;
27
+ }
28
+ return fallback;
29
+ };
30
+ const toFontWeight = (value, fallback) => {
31
+ if (typeof value === 'number') return String(value);
32
+ if (typeof value === 'string') return value;
33
+ return fallback;
34
+ };
35
+
36
+ /**
37
+ * `PoweredByLabel` renders the small "Powered by RBI-regulated account
38
+ * aggregator" badge with a trailing brand logo, used to attribute the
39
+ * underlying account-aggregator partner in flows such as bank-account
40
+ * linking and consent screens.
41
+ *
42
+ * The component is composed of:
43
+ *
44
+ * 1. A token-styled pill container (`poweredByLabel/background`,
45
+ * `poweredByLabel/padding/*`).
46
+ * 2. The disclosure copy rendered through the `poweredByLabel/*` typography
47
+ * tokens.
48
+ * 3. A configurable brand logo slot. Defaults to the bundled FINVU mark, but
49
+ * callers can pass any image via `imageSource` or fully replace the slot
50
+ * via `imageSlot`.
51
+ *
52
+ * @component
53
+ * @param {PoweredByLabelProps} props
54
+ */
55
+ function PoweredByLabel({
56
+ label = DEFAULT_LABEL,
57
+ imageSource,
58
+ imageWidth = DEFAULT_IMAGE_WIDTH,
59
+ imageHeight = DEFAULT_IMAGE_HEIGHT,
60
+ imageSlot,
61
+ modes: propModes = _reactUtils.EMPTY_MODES,
62
+ style,
63
+ textStyle,
64
+ imageStyle,
65
+ accessibilityLabel
66
+ }) {
67
+ const {
68
+ modes: globalModes
69
+ } = (0, _JFSThemeProvider.useTokens)();
70
+ const modes = (0, _react.useMemo)(() => globalModes === _reactUtils.EMPTY_MODES && propModes === _reactUtils.EMPTY_MODES ? _reactUtils.EMPTY_MODES : {
71
+ ...globalModes,
72
+ ...propModes
73
+ }, [globalModes, propModes]);
74
+ const background = (0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/background', modes) ?? '#f5f5f5';
75
+ const foreground = (0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/foreground', modes) ?? '#191b1e';
76
+ const fontFamily = (0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/fontFamily', modes) ?? 'JioType Var';
77
+ const fontSize = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/fontSize', modes), 10);
78
+ const lineHeight = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/lineHeight', modes), 12);
79
+ const fontWeight = toFontWeight((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/fontWeight', modes), '400');
80
+ const gap = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/gap', modes), 10);
81
+ const paddingHorizontal = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/padding/horizontal', modes), 16);
82
+ const paddingVertical = toNumber((0, _figmaVariablesResolver.getVariableByName)('poweredByLabel/padding/vertical', modes), 6);
83
+ const containerStyle = {
84
+ flexDirection: 'row',
85
+ alignItems: 'center',
86
+ justifyContent: 'center',
87
+ backgroundColor: background,
88
+ paddingHorizontal,
89
+ paddingVertical,
90
+ gap,
91
+ // Hug content horizontally so the pill does not stretch to fill the
92
+ // parent (matches Badge, BrandChip, etc.). Override via `style` if
93
+ // you want it full-width (e.g. inside a card footer).
94
+ alignSelf: 'flex-start'
95
+ };
96
+ const labelTextStyle = {
97
+ color: foreground,
98
+ fontFamily,
99
+ fontSize,
100
+ lineHeight,
101
+ fontWeight,
102
+ textAlign: 'center',
103
+ flexShrink: 1
104
+ };
105
+ const renderImage = () => {
106
+ if (imageSlot !== undefined && imageSlot !== null) {
107
+ const processed = (0, _reactUtils.cloneChildrenWithModes)(imageSlot, modes);
108
+ if (processed.length === 0) return null;
109
+ return processed.length === 1 ? processed[0] : processed;
110
+ }
111
+ const resolvedSource = imageSource ?? DEFAULT_LOGO;
112
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_MediaSource.default, {
113
+ source: resolvedSource,
114
+ width: imageWidth,
115
+ height: imageHeight,
116
+ resizeMode: "contain",
117
+ style: imageStyle,
118
+ accessibilityElementsHidden: true,
119
+ importantForAccessibility: "no"
120
+ });
121
+ };
122
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
123
+ accessibilityRole: "text",
124
+ accessibilityLabel: accessibilityLabel ?? label,
125
+ style: [containerStyle, style],
126
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
127
+ style: [labelTextStyle, textStyle],
128
+ accessibilityElementsHidden: true,
129
+ importantForAccessibility: "no",
130
+ numberOfLines: 1,
131
+ children: label
132
+ }), renderImage()]
133
+ });
134
+ }
135
+ var _default = exports.default = PoweredByLabel;
@@ -15,7 +15,8 @@ const TEXT_ALIGN_MAP = {
15
15
  Center: 'center'
16
16
  };
17
17
  function Text({
18
- text = 'Korem ipsum ',
18
+ text,
19
+ children,
19
20
  textAlign = 'Left',
20
21
  modes = _reactUtils.EMPTY_MODES,
21
22
  style,
@@ -36,10 +37,16 @@ function Text({
36
37
  letterSpacing: letterSpacing,
37
38
  textAlign: TEXT_ALIGN_MAP[textAlign]
38
39
  };
40
+
41
+ // Prefer JSX children when present, otherwise fall back to the `text` prop.
42
+ // Keep the storybook placeholder as a last resort so the Default story
43
+ // still renders something visible when no content is supplied via either
44
+ // route.
45
+ const content = children !== undefined && children !== null && children !== false ? children : text !== undefined ? text : 'Korem ipsum ';
39
46
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
40
47
  style: [textStyle, style],
41
48
  numberOfLines: numberOfLines,
42
- children: text
49
+ children: content
43
50
  });
44
51
  }
45
52
  var _default = exports.default = Text;
@@ -172,7 +172,9 @@ function TooltipTrigger({
172
172
  }
173
173
  function TooltipContent({
174
174
  children,
175
- sideOffset = 4
175
+ sideOffset = 4,
176
+ gap = 4,
177
+ alignItems = 'flex-start'
176
178
  }) {
177
179
  const {
178
180
  isVisible,
@@ -397,6 +399,35 @@ function TooltipContent({
397
399
  paddingHorizontal: paddingH,
398
400
  paddingVertical: paddingV
399
401
  };
402
+
403
+ // Vertical slot wrapper: stack arbitrary children top-to-bottom with a gap.
404
+ // Raw <Text> children still get auto-styled with the tooltip label tokens
405
+ // so the simple <TooltipContent><Text>label</Text></TooltipContent> usage
406
+ // keeps working without any changes.
407
+ const slotStyle = {
408
+ flexDirection: 'column',
409
+ alignItems,
410
+ gap
411
+ };
412
+ const renderSlotChildren = () => {
413
+ if (typeof children === 'string') {
414
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
415
+ style: textStyle,
416
+ children: children
417
+ });
418
+ }
419
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
420
+ style: slotStyle,
421
+ children: _react.default.Children.map(children, child => {
422
+ if (/*#__PURE__*/_react.default.isValidElement(child) && (child.type === _reactNative.Text || child.type.displayName === 'Text')) {
423
+ return /*#__PURE__*/_react.default.cloneElement(child, {
424
+ style: [textStyle, child.props.style]
425
+ });
426
+ }
427
+ return child;
428
+ })
429
+ });
430
+ };
400
431
  if (!hasMeasured) {
401
432
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Modal, {
402
433
  transparent: true,
@@ -408,19 +439,7 @@ function TooltipContent({
408
439
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
409
440
  style: measureStyle,
410
441
  onLayout: e => setContentSize(e.nativeEvent.layout),
411
- children: typeof children === 'string' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
412
- style: textStyle,
413
- children: children
414
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
415
- children: _react.default.Children.map(children, child => {
416
- if (/*#__PURE__*/_react.default.isValidElement(child) && (child.type === _reactNative.Text || child.type.displayName === 'Text')) {
417
- return /*#__PURE__*/_react.default.cloneElement(child, {
418
- style: [textStyle, child.props.style]
419
- });
420
- }
421
- return child;
422
- })
423
- })
442
+ children: renderSlotChildren()
424
443
  })
425
444
  })
426
445
  });
@@ -451,19 +470,7 @@ function TooltipContent({
451
470
  shadowRadius: 3.84,
452
471
  elevation: 5
453
472
  }],
454
- children: [typeof children === 'string' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
455
- style: textStyle,
456
- children: children
457
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
458
- children: _react.default.Children.map(children, child => {
459
- if (/*#__PURE__*/_react.default.isValidElement(child) && (child.type === _reactNative.Text || child.type.displayName === 'Text')) {
460
- return /*#__PURE__*/_react.default.cloneElement(child, {
461
- style: [textStyle, child.props.style]
462
- });
463
- }
464
- return child;
465
- })
466
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
473
+ children: [renderSlotChildren(), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
467
474
  style: {
468
475
  position: 'absolute',
469
476
  left: arrowX,