jfs-components 0.1.0 → 0.1.8
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 +37 -0
- package/lib/commonjs/components/AmountInput/AmountInput.js +8 -5
- package/lib/commonjs/components/AreaLineChart/AreaLineChart.js +1 -1
- package/lib/commonjs/components/Balance/Balance.js +17 -12
- package/lib/commonjs/components/BenefitCard/BenefitCard.js +231 -0
- package/lib/commonjs/components/Card/Card.js +2 -1
- package/lib/commonjs/components/CardFeedback/CardFeedback.js +2 -1
- package/lib/commonjs/components/CcCard/CcCard.js +470 -0
- package/lib/commonjs/components/Checkbox/Checkbox.js +6 -4
- package/lib/commonjs/components/CheckboxItem/CheckboxItem.js +4 -3
- package/lib/commonjs/components/CompareTable/CompareTable.js +372 -0
- package/lib/commonjs/components/ComparisonBar/ComparisonBar.js +266 -0
- package/lib/commonjs/components/Drawer/Drawer.js +13 -4
- package/lib/commonjs/components/DropdownInput/DropdownInput.js +36 -4
- package/lib/commonjs/components/FormField/FormField.js +4 -3
- package/lib/commonjs/components/FullscreenModal/FullscreenModal.js +62 -2
- package/lib/commonjs/components/Image/Image.js +11 -5
- package/lib/commonjs/components/InputSearch/InputSearch.js +6 -4
- package/lib/commonjs/components/LottiePlayer/loadNativeLottieView.js +8 -13
- package/lib/commonjs/components/NoteInput/NoteInput.js +6 -5
- package/lib/commonjs/components/Overlay/Overlay.js +92 -0
- package/lib/commonjs/components/PdpCcCard/PdpCcCard.js +273 -0
- package/lib/commonjs/components/PlanComparisonCard/PlanComparisonCard.js +2 -1
- package/lib/commonjs/components/ProductMerchandisingCard/GlassFill.js +263 -0
- package/lib/commonjs/components/ProductMerchandisingCard/GlassFill.web.js +116 -0
- package/lib/commonjs/components/ProductMerchandisingCard/ProductMerchandisingCard.js +353 -0
- package/lib/commonjs/components/ProjectionMarker/ProjectionMarker.js +161 -0
- package/lib/commonjs/components/Radio/Radio.js +5 -5
- package/lib/commonjs/components/Slider/Slider.js +473 -0
- package/lib/commonjs/components/TextInput/TextInput.js +15 -9
- package/lib/commonjs/components/TextSegment/TextSegment.js +118 -0
- package/lib/commonjs/components/docs/modeControls.js +116 -0
- package/lib/commonjs/components/index.js +70 -0
- package/lib/commonjs/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/commonjs/design-tokens/JFSThemeProvider.js +1 -1
- package/lib/commonjs/design-tokens/figma-modes.generated.js +420 -0
- package/lib/commonjs/design-tokens/index.js +11 -0
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/commonjs/utils/react-utils.js +22 -0
- package/lib/module/components/Accordion/Accordion.js +1 -2
- package/lib/module/components/AmountInput/AmountInput.js +6 -4
- package/lib/module/components/AreaLineChart/AreaLineChart.js +1 -1
- package/lib/module/components/Balance/Balance.js +18 -13
- package/lib/module/components/BenefitCard/BenefitCard.js +225 -0
- package/lib/module/components/Card/Card.js +1 -2
- package/lib/module/components/CardFeedback/CardFeedback.js +1 -2
- package/lib/module/components/CcCard/CcCard.js +464 -0
- package/lib/module/components/Checkbox/Checkbox.js +6 -6
- package/lib/module/components/CheckboxItem/CheckboxItem.js +5 -4
- package/lib/module/components/CompareTable/CompareTable.js +367 -0
- package/lib/module/components/ComparisonBar/ComparisonBar.js +260 -0
- package/lib/module/components/Drawer/Drawer.js +12 -4
- package/lib/module/components/DropdownInput/DropdownInput.js +37 -5
- package/lib/module/components/FormField/FormField.js +5 -4
- package/lib/module/components/FullscreenModal/FullscreenModal.js +64 -5
- package/lib/module/components/Image/Image.js +11 -5
- package/lib/module/components/InputSearch/InputSearch.js +6 -4
- package/lib/module/components/InstitutionBadge/InstitutionBadge.js +1 -2
- package/lib/module/components/LottiePlayer/loadNativeLottieView.js +8 -13
- package/lib/module/components/MoneyValue/MoneyValue.js +1 -2
- package/lib/module/components/NoteInput/NoteInput.js +7 -6
- package/lib/module/components/OTP/OTP.js +1 -2
- package/lib/module/components/Overlay/Overlay.js +87 -0
- package/lib/module/components/PdpCcCard/PdpCcCard.js +267 -0
- package/lib/module/components/PlanComparisonCard/PlanComparisonCard.js +1 -2
- package/lib/module/components/PoweredByLabel/PoweredByLabel.js +1 -2
- package/lib/module/components/ProductMerchandisingCard/GlassFill.js +257 -0
- package/lib/module/components/ProductMerchandisingCard/GlassFill.web.js +111 -0
- package/lib/module/components/ProductMerchandisingCard/ProductMerchandisingCard.js +347 -0
- package/lib/module/components/ProjectionMarker/ProjectionMarker.js +156 -0
- package/lib/module/components/Radio/Radio.js +5 -4
- package/lib/module/components/RechargeCard/RechargeCard.js +1 -2
- package/lib/module/components/Section/Section.js +1 -2
- package/lib/module/components/Slider/Slider.js +468 -0
- package/lib/module/components/TextInput/TextInput.js +16 -12
- package/lib/module/components/TextSegment/TextSegment.js +113 -0
- package/lib/module/components/UpiHandle/UpiHandle.js +1 -2
- package/lib/module/components/docs/modeControls.js +111 -0
- package/lib/module/components/index.js +10 -0
- package/lib/module/design-tokens/Coin Variables-variables-full.json +1 -1
- package/lib/module/design-tokens/JFSThemeProvider.js +1 -1
- package/lib/module/design-tokens/figma-modes.generated.js +416 -0
- package/lib/module/design-tokens/index.js +2 -1
- package/lib/module/icons/registry.js +1 -1
- package/lib/module/utils/react-utils.js +21 -1
- package/lib/typescript/src/components/Accordion/Accordion.d.ts +2 -1
- package/lib/typescript/src/components/AccordionCheckbox/AccordionCheckbox.d.ts +2 -1
- package/lib/typescript/src/components/AccountCard/AccountCard.d.ts +2 -1
- package/lib/typescript/src/components/ActionFooter/ActionFooter.d.ts +2 -1
- package/lib/typescript/src/components/ActionTile/ActionTile.d.ts +2 -1
- package/lib/typescript/src/components/AllocationComparisonChart/AllocationComparisonChart.d.ts +2 -1
- package/lib/typescript/src/components/AmountInput/AmountInput.d.ts +5 -3
- package/lib/typescript/src/components/AppBar/AppBar.d.ts +2 -1
- package/lib/typescript/src/components/AreaLineChart/AreaLineChart.d.ts +3 -2
- package/lib/typescript/src/components/Attached/Attached.d.ts +2 -1
- package/lib/typescript/src/components/Avatar/Avatar.d.ts +2 -1
- package/lib/typescript/src/components/AvatarGroup/AvatarGroup.d.ts +2 -1
- package/lib/typescript/src/components/Badge/Badge.d.ts +2 -1
- package/lib/typescript/src/components/Balance/Balance.d.ts +2 -1
- package/lib/typescript/src/components/BenefitCard/BenefitCard.d.ts +93 -0
- package/lib/typescript/src/components/BottomNav/BottomNav.d.ts +2 -1
- package/lib/typescript/src/components/BottomNavItem/BottomNavItem.d.ts +2 -1
- package/lib/typescript/src/components/BrandChip/BrandChip.d.ts +2 -1
- package/lib/typescript/src/components/BubbleChart/BubbleChart.d.ts +2 -1
- package/lib/typescript/src/components/Button/Button.d.ts +2 -1
- package/lib/typescript/src/components/ButtonGroup/ButtonGroup.d.ts +2 -1
- package/lib/typescript/src/components/Card/Card.d.ts +3 -2
- package/lib/typescript/src/components/CardAdvisory/CardAdvisory.d.ts +2 -1
- package/lib/typescript/src/components/CardBankAccount/CardBankAccount.d.ts +2 -1
- package/lib/typescript/src/components/CardCTA/CardCTA.d.ts +2 -1
- package/lib/typescript/src/components/CardFeedback/CardFeedback.d.ts +7 -6
- package/lib/typescript/src/components/CardFinancialCondition/CardFinancialCondition.d.ts +2 -1
- package/lib/typescript/src/components/CardInsight/CardInsight.d.ts +2 -1
- package/lib/typescript/src/components/CardProviderInfo/CardProviderInfo.d.ts +2 -1
- package/lib/typescript/src/components/Carousel/Carousel.d.ts +4 -3
- package/lib/typescript/src/components/CcCard/CcCard.d.ts +137 -0
- package/lib/typescript/src/components/Checkbox/Checkbox.d.ts +5 -3
- package/lib/typescript/src/components/CheckboxGroup/CheckboxGroup.d.ts +2 -1
- package/lib/typescript/src/components/CheckboxItem/CheckboxItem.d.ts +4 -3
- package/lib/typescript/src/components/ChipGroup/ChipGroup.d.ts +2 -1
- package/lib/typescript/src/components/ChipSelect/ChipSelect.d.ts +2 -1
- package/lib/typescript/src/components/CircularProgressBar/CircularProgressBar.d.ts +2 -1
- package/lib/typescript/src/components/CircularProgressBarDoted/CircularProgressBarDoted.d.ts +2 -1
- package/lib/typescript/src/components/CircularRating/CircularRating.d.ts +2 -1
- package/lib/typescript/src/components/ClusterBubble/ClusterBubble.d.ts +2 -1
- package/lib/typescript/src/components/CompareTable/CompareTable.d.ts +88 -0
- package/lib/typescript/src/components/ComparisonBar/ComparisonBar.d.ts +118 -0
- package/lib/typescript/src/components/CoverageBarComparison/CoverageBarComparison.d.ts +3 -2
- package/lib/typescript/src/components/CoverageRing/CoverageRing.d.ts +2 -1
- package/lib/typescript/src/components/DebitCard/DebitCard.d.ts +2 -1
- package/lib/typescript/src/components/Disclaimer/Disclaimer.d.ts +2 -1
- package/lib/typescript/src/components/Divider/Divider.d.ts +2 -1
- package/lib/typescript/src/components/DonutChart/DonutChart.d.ts +4 -3
- package/lib/typescript/src/components/DonutChartSummary/DonutChartSummary.d.ts +3 -2
- package/lib/typescript/src/components/Drawer/Drawer.d.ts +15 -1
- package/lib/typescript/src/components/Dropdown/Dropdown.d.ts +3 -2
- package/lib/typescript/src/components/DropdownInput/DropdownInput.d.ts +22 -2
- package/lib/typescript/src/components/EmptyState/EmptyState.d.ts +2 -1
- package/lib/typescript/src/components/ExpandableCheckbox/ExpandableCheckbox.d.ts +2 -1
- package/lib/typescript/src/components/FilterBar/FilterBar.d.ts +3 -2
- package/lib/typescript/src/components/Form/Form.d.ts +2 -1
- package/lib/typescript/src/components/FormField/FormField.d.ts +4 -3
- package/lib/typescript/src/components/FullscreenModal/FullscreenModal.d.ts +2 -1
- package/lib/typescript/src/components/Gauge/Gauge.d.ts +2 -1
- package/lib/typescript/src/components/HStack/HStack.d.ts +2 -1
- package/lib/typescript/src/components/HoldingsCard/HoldingsCard.d.ts +2 -1
- package/lib/typescript/src/components/Icon/Icon.d.ts +2 -1
- package/lib/typescript/src/components/IconButton/IconButton.d.ts +2 -1
- package/lib/typescript/src/components/IconCapsule/IconCapsule.d.ts +2 -1
- package/lib/typescript/src/components/Image/Image.d.ts +17 -1
- package/lib/typescript/src/components/InputSearch/InputSearch.d.ts +25 -3
- package/lib/typescript/src/components/InstitutionBadge/InstitutionBadge.d.ts +2 -1
- package/lib/typescript/src/components/LazyList/LazyList.d.ts +2 -1
- package/lib/typescript/src/components/LinearMeter/LinearMeter.d.ts +3 -2
- package/lib/typescript/src/components/LinearProgress/LinearProgress.d.ts +2 -1
- package/lib/typescript/src/components/ListGroup/ListGroup.d.ts +2 -1
- package/lib/typescript/src/components/ListItem/ListItem.d.ts +2 -1
- package/lib/typescript/src/components/LottieIntroBlock/LottieIntroBlock.d.ts +2 -1
- package/lib/typescript/src/components/LottiePlayer/LottiePlayer.d.ts +2 -1
- package/lib/typescript/src/components/LottiePlayer/LottiePlayer.web.d.ts +2 -1
- package/lib/typescript/src/components/MediaCard/MediaCard.d.ts +6 -5
- package/lib/typescript/src/components/MerchantProfile/MerchantProfile.d.ts +2 -1
- package/lib/typescript/src/components/MessageField/MessageField.d.ts +2 -1
- package/lib/typescript/src/components/MetricLegendItem/MetricLegendItem.d.ts +2 -1
- package/lib/typescript/src/components/MoneyValue/MoneyValue.d.ts +2 -1
- package/lib/typescript/src/components/MonthlyStatusGrid/MonthlyStatusGrid.d.ts +4 -3
- package/lib/typescript/src/components/NavArrow/NavArrow.d.ts +2 -1
- package/lib/typescript/src/components/NoteInput/NoteInput.d.ts +21 -3
- package/lib/typescript/src/components/Nudge/Nudge.d.ts +2 -1
- package/lib/typescript/src/components/Numpad/Numpad.d.ts +2 -1
- package/lib/typescript/src/components/OTP/OTP.d.ts +3 -2
- package/lib/typescript/src/components/Overlay/Overlay.d.ts +52 -0
- package/lib/typescript/src/components/PageHero/PageHero.d.ts +2 -1
- package/lib/typescript/src/components/PaymentFeedback/PaymentFeedback.d.ts +2 -1
- package/lib/typescript/src/components/PdpCcCard/PdpCcCard.d.ts +84 -0
- package/lib/typescript/src/components/PlanComparisonCard/PlanComparisonCard.d.ts +2 -1
- package/lib/typescript/src/components/Popup/Popup.d.ts +2 -1
- package/lib/typescript/src/components/PortfolioHero/PortfolioHero.d.ts +2 -1
- package/lib/typescript/src/components/PoweredByLabel/PoweredByLabel.d.ts +2 -1
- package/lib/typescript/src/components/ProductLabel/ProductLabel.d.ts +2 -1
- package/lib/typescript/src/components/ProductMerchandisingCard/GlassFill.d.ts +56 -0
- package/lib/typescript/src/components/ProductMerchandisingCard/GlassFill.web.d.ts +27 -0
- package/lib/typescript/src/components/ProductMerchandisingCard/ProductMerchandisingCard.d.ts +81 -0
- package/lib/typescript/src/components/ProductOverview/ProductOverview.d.ts +2 -1
- package/lib/typescript/src/components/ProgressBadge/ProgressBadge.d.ts +2 -1
- package/lib/typescript/src/components/ProjectionMarker/ProjectionMarker.d.ts +82 -0
- package/lib/typescript/src/components/Radio/Radio.d.ts +5 -3
- package/lib/typescript/src/components/RadioButton/RadioButton.d.ts +2 -2
- package/lib/typescript/src/components/RangeTrack/RangeTrack.d.ts +3 -2
- package/lib/typescript/src/components/RechargeCard/RechargeCard.d.ts +2 -1
- package/lib/typescript/src/components/SavingsGoalSummary/SavingsGoalSummary.d.ts +2 -1
- package/lib/typescript/src/components/Screen/Screen.d.ts +2 -1
- package/lib/typescript/src/components/Section/Section.d.ts +3 -2
- package/lib/typescript/src/components/SegmentedControl/SegmentedControl.d.ts +2 -1
- package/lib/typescript/src/components/SegmentedTrack/SegmentedTrack.d.ts +4 -3
- package/lib/typescript/src/components/Slider/Slider.d.ts +99 -0
- package/lib/typescript/src/components/Slot/Slot.d.ts +2 -1
- package/lib/typescript/src/components/Spinner/Spinner.d.ts +2 -1
- package/lib/typescript/src/components/StatGroup/StatGroup.d.ts +2 -1
- package/lib/typescript/src/components/StatItem/StatItem.d.ts +2 -1
- package/lib/typescript/src/components/StatusHero/StatusHero.d.ts +2 -1
- package/lib/typescript/src/components/Stepper/Step.d.ts +2 -1
- package/lib/typescript/src/components/Stepper/StepLabel.d.ts +2 -1
- package/lib/typescript/src/components/Stepper/Stepper.d.ts +2 -1
- package/lib/typescript/src/components/StrengthIndicator/StrengthIndicator.d.ts +2 -1
- package/lib/typescript/src/components/SuggestiveSearch/SuggestiveSearch.d.ts +2 -1
- package/lib/typescript/src/components/SummaryTile/SummaryTile.d.ts +2 -1
- package/lib/typescript/src/components/SupportText/SupportText.d.ts +2 -1
- package/lib/typescript/src/components/SupportText/SupportTextIcon.d.ts +2 -1
- package/lib/typescript/src/components/SwappableAmount/SwappableAmount.d.ts +2 -1
- package/lib/typescript/src/components/Tabs/TabItem.d.ts +2 -1
- package/lib/typescript/src/components/Tabs/Tabs.d.ts +2 -1
- package/lib/typescript/src/components/TestimonialsCard/TestimonialsCard.d.ts +2 -1
- package/lib/typescript/src/components/Text/Text.d.ts +2 -1
- package/lib/typescript/src/components/TextInput/TextInput.d.ts +12 -31
- package/lib/typescript/src/components/TextSegment/TextSegment.d.ts +100 -0
- package/lib/typescript/src/components/ThreadHero/ThreadHero.d.ts +2 -1
- package/lib/typescript/src/components/Title/Title.d.ts +2 -1
- package/lib/typescript/src/components/Toast/Toast.d.ts +2 -1
- package/lib/typescript/src/components/Toast/ToastProvider.d.ts +2 -1
- package/lib/typescript/src/components/Toast/useToast.d.ts +3 -2
- package/lib/typescript/src/components/Toggle/Toggle.d.ts +2 -1
- package/lib/typescript/src/components/Tooltip/Tooltip.d.ts +2 -1
- package/lib/typescript/src/components/TransactionBubble/TransactionBubble.d.ts +2 -1
- package/lib/typescript/src/components/TransactionDetails/TransactionDetails.d.ts +3 -2
- package/lib/typescript/src/components/TransactionStatus/TransactionStatus.d.ts +2 -1
- package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +2 -1
- package/lib/typescript/src/components/VStack/VStack.d.ts +2 -1
- package/lib/typescript/src/components/docs/modeControls.d.ts +28 -0
- package/lib/typescript/src/components/index.d.ts +11 -1
- package/lib/typescript/src/design-tokens/JFSThemeProvider.d.ts +4 -3
- package/lib/typescript/src/design-tokens/figma-modes.generated.d.ts +284 -0
- package/lib/typescript/src/design-tokens/index.d.ts +1 -0
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/lib/typescript/src/skeleton/Skeleton.d.ts +2 -1
- package/lib/typescript/src/utils/react-utils.d.ts +12 -1
- package/package.json +4 -2
- package/src/components/Accordion/Accordion.tsx +2 -1
- package/src/components/AccordionCheckbox/AccordionCheckbox.tsx +2 -1
- package/src/components/AccountCard/AccountCard.tsx +2 -1
- package/src/components/ActionFooter/ActionFooter.tsx +2 -1
- package/src/components/ActionTile/ActionTile.tsx +2 -1
- package/src/components/AllocationComparisonChart/AllocationComparisonChart.tsx +2 -1
- package/src/components/AmountInput/AmountInput.tsx +9 -6
- package/src/components/AppBar/AppBar.tsx +2 -1
- package/src/components/AreaLineChart/AreaLineChart.tsx +8 -7
- package/src/components/Attached/Attached.tsx +2 -1
- package/src/components/Avatar/Avatar.tsx +3 -2
- package/src/components/AvatarGroup/AvatarGroup.tsx +2 -1
- package/src/components/Badge/Badge.tsx +2 -1
- package/src/components/Balance/Balance.tsx +18 -12
- package/src/components/BenefitCard/BenefitCard.tsx +309 -0
- package/src/components/BottomNav/BottomNav.tsx +2 -1
- package/src/components/BottomNavItem/BottomNavItem.tsx +3 -2
- package/src/components/BrandChip/BrandChip.tsx +3 -2
- package/src/components/BubbleChart/BubbleChart.tsx +2 -1
- package/src/components/Button/Button.tsx +3 -2
- package/src/components/ButtonGroup/ButtonGroup.tsx +2 -1
- package/src/components/Card/Card.tsx +4 -3
- package/src/components/CardAdvisory/CardAdvisory.tsx +3 -2
- package/src/components/CardBankAccount/CardBankAccount.tsx +2 -1
- package/src/components/CardCTA/CardCTA.tsx +3 -2
- package/src/components/CardFeedback/CardFeedback.tsx +11 -10
- package/src/components/CardFinancialCondition/CardFinancialCondition.tsx +3 -2
- package/src/components/CardInsight/CardInsight.tsx +2 -1
- package/src/components/CardProviderInfo/CardProviderInfo.tsx +2 -1
- package/src/components/Carousel/Carousel.tsx +5 -4
- package/src/components/CcCard/CcCard.tsx +598 -0
- package/src/components/Checkbox/Checkbox.tsx +7 -5
- package/src/components/CheckboxGroup/CheckboxGroup.tsx +2 -1
- package/src/components/CheckboxItem/CheckboxItem.tsx +7 -5
- package/src/components/ChipGroup/ChipGroup.tsx +2 -1
- package/src/components/ChipSelect/ChipSelect.tsx +2 -1
- package/src/components/CircularProgressBar/CircularProgressBar.tsx +2 -1
- package/src/components/CircularProgressBarDoted/CircularProgressBarDoted.tsx +2 -1
- package/src/components/CircularRating/CircularRating.tsx +3 -2
- package/src/components/ClusterBubble/ClusterBubble.tsx +2 -1
- package/src/components/CompareTable/CompareTable.tsx +477 -0
- package/src/components/ComparisonBar/ComparisonBar.tsx +356 -0
- package/src/components/CoverageBarComparison/CoverageBarComparison.tsx +3 -2
- package/src/components/CoverageRing/CoverageRing.tsx +2 -1
- package/src/components/DebitCard/DebitCard.tsx +2 -1
- package/src/components/Disclaimer/Disclaimer.tsx +2 -1
- package/src/components/Divider/Divider.tsx +2 -1
- package/src/components/DonutChart/DonutChart.tsx +6 -5
- package/src/components/DonutChartSummary/DonutChartSummary.tsx +3 -2
- package/src/components/Drawer/Drawer.tsx +21 -1
- package/src/components/Dropdown/Dropdown.tsx +4 -3
- package/src/components/DropdownInput/DropdownInput.tsx +60 -7
- package/src/components/EmptyState/EmptyState.tsx +2 -1
- package/src/components/ExpandableCheckbox/ExpandableCheckbox.tsx +2 -1
- package/src/components/FilterBar/FilterBar.tsx +3 -2
- package/src/components/Form/Form.tsx +2 -1
- package/src/components/FormField/FormField.tsx +8 -6
- package/src/components/FullscreenModal/FullscreenModal.tsx +68 -10
- package/src/components/Gauge/Gauge.tsx +2 -1
- package/src/components/HStack/HStack.tsx +2 -1
- package/src/components/HoldingsCard/HoldingsCard.tsx +2 -1
- package/src/components/Icon/Icon.tsx +3 -2
- package/src/components/IconButton/IconButton.tsx +3 -2
- package/src/components/IconCapsule/IconCapsule.tsx +3 -2
- package/src/components/Image/Image.tsx +29 -5
- package/src/components/InputSearch/InputSearch.tsx +11 -7
- package/src/components/InstitutionBadge/InstitutionBadge.tsx +3 -2
- package/src/components/LazyList/LazyList.tsx +2 -1
- package/src/components/LinearMeter/LinearMeter.tsx +3 -2
- package/src/components/LinearProgress/LinearProgress.tsx +2 -1
- package/src/components/ListGroup/ListGroup.tsx +2 -1
- package/src/components/ListItem/ListItem.tsx +3 -2
- package/src/components/LottieIntroBlock/LottieIntroBlock.tsx +2 -1
- package/src/components/LottiePlayer/LottiePlayer.tsx +3 -2
- package/src/components/LottiePlayer/LottiePlayer.web.tsx +3 -2
- package/src/components/LottiePlayer/loadNativeLottieView.tsx +9 -13
- package/src/components/MediaCard/MediaCard.tsx +7 -6
- package/src/components/MerchantProfile/MerchantProfile.tsx +2 -1
- package/src/components/MessageField/MessageField.tsx +3 -2
- package/src/components/MetricLegendItem/MetricLegendItem.tsx +2 -1
- package/src/components/MoneyValue/MoneyValue.tsx +2 -1
- package/src/components/MonthlyStatusGrid/MonthlyStatusGrid.tsx +5 -4
- package/src/components/NavArrow/NavArrow.tsx +3 -2
- package/src/components/NoteInput/NoteInput.tsx +10 -7
- package/src/components/Nudge/Nudge.tsx +3 -2
- package/src/components/Numpad/Numpad.tsx +2 -1
- package/src/components/OTP/OTP.tsx +3 -2
- package/src/components/Overlay/Overlay.tsx +114 -0
- package/src/components/PageHero/PageHero.tsx +2 -1
- package/src/components/PaymentFeedback/PaymentFeedback.tsx +2 -1
- package/src/components/PdpCcCard/PdpCcCard.tsx +356 -0
- package/src/components/PlanComparisonCard/PlanComparisonCard.tsx +2 -1
- package/src/components/Popup/Popup.tsx +2 -1
- package/src/components/PortfolioHero/PortfolioHero.tsx +2 -1
- package/src/components/PoweredByLabel/PoweredByLabel.tsx +2 -1
- package/src/components/ProductLabel/ProductLabel.tsx +2 -1
- package/src/components/ProductMerchandisingCard/GlassFill.tsx +276 -0
- package/src/components/ProductMerchandisingCard/GlassFill.web.tsx +127 -0
- package/src/components/ProductMerchandisingCard/ProductMerchandisingCard.tsx +423 -0
- package/src/components/ProductOverview/ProductOverview.tsx +2 -1
- package/src/components/ProgressBadge/ProgressBadge.tsx +2 -1
- package/src/components/ProjectionMarker/ProjectionMarker.tsx +277 -0
- package/src/components/Radio/Radio.tsx +7 -5
- package/src/components/RangeTrack/RangeTrack.tsx +3 -2
- package/src/components/RechargeCard/RechargeCard.tsx +2 -1
- package/src/components/SavingsGoalSummary/SavingsGoalSummary.tsx +2 -1
- package/src/components/Screen/Screen.tsx +2 -1
- package/src/components/Section/Section.tsx +6 -5
- package/src/components/SegmentedControl/SegmentedControl.tsx +3 -2
- package/src/components/SegmentedTrack/SegmentedTrack.tsx +5 -4
- package/src/components/Slider/Slider.tsx +628 -0
- package/src/components/Slot/Slot.tsx +2 -1
- package/src/components/Spinner/Spinner.tsx +2 -1
- package/src/components/StatGroup/StatGroup.tsx +3 -2
- package/src/components/StatItem/StatItem.tsx +2 -1
- package/src/components/StatusHero/StatusHero.tsx +2 -1
- package/src/components/Stepper/Step.tsx +2 -1
- package/src/components/Stepper/StepLabel.tsx +2 -1
- package/src/components/Stepper/Stepper.tsx +2 -1
- package/src/components/StrengthIndicator/StrengthIndicator.tsx +2 -1
- package/src/components/SuggestiveSearch/SuggestiveSearch.tsx +4 -3
- package/src/components/SummaryTile/SummaryTile.tsx +2 -1
- package/src/components/SupportText/SupportText.tsx +2 -1
- package/src/components/SupportText/SupportTextIcon.tsx +2 -1
- package/src/components/SwappableAmount/SwappableAmount.tsx +2 -1
- package/src/components/Tabs/TabItem.tsx +2 -1
- package/src/components/Tabs/Tabs.tsx +2 -1
- package/src/components/TestimonialsCard/TestimonialsCard.tsx +2 -1
- package/src/components/Text/Text.tsx +2 -1
- package/src/components/TextInput/TextInput.tsx +18 -13
- package/src/components/TextSegment/TextSegment.tsx +166 -0
- package/src/components/ThreadHero/ThreadHero.tsx +2 -1
- package/src/components/Title/Title.tsx +2 -1
- package/src/components/Toast/Toast.tsx +2 -1
- package/src/components/Toast/ToastProvider.tsx +2 -1
- package/src/components/Toast/useToast.ts +3 -2
- package/src/components/Toggle/Toggle.tsx +2 -1
- package/src/components/Tooltip/Tooltip.tsx +3 -2
- package/src/components/TransactionBubble/TransactionBubble.tsx +2 -1
- package/src/components/TransactionDetails/TransactionDetails.tsx +3 -2
- package/src/components/TransactionStatus/TransactionStatus.tsx +3 -2
- package/src/components/UpiHandle/UpiHandle.tsx +3 -2
- package/src/components/VStack/VStack.tsx +2 -1
- package/src/components/docs/modeControls.tsx +122 -0
- package/src/components/index.ts +11 -1
- package/src/design-tokens/Coin Variables-variables-full.json +1 -1
- package/src/design-tokens/JFSThemeProvider.tsx +4 -3
- package/src/design-tokens/figma-modes.generated.ts +425 -0
- package/src/design-tokens/index.ts +1 -0
- package/src/icons/registry.ts +1 -1
- package/src/skeleton/Skeleton.tsx +2 -1
- package/src/utils/react-utils.ts +26 -2
- package/lib/typescript/scripts/extract-component-tokens.d.ts +0 -9
- package/lib/typescript/scripts/generate-component-docs.d.ts +0 -9
- package/lib/typescript/scripts/generate-icon-registry.d.ts +0 -3
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React, {
|
|
2
|
+
forwardRef,
|
|
2
3
|
useCallback,
|
|
3
4
|
useEffect,
|
|
5
|
+
useImperativeHandle,
|
|
4
6
|
useMemo,
|
|
5
7
|
useRef,
|
|
6
8
|
useState,
|
|
@@ -27,6 +29,7 @@ import Icon from '../../icons/Icon'
|
|
|
27
29
|
import SupportText from '../SupportText/SupportText'
|
|
28
30
|
import type { SupportTextStatus } from '../SupportText/SupportTextIcon'
|
|
29
31
|
import Dropdown, { DropdownItem, type DropdownItemProps } from '../Dropdown/Dropdown'
|
|
32
|
+
import type { Modes } from '../../design-tokens'
|
|
30
33
|
|
|
31
34
|
const IS_WEB = Platform.OS === 'web'
|
|
32
35
|
|
|
@@ -51,6 +54,28 @@ export type DropdownInputOption = {
|
|
|
51
54
|
|
|
52
55
|
type Rect = { x: number; y: number; width: number; height: number }
|
|
53
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Imperative handle exposed via `ref`. Lets the consumer drive the dropdown
|
|
59
|
+
* from outside — e.g. close it when an Android hardware/system button is
|
|
60
|
+
* pressed, or open it programmatically from a sibling control.
|
|
61
|
+
*/
|
|
62
|
+
export type DropdownInputHandle = {
|
|
63
|
+
/** Opens the options menu (no-op when disabled / read-only). */
|
|
64
|
+
open: () => void
|
|
65
|
+
/** Closes the options menu. */
|
|
66
|
+
close: () => void
|
|
67
|
+
/** Toggles the options menu open/closed. */
|
|
68
|
+
toggle: () => void
|
|
69
|
+
/** Moves focus to the trigger (web). */
|
|
70
|
+
focus: () => void
|
|
71
|
+
/** Removes focus from the trigger (web). */
|
|
72
|
+
blur: () => void
|
|
73
|
+
/** Measures the trigger in window coordinates. */
|
|
74
|
+
measureInWindow: (
|
|
75
|
+
callback: (x: number, y: number, width: number, height: number) => void
|
|
76
|
+
) => void
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
export type DropdownInputProps = {
|
|
55
80
|
/** Label rendered above the input. */
|
|
56
81
|
label?: string
|
|
@@ -131,7 +156,7 @@ export type DropdownInputProps = {
|
|
|
131
156
|
/** Whether tapping the backdrop closes the menu. */
|
|
132
157
|
closeOnBackdropPress?: boolean
|
|
133
158
|
/** Modes for design token resolution. */
|
|
134
|
-
modes?:
|
|
159
|
+
modes?: Modes
|
|
135
160
|
/** Style overrides for the outermost wrapper. */
|
|
136
161
|
style?: StyleProp<ViewStyle>
|
|
137
162
|
/** Style overrides for the input row. */
|
|
@@ -152,7 +177,7 @@ export type DropdownInputProps = {
|
|
|
152
177
|
// Token resolution
|
|
153
178
|
// ---------------------------------------------------------------------------
|
|
154
179
|
|
|
155
|
-
function useChevronTokens(modes:
|
|
180
|
+
function useChevronTokens(modes: Modes) {
|
|
156
181
|
return useMemo(() => {
|
|
157
182
|
const iconSize =
|
|
158
183
|
parseInt(getVariableByName('input/iconSize', modes), 10) || 32
|
|
@@ -172,7 +197,7 @@ function toNumber(value: unknown, fallback: number): number {
|
|
|
172
197
|
return fallback
|
|
173
198
|
}
|
|
174
199
|
|
|
175
|
-
function useFormFieldTokens(modes:
|
|
200
|
+
function useFormFieldTokens(modes: Modes) {
|
|
176
201
|
return useMemo(() => {
|
|
177
202
|
const labelColor =
|
|
178
203
|
(getVariableByName('formField/label/color', modes) as string) ||
|
|
@@ -306,7 +331,7 @@ function collectOptionsFromChildren(
|
|
|
306
331
|
// Component
|
|
307
332
|
// ---------------------------------------------------------------------------
|
|
308
333
|
|
|
309
|
-
function DropdownInput({
|
|
334
|
+
const DropdownInput = forwardRef<DropdownInputHandle, DropdownInputProps>(function DropdownInput({
|
|
310
335
|
label,
|
|
311
336
|
placeholder = 'Select an option',
|
|
312
337
|
items,
|
|
@@ -337,7 +362,7 @@ function DropdownInput({
|
|
|
337
362
|
accessibilityHint,
|
|
338
363
|
onFocus,
|
|
339
364
|
onBlur,
|
|
340
|
-
}: DropdownInputProps) {
|
|
365
|
+
}: DropdownInputProps, ref: React.Ref<DropdownInputHandle>) {
|
|
341
366
|
// ---------------- Modes ----------------
|
|
342
367
|
const { modes: globalModes } = useTokens()
|
|
343
368
|
const baseModes = useMemo(
|
|
@@ -496,6 +521,34 @@ function DropdownInput({
|
|
|
496
521
|
[measure]
|
|
497
522
|
)
|
|
498
523
|
|
|
524
|
+
// ---------------- Imperative handle ----------------
|
|
525
|
+
useImperativeHandle(
|
|
526
|
+
ref,
|
|
527
|
+
() => ({
|
|
528
|
+
open: () => {
|
|
529
|
+
if (isDisabled || isReadOnly) return
|
|
530
|
+
measure()
|
|
531
|
+
setOpenState(true)
|
|
532
|
+
},
|
|
533
|
+
close: closeMenu,
|
|
534
|
+
toggle: () => {
|
|
535
|
+
if (isDisabled || isReadOnly) return
|
|
536
|
+
measure()
|
|
537
|
+
toggleMenu()
|
|
538
|
+
},
|
|
539
|
+
focus: () => {
|
|
540
|
+
;(triggerRef.current as unknown as { focus?: () => void })?.focus?.()
|
|
541
|
+
},
|
|
542
|
+
blur: () => {
|
|
543
|
+
;(triggerRef.current as unknown as { blur?: () => void })?.blur?.()
|
|
544
|
+
},
|
|
545
|
+
measureInWindow: (callback) => {
|
|
546
|
+
triggerRef.current?.measureInWindow(callback)
|
|
547
|
+
},
|
|
548
|
+
}),
|
|
549
|
+
[isDisabled, isReadOnly, measure, setOpenState, closeMenu, toggleMenu]
|
|
550
|
+
)
|
|
551
|
+
|
|
499
552
|
// ---------------- Popup positioning ----------------
|
|
500
553
|
const [menuSize, setMenuSize] = useState<{
|
|
501
554
|
width: number
|
|
@@ -829,7 +882,7 @@ function DropdownInput({
|
|
|
829
882
|
transparent
|
|
830
883
|
statusBarTranslucent
|
|
831
884
|
navigationBarTranslucent
|
|
832
|
-
animationType="
|
|
885
|
+
animationType="none"
|
|
833
886
|
onRequestClose={closeMenu}
|
|
834
887
|
>
|
|
835
888
|
<Pressable
|
|
@@ -862,7 +915,7 @@ function DropdownInput({
|
|
|
862
915
|
</Modal>
|
|
863
916
|
</View>
|
|
864
917
|
)
|
|
865
|
-
}
|
|
918
|
+
})
|
|
866
919
|
|
|
867
920
|
const webNoOutline: any = {
|
|
868
921
|
outlineStyle: 'none',
|
|
@@ -5,6 +5,7 @@ import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
|
5
5
|
import IconCapsule from '../IconCapsule/IconCapsule'
|
|
6
6
|
import Button from '../Button/Button'
|
|
7
7
|
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
8
|
+
import type { Modes } from '../../design-tokens'
|
|
8
9
|
|
|
9
10
|
export type EmptyStateProps = {
|
|
10
11
|
/**
|
|
@@ -35,7 +36,7 @@ export type EmptyStateProps = {
|
|
|
35
36
|
/**
|
|
36
37
|
* Mode configuration for theming
|
|
37
38
|
*/
|
|
38
|
-
modes?:
|
|
39
|
+
modes?: Modes;
|
|
39
40
|
style?: StyleProp<ViewStyle>;
|
|
40
41
|
testID?: string;
|
|
41
42
|
}
|
|
@@ -10,6 +10,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
|
10
10
|
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
11
11
|
import Checkbox from '../Checkbox/Checkbox'
|
|
12
12
|
import Button from '../Button/Button'
|
|
13
|
+
import type { Modes } from '../../design-tokens'
|
|
13
14
|
|
|
14
15
|
export type ExpandableCheckboxProps = {
|
|
15
16
|
/** Long text label rendered next to the checkbox. */
|
|
@@ -35,7 +36,7 @@ export type ExpandableCheckboxProps = {
|
|
|
35
36
|
/** Number of lines to show when collapsed. Defaults to `1`. */
|
|
36
37
|
collapsedLines?: number
|
|
37
38
|
/** Design token modes for theming (e.g. `{ 'Color Mode': 'Light' }`). */
|
|
38
|
-
modes?:
|
|
39
|
+
modes?: Modes
|
|
39
40
|
/** Override outer container styles. */
|
|
40
41
|
style?: StyleProp<ViewStyle>
|
|
41
42
|
/** Override the label text styles. */
|
|
@@ -3,12 +3,13 @@ import { View, type StyleProp, type ViewStyle } from 'react-native'
|
|
|
3
3
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
4
|
import TextInput from '../TextInput/TextInput'
|
|
5
5
|
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
|
|
6
|
+
import type { Modes } from '../../design-tokens'
|
|
6
7
|
|
|
7
8
|
type RenderInputArgs = {
|
|
8
9
|
placeholder: string;
|
|
9
10
|
value: string;
|
|
10
11
|
onChangeText?: ((text: string) => void) | undefined;
|
|
11
|
-
modes:
|
|
12
|
+
modes: Modes;
|
|
12
13
|
accessibilityLabel: string;
|
|
13
14
|
accessibilityHint?: string | undefined;
|
|
14
15
|
onFocus?: (e: any) => void;
|
|
@@ -30,7 +31,7 @@ type FilterBarProps = {
|
|
|
30
31
|
* respect the higher-level FilterBar API.
|
|
31
32
|
*/
|
|
32
33
|
renderInput?: (args: RenderInputArgs) => React.ReactNode;
|
|
33
|
-
modes?:
|
|
34
|
+
modes?: Modes;
|
|
34
35
|
style?: StyleProp<ViewStyle>;
|
|
35
36
|
accessibilityLabel?: string;
|
|
36
37
|
accessibilityHint?: string;
|
|
@@ -3,6 +3,7 @@ import { View, type StyleProp, type ViewStyle } from 'react-native'
|
|
|
3
3
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
4
|
import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
5
5
|
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
6
|
+
import type { Modes } from '../../design-tokens'
|
|
6
7
|
|
|
7
8
|
type FormContextValue = {
|
|
8
9
|
validationErrors: Record<string, string | string[]>;
|
|
@@ -19,7 +20,7 @@ export type FormProps = {
|
|
|
19
20
|
children: React.ReactNode;
|
|
20
21
|
validationErrors?: Record<string, string | string[]>;
|
|
21
22
|
onSubmit?: () => void;
|
|
22
|
-
modes?:
|
|
23
|
+
modes?: Modes;
|
|
23
24
|
style?: StyleProp<ViewStyle>;
|
|
24
25
|
accessibilityLabel?: string;
|
|
25
26
|
testID?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useMemo, useState } from 'react'
|
|
1
|
+
import React, { forwardRef, useCallback, useMemo, useState } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
@@ -15,6 +15,7 @@ import SupportText from '../SupportText/SupportText'
|
|
|
15
15
|
import type { SupportTextStatus } from '../SupportText/SupportTextIcon'
|
|
16
16
|
import Icon from '../../icons/Icon'
|
|
17
17
|
import { useFormContext } from '../Form/Form'
|
|
18
|
+
import type { Modes } from '../../design-tokens'
|
|
18
19
|
|
|
19
20
|
export type FormFieldType = 'text' | 'password' | 'email' | 'search' | 'number' | 'phone' | 'url'
|
|
20
21
|
|
|
@@ -76,7 +77,7 @@ export type FormFieldProps = {
|
|
|
76
77
|
/** When true, focuses the input on mount. */
|
|
77
78
|
autoFocus?: boolean
|
|
78
79
|
/** Modes for design token resolution. */
|
|
79
|
-
modes?:
|
|
80
|
+
modes?: Modes
|
|
80
81
|
/** Style overrides for the outermost wrapper. */
|
|
81
82
|
style?: StyleProp<ViewStyle>
|
|
82
83
|
/** Style overrides for the input row container. */
|
|
@@ -116,7 +117,7 @@ function toFontWeight(value: unknown, fallback: TextStyle['fontWeight']): TextSt
|
|
|
116
117
|
return fallback
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
function useFormFieldTokens(modes:
|
|
120
|
+
function useFormFieldTokens(modes: Modes) {
|
|
120
121
|
return useMemo(() => {
|
|
121
122
|
// Wrapper
|
|
122
123
|
const gap = toNumber(getVariableByName('formField/gap', modes), 8)
|
|
@@ -300,7 +301,7 @@ function firstError(error: string | string[] | undefined): string | undefined {
|
|
|
300
301
|
// Component
|
|
301
302
|
// ---------------------------------------------------------------------------
|
|
302
303
|
|
|
303
|
-
function FormField({
|
|
304
|
+
const FormField = forwardRef<RNTextInput, FormFieldProps>(function FormField({
|
|
304
305
|
label,
|
|
305
306
|
placeholder,
|
|
306
307
|
value,
|
|
@@ -328,7 +329,7 @@ function FormField({
|
|
|
328
329
|
accessibilityLabel,
|
|
329
330
|
accessibilityHint,
|
|
330
331
|
testID,
|
|
331
|
-
}: FormFieldProps) {
|
|
332
|
+
}: FormFieldProps, ref: React.Ref<RNTextInput>) {
|
|
332
333
|
// -- Form context integration -------------------------------------------
|
|
333
334
|
const formCtx = useFormContext()
|
|
334
335
|
const formError =
|
|
@@ -551,6 +552,7 @@ function FormField({
|
|
|
551
552
|
</View>
|
|
552
553
|
)}
|
|
553
554
|
<RNTextInput
|
|
555
|
+
ref={ref}
|
|
554
556
|
style={[inputTextStyles, inputTextStyle]}
|
|
555
557
|
value={value ?? ''}
|
|
556
558
|
onChangeText={handleChangeText}
|
|
@@ -589,6 +591,6 @@ function FormField({
|
|
|
589
591
|
)}
|
|
590
592
|
</View>
|
|
591
593
|
)
|
|
592
|
-
}
|
|
594
|
+
})
|
|
593
595
|
|
|
594
596
|
export default FormField
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React, { useMemo, useRef } from 'react'
|
|
1
|
+
import React, { useMemo, useRef, useState, useCallback } from 'react'
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
5
5
|
Animated,
|
|
6
|
+
type LayoutChangeEvent,
|
|
6
7
|
type StyleProp,
|
|
7
8
|
type ViewStyle,
|
|
8
9
|
type TextStyle,
|
|
@@ -16,6 +17,7 @@ import Disclaimer from '../Disclaimer/Disclaimer'
|
|
|
16
17
|
import IconButton from '../IconButton/IconButton'
|
|
17
18
|
import ActionFooter from '../ActionFooter/ActionFooter'
|
|
18
19
|
import Slot from '../Slot/Slot'
|
|
20
|
+
import type { Modes } from '../../design-tokens'
|
|
19
21
|
|
|
20
22
|
// ---------------------------------------------------------------------------
|
|
21
23
|
// Forced modes
|
|
@@ -99,7 +101,7 @@ export type FullscreenModalProps = {
|
|
|
99
101
|
* and `context5` is always forced to `'Fullscreen Modal'` (non-overridable).
|
|
100
102
|
* The resolved modes cascade to the body, hero media, and the `ActionFooter`.
|
|
101
103
|
*/
|
|
102
|
-
modes?:
|
|
104
|
+
modes?: Modes
|
|
103
105
|
/** Style overrides for the outer container. */
|
|
104
106
|
style?: StyleProp<ViewStyle>
|
|
105
107
|
/** Style overrides for the transparent body wrapper. */
|
|
@@ -118,7 +120,7 @@ type HeroTextProps = {
|
|
|
118
120
|
headline?: string
|
|
119
121
|
supportingText?: string
|
|
120
122
|
priceText?: string
|
|
121
|
-
modes:
|
|
123
|
+
modes: Modes
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
function HeroText({ eyebrow, headline, supportingText, priceText, modes }: HeroTextProps) {
|
|
@@ -300,11 +302,57 @@ function FullscreenModal({
|
|
|
300
302
|
)
|
|
301
303
|
const heroTranslateY = useMemo(() => Animated.multiply(scrollY, -1), [scrollY])
|
|
302
304
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
)
|
|
305
|
+
// The hero media is a full-bleed background pinned to the top of the modal.
|
|
306
|
+
// Its wrapper is absolutely positioned (`top/left/right: 0`) so it never
|
|
307
|
+
// contributes to scroll height. We measure the modal's own width so we can
|
|
308
|
+
// give the hero media a DEFINITE { width, height } box (see
|
|
309
|
+
// `processedHeroMedia` below) — relying on the media's own `width: '100%'` +
|
|
310
|
+
// `aspectRatio` is unreliable inside an indefinite-height absolute box (RN's
|
|
311
|
+
// `<Image>` falls back to its intrinsic width and leaves a gap), so we size
|
|
312
|
+
// it explicitly here instead.
|
|
313
|
+
const [containerWidth, setContainerWidth] = useState(0)
|
|
314
|
+
const onContainerLayout = useCallback((e: LayoutChangeEvent) => {
|
|
315
|
+
const w = e.nativeEvent.layout.width
|
|
316
|
+
setContainerWidth((prev) => (prev !== w ? w : prev))
|
|
317
|
+
}, [])
|
|
318
|
+
|
|
319
|
+
const processedHeroMedia = useMemo(() => {
|
|
320
|
+
if (!heroMedia) return null
|
|
321
|
+
// Defer rendering the hero until we have measured the modal width. This
|
|
322
|
+
// matters for image sharpness: React Native decodes a bitmap once, on the
|
|
323
|
+
// first render, and caches it. If we rendered the media before knowing the
|
|
324
|
+
// final box, that first decode would be sized/sampled for the wrong box and
|
|
325
|
+
// the cached (downsampled) bitmap would then just be scaled up — blurry.
|
|
326
|
+
// Rendering only once the explicit { width, height } box is known means the
|
|
327
|
+
// very first decode is already full-resolution for the correct box.
|
|
328
|
+
if (containerWidth <= 0) return null
|
|
329
|
+
const withModes = cloneChildrenWithModes(heroMedia, modes, FULLSCREEN_MODAL_FORCED_MODES)
|
|
330
|
+
|
|
331
|
+
// Force the hero to fill the modal width edge to edge, top-aligned, with the
|
|
332
|
+
// height derived from the media's native aspect ratio.
|
|
333
|
+
//
|
|
334
|
+
// Why we inject explicit width/height instead of relying on the media's own
|
|
335
|
+
// `width: '100%'` + `aspectRatio`: the hero wrapper is absolutely positioned
|
|
336
|
+
// with an INDEFINITE height, and in that layout context React Native's
|
|
337
|
+
// `<Image>` falls back to its INTRINSIC width (so a 361px-wide asset renders
|
|
338
|
+
// 361px wide and leaves a gap on the right) rather than stretching to the
|
|
339
|
+
// parent. By computing `height = containerWidth / ratio` here and passing a
|
|
340
|
+
// DEFINITE { width, height } box (which makes `<Image>` skip aspectRatio and
|
|
341
|
+
// cover-fit into that exact box), the hero always fills the width with the
|
|
342
|
+
// correct ratio-derived height.
|
|
343
|
+
return React.Children.map(withModes, (child) => {
|
|
344
|
+
if (!React.isValidElement(child)) return child
|
|
345
|
+
const props = child.props as { ratio?: number; width?: unknown; height?: unknown }
|
|
346
|
+
const ratio = typeof props.ratio === 'number' && props.ratio > 0 ? props.ratio : undefined
|
|
347
|
+
// Only size media that exposes a numeric `ratio` and hasn't already been
|
|
348
|
+
// given an explicit box by the caller.
|
|
349
|
+
if (ratio == null || props.width != null || props.height != null) return child
|
|
350
|
+
return React.cloneElement(child, {
|
|
351
|
+
width: containerWidth,
|
|
352
|
+
height: containerWidth / ratio,
|
|
353
|
+
} as Partial<typeof props>)
|
|
354
|
+
})
|
|
355
|
+
}, [heroMedia, modes, containerWidth])
|
|
308
356
|
|
|
309
357
|
const processedChildren = useMemo(
|
|
310
358
|
() =>
|
|
@@ -369,7 +417,7 @@ function FullscreenModal({
|
|
|
369
417
|
}
|
|
370
418
|
|
|
371
419
|
return (
|
|
372
|
-
<View style={[rootStyle, style]} testID={testID}>
|
|
420
|
+
<View style={[rootStyle, style]} testID={testID} onLayout={onContainerLayout}>
|
|
373
421
|
{/*
|
|
374
422
|
* Layout model:
|
|
375
423
|
* - `processedHeroMedia` is a ROOT-LEVEL full-bleed background pinned to
|
|
@@ -387,7 +435,17 @@ function FullscreenModal({
|
|
|
387
435
|
*/}
|
|
388
436
|
{processedHeroMedia ? (
|
|
389
437
|
<Animated.View
|
|
390
|
-
style={[
|
|
438
|
+
style={[
|
|
439
|
+
heroBackgroundStyle,
|
|
440
|
+
// Give the absolute wrapper a DEFINITE width (the measured modal
|
|
441
|
+
// width) so the media's `width: '100%'` + `aspectRatio` resolves to
|
|
442
|
+
// a true edge-to-edge fill with a ratio-derived height, top-aligned.
|
|
443
|
+
// Before the first layout pass `containerWidth` is 0 — fall back to
|
|
444
|
+
// stretching via `left/right: 0` so there is no flash of a mis-sized
|
|
445
|
+
// image.
|
|
446
|
+
containerWidth > 0 ? { width: containerWidth } : null,
|
|
447
|
+
{ transform: [{ translateY: heroTranslateY }] },
|
|
448
|
+
]}
|
|
391
449
|
pointerEvents="none"
|
|
392
450
|
>
|
|
393
451
|
{processedHeroMedia}
|
|
@@ -5,6 +5,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
|
5
5
|
import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
6
6
|
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
|
|
7
7
|
import SupportText, { type SupportTextProps } from '../SupportText/SupportText'
|
|
8
|
+
import type { Modes } from '../../design-tokens'
|
|
8
9
|
|
|
9
10
|
type GaugeBaseProps = Omit<React.ComponentProps<typeof View>, 'children' | 'style'>
|
|
10
11
|
|
|
@@ -32,7 +33,7 @@ export type GaugeProps = GaugeBaseProps & {
|
|
|
32
33
|
/** Hides default support text when no custom readout slot is provided. */
|
|
33
34
|
showSupportText?: boolean
|
|
34
35
|
/** Design token modes forwarded to token lookups and slot children. */
|
|
35
|
-
modes?:
|
|
36
|
+
modes?: Modes
|
|
36
37
|
/** Slot rendered in the center of the gauge arc. Receives `modes` recursively. */
|
|
37
38
|
children?: React.ReactNode
|
|
38
39
|
/** Container style override. */
|
|
@@ -3,6 +3,7 @@ import { View, StyleProp, ViewStyle, ViewProps } from 'react-native'
|
|
|
3
3
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
4
4
|
import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
5
5
|
import { cloneChildrenWithModes, EMPTY_MODES } from '../../utils/react-utils'
|
|
6
|
+
import type { Modes } from '../../design-tokens'
|
|
6
7
|
|
|
7
8
|
export interface HStackProps extends ViewProps {
|
|
8
9
|
/**
|
|
@@ -35,7 +36,7 @@ export interface HStackProps extends ViewProps {
|
|
|
35
36
|
/**
|
|
36
37
|
* Modes object to override default variable values.
|
|
37
38
|
*/
|
|
38
|
-
modes?:
|
|
39
|
+
modes?: Modes;
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
/**
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
12
12
|
import Radio from '../Radio/Radio'
|
|
13
13
|
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
14
|
+
import type { Modes } from '../../design-tokens'
|
|
14
15
|
|
|
15
16
|
export interface HoldingsCardDetailItem {
|
|
16
17
|
label: string
|
|
@@ -33,7 +34,7 @@ export interface HoldingsCardProps {
|
|
|
33
34
|
/** Called when the card is pressed (toggles selection). */
|
|
34
35
|
onPress?: () => void
|
|
35
36
|
/** Modes object for design-token resolution. */
|
|
36
|
-
modes?:
|
|
37
|
+
modes?: Modes
|
|
37
38
|
/** Custom style for the outer container. */
|
|
38
39
|
style?: StyleProp<ViewStyle>
|
|
39
40
|
/** Test ID for testing. */
|
|
@@ -10,6 +10,7 @@ import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
|
10
10
|
import { EMPTY_MODES, cloneChildrenWithModes } from '../../utils/react-utils'
|
|
11
11
|
import BaseIcon from '../../icons/Icon'
|
|
12
12
|
import type { UnifiedSource } from '../../utils/MediaSource'
|
|
13
|
+
import type { Modes } from '../../design-tokens'
|
|
13
14
|
|
|
14
15
|
type IconProps = AccessibilityProps & {
|
|
15
16
|
/**
|
|
@@ -43,7 +44,7 @@ type IconProps = AccessibilityProps & {
|
|
|
43
44
|
* from the `icon/size` design token.
|
|
44
45
|
*/
|
|
45
46
|
size?: number
|
|
46
|
-
modes?:
|
|
47
|
+
modes?: Modes
|
|
47
48
|
style?: StyleProp<ViewStyle>
|
|
48
49
|
}
|
|
49
50
|
|
|
@@ -53,7 +54,7 @@ interface IconTokens {
|
|
|
53
54
|
iconSize: number
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
function resolveIconTokens(modes:
|
|
57
|
+
function resolveIconTokens(modes: Modes): IconTokens {
|
|
57
58
|
const iconColor = (getVariableByName('icon/color', modes) || '#ad8444') as string
|
|
58
59
|
const iconSize = (getVariableByName('icon/size', modes) || 18) as number
|
|
59
60
|
const paddingLeft = (getVariableByName('icon/padding/left', modes) || 0) as number
|
|
@@ -14,6 +14,7 @@ import { EMPTY_MODES } from '../../utils/react-utils'
|
|
|
14
14
|
import type { UnifiedSource } from '../../utils/MediaSource'
|
|
15
15
|
import Skeleton from '../../skeleton/Skeleton'
|
|
16
16
|
import { useSkeleton } from '../../skeleton/SkeletonGroup'
|
|
17
|
+
import type { Modes } from '../../design-tokens'
|
|
17
18
|
|
|
18
19
|
type IconButtonProps = SafePressableProps & {
|
|
19
20
|
/** Built-in icon name from the registry (default state). */
|
|
@@ -26,7 +27,7 @@ type IconButtonProps = SafePressableProps & {
|
|
|
26
27
|
* follows design tokens just like a built-in icon. See {@link UnifiedSource}.
|
|
27
28
|
*/
|
|
28
29
|
source?: UnifiedSource;
|
|
29
|
-
modes?:
|
|
30
|
+
modes?: Modes;
|
|
30
31
|
onPress?: () => void;
|
|
31
32
|
disabled?: boolean;
|
|
32
33
|
style?: StyleProp<ViewStyle>;
|
|
@@ -96,7 +97,7 @@ interface IconButtonTokens {
|
|
|
96
97
|
iconSize: number;
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
function resolveIconButtonTokens(modes:
|
|
100
|
+
function resolveIconButtonTokens(modes: Modes, disabled: boolean): IconButtonTokens {
|
|
100
101
|
const radiusRaw = (getVariableByName('iconButton/radius', modes) ?? 9999) as number
|
|
101
102
|
const padding = (getVariableByName('iconButton/padding', modes) ?? 12) as number
|
|
102
103
|
const backgroundColor = (getVariableByName('iconButton/background', modes) ?? '#cfa159') as string
|
|
@@ -5,6 +5,7 @@ import { useTokens } from '../../design-tokens/JFSThemeProvider'
|
|
|
5
5
|
import { EMPTY_MODES } from '../../utils/react-utils'
|
|
6
6
|
import Icon from '../../icons/Icon'
|
|
7
7
|
import type { UnifiedSource } from '../../utils/MediaSource'
|
|
8
|
+
import type { Modes } from '../../design-tokens'
|
|
8
9
|
|
|
9
10
|
type IconCapsuleProps = {
|
|
10
11
|
iconName?: string;
|
|
@@ -17,7 +18,7 @@ type IconCapsuleProps = {
|
|
|
17
18
|
* {@link UnifiedSource}.
|
|
18
19
|
*/
|
|
19
20
|
source?: UnifiedSource;
|
|
20
|
-
modes?:
|
|
21
|
+
modes?: Modes;
|
|
21
22
|
accessibilityLabel?: string;
|
|
22
23
|
accessibilityRole?: string;
|
|
23
24
|
} & React.ComponentProps<typeof View>;
|
|
@@ -28,7 +29,7 @@ interface IconCapsuleTokens {
|
|
|
28
29
|
iconSize: number;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
function resolveIconCapsuleTokens(modes:
|
|
32
|
+
function resolveIconCapsuleTokens(modes: Modes): IconCapsuleTokens {
|
|
32
33
|
const size = (getVariableByName('iconCapsule/size', modes) || 42) as number
|
|
33
34
|
const radiusRaw = (getVariableByName('iconCapsule/radius', modes) || 9999) as number
|
|
34
35
|
const backgroundColor = (getVariableByName('iconCapsule/background', modes) || '#cfa159') as string
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
type ViewStyle,
|
|
9
9
|
type ImageResizeMode,
|
|
10
10
|
} from 'react-native'
|
|
11
|
+
|
|
12
|
+
type ImageResizeMethod = 'auto' | 'resize' | 'scale' | 'none'
|
|
11
13
|
import Skeleton from '../../skeleton/Skeleton'
|
|
12
14
|
import { useSkeleton } from '../../skeleton/SkeletonGroup'
|
|
13
15
|
|
|
@@ -33,6 +35,21 @@ export type ImageProps = {
|
|
|
33
35
|
ratio?: number | undefined
|
|
34
36
|
/** How the image is fit inside its box. Defaults to `'cover'`. */
|
|
35
37
|
resizeMode?: ImageResizeMode | undefined
|
|
38
|
+
/**
|
|
39
|
+
* (Android only) How the bitmap is resampled when the source resolution
|
|
40
|
+
* differs from the rendered box.
|
|
41
|
+
*
|
|
42
|
+
* RN's own default is `'auto'`, which for large source images silently picks
|
|
43
|
+
* `'resize'`: a pre-decode software downsample that DESTROYS detail and makes
|
|
44
|
+
* big hero/background images look soft/pixelated even when the asset is
|
|
45
|
+
* high-res. To avoid that, this component defaults to:
|
|
46
|
+
* - `'none'` when an explicit `width` + `height` box is set (full-bleed
|
|
47
|
+
* hero/background usage — full resolution, maximum sharpness), and
|
|
48
|
+
* - `'scale'` otherwise (GPU scaling — high quality and memory-safe for
|
|
49
|
+
* ordinary aspect-ratio images).
|
|
50
|
+
* Pass an explicit value to override. No-op on iOS/web.
|
|
51
|
+
*/
|
|
52
|
+
resizeMethod?: ImageResizeMethod | undefined
|
|
36
53
|
/**
|
|
37
54
|
* Optional explicit width. If omitted and a `ratio` is set, the image
|
|
38
55
|
* defaults to `width: '100%'` so it fills its parent.
|
|
@@ -96,6 +113,7 @@ function Image({
|
|
|
96
113
|
imageSource,
|
|
97
114
|
ratio = DEFAULT_RATIO,
|
|
98
115
|
resizeMode = 'cover',
|
|
116
|
+
resizeMethod,
|
|
99
117
|
width,
|
|
100
118
|
height,
|
|
101
119
|
borderRadius,
|
|
@@ -107,11 +125,16 @@ function Image({
|
|
|
107
125
|
}: ImageProps) {
|
|
108
126
|
const source = useMemo(() => normalizeSource(imageSource), [imageSource])
|
|
109
127
|
|
|
128
|
+
// Explicit { width, height } means a "fill an exact box" layout — typically a
|
|
129
|
+
// full-bleed hero/background where the asset is high-res and sharpness
|
|
130
|
+
// matters most. There, default to `'none'` (full-resolution, no pre-decode
|
|
131
|
+
// downsample) so detail is never thrown away. Aspect-ratio images keep the
|
|
132
|
+
// memory-safe `'scale'` default. A caller-supplied `resizeMethod` always wins.
|
|
133
|
+
const isExplicitBox = width != null && height != null
|
|
134
|
+
const effectiveResizeMethod: ImageResizeMethod =
|
|
135
|
+
resizeMethod ?? (isExplicitBox ? 'none' : 'scale')
|
|
136
|
+
|
|
110
137
|
const layoutStyle: ImageStyle = useMemo(() => {
|
|
111
|
-
// If the caller has fully specified width AND height, they're doing a
|
|
112
|
-
// non-aspect layout (e.g. "fill the parent") — respect that and skip
|
|
113
|
-
// `aspectRatio` so it doesn't conflict.
|
|
114
|
-
const isExplicitBox = width != null && height != null
|
|
115
138
|
const s: ImageStyle = {
|
|
116
139
|
width: width ?? '100%',
|
|
117
140
|
...(isExplicitBox
|
|
@@ -120,7 +143,7 @@ function Image({
|
|
|
120
143
|
}
|
|
121
144
|
if (borderRadius != null) s.borderRadius = borderRadius
|
|
122
145
|
return s
|
|
123
|
-
}, [ratio, width, height, borderRadius])
|
|
146
|
+
}, [ratio, width, height, borderRadius, isExplicitBox])
|
|
124
147
|
|
|
125
148
|
const { active: groupActive } = useSkeleton()
|
|
126
149
|
const isLoading = loading ?? groupActive
|
|
@@ -146,6 +169,7 @@ function Image({
|
|
|
146
169
|
source={source}
|
|
147
170
|
style={[layoutStyle, style]}
|
|
148
171
|
resizeMode={resizeMode}
|
|
172
|
+
resizeMethod={effectiveResizeMethod}
|
|
149
173
|
accessibilityLabel={accessibilityLabel}
|
|
150
174
|
accessibilityElementsHidden={accessibilityElementsHidden}
|
|
151
175
|
importantForAccessibility={importantForAccessibility}
|