jfs-components 0.0.71 → 0.0.73

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 (141) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/lib/commonjs/components/AccordionCheckbox/AccordionCheckbox.js +239 -0
  3. package/lib/commonjs/components/BrandChip/BrandChip.js +149 -0
  4. package/lib/commonjs/components/CardAdvisory/CardAdvisory.js +2 -2
  5. package/lib/commonjs/components/CardBankAccount/CardBankAccount.js +213 -0
  6. package/lib/commonjs/components/CardFinancialCondition/CardFinancialCondition.js +213 -0
  7. package/lib/commonjs/components/CardInsight/CardInsight.js +166 -0
  8. package/lib/commonjs/components/Carousel/Carousel.js +9 -7
  9. package/lib/commonjs/components/CheckboxGroup/CheckboxGroup.js +67 -0
  10. package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +125 -0
  11. package/lib/commonjs/components/CircularProgressBar/CircularProgressBar.js +56 -9
  12. package/lib/commonjs/components/CoverageBarComparison/CoverageBarComparison.js +272 -0
  13. package/lib/commonjs/components/CoverageRing/CoverageRing.js +141 -0
  14. package/lib/commonjs/components/DonutChart/DonutChart.js +309 -0
  15. package/lib/commonjs/components/DonutChartSummary/DonutChartSummary.js +155 -0
  16. package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +2 -2
  17. package/lib/commonjs/components/InstitutionBadge/InstitutionBadge.js +132 -0
  18. package/lib/commonjs/components/LinearMeter/LinearMeter.js +9 -28
  19. package/lib/commonjs/components/LinearProgress/LinearProgress.js +68 -0
  20. package/lib/commonjs/components/MetricLegendItem/MetricLegendItem.js +95 -0
  21. package/lib/commonjs/components/MonthlyStatusGrid/MonthlyStatusGrid.js +286 -0
  22. package/lib/commonjs/components/OTP/OTP.js +381 -37
  23. package/lib/commonjs/components/ProductOverview/ProductOverview.js +147 -0
  24. package/lib/commonjs/components/Radio/Radio.js +194 -0
  25. package/lib/commonjs/components/RadioButton/RadioButton.js +21 -188
  26. package/lib/commonjs/components/RangeTrack/RangeTrack.js +269 -0
  27. package/lib/commonjs/components/SavingsGoalSummary/SavingsGoalSummary.js +181 -0
  28. package/lib/commonjs/components/SegmentedTrack/SegmentedTrack.js +171 -0
  29. package/lib/commonjs/components/StatGroup/StatGroup.js +128 -0
  30. package/lib/commonjs/components/StatItem/StatItem.js +65 -35
  31. package/lib/commonjs/components/StrengthIndicator/StrengthIndicator.js +157 -0
  32. package/lib/commonjs/components/SummaryTile/SummaryTile.js +150 -0
  33. package/lib/commonjs/components/index.js +192 -1
  34. package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
  35. package/lib/commonjs/icons/registry.js +1 -1
  36. package/lib/commonjs/utils/index.js +7 -0
  37. package/lib/commonjs/utils/number-utils.js +57 -0
  38. package/lib/module/components/AccordionCheckbox/AccordionCheckbox.js +233 -0
  39. package/lib/module/components/BrandChip/BrandChip.js +143 -0
  40. package/lib/module/components/CardAdvisory/CardAdvisory.js +2 -2
  41. package/lib/module/components/CardBankAccount/CardBankAccount.js +208 -0
  42. package/lib/module/components/CardFinancialCondition/CardFinancialCondition.js +207 -0
  43. package/lib/module/components/CardInsight/CardInsight.js +161 -0
  44. package/lib/module/components/Carousel/Carousel.js +9 -7
  45. package/lib/module/components/CheckboxGroup/CheckboxGroup.js +62 -0
  46. package/lib/module/components/CheckboxItem/CheckboxItem.js +119 -0
  47. package/lib/module/components/CircularProgressBar/CircularProgressBar.js +56 -9
  48. package/lib/module/components/CoverageBarComparison/CoverageBarComparison.js +266 -0
  49. package/lib/module/components/CoverageRing/CoverageRing.js +136 -0
  50. package/lib/module/components/DonutChart/DonutChart.js +303 -0
  51. package/lib/module/components/DonutChartSummary/DonutChartSummary.js +150 -0
  52. package/lib/module/components/HoldingsCard/HoldingsCard.js +2 -2
  53. package/lib/module/components/InstitutionBadge/InstitutionBadge.js +127 -0
  54. package/lib/module/components/LinearMeter/LinearMeter.js +9 -28
  55. package/lib/module/components/LinearProgress/LinearProgress.js +63 -0
  56. package/lib/module/components/MetricLegendItem/MetricLegendItem.js +90 -0
  57. package/lib/module/components/MonthlyStatusGrid/MonthlyStatusGrid.js +281 -0
  58. package/lib/module/components/OTP/OTP.js +381 -38
  59. package/lib/module/components/ProductOverview/ProductOverview.js +142 -0
  60. package/lib/module/components/Radio/Radio.js +188 -0
  61. package/lib/module/components/RadioButton/RadioButton.js +20 -185
  62. package/lib/module/components/RangeTrack/RangeTrack.js +263 -0
  63. package/lib/module/components/SavingsGoalSummary/SavingsGoalSummary.js +175 -0
  64. package/lib/module/components/SegmentedTrack/SegmentedTrack.js +166 -0
  65. package/lib/module/components/StatGroup/StatGroup.js +123 -0
  66. package/lib/module/components/StatItem/StatItem.js +66 -36
  67. package/lib/module/components/StrengthIndicator/StrengthIndicator.js +152 -0
  68. package/lib/module/components/SummaryTile/SummaryTile.js +145 -0
  69. package/lib/module/components/index.js +28 -1
  70. package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
  71. package/lib/module/icons/registry.js +1 -1
  72. package/lib/module/utils/index.js +2 -1
  73. package/lib/module/utils/number-utils.js +53 -0
  74. package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +71 -0
  75. package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +43 -0
  76. package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +79 -0
  77. package/lib/typescript/src/components/CardFinancialCondition/CardFinancialCondition.d.ts +50 -0
  78. package/lib/typescript/src/components/CardInsight/CardInsight.d.ts +48 -0
  79. package/lib/typescript/src/components/CheckboxGroup/CheckboxGroup.d.ts +41 -0
  80. package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +56 -0
  81. package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +11 -1
  82. package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +105 -0
  83. package/lib/typescript/src/components/CoverageRing/CoverageRing.d.ts +90 -0
  84. package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +117 -0
  85. package/lib/typescript/src/components/DonutChartSummary/DonutChartSummary.d.ts +103 -0
  86. package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +30 -0
  87. package/lib/typescript/src/components/LinearProgress/LinearProgress.d.ts +17 -0
  88. package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +37 -0
  89. package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +119 -0
  90. package/lib/typescript/src/components/OTP/OTP.d.ts +88 -2
  91. package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +39 -0
  92. package/lib/typescript/src/components/Radio/Radio.d.ts +30 -0
  93. package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +20 -28
  94. package/lib/typescript/src/components/RangeTrack/RangeTrack.d.ts +173 -0
  95. package/lib/typescript/src/components/SavingsGoalSummary/SavingsGoalSummary.d.ts +95 -0
  96. package/lib/typescript/src/components/SegmentedTrack/SegmentedTrack.d.ts +108 -0
  97. package/lib/typescript/src/components/StatGroup/StatGroup.d.ts +45 -0
  98. package/lib/typescript/src/components/StatItem/StatItem.d.ts +24 -7
  99. package/lib/typescript/src/components/StrengthIndicator/StrengthIndicator.d.ts +58 -0
  100. package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +60 -0
  101. package/lib/typescript/src/components/index.d.ts +29 -2
  102. package/lib/typescript/src/icons/registry.d.ts +1 -1
  103. package/lib/typescript/src/utils/index.d.ts +1 -0
  104. package/lib/typescript/src/utils/number-utils.d.ts +29 -0
  105. package/package.json +1 -1
  106. package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +323 -0
  107. package/src/components/BrandChip/BrandChip.tsx +235 -0
  108. package/src/components/CardAdvisory/CardAdvisory.tsx +2 -2
  109. package/src/components/CardBankAccount/CardBankAccount.tsx +295 -0
  110. package/src/components/CardFinancialCondition/CardFinancialCondition.tsx +366 -0
  111. package/src/components/CardInsight/CardInsight.tsx +239 -0
  112. package/src/components/Carousel/Carousel.tsx +14 -6
  113. package/src/components/CheckboxGroup/CheckboxGroup.tsx +86 -0
  114. package/src/components/CheckboxItem/CheckboxItem.tsx +174 -0
  115. package/src/components/CircularProgressBar/CircularProgressBar.tsx +74 -9
  116. package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +378 -0
  117. package/src/components/CoverageRing/CoverageRing.tsx +225 -0
  118. package/src/components/DonutChart/DonutChart.tsx +503 -0
  119. package/src/components/DonutChartSummary/DonutChartSummary.tsx +256 -0
  120. package/src/components/HoldingsCard/HoldingsCard.tsx +2 -2
  121. package/src/components/InstitutionBadge/InstitutionBadge.tsx +216 -0
  122. package/src/components/LinearMeter/LinearMeter.tsx +9 -39
  123. package/src/components/LinearProgress/LinearProgress.tsx +92 -0
  124. package/src/components/MetricLegendItem/MetricLegendItem.tsx +167 -0
  125. package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +438 -0
  126. package/src/components/OTP/OTP.tsx +476 -29
  127. package/src/components/ProductOverview/ProductOverview.tsx +236 -0
  128. package/src/components/Radio/Radio.tsx +227 -0
  129. package/src/components/RadioButton/RadioButton.tsx +23 -225
  130. package/src/components/RangeTrack/RangeTrack.tsx +394 -0
  131. package/src/components/SavingsGoalSummary/SavingsGoalSummary.tsx +269 -0
  132. package/src/components/SegmentedTrack/SegmentedTrack.tsx +268 -0
  133. package/src/components/StatGroup/StatGroup.tsx +169 -0
  134. package/src/components/StatItem/StatItem.tsx +117 -40
  135. package/src/components/StrengthIndicator/StrengthIndicator.tsx +205 -0
  136. package/src/components/SummaryTile/SummaryTile.tsx +251 -0
  137. package/src/components/index.ts +39 -2
  138. package/src/design-tokens/Coin Variables-variables-full.json +1 -1
  139. package/src/icons/registry.ts +1 -1
  140. package/src/utils/index.ts +1 -0
  141. package/src/utils/number-utils.ts +60 -0
