jfs-components 0.0.71 → 0.0.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/lib/commonjs/components/CardAdvisory/CardAdvisory.js +2 -2
- package/lib/commonjs/components/CardFinancialCondition/CardFinancialCondition.js +213 -0
- package/lib/commonjs/components/Carousel/Carousel.js +9 -7
- package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +2 -2
- package/lib/commonjs/components/InstitutionBadge/InstitutionBadge.js +132 -0
- package/lib/commonjs/components/Radio/Radio.js +194 -0
- package/lib/commonjs/components/RadioButton/RadioButton.js +21 -188
- package/lib/commonjs/components/index.js +21 -0
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/module/components/CardAdvisory/CardAdvisory.js +2 -2
- package/lib/module/components/CardFinancialCondition/CardFinancialCondition.js +207 -0
- package/lib/module/components/Carousel/Carousel.js +9 -7
- package/lib/module/components/HoldingsCard/HoldingsCard.js +2 -2
- package/lib/module/components/InstitutionBadge/InstitutionBadge.js +127 -0
- package/lib/module/components/Radio/Radio.js +188 -0
- package/lib/module/components/RadioButton/RadioButton.js +20 -185
- package/lib/module/components/index.js +7 -0
- package/lib/module/icons/registry.js +1 -1
- package/lib/typescript/src/components/CardFinancialCondition/CardFinancialCondition.d.ts +50 -0
- package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +30 -0
- package/lib/typescript/src/components/Radio/Radio.d.ts +30 -0
- package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +20 -28
- package/lib/typescript/src/components/index.d.ts +7 -0
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/CardAdvisory/CardAdvisory.tsx +2 -2
- package/src/components/CardFinancialCondition/CardFinancialCondition.tsx +366 -0
- package/src/components/Carousel/Carousel.tsx +14 -6
- package/src/components/HoldingsCard/HoldingsCard.tsx +2 -2
- package/src/components/InstitutionBadge/InstitutionBadge.tsx +216 -0
- package/src/components/Radio/Radio.tsx +227 -0
- package/src/components/RadioButton/RadioButton.tsx +23 -225
- package/src/components/index.ts +7 -0
- package/src/icons/registry.ts +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, type StyleProp, type TextStyle, type ViewStyle } from 'react-native';
|
|
3
|
+
import { type CircularProgressBarProps } from '../CircularProgressBar/CircularProgressBar';
|
|
4
|
+
type CardFinancialConditionBaseProps = Omit<React.ComponentProps<typeof View>, 'children' | 'style'>;
|
|
5
|
+
export type CardFinancialConditionProps = CardFinancialConditionBaseProps & {
|
|
6
|
+
/** Title text shown in the header. */
|
|
7
|
+
title?: string;
|
|
8
|
+
/** Body / description shown below the title. */
|
|
9
|
+
body?: string;
|
|
10
|
+
/** Progress score for the circular indicator. Forwarded to CircularProgressBar. */
|
|
11
|
+
value?: number;
|
|
12
|
+
/** Visual state of the circular indicator. Forwarded to CircularProgressBar. */
|
|
13
|
+
progressState?: CircularProgressBarProps['state'];
|
|
14
|
+
/** Optional formatted value label for the active state. */
|
|
15
|
+
valueLabel?: string;
|
|
16
|
+
/** Show the bottom advisory nudge. */
|
|
17
|
+
showNudge?: boolean;
|
|
18
|
+
/** Body text for the default nudge. Use `\n` to add a second line. */
|
|
19
|
+
nudgeBody?: string;
|
|
20
|
+
/** Show the bottom divider above the action button. */
|
|
21
|
+
showDivider?: boolean;
|
|
22
|
+
/** Show the action button at the bottom of the card. */
|
|
23
|
+
showButton?: boolean;
|
|
24
|
+
/** Label for the default action button. */
|
|
25
|
+
buttonLabel?: string;
|
|
26
|
+
/** Callback for the default action button press. */
|
|
27
|
+
onPressButton?: () => void;
|
|
28
|
+
/** Slot replacing the default circular progress bar. Receives `modes` recursively. */
|
|
29
|
+
progressSlot?: React.ReactNode;
|
|
30
|
+
/** Slot replacing the default Nudge. Receives `modes` recursively. */
|
|
31
|
+
nudgeSlot?: React.ReactNode;
|
|
32
|
+
/** Slot replacing the default action button. Receives `modes` recursively. */
|
|
33
|
+
buttonSlot?: React.ReactNode;
|
|
34
|
+
/** Design token modes forwarded to token lookups and child components. */
|
|
35
|
+
modes?: Record<string, any>;
|
|
36
|
+
/** Container style override. */
|
|
37
|
+
style?: StyleProp<ViewStyle>;
|
|
38
|
+
/** Header row style override. */
|
|
39
|
+
headerStyle?: StyleProp<ViewStyle>;
|
|
40
|
+
/** Title text style override. */
|
|
41
|
+
titleStyle?: StyleProp<TextStyle>;
|
|
42
|
+
/** Body text style override. */
|
|
43
|
+
bodyStyle?: StyleProp<TextStyle>;
|
|
44
|
+
/** Accessibility label for the whole card. */
|
|
45
|
+
accessibilityLabel?: string;
|
|
46
|
+
};
|
|
47
|
+
declare function CardFinancialCondition({ title, body, value, progressState, valueLabel, showNudge, nudgeBody, showDivider, showButton, buttonLabel, onPressButton, progressSlot, nudgeSlot, buttonSlot, modes: propModes, style, headerStyle, titleStyle, bodyStyle, accessibilityLabel, ...rest }: CardFinancialConditionProps): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
declare const _default: React.MemoExoticComponent<typeof CardFinancialCondition>;
|
|
49
|
+
export default _default;
|
|
50
|
+
//# sourceMappingURL=CardFinancialCondition.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, type StyleProp, type TextStyle, type ViewStyle } from 'react-native';
|
|
3
|
+
import { type UnifiedSource } from '../../utils/MediaSource';
|
|
4
|
+
type InstitutionBadgeBaseProps = Omit<React.ComponentProps<typeof View>, 'children' | 'style'>;
|
|
5
|
+
export type InstitutionBadgeProps = InstitutionBadgeBaseProps & {
|
|
6
|
+
/** Visible label for the institution (e.g. bank name). */
|
|
7
|
+
label?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Unified avatar source. Accepts a remote URI (raster or `.svg`), an
|
|
10
|
+
* inline SVG XML string, a `require()` asset, an SVG React component,
|
|
11
|
+
* or an already-rendered React element. Smart-detects raster vs SVG so
|
|
12
|
+
* the same prop works on iOS, Android and web. See {@link UnifiedSource}.
|
|
13
|
+
* Ignored when `avatarSlot` is provided.
|
|
14
|
+
*/
|
|
15
|
+
source?: UnifiedSource;
|
|
16
|
+
/** Slot replacing the default Avatar (e.g. for monogram avatars). Receives `modes` recursively. */
|
|
17
|
+
avatarSlot?: React.ReactNode;
|
|
18
|
+
/** Design token modes forwarded to token lookups and the Avatar slot. */
|
|
19
|
+
modes?: Record<string, any>;
|
|
20
|
+
/** Container style override. */
|
|
21
|
+
style?: StyleProp<ViewStyle>;
|
|
22
|
+
/** Label style override. */
|
|
23
|
+
labelStyle?: StyleProp<TextStyle>;
|
|
24
|
+
/** Accessibility label. Defaults to `label`. */
|
|
25
|
+
accessibilityLabel?: string;
|
|
26
|
+
};
|
|
27
|
+
declare function InstitutionBadge({ label, source, avatarSlot, modes: propModes, style, labelStyle, accessibilityLabel, ...rest }: InstitutionBadgeProps): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
declare const _default: React.MemoExoticComponent<typeof InstitutionBadge>;
|
|
29
|
+
export default _default;
|
|
30
|
+
//# sourceMappingURL=InstitutionBadge.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ViewStyle, StyleProp } from 'react-native';
|
|
2
|
+
export interface RadioProps {
|
|
3
|
+
/**
|
|
4
|
+
* Whether the radio is selected.
|
|
5
|
+
*/
|
|
6
|
+
selected?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Whether the radio is disabled.
|
|
9
|
+
*/
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Function to call when the radio is pressed.
|
|
13
|
+
*/
|
|
14
|
+
onPress?: () => void;
|
|
15
|
+
/**
|
|
16
|
+
* Modes object for design-token resolution.
|
|
17
|
+
*/
|
|
18
|
+
modes?: Record<string, any>;
|
|
19
|
+
/**
|
|
20
|
+
* Custom style for the radio container.
|
|
21
|
+
*/
|
|
22
|
+
style?: StyleProp<ViewStyle>;
|
|
23
|
+
/**
|
|
24
|
+
* Test ID for testing.
|
|
25
|
+
*/
|
|
26
|
+
testID?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function Radio({ selected, disabled, onPress, modes, style, testID, }: RadioProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export default Radio;
|
|
30
|
+
//# sourceMappingURL=Radio.d.ts.map
|
|
@@ -1,30 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
style?: StyleProp<ViewStyle>;
|
|
23
|
-
/**
|
|
24
|
-
* Test ID for testing.
|
|
25
|
-
*/
|
|
26
|
-
testID?: string;
|
|
27
|
-
}
|
|
28
|
-
export declare function RadioButton({ selected, disabled, onPress, modes, style, testID, }: RadioButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated `RadioButton` has been renamed to `Radio`.
|
|
3
|
+
*
|
|
4
|
+
* This file is kept as a backward-compatibility shim for teams that may be
|
|
5
|
+
* importing `RadioButton` directly from this deep path:
|
|
6
|
+
*
|
|
7
|
+
* import RadioButton from 'jfs-components/src/components/RadioButton/RadioButton'
|
|
8
|
+
* import { RadioButton, RadioButtonProps } from '...'
|
|
9
|
+
*
|
|
10
|
+
* The recommended public import is now:
|
|
11
|
+
*
|
|
12
|
+
* import { Radio, type RadioProps } from 'jfs-components'
|
|
13
|
+
*
|
|
14
|
+
* Going forward, this component is called `Radio`. This shim only re-exports
|
|
15
|
+
* the new `Radio` component under the old `RadioButton` names; please migrate
|
|
16
|
+
* existing usages to `Radio` at your earliest convenience.
|
|
17
|
+
*/
|
|
18
|
+
import { Radio, type RadioProps } from '../Radio/Radio';
|
|
19
|
+
export type RadioButtonProps = RadioProps;
|
|
20
|
+
export declare const RadioButton: typeof Radio;
|
|
29
21
|
export default RadioButton;
|
|
30
22
|
//# sourceMappingURL=RadioButton.d.ts.map
|
|
@@ -12,6 +12,7 @@ export { default as Carousel } from './Carousel/Carousel';
|
|
|
12
12
|
export type { CarouselProps, CarouselItemProps, PaginationProps } from './Carousel/Carousel';
|
|
13
13
|
export { default as Checkbox, type CheckboxProps } from './Checkbox/Checkbox';
|
|
14
14
|
export { default as CardFeedback, type CardFeedbackProps } from './CardFeedback/CardFeedback';
|
|
15
|
+
export { default as CardFinancialCondition, type CardFinancialConditionProps } from './CardFinancialCondition/CardFinancialCondition';
|
|
15
16
|
export { default as Disclaimer } from './Disclaimer/Disclaimer';
|
|
16
17
|
export { default as Divider, type DividerProps, type DividerDirection } from './Divider/Divider';
|
|
17
18
|
export { default as Drawer } from './Drawer/Drawer';
|
|
@@ -65,8 +66,14 @@ export { default as ButtonGroup, type ButtonGroupProps } from './ButtonGroup/But
|
|
|
65
66
|
export { default as CardProviderInfo, type CardProviderInfoProps } from './CardProviderInfo/CardProviderInfo';
|
|
66
67
|
export { default as ChipSelect, type ChipSelectProps } from './ChipSelect/ChipSelect';
|
|
67
68
|
export { default as InputSearch, type InputSearchProps } from './InputSearch/InputSearch';
|
|
69
|
+
export { default as InstitutionBadge, type InstitutionBadgeProps } from './InstitutionBadge/InstitutionBadge';
|
|
68
70
|
export { default as SupportText, type SupportTextProps } from './SupportText/SupportText';
|
|
69
71
|
export { default as SupportTextIcon, type SupportTextIconProps, type SupportTextStatus } from './SupportText/SupportTextIcon';
|
|
72
|
+
export { default as Radio, type RadioProps } from './Radio/Radio';
|
|
73
|
+
/**
|
|
74
|
+
* @deprecated Use `Radio` instead. `RadioButton` is kept as an alias for
|
|
75
|
+
* backward compatibility and will be removed in a future major release.
|
|
76
|
+
*/
|
|
70
77
|
export { default as RadioButton, type RadioButtonProps } from './RadioButton/RadioButton';
|
|
71
78
|
export { default as RechargeCard, type RechargeCardProps } from './RechargeCard/RechargeCard';
|
|
72
79
|
export { default as Tabs, type TabsProps } from './Tabs/Tabs';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Auto-generated from SVG files in src/icons/
|
|
5
5
|
* DO NOT EDIT MANUALLY - Run "npm run icons:generate" to regenerate
|
|
6
6
|
*
|
|
7
|
-
* Generated: 2026-
|
|
7
|
+
* Generated: 2026-05-04T12:27:11.660Z
|
|
8
8
|
*/
|
|
9
9
|
export declare const iconRegistry: Record<string, {
|
|
10
10
|
path: string;
|
package/package.json
CHANGED
|
@@ -97,8 +97,8 @@ const toFontWeight = (value: unknown, fallback: TextStyle['fontWeight']) => {
|
|
|
97
97
|
function resolveCardAdvisoryTokens(modes: Record<string, any>): CardAdvisoryTokens {
|
|
98
98
|
const width = toNumber(getVariableByName('cardAdvisory/width', modes), 360)
|
|
99
99
|
const gap = toNumber(getVariableByName('cardAdvisory/gap', modes), 16)
|
|
100
|
-
const paddingHorizontal = toNumber(getVariableByName('cardAdvisory/padding/horizontal', modes),
|
|
101
|
-
const paddingVertical = toNumber(getVariableByName('cardAdvisory/padding/vertical', modes),
|
|
100
|
+
const paddingHorizontal = toNumber(getVariableByName('cardAdvisory/padding/horizontal', modes), 0)
|
|
101
|
+
const paddingVertical = toNumber(getVariableByName('cardAdvisory/padding/vertical', modes), 0)
|
|
102
102
|
const radius = toNumber(getVariableByName('cardAdvisory/radius', modes), 0)
|
|
103
103
|
const background = getVariableByName('cardAdvisory/background', modes) || '#ffffff'
|
|
104
104
|
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import React, { useMemo } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
Text,
|
|
4
|
+
View,
|
|
5
|
+
type StyleProp,
|
|
6
|
+
type TextStyle,
|
|
7
|
+
type ViewStyle,
|
|
8
|
+
} from 'react-native'
|
|
9
|
+
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
10
|
+
import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
11
|
+
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
|
|
12
|
+
import Button from '../Button/Button'
|
|
13
|
+
import CircularProgressBar, {
|
|
14
|
+
type CircularProgressBarProps,
|
|
15
|
+
} from '../CircularProgressBar/CircularProgressBar'
|
|
16
|
+
import Divider from '../Divider/Divider'
|
|
17
|
+
import Nudge from '../Nudge/Nudge'
|
|
18
|
+
|
|
19
|
+
type CardFinancialConditionBaseProps = Omit<
|
|
20
|
+
React.ComponentProps<typeof View>,
|
|
21
|
+
'children' | 'style'
|
|
22
|
+
>
|
|
23
|
+
|
|
24
|
+
export type CardFinancialConditionProps = CardFinancialConditionBaseProps & {
|
|
25
|
+
/** Title text shown in the header. */
|
|
26
|
+
title?: string
|
|
27
|
+
/** Body / description shown below the title. */
|
|
28
|
+
body?: string
|
|
29
|
+
/** Progress score for the circular indicator. Forwarded to CircularProgressBar. */
|
|
30
|
+
value?: number
|
|
31
|
+
/** Visual state of the circular indicator. Forwarded to CircularProgressBar. */
|
|
32
|
+
progressState?: CircularProgressBarProps['state']
|
|
33
|
+
/** Optional formatted value label for the active state. */
|
|
34
|
+
valueLabel?: string
|
|
35
|
+
/** Show the bottom advisory nudge. */
|
|
36
|
+
showNudge?: boolean
|
|
37
|
+
/** Body text for the default nudge. Use `\n` to add a second line. */
|
|
38
|
+
nudgeBody?: string
|
|
39
|
+
/** Show the bottom divider above the action button. */
|
|
40
|
+
showDivider?: boolean
|
|
41
|
+
/** Show the action button at the bottom of the card. */
|
|
42
|
+
showButton?: boolean
|
|
43
|
+
/** Label for the default action button. */
|
|
44
|
+
buttonLabel?: string
|
|
45
|
+
/** Callback for the default action button press. */
|
|
46
|
+
onPressButton?: () => void
|
|
47
|
+
/** Slot replacing the default circular progress bar. Receives `modes` recursively. */
|
|
48
|
+
progressSlot?: React.ReactNode
|
|
49
|
+
/** Slot replacing the default Nudge. Receives `modes` recursively. */
|
|
50
|
+
nudgeSlot?: React.ReactNode
|
|
51
|
+
/** Slot replacing the default action button. Receives `modes` recursively. */
|
|
52
|
+
buttonSlot?: React.ReactNode
|
|
53
|
+
/** Design token modes forwarded to token lookups and child components. */
|
|
54
|
+
modes?: Record<string, any>
|
|
55
|
+
/** Container style override. */
|
|
56
|
+
style?: StyleProp<ViewStyle>
|
|
57
|
+
/** Header row style override. */
|
|
58
|
+
headerStyle?: StyleProp<ViewStyle>
|
|
59
|
+
/** Title text style override. */
|
|
60
|
+
titleStyle?: StyleProp<TextStyle>
|
|
61
|
+
/** Body text style override. */
|
|
62
|
+
bodyStyle?: StyleProp<TextStyle>
|
|
63
|
+
/** Accessibility label for the whole card. */
|
|
64
|
+
accessibilityLabel?: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface CardFinancialConditionTokens {
|
|
68
|
+
containerStyle: ViewStyle
|
|
69
|
+
headerStyle: ViewStyle
|
|
70
|
+
textContentStyle: ViewStyle
|
|
71
|
+
titleStyle: TextStyle
|
|
72
|
+
bodyStyle: TextStyle
|
|
73
|
+
nudgeBodyStyle: TextStyle
|
|
74
|
+
buttonWrapStyle: ViewStyle
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const toNumber = (value: unknown, fallback: number) => {
|
|
78
|
+
if (typeof value === 'number') {
|
|
79
|
+
return Number.isFinite(value) ? value : fallback
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (typeof value === 'string') {
|
|
83
|
+
const parsed = Number(value)
|
|
84
|
+
return Number.isFinite(parsed) ? parsed : fallback
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return fallback
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const toFontWeight = (value: unknown, fallback: TextStyle['fontWeight']) => {
|
|
91
|
+
if (typeof value === 'number') {
|
|
92
|
+
return String(value) as TextStyle['fontWeight']
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (typeof value === 'string') {
|
|
96
|
+
return value as TextStyle['fontWeight']
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return fallback
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function resolveCardFinancialConditionTokens(
|
|
103
|
+
modes: Record<string, any>
|
|
104
|
+
): CardFinancialConditionTokens {
|
|
105
|
+
const background =
|
|
106
|
+
(getVariableByName('financialConditionCard/background', modes) as string) ||
|
|
107
|
+
'#ffffff'
|
|
108
|
+
const radius = toNumber(
|
|
109
|
+
getVariableByName('financialConditionCard/radius', modes),
|
|
110
|
+
16
|
|
111
|
+
)
|
|
112
|
+
const paddingH = toNumber(
|
|
113
|
+
getVariableByName('financialConditionCard/padding/horizontal', modes),
|
|
114
|
+
16
|
|
115
|
+
)
|
|
116
|
+
const paddingV = toNumber(
|
|
117
|
+
getVariableByName('financialConditionCard/padding/vertical', modes),
|
|
118
|
+
16
|
|
119
|
+
)
|
|
120
|
+
const gap = toNumber(
|
|
121
|
+
getVariableByName('financialConditionCard/gap', modes),
|
|
122
|
+
8
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
const headerGap = toNumber(
|
|
126
|
+
getVariableByName('financialConditionCard/header/gap', modes),
|
|
127
|
+
16
|
|
128
|
+
)
|
|
129
|
+
const textContentGap = toNumber(
|
|
130
|
+
getVariableByName('financialConditionCard/textContent/gap', modes),
|
|
131
|
+
8
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
const titleColor =
|
|
135
|
+
(getVariableByName('financialConditionCard/title/color', modes) as string) ||
|
|
136
|
+
'#0c0d10'
|
|
137
|
+
const titleFontSize = toNumber(
|
|
138
|
+
getVariableByName('financialConditionCard/title/fontSize', modes),
|
|
139
|
+
16
|
|
140
|
+
)
|
|
141
|
+
const titleFontFamily =
|
|
142
|
+
(getVariableByName(
|
|
143
|
+
'financialConditionCard/title/fontFamily',
|
|
144
|
+
modes
|
|
145
|
+
) as string) || 'JioType Var'
|
|
146
|
+
const titleLineHeight = toNumber(
|
|
147
|
+
getVariableByName('financialConditionCard/title/lineHeight', modes),
|
|
148
|
+
18
|
|
149
|
+
)
|
|
150
|
+
const titleFontWeight = toFontWeight(
|
|
151
|
+
getVariableByName('financialConditionCard/title/fontWeight', modes),
|
|
152
|
+
'700'
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
const bodyColor =
|
|
156
|
+
(getVariableByName('financialConditionCard/body/color', modes) as string) ||
|
|
157
|
+
'#0c0d10'
|
|
158
|
+
const bodyFontSize = toNumber(
|
|
159
|
+
getVariableByName('financialConditionCard/body/fontSize', modes),
|
|
160
|
+
14
|
|
161
|
+
)
|
|
162
|
+
const bodyFontFamily =
|
|
163
|
+
(getVariableByName(
|
|
164
|
+
'financialConditionCard/body/fontFamily',
|
|
165
|
+
modes
|
|
166
|
+
) as string) || 'JioType Var'
|
|
167
|
+
const bodyLineHeight = toNumber(
|
|
168
|
+
getVariableByName('financialConditionCard/body/lineHeight', modes),
|
|
169
|
+
17
|
|
170
|
+
)
|
|
171
|
+
const bodyFontWeight = toFontWeight(
|
|
172
|
+
getVariableByName('financialConditionCard/body/fontWeight', modes),
|
|
173
|
+
'400'
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
const nudgeBodyColor =
|
|
177
|
+
(getVariableByName('nudge/body/color', modes) as string) || '#1a1c1f'
|
|
178
|
+
const nudgeBodyFontSize = toNumber(
|
|
179
|
+
getVariableByName('nudge/body/fontSize', modes),
|
|
180
|
+
12
|
|
181
|
+
)
|
|
182
|
+
const nudgeBodyFontFamily =
|
|
183
|
+
(getVariableByName('nudge/body/fontFamily', modes) as string) || 'JioType Var'
|
|
184
|
+
const nudgeBodyLineHeight = toNumber(
|
|
185
|
+
getVariableByName('nudge/body/lineHeight', modes),
|
|
186
|
+
16
|
|
187
|
+
)
|
|
188
|
+
const nudgeBodyFontWeight = toFontWeight(
|
|
189
|
+
getVariableByName('nudge/body/fontWeight', modes),
|
|
190
|
+
'500'
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
containerStyle: {
|
|
195
|
+
alignItems: 'flex-start',
|
|
196
|
+
backgroundColor: background,
|
|
197
|
+
borderRadius: radius,
|
|
198
|
+
gap,
|
|
199
|
+
justifyContent: 'center',
|
|
200
|
+
overflow: 'hidden',
|
|
201
|
+
paddingHorizontal: paddingH,
|
|
202
|
+
paddingVertical: paddingV,
|
|
203
|
+
},
|
|
204
|
+
headerStyle: {
|
|
205
|
+
alignItems: 'center',
|
|
206
|
+
flexDirection: 'row',
|
|
207
|
+
gap: headerGap,
|
|
208
|
+
width: '100%',
|
|
209
|
+
},
|
|
210
|
+
textContentStyle: {
|
|
211
|
+
alignItems: 'flex-start',
|
|
212
|
+
flex: 1,
|
|
213
|
+
gap: textContentGap,
|
|
214
|
+
minWidth: 1,
|
|
215
|
+
},
|
|
216
|
+
titleStyle: {
|
|
217
|
+
color: titleColor,
|
|
218
|
+
fontFamily: titleFontFamily,
|
|
219
|
+
fontSize: titleFontSize,
|
|
220
|
+
fontWeight: titleFontWeight,
|
|
221
|
+
lineHeight: titleLineHeight,
|
|
222
|
+
},
|
|
223
|
+
bodyStyle: {
|
|
224
|
+
color: bodyColor,
|
|
225
|
+
fontFamily: bodyFontFamily,
|
|
226
|
+
fontSize: bodyFontSize,
|
|
227
|
+
fontWeight: bodyFontWeight,
|
|
228
|
+
lineHeight: bodyLineHeight,
|
|
229
|
+
},
|
|
230
|
+
nudgeBodyStyle: {
|
|
231
|
+
color: nudgeBodyColor,
|
|
232
|
+
fontFamily: nudgeBodyFontFamily,
|
|
233
|
+
fontSize: nudgeBodyFontSize,
|
|
234
|
+
fontWeight: nudgeBodyFontWeight,
|
|
235
|
+
lineHeight: nudgeBodyLineHeight,
|
|
236
|
+
},
|
|
237
|
+
buttonWrapStyle: {
|
|
238
|
+
alignSelf: 'stretch',
|
|
239
|
+
alignItems: 'flex-start',
|
|
240
|
+
},
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function CardFinancialCondition({
|
|
245
|
+
title = 'Protection',
|
|
246
|
+
body = 'Check your coverage and gaps',
|
|
247
|
+
value = 0,
|
|
248
|
+
progressState = 'Inactive',
|
|
249
|
+
valueLabel,
|
|
250
|
+
showNudge = true,
|
|
251
|
+
nudgeBody = 'There may be gaps in your health or life cover\nAdd coverage to stay financially secure',
|
|
252
|
+
showDivider = true,
|
|
253
|
+
showButton = true,
|
|
254
|
+
buttonLabel = 'View Details',
|
|
255
|
+
onPressButton,
|
|
256
|
+
progressSlot,
|
|
257
|
+
nudgeSlot,
|
|
258
|
+
buttonSlot,
|
|
259
|
+
modes: propModes = EMPTY_MODES,
|
|
260
|
+
style,
|
|
261
|
+
headerStyle,
|
|
262
|
+
titleStyle,
|
|
263
|
+
bodyStyle,
|
|
264
|
+
accessibilityLabel,
|
|
265
|
+
...rest
|
|
266
|
+
}: CardFinancialConditionProps) {
|
|
267
|
+
const { modes: globalModes } = useTokens()
|
|
268
|
+
const modes = useMemo(
|
|
269
|
+
() =>
|
|
270
|
+
globalModes === EMPTY_MODES && propModes === EMPTY_MODES
|
|
271
|
+
? EMPTY_MODES
|
|
272
|
+
: { ...globalModes, ...propModes },
|
|
273
|
+
[globalModes, propModes]
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
const tokens = useMemo(
|
|
277
|
+
() => resolveCardFinancialConditionTokens(modes),
|
|
278
|
+
[modes]
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
// Match Figma: the action button is the primary call-to-action and uses the
|
|
282
|
+
// Secondary brand (purple) regardless of the card's overall AppearanceBrand,
|
|
283
|
+
// while Nudge / CircularProgressBar still follow the user-supplied modes.
|
|
284
|
+
const buttonModes = useMemo(
|
|
285
|
+
() => ({ ...modes, AppearanceBrand: 'Secondary' }),
|
|
286
|
+
[modes]
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
const processedProgressSlot = useMemo(() => {
|
|
290
|
+
if (!progressSlot) return null
|
|
291
|
+
const processed = cloneChildrenWithModes(
|
|
292
|
+
React.Children.toArray(progressSlot),
|
|
293
|
+
modes
|
|
294
|
+
)
|
|
295
|
+
return processed.length === 1 ? processed[0] : processed
|
|
296
|
+
}, [progressSlot, modes])
|
|
297
|
+
|
|
298
|
+
const processedNudgeSlot = useMemo(() => {
|
|
299
|
+
if (!nudgeSlot) return null
|
|
300
|
+
const processed = cloneChildrenWithModes(
|
|
301
|
+
React.Children.toArray(nudgeSlot),
|
|
302
|
+
modes
|
|
303
|
+
)
|
|
304
|
+
return processed.length === 1 ? processed[0] : processed
|
|
305
|
+
}, [nudgeSlot, modes])
|
|
306
|
+
|
|
307
|
+
const processedButtonSlot = useMemo(() => {
|
|
308
|
+
if (!buttonSlot) return null
|
|
309
|
+
const processed = cloneChildrenWithModes(
|
|
310
|
+
React.Children.toArray(buttonSlot),
|
|
311
|
+
buttonModes
|
|
312
|
+
)
|
|
313
|
+
return processed.length === 1 ? processed[0] : processed
|
|
314
|
+
}, [buttonSlot, buttonModes])
|
|
315
|
+
|
|
316
|
+
const defaultAccessibilityLabel =
|
|
317
|
+
accessibilityLabel ?? `${title}. ${body}.`
|
|
318
|
+
|
|
319
|
+
return (
|
|
320
|
+
<View
|
|
321
|
+
accessibilityLabel={defaultAccessibilityLabel}
|
|
322
|
+
style={[tokens.containerStyle, style]}
|
|
323
|
+
{...rest}
|
|
324
|
+
>
|
|
325
|
+
<View style={[tokens.headerStyle, headerStyle]}>
|
|
326
|
+
<View style={tokens.textContentStyle}>
|
|
327
|
+
<Text style={[tokens.titleStyle, titleStyle]}>{title}</Text>
|
|
328
|
+
<Text style={[tokens.bodyStyle, bodyStyle]}>{body}</Text>
|
|
329
|
+
</View>
|
|
330
|
+
|
|
331
|
+
{processedProgressSlot || (
|
|
332
|
+
<CircularProgressBar
|
|
333
|
+
state={progressState}
|
|
334
|
+
value={value}
|
|
335
|
+
modes={modes}
|
|
336
|
+
{...(valueLabel ? { valueLabel } : {})}
|
|
337
|
+
/>
|
|
338
|
+
)}
|
|
339
|
+
</View>
|
|
340
|
+
|
|
341
|
+
{showNudge ? (
|
|
342
|
+
processedNudgeSlot || (
|
|
343
|
+
<Nudge type="inline-compact" modes={modes} style={{ width: '100%' }}>
|
|
344
|
+
<Text style={tokens.nudgeBodyStyle}>{nudgeBody}</Text>
|
|
345
|
+
</Nudge>
|
|
346
|
+
)
|
|
347
|
+
) : null}
|
|
348
|
+
|
|
349
|
+
{showDivider ? <Divider modes={modes} /> : null}
|
|
350
|
+
|
|
351
|
+
{showButton ? (
|
|
352
|
+
<View style={tokens.buttonWrapStyle}>
|
|
353
|
+
{processedButtonSlot || (
|
|
354
|
+
<Button
|
|
355
|
+
label={buttonLabel}
|
|
356
|
+
modes={buttonModes}
|
|
357
|
+
{...(onPressButton ? { onPress: onPressButton } : {})}
|
|
358
|
+
/>
|
|
359
|
+
)}
|
|
360
|
+
</View>
|
|
361
|
+
) : null}
|
|
362
|
+
</View>
|
|
363
|
+
)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export default React.memo(CardFinancialCondition)
|
|
@@ -102,6 +102,10 @@ export function Carousel({
|
|
|
102
102
|
const containerPaddingV = parseFloat(
|
|
103
103
|
getVariableByName('carousel/padding/vertical', modes) || '0',
|
|
104
104
|
)
|
|
105
|
+
// Outer container max height per Figma (`carousel/maxHeight`).
|
|
106
|
+
const maxHeight = parseFloat(
|
|
107
|
+
getVariableByName('carousel/maxHeight', modes) || '280',
|
|
108
|
+
)
|
|
105
109
|
// Spacing between the cards row and the pagination dots uses `carousel/gap`.
|
|
106
110
|
const paginationOffset = gap
|
|
107
111
|
|
|
@@ -251,6 +255,7 @@ export function Carousel({
|
|
|
251
255
|
// ---- Render ----
|
|
252
256
|
const outerStyle: ViewStyle = {
|
|
253
257
|
paddingVertical: containerPaddingV,
|
|
258
|
+
maxHeight,
|
|
254
259
|
}
|
|
255
260
|
|
|
256
261
|
const contentContainerStyle: ViewStyle = {
|
|
@@ -364,21 +369,24 @@ export function Pagination({ modes: propModes, style }: PaginationProps) {
|
|
|
364
369
|
const modes = propModes || ctxModes || {}
|
|
365
370
|
|
|
366
371
|
// Token resolution for dots — matches Figma tokens
|
|
367
|
-
// (carousel/pagination/gap, carousel/pagination/indicator/{
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
372
|
+
// (carousel/pagination/gap, carousel/pagination/indicator/{activeColor,inactiveColor,radius,size,activeWidth}).
|
|
373
|
+
const dotSize = parseFloat(
|
|
374
|
+
getVariableByName('carousel/pagination/indicator/size', modes) || '6',
|
|
375
|
+
)
|
|
376
|
+
const dotActiveWidth = parseFloat(
|
|
377
|
+
getVariableByName('carousel/pagination/indicator/activeWidth', modes) || '16',
|
|
378
|
+
)
|
|
371
379
|
const dotGap = parseFloat(
|
|
372
380
|
getVariableByName('carousel/pagination/gap', modes) || '4',
|
|
373
381
|
)
|
|
374
382
|
const dotColor =
|
|
375
383
|
(getVariableByName(
|
|
376
|
-
'carousel/pagination/indicator/
|
|
384
|
+
'carousel/pagination/indicator/inactiveColor',
|
|
377
385
|
modes,
|
|
378
386
|
) as string) || 'rgba(0,0,0,0.3)'
|
|
379
387
|
const dotActiveColor =
|
|
380
388
|
(getVariableByName(
|
|
381
|
-
'carousel/pagination/indicator/
|
|
389
|
+
'carousel/pagination/indicator/activeColor',
|
|
382
390
|
modes,
|
|
383
391
|
) as string) || '#170d0a'
|
|
384
392
|
const dotRadius = parseFloat(
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
type ImageSourcePropType,
|
|
10
10
|
} from 'react-native'
|
|
11
11
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
12
|
-
import
|
|
12
|
+
import Radio from '../Radio/Radio'
|
|
13
13
|
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
14
14
|
|
|
15
15
|
export interface HoldingsCardDetailItem {
|
|
@@ -198,7 +198,7 @@ export default function HoldingsCard({
|
|
|
198
198
|
|
|
199
199
|
{/* Pointer events disabled — the whole card is the pressable target */}
|
|
200
200
|
<View pointerEvents="none">
|
|
201
|
-
<
|
|
201
|
+
<Radio
|
|
202
202
|
selected={selected}
|
|
203
203
|
disabled={disabled}
|
|
204
204
|
modes={modes}
|