@@ -5,13 +5,19 @@ export { default as AvatarGroup } from './AvatarGroup/AvatarGroup';
5
5
  export { default as Badge } from './Badge/Badge';
6
6
  export { default as BottomNav } from './BottomNav/BottomNav';
7
7
  export { default as BottomNavItem } from './BottomNavItem/BottomNavItem';
8
+ export { default as BrandChip, type BrandChipProps } from './BrandChip/BrandChip';
8
9
  export { default as Button, type ButtonProps } from './Button/Button';
9
10
  export { default as Card } from './Card/Card';
10
11
  export { default as CardAdvisory, type CardAdvisoryProps } from './CardAdvisory/CardAdvisory';
12
+ export { default as CardBankAccount, type CardBankAccountProps, type CardBankAccountItem } from './CardBankAccount/CardBankAccount';
11
13
  export { default as Carousel } from './Carousel/Carousel';
12
14
  export type { CarouselProps, CarouselItemProps, PaginationProps } from './Carousel/Carousel';
13
15
  export { default as Checkbox, type CheckboxProps } from './Checkbox/Checkbox';
16
+ export { default as CheckboxItem, type CheckboxItemProps } from './CheckboxItem/CheckboxItem';
17
+ export { default as CheckboxGroup, type CheckboxGroupProps } from './CheckboxGroup/CheckboxGroup';
14
18
  export { default as CardFeedback, type CardFeedbackProps } from './CardFeedback/CardFeedback';
19
+ export { default as CardFinancialCondition, type CardFinancialConditionProps } from './CardFinancialCondition/CardFinancialCondition';
20
+ export { default as CardInsight, type CardInsightProps } from './CardInsight/CardInsight';
15
21
  export { default as Disclaimer } from './Disclaimer/Disclaimer';
16
22
  export { default as Divider, type DividerProps, type DividerDirection } from './Divider/Divider';
17
23
  export { default as Drawer } from './Drawer/Drawer';
@@ -24,6 +30,9 @@ export { default as FormField, type FormFieldProps, type FormFieldType } from '.
24
30
  export { default as CircularProgressBar, type CircularProgressBarProps } from './CircularProgressBar/CircularProgressBar';
25
31
  export { default as CircularProgressBarDoted, type CircularProgressBarDotedProps } from './CircularProgressBarDoted/CircularProgressBarDoted';
26
32
  export { default as CircularRating, type CircularRatingProps } from './CircularRating/CircularRating';
33
+ export { default as CoverageRing, type CoverageRingProps } from './CoverageRing/CoverageRing';
34
+ export { default as CoverageBarComparison, type CoverageBarComparisonProps, type CoverageBarComparisonItem } from './CoverageBarComparison/CoverageBarComparison';
35
+ export { default as MonthlyStatusGrid, CalendarGlyph, type MonthlyStatusGridProps, type MonthlyStatusGridMonth, type MonthlyStatus, type CalendarGlyphProps } from './MonthlyStatusGrid/MonthlyStatusGrid';
27
36
  export { default as Gauge, type GaugeProps } from './Gauge/Gauge';
28
37
  export { default as HoldingsCard, type HoldingsCardProps } from './HoldingsCard/HoldingsCard';
29
38
  export { default as HStack, type HStackProps } from './HStack/HStack';
@@ -32,10 +41,12 @@ export { default as IconCapsule } from './IconCapsule/IconCapsule';
32
41
  export { default as Image, type ImageProps } from './Image/Image';
33
42
  export { default as LazyList } from './LazyList/LazyList';
34
43
  export { default as LinearMeter, type LinearMeterProps } from './LinearMeter/LinearMeter';
44
+ export { default as LinearProgress, type LinearProgressProps } from './LinearProgress/LinearProgress';
35
45
  export { default as ListGroup } from './ListGroup/ListGroup';
36
46
  export { default as ListItem } from './ListItem/ListItem';
37
47
  export { default as MediaCard, type MediaCardProps } from './MediaCard/MediaCard';
38
48
  export { default as MerchantProfile, type MerchantProfileProps } from './MerchantProfile/MerchantProfile';
49
+ export { default as MetricLegendItem, type MetricLegendItemProps } from './MetricLegendItem/MetricLegendItem';
39
50
  export { default as MoneyValue } from './MoneyValue/MoneyValue';
40
51
  export { default as NoteInput, type NoteInputProps } from './NoteInput/NoteInput';
41
52
  export { default as Nudge, type NudgeProps } from './Nudge/Nudge';
@@ -59,16 +70,28 @@ export { default as VStack, type VStackProps } from './VStack/VStack';
59
70
  export { default as ChipGroup, type ChipGroupProps } from './ChipGroup/ChipGroup';
60
71
  export { default as EmptyState, type EmptyStateProps } from './EmptyState/EmptyState';
61
72
  export { default as Accordion, type AccordionProps } from './Accordion/Accordion';
73
+ export { default as AccordionCheckbox, type AccordionCheckboxProps } from './AccordionCheckbox/AccordionCheckbox';
62
74
  export { default as ActionTile, type ActionTileProps } from './ActionTile/ActionTile';
63
75
  export { default as Balance, type BalanceProps } from './Balance/Balance';
64
76
  export { default as ButtonGroup, type ButtonGroupProps } from './ButtonGroup/ButtonGroup';
65
77
  export { default as CardProviderInfo, type CardProviderInfoProps } from './CardProviderInfo/CardProviderInfo';
66
78
  export { default as ChipSelect, type ChipSelectProps } from './ChipSelect/ChipSelect';
67
79
  export { default as InputSearch, type InputSearchProps } from './InputSearch/InputSearch';
80
+ export { default as InstitutionBadge, type InstitutionBadgeProps } from './InstitutionBadge/InstitutionBadge';
68
81
  export { default as SupportText, type SupportTextProps } from './SupportText/SupportText';
69
82
  export { default as SupportTextIcon, type SupportTextIconProps, type SupportTextStatus } from './SupportText/SupportTextIcon';
83
+ export { default as Radio, type RadioProps } from './Radio/Radio';
84
+ /**
85
+ * @deprecated Use `Radio` instead. `RadioButton` is kept as an alias for
86
+ * backward compatibility and will be removed in a future major release.
87
+ */
70
88
  export { default as RadioButton, type RadioButtonProps } from './RadioButton/RadioButton';
71
89
  export { default as RechargeCard, type RechargeCardProps } from './RechargeCard/RechargeCard';
90
+ export { default as SavingsGoalSummary, type SavingsGoalSummaryProps, type SavingsGoalSummaryItem } from './SavingsGoalSummary/SavingsGoalSummary';
91
+ export { default as DonutChart, type DonutChartProps, type DonutChartSegmentData, type DonutChartSegmentProps, DonutChartSegment } from './DonutChart/DonutChart';
92
+ export { default as DonutChartSummary, type DonutChartSummaryProps, type DonutChartSummaryItem } from './DonutChartSummary/DonutChartSummary';
93
+ export { default as RangeTrack, type RangeTrackProps, type RangeTrackTab, type RangeTrackItem } from './RangeTrack/RangeTrack';
94
+ export { default as SegmentedTrack, type SegmentedTrackProps, type SegmentedTrackSegmentData, type SegmentedTrackSegmentProps, SegmentedTrackSegment } from './SegmentedTrack/SegmentedTrack';
72
95
  export { default as Tabs, type TabsProps } from './Tabs/Tabs';
73
96
  export { default as TabItem, type TabItemProps } from './Tabs/TabItem';
74
97
  export { default as Toast, type ToastProps } from './Toast/Toast';
@@ -78,11 +101,15 @@ export { default as AmountInput, type AmountInputProps } from './AmountInput/Amo
78
101
  export { default as Popup, type PopupProps, type PopupRef } from './Popup/Popup';
79
102
  export { default as PortfolioHero, type PortfolioHeroProps } from './PortfolioHero/PortfolioHero';
80
103
  export { default as ProductLabel, type ProductLabelProps } from './ProductLabel/ProductLabel';
104
+ export { default as ProductOverview, type ProductOverviewProps, type ProductOverviewStat } from './ProductOverview/ProductOverview';
81
105
  export { default as ProgressBadge, type ProgressBadgeProps } from './ProgressBadge/ProgressBadge';
82
106
  export { default as SwappableAmount, type SwappableAmountProps } from './SwappableAmount/SwappableAmount';
83
- export { default as OTP, type OTPProps } from './OTP/OTP';
107
+ export { default as OTP, OTPResend, useOtpResend, type OTPProps, type OTPResendProps, type OTPResendConfig, type UseOtpResendOptions, type UseOtpResendReturn, type OtpResendState, } from './OTP/OTP';
84
108
  export { default as PaymentFeedback, type PaymentFeedbackProps } from './PaymentFeedback/PaymentFeedback';
85
- export { default as StatItem, type StatItemProps } from './StatItem/StatItem';
109
+ export { default as StatItem, type StatItemProps, type StatItemLabelPosition } from './StatItem/StatItem';
110
+ export { default as StatGroup, type StatGroupProps, type StatGroupItem } from './StatGroup/StatGroup';
111
+ export { default as StrengthIndicator, type StrengthIndicatorProps, type StrengthIndicatorConfidence, type StrengthIndicatorConfidenceValue } from './StrengthIndicator/StrengthIndicator';
112
+ export { default as SummaryTile, type SummaryTileProps } from './SummaryTile/SummaryTile';
86
113
  export { default as Text, type TextProps } from './Text/Text';
87
114
  export { default as SegmentedControl, type SegmentedControlProps, type SegmentedControlItem } from './SegmentedControl/SegmentedControl';
88
115
  export { default as Toggle, type ToggleProps } from './Toggle/Toggle';
@@ -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-04-30T09:22:52.462Z
7
+ * Generated: 2026-05-15T16:18:56.427Z
8
8
  */
9
9
  export declare const iconRegistry: Record<string, {
10
10
  path: string;
@@ -1,4 +1,5 @@
1
1
  export { cloneChildrenWithModes, flattenChildren } from './react-utils';
2
2
  export { default as MediaSource } from './MediaSource';
3
3
  export type { UnifiedSource, MediaSourceProps } from './MediaSource';
4
+ export { formatIndianNumber } from './number-utils';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Format a number using the Indian numeric system.
3
+ *
4
+ * - Below 1 lakh (100,000): standard Indian-locale comma grouping (e.g. `12,400`).
5
+ * - 1 lakh up to (but excluding) 1 crore: shorthand `L` (e.g. `2.4L`).
6
+ * - 1 crore and above: shorthand `Cr` (e.g. `1.2Cr`).
7
+ *
8
+ * Trailing zero decimals are trimmed, so `100000` becomes `1L` rather than `1.0L`.
9
+ * Negative values keep the sign (`-2.4L`). Non-finite inputs (`NaN`, `Infinity`)
10
+ * are returned via `String(value)` so callers can decide how to handle them.
11
+ *
12
+ * @example formatIndianNumber(240000) // "2.4L"
13
+ * @example formatIndianNumber(12400) // "12,400"
14
+ * @example formatIndianNumber(15000000) // "1.5Cr"
15
+ * @example formatIndianNumber(-100000) // "-1L"
16
+ * @example formatIndianNumber(99999) // "99,999"
17
+ *
18
+ * @param value The number to format.
19
+ * @param options Optional formatting overrides.
20
+ * @param options.decimals Maximum number of decimal places used in the
21
+ * shorthand `L` / `Cr` form. Defaults to `1`.
22
+ * @param options.prefix String to prefix the output with — useful for a
23
+ * currency symbol, e.g. `'₹'`. Defaults to `''`.
24
+ */
25
+ export declare function formatIndianNumber(value: number, options?: {
26
+ decimals?: number;
27
+ prefix?: string;
28
+ }): string;
29
+ //# sourceMappingURL=number-utils.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jfs-components",
3
- "version": "0.0.71",
3
+ "version": "0.0.73",
4
4
  "description": "React Native Jio Finance Components Library",
5
5
  "author": "sunshuaiqi@gmail.com",
6
6
  "license": "MIT",
@@ -0,0 +1,323 @@
1
+ import React, { useCallback, useState } from 'react'
2
+ import {
3
+ View,
4
+ Text,
5
+ Pressable,
6
+ LayoutAnimation,
7
+ Platform,
8
+ UIManager,
9
+ type StyleProp,
10
+ type ViewStyle,
11
+ type TextStyle,
12
+ } from 'react-native'
13
+ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
14
+ import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
15
+ import Checkbox from '../Checkbox/Checkbox'
16
+ import Divider from '../Divider/Divider'
17
+ import Icon from '../../icons/Icon'
18
+
19
+ if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) {
20
+ UIManager.setLayoutAnimationEnabledExperimental(true)
21
+ }
22
+
23
+ export type AccordionCheckboxProps = {
24
+ /** Title shown next to the checkbox (e.g. "Axis Bank"). */
25
+ title?: string
26
+ /** Subtitle shown beneath the title (e.g. "3 accounts"). */
27
+ subtitle?: string
28
+ /** Initial expanded state (uncontrolled). Defaults to `false`. */
29
+ defaultExpanded?: boolean
30
+ /** Controlled expanded state. When provided, the component becomes controlled. */
31
+ expanded?: boolean
32
+ /** Callback fired whenever the expanded state changes. */
33
+ onExpandedChange?: (expanded: boolean) => void
34
+ /** Initial checked state of the header checkbox (uncontrolled). */
35
+ defaultChecked?: boolean
36
+ /** Controlled checked state of the header checkbox. */
37
+ checked?: boolean
38
+ /** Callback fired whenever the header checkbox value changes. */
39
+ onCheckedChange?: (checked: boolean) => void
40
+ /** Disables the entire component (header press + checkbox + content). */
41
+ disabled?: boolean
42
+ /**
43
+ * Slot — content rendered below the divider when expanded. Typically a
44
+ * `CheckboxGroup` of child `CheckboxItem`s. The `modes` prop is forwarded
45
+ * recursively to every child.
46
+ */
47
+ children?: React.ReactNode
48
+ /** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
49
+ modes?: Record<string, any>
50
+ /** Override outer container styles. */
51
+ style?: StyleProp<ViewStyle>
52
+ /** Accessibility label for the header press target. Defaults to `title`. */
53
+ accessibilityLabel?: string
54
+ }
55
+
56
+ /**
57
+ * AccordionCheckbox composes a header (with a `Checkbox`, title, subtitle and
58
+ * chevron) and a collapsible content slot. It mirrors the Figma
59
+ * "Accordion Checkbox" component.
60
+ *
61
+ * Two independent interactions live inside the header:
62
+ * - **Pressing the checkbox** toggles the parent checked state via
63
+ * `onCheckedChange` (typically used for "select all" behaviour).
64
+ * - **Pressing anywhere else on the header** toggles the expanded state via
65
+ * `onExpandedChange`.
66
+ *
67
+ * When expanded, a divider is shown and `children` are rendered with `modes`
68
+ * automatically forwarded through `cloneChildrenWithModes`.
69
+ *
70
+ * @component
71
+ * @param {AccordionCheckboxProps} props
72
+ *
73
+ * @example
74
+ * ```tsx
75
+ * <AccordionCheckbox
76
+ * title="Axis Bank"
77
+ * subtitle="3 accounts"
78
+ * defaultExpanded
79
+ * defaultChecked
80
+ * modes={{ 'Color Mode': 'Light' }}
81
+ * >
82
+ * <CheckboxGroup>
83
+ * <CheckboxItem label="Fixed deposit • 0245" />
84
+ * <CheckboxItem label="Recurring deposit • 1182" />
85
+ * <CheckboxItem label="Mutual fund • Equity" />
86
+ * </CheckboxGroup>
87
+ * </AccordionCheckbox>
88
+ * ```
89
+ */
90
+ function AccordionCheckbox({
91
+ title = 'Axis Bank',
92
+ subtitle = '3 accounts',
93
+ defaultExpanded = false,
94
+ expanded: controlledExpanded,
95
+ onExpandedChange,
96
+ defaultChecked = false,
97
+ checked: controlledChecked,
98
+ onCheckedChange,
99
+ disabled = false,
100
+ children,
101
+ modes = EMPTY_MODES,
102
+ style,
103
+ accessibilityLabel,
104
+ }: AccordionCheckboxProps) {
105
+ const isExpandedControlled = controlledExpanded !== undefined
106
+ const [internalExpanded, setInternalExpanded] = useState(defaultExpanded)
107
+ const isExpanded = isExpandedControlled ? controlledExpanded : internalExpanded
108
+
109
+ const isCheckedControlled = controlledChecked !== undefined
110
+ const [internalChecked, setInternalChecked] = useState(defaultChecked)
111
+ const isChecked = isCheckedControlled ? controlledChecked : internalChecked
112
+
113
+ const handleToggleExpanded = useCallback(() => {
114
+ if (disabled) return
115
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
116
+ const next = !isExpanded
117
+ if (!isExpandedControlled) {
118
+ setInternalExpanded(next)
119
+ }
120
+ onExpandedChange?.(next)
121
+ }, [disabled, isExpanded, isExpandedControlled, onExpandedChange])
122
+
123
+ const handleToggleChecked = useCallback(
124
+ (next: boolean) => {
125
+ if (disabled) return
126
+ if (!isCheckedControlled) {
127
+ setInternalChecked(next)
128
+ }
129
+ onCheckedChange?.(next)
130
+ },
131
+ [disabled, isCheckedControlled, onCheckedChange]
132
+ )
133
+
134
+ const background =
135
+ (getVariableByName('accordionCheckbox/background', modes) as string | null) ?? '#ffffff'
136
+ const radius = (getVariableByName('accordionCheckbox/radius', modes) as number | null) ?? 12
137
+ const paddingHorizontal =
138
+ (getVariableByName('accordionCheckbox/padding/horizontal', modes) as number | null) ?? 12
139
+ const paddingVertical =
140
+ (getVariableByName('accordionCheckbox/padding/vertical', modes) as number | null) ?? 16
141
+ const containerGap =
142
+ (getVariableByName('accordionCheckbox/gap', modes) as number | null) ?? 12
143
+ const borderColor =
144
+ (getVariableByName('accordionCheckbox/border/color', modes) as string | null) ?? '#ebebed'
145
+ const borderSize =
146
+ (getVariableByName('accordionCheckbox/border/size', modes) as number | null) ?? 1
147
+
148
+ const headerGap =
149
+ (getVariableByName('accordionCheckbox/header/gap', modes) as number | null) ?? 12
150
+ const headerPaddingHorizontal =
151
+ (getVariableByName('accordionCheckbox/header/padding/horizontal', modes) as number | null) ?? 0
152
+ const headerPaddingVertical =
153
+ (getVariableByName('accordionCheckbox/header/padding/vertical', modes) as number | null) ?? 0
154
+ const headerWrapGap =
155
+ (getVariableByName('accordionCheckbox/header/wrap/gap', modes) as number | null) ?? 12
156
+
157
+ const textWrapGap =
158
+ (getVariableByName('accordionCheckbox/textWrap/gap', modes) as number | null) ?? 2
159
+
160
+ const titleColor =
161
+ (getVariableByName('accordionCheckbox/title/color', modes) as string | null) ?? '#000000'
162
+ const titleFontSize =
163
+ (getVariableByName('accordionCheckbox/title/fontSize', modes) as number | null) ?? 14
164
+ const titleFontFamily =
165
+ (getVariableByName('accordionCheckbox/title/fontFamily', modes) as string | null) ?? 'JioType Var'
166
+ const titleLineHeight =
167
+ (getVariableByName('accordionCheckbox/title/lineHeight', modes) as number | null) ?? 18
168
+ const titleFontWeightRaw =
169
+ getVariableByName('accordionCheckbox/title/fontWeight', modes) ?? 600
170
+ const titleFontWeight = String(titleFontWeightRaw) as TextStyle['fontWeight']
171
+
172
+ const subtitleColor =
173
+ (getVariableByName('accordionCheckbox/subtitle/color', modes) as string | null) ?? '#23190a'
174
+ const subtitleFontSize =
175
+ (getVariableByName('accordionCheckbox/subtitle/fontSize', modes) as number | null) ?? 12
176
+ const subtitleFontFamily =
177
+ (getVariableByName('accordionCheckbox/subtitle/fontFamily', modes) as string | null) ?? 'JioType Var'
178
+ const subtitleLineHeight =
179
+ (getVariableByName('accordionCheckbox/subtitle/lineHeight', modes) as number | null) ?? 16
180
+ const subtitleFontWeightRaw =
181
+ getVariableByName('accordionCheckbox/subtitle/fontWeight', modes) ?? 500
182
+ const subtitleFontWeight = String(subtitleFontWeightRaw) as TextStyle['fontWeight']
183
+
184
+ const iconColor =
185
+ (getVariableByName('accordionCheckbox/icon/color', modes) as string | null) ?? '#000000'
186
+ const iconSize =
187
+ (getVariableByName('accordionCheckbox/icon/size', modes) as number | null) ?? 24
188
+
189
+ const contentGap =
190
+ (getVariableByName('accordionCheckbox/content/gap', modes) as number | null) ?? 0
191
+ const contentPaddingTop =
192
+ (getVariableByName('accordionCheckbox/content/padding/top', modes) as number | null) ?? 8
193
+ const contentPaddingBottom =
194
+ (getVariableByName('accordionCheckbox/content/padding/bottom', modes) as number | null) ?? 0
195
+ const contentPaddingHorizontal =
196
+ (getVariableByName('accordionCheckbox/content/padding/horizontal', modes) as number | null) ?? 0
197
+
198
+ const containerStyle: ViewStyle = {
199
+ backgroundColor: background,
200
+ borderRadius: radius,
201
+ paddingHorizontal,
202
+ paddingVertical,
203
+ flexDirection: 'column',
204
+ alignItems: 'stretch',
205
+ gap: containerGap,
206
+ overflow: 'hidden',
207
+ ...(isExpanded
208
+ ? { borderWidth: borderSize, borderColor }
209
+ : null),
210
+ ...(disabled ? { opacity: 0.6 } : null),
211
+ }
212
+
213
+ const headerStyle: ViewStyle = {
214
+ flexDirection: 'row',
215
+ alignItems: 'center',
216
+ gap: headerGap,
217
+ paddingHorizontal: headerPaddingHorizontal,
218
+ paddingVertical: headerPaddingVertical,
219
+ }
220
+
221
+ const wrapStyle: ViewStyle = {
222
+ flex: 1,
223
+ minWidth: 0,
224
+ flexDirection: 'row',
225
+ alignItems: 'center',
226
+ gap: headerWrapGap,
227
+ }
228
+
229
+ const textWrapStyle: ViewStyle = {
230
+ flex: 1,
231
+ minWidth: 0,
232
+ flexDirection: 'column',
233
+ alignItems: 'flex-start',
234
+ gap: textWrapGap,
235
+ }
236
+
237
+ const titleStyle: TextStyle = {
238
+ color: titleColor,
239
+ fontSize: titleFontSize,
240
+ lineHeight: titleLineHeight,
241
+ fontFamily: titleFontFamily,
242
+ fontWeight: titleFontWeight,
243
+ }
244
+
245
+ const subtitleStyle: TextStyle = {
246
+ color: subtitleColor,
247
+ fontSize: subtitleFontSize,
248
+ lineHeight: subtitleLineHeight,
249
+ fontFamily: subtitleFontFamily,
250
+ fontWeight: subtitleFontWeight,
251
+ }
252
+
253
+ const contentStyle: ViewStyle = {
254
+ flexDirection: 'column',
255
+ alignItems: 'stretch',
256
+ justifyContent: 'center',
257
+ gap: contentGap,
258
+ paddingTop: contentPaddingTop,
259
+ paddingBottom: contentPaddingBottom,
260
+ paddingHorizontal: contentPaddingHorizontal,
261
+ }
262
+
263
+ const a11yLabel = accessibilityLabel ?? title
264
+
265
+ return (
266
+ <View style={[containerStyle, style]}>
267
+ <Pressable
268
+ onPress={handleToggleExpanded}
269
+ disabled={disabled}
270
+ accessibilityRole="button"
271
+ accessibilityState={{ expanded: isExpanded, disabled }}
272
+ accessibilityLabel={a11yLabel}
273
+ accessibilityHint={isExpanded ? 'Collapse' : 'Expand'}
274
+ style={({ pressed }) => [
275
+ headerStyle,
276
+ pressed && !disabled ? { opacity: 0.9 } : null,
277
+ ]}
278
+ >
279
+ <View style={wrapStyle}>
280
+ <Checkbox
281
+ checked={isChecked}
282
+ onValueChange={handleToggleChecked}
283
+ disabled={disabled}
284
+ modes={modes}
285
+ accessibilityLabel={
286
+ typeof title === 'string' ? `Select ${title}` : undefined
287
+ }
288
+ />
289
+ <View style={textWrapStyle}>
290
+ <Text style={titleStyle} numberOfLines={1} selectable={false}>
291
+ {title}
292
+ </Text>
293
+ {subtitle ? (
294
+ <Text style={subtitleStyle} numberOfLines={1} selectable={false}>
295
+ {subtitle}
296
+ </Text>
297
+ ) : null}
298
+ </View>
299
+ </View>
300
+ <Icon
301
+ name={isExpanded ? 'ic_chevron_up' : 'ic_chevron_down'}
302
+ size={iconSize}
303
+ color={iconColor}
304
+ accessibilityElementsHidden={true}
305
+ importantForAccessibility="no"
306
+ />
307
+ </Pressable>
308
+
309
+ {isExpanded ? (
310
+ <>
311
+ <Divider modes={modes} />
312
+ {children ? (
313
+ <View style={contentStyle}>
314
+ {cloneChildrenWithModes(children, modes)}
315
+ </View>
316
+ ) : null}
317
+ </>
318
+ ) : null}
319
+ </View>
320
+ )
321
+ }
322
+
323
+ export default AccordionCheckbox