jfs-components 0.0.61 → 0.0.63
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 +36 -0
- package/lib/commonjs/components/Accordion/Accordion.js +1 -1
- package/lib/commonjs/components/ActionFooter/ActionFooter.js +1 -1
- package/lib/commonjs/components/ActionTile/ActionTile.js +2 -1
- package/lib/commonjs/components/AmountInput/AmountInput.js +2 -1
- package/lib/commonjs/components/AppBar/AppBar.js +1 -1
- package/lib/commonjs/components/Avatar/Avatar.js +184 -162
- package/lib/commonjs/components/AvatarGroup/AvatarGroup.js +1 -1
- package/lib/commonjs/components/Badge/Badge.js +2 -1
- package/lib/commonjs/components/Balance/Balance.js +2 -1
- package/lib/commonjs/components/BottomNav/BottomNav.js +2 -1
- package/lib/commonjs/components/BottomNavItem/BottomNavItem.js +106 -86
- package/lib/commonjs/components/Button/Button.js +190 -93
- package/lib/commonjs/components/ButtonGroup/ButtonGroup.js +1 -1
- package/lib/commonjs/components/Card/Card.js +2 -1
- package/lib/commonjs/components/CardCTA/CardCTA.js +1 -1
- package/lib/commonjs/components/CardProviderInfo/CardProviderInfo.js +1 -1
- package/lib/commonjs/components/Carousel/Carousel.js +3 -2
- package/lib/commonjs/components/Checkbox/Checkbox.js +2 -1
- package/lib/commonjs/components/ChipGroup/ChipGroup.js +1 -1
- package/lib/commonjs/components/ChipSelect/ChipSelect.js +2 -1
- package/lib/commonjs/components/DebitCard/DebitCard.js +1 -1
- package/lib/commonjs/components/Disclaimer/Disclaimer.js +2 -1
- package/lib/commonjs/components/Divider/Divider.js +2 -1
- package/lib/commonjs/components/Drawer/Drawer.js +2 -1
- package/lib/commonjs/components/EmptyState/EmptyState.js +2 -1
- package/lib/commonjs/components/FilterBar/FilterBar.js +1 -1
- package/lib/commonjs/components/Form/Form.js +2 -1
- package/lib/commonjs/components/FormField/FormField.js +3 -2
- package/lib/commonjs/components/HStack/HStack.js +1 -1
- package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +2 -1
- package/lib/commonjs/components/IconButton/IconButton.js +118 -128
- package/lib/commonjs/components/IconCapsule/IconCapsule.js +61 -57
- package/lib/commonjs/components/InputSearch/InputSearch.js +7 -3
- package/lib/commonjs/components/LazyList/LazyList.js +1 -1
- package/lib/commonjs/components/LinearMeter/LinearMeter.js +3 -2
- package/lib/commonjs/components/ListGroup/ListGroup.js +2 -3
- package/lib/commonjs/components/ListItem/ListItem.js +190 -142
- package/lib/commonjs/components/MediaCard/MediaCard.js +3 -3
- package/lib/commonjs/components/MerchantProfile/MerchantProfile.js +2 -1
- package/lib/commonjs/components/MoneyValue/MoneyValue.js +2 -1
- package/lib/commonjs/components/NavArrow/NavArrow.js +82 -59
- package/lib/commonjs/components/NoteInput/NoteInput.js +2 -1
- package/lib/commonjs/components/Nudge/Nudge.js +1 -1
- package/lib/commonjs/components/Numpad/Numpad.js +2 -1
- package/lib/commonjs/components/OTP/OTP.js +1 -1
- package/lib/commonjs/components/PaymentFeedback/PaymentFeedback.js +2 -1
- package/lib/commonjs/components/Popup/Popup.js +2 -1
- package/lib/commonjs/components/ProductLabel/ProductLabel.js +2 -1
- package/lib/commonjs/components/ProgressBadge/ProgressBadge.js +2 -1
- package/lib/commonjs/components/RadioButton/RadioButton.js +2 -1
- package/lib/commonjs/components/RechargeCard/RechargeCard.js +2 -1
- package/lib/commonjs/components/Screen/Screen.js +1 -1
- package/lib/commonjs/components/Section/Section.js +268 -156
- package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +3 -2
- package/lib/commonjs/components/StatItem/StatItem.js +2 -1
- package/lib/commonjs/components/StatusHero/StatusHero.js +2 -1
- package/lib/commonjs/components/Stepper/Step.js +2 -1
- package/lib/commonjs/components/Stepper/StepLabel.js +2 -1
- package/lib/commonjs/components/Stepper/Stepper.js +2 -1
- package/lib/commonjs/components/SupportText/SupportText.js +2 -1
- package/lib/commonjs/components/SupportText/SupportTextIcon.js +2 -1
- package/lib/commonjs/components/SwappableAmount/SwappableAmount.js +2 -1
- package/lib/commonjs/components/Tabs/TabItem.js +2 -1
- package/lib/commonjs/components/Tabs/Tabs.js +2 -1
- package/lib/commonjs/components/Text/Text.js +2 -1
- package/lib/commonjs/components/TextInput/TextInput.js +2 -2
- package/lib/commonjs/components/ThreadHero/ThreadHero.js +2 -1
- package/lib/commonjs/components/Title/Title.js +2 -1
- package/lib/commonjs/components/Toast/Toast.js +2 -1
- package/lib/commonjs/components/Toggle/Toggle.js +2 -1
- package/lib/commonjs/components/Tooltip/Tooltip.js +2 -1
- package/lib/commonjs/components/TransactionBubble/TransactionBubble.js +1 -1
- package/lib/commonjs/components/TransactionDetails/TransactionDetails.js +2 -2
- package/lib/commonjs/components/TransactionStatus/TransactionStatus.js +3 -2
- package/lib/commonjs/components/UpiHandle/UpiHandle.js +144 -110
- package/lib/commonjs/components/VStack/VStack.js +1 -1
- package/lib/commonjs/design-tokens/JFSThemeProvider.js +2 -38
- package/lib/commonjs/design-tokens/figma-variables-resolver.js +21 -3
- package/lib/commonjs/icons/registry.js +1 -1
- package/lib/commonjs/utils/react-utils.js +26 -3
- package/lib/module/components/Accordion/Accordion.js +2 -2
- package/lib/module/components/ActionFooter/ActionFooter.js +2 -2
- package/lib/module/components/ActionTile/ActionTile.js +2 -1
- package/lib/module/components/AmountInput/AmountInput.js +2 -1
- package/lib/module/components/AppBar/AppBar.js +2 -2
- package/lib/module/components/Avatar/Avatar.js +184 -162
- package/lib/module/components/AvatarGroup/AvatarGroup.js +2 -2
- package/lib/module/components/Badge/Badge.js +2 -1
- package/lib/module/components/Balance/Balance.js +2 -1
- package/lib/module/components/BottomNav/BottomNav.js +2 -1
- package/lib/module/components/BottomNavItem/BottomNavItem.js +108 -88
- package/lib/module/components/Button/Button.js +192 -95
- package/lib/module/components/ButtonGroup/ButtonGroup.js +2 -2
- package/lib/module/components/Card/Card.js +2 -1
- package/lib/module/components/CardCTA/CardCTA.js +2 -2
- package/lib/module/components/CardProviderInfo/CardProviderInfo.js +2 -2
- package/lib/module/components/Carousel/Carousel.js +3 -2
- package/lib/module/components/Checkbox/Checkbox.js +2 -1
- package/lib/module/components/ChipGroup/ChipGroup.js +2 -2
- package/lib/module/components/ChipSelect/ChipSelect.js +2 -1
- package/lib/module/components/DebitCard/DebitCard.js +2 -2
- package/lib/module/components/Disclaimer/Disclaimer.js +2 -1
- package/lib/module/components/Divider/Divider.js +2 -1
- package/lib/module/components/Drawer/Drawer.js +2 -1
- package/lib/module/components/EmptyState/EmptyState.js +2 -1
- package/lib/module/components/FilterBar/FilterBar.js +2 -2
- package/lib/module/components/Form/Form.js +2 -1
- package/lib/module/components/FormField/FormField.js +3 -2
- package/lib/module/components/HStack/HStack.js +2 -2
- package/lib/module/components/HoldingsCard/HoldingsCard.js +2 -1
- package/lib/module/components/IconButton/IconButton.js +120 -130
- package/lib/module/components/IconCapsule/IconCapsule.js +60 -57
- package/lib/module/components/InputSearch/InputSearch.js +7 -3
- package/lib/module/components/LazyList/LazyList.js +2 -2
- package/lib/module/components/LinearMeter/LinearMeter.js +3 -2
- package/lib/module/components/ListGroup/ListGroup.js +3 -4
- package/lib/module/components/ListItem/ListItem.js +194 -146
- package/lib/module/components/MediaCard/MediaCard.js +4 -2
- package/lib/module/components/MerchantProfile/MerchantProfile.js +2 -1
- package/lib/module/components/MoneyValue/MoneyValue.js +2 -1
- package/lib/module/components/NavArrow/NavArrow.js +82 -58
- package/lib/module/components/NoteInput/NoteInput.js +2 -1
- package/lib/module/components/Nudge/Nudge.js +2 -2
- package/lib/module/components/Numpad/Numpad.js +2 -1
- package/lib/module/components/OTP/OTP.js +2 -2
- package/lib/module/components/PaymentFeedback/PaymentFeedback.js +2 -1
- package/lib/module/components/Popup/Popup.js +2 -1
- package/lib/module/components/ProductLabel/ProductLabel.js +2 -1
- package/lib/module/components/ProgressBadge/ProgressBadge.js +2 -1
- package/lib/module/components/RadioButton/RadioButton.js +2 -1
- package/lib/module/components/RechargeCard/RechargeCard.js +2 -1
- package/lib/module/components/Screen/Screen.js +2 -2
- package/lib/module/components/Section/Section.js +271 -159
- package/lib/module/components/SegmentedControl/SegmentedControl.js +3 -2
- package/lib/module/components/StatItem/StatItem.js +2 -1
- package/lib/module/components/StatusHero/StatusHero.js +2 -1
- package/lib/module/components/Stepper/Step.js +2 -1
- package/lib/module/components/Stepper/StepLabel.js +2 -1
- package/lib/module/components/Stepper/Stepper.js +2 -1
- package/lib/module/components/SupportText/SupportText.js +2 -1
- package/lib/module/components/SupportText/SupportTextIcon.js +2 -1
- package/lib/module/components/SwappableAmount/SwappableAmount.js +2 -1
- package/lib/module/components/Tabs/TabItem.js +2 -1
- package/lib/module/components/Tabs/Tabs.js +2 -1
- package/lib/module/components/Text/Text.js +2 -1
- package/lib/module/components/TextInput/TextInput.js +3 -3
- package/lib/module/components/ThreadHero/ThreadHero.js +2 -1
- package/lib/module/components/Title/Title.js +2 -1
- package/lib/module/components/Toast/Toast.js +2 -1
- package/lib/module/components/Toggle/Toggle.js +2 -1
- package/lib/module/components/Tooltip/Tooltip.js +2 -1
- package/lib/module/components/TransactionBubble/TransactionBubble.js +2 -2
- package/lib/module/components/TransactionDetails/TransactionDetails.js +3 -3
- package/lib/module/components/TransactionStatus/TransactionStatus.js +3 -2
- package/lib/module/components/UpiHandle/UpiHandle.js +147 -113
- package/lib/module/components/VStack/VStack.js +2 -2
- package/lib/module/design-tokens/JFSThemeProvider.js +2 -35
- package/lib/module/design-tokens/figma-variables-resolver.js +21 -3
- package/lib/module/icons/registry.js +1 -1
- package/lib/module/utils/react-utils.js +25 -3
- package/lib/typescript/src/components/Avatar/Avatar.d.ts +11 -17
- package/lib/typescript/src/components/BottomNavItem/BottomNavItem.d.ts +12 -8
- package/lib/typescript/src/components/Button/Button.d.ts +18 -1
- package/lib/typescript/src/components/IconButton/IconButton.d.ts +12 -29
- package/lib/typescript/src/components/IconCapsule/IconCapsule.d.ts +10 -18
- package/lib/typescript/src/components/InputSearch/InputSearch.d.ts +8 -3
- package/lib/typescript/src/components/ListItem/ListItem.d.ts +14 -1
- package/lib/typescript/src/components/NavArrow/NavArrow.d.ts +12 -11
- package/lib/typescript/src/components/Section/Section.d.ts +2 -48
- package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +13 -12
- package/lib/typescript/src/design-tokens/JFSThemeProvider.d.ts +0 -15
- package/lib/typescript/src/icons/registry.d.ts +1 -1
- package/lib/typescript/src/utils/react-utils.d.ts +15 -0
- package/package.json +4 -6
- package/src/components/Accordion/Accordion.tsx +2 -2
- package/src/components/ActionFooter/ActionFooter.tsx +2 -2
- package/src/components/ActionTile/ActionTile.tsx +2 -1
- package/src/components/AmountInput/AmountInput.tsx +2 -1
- package/src/components/AppBar/AppBar.tsx +2 -2
- package/src/components/Avatar/Avatar.tsx +229 -158
- package/src/components/AvatarGroup/AvatarGroup.tsx +2 -2
- package/src/components/Badge/Badge.tsx +2 -1
- package/src/components/Balance/Balance.tsx +2 -1
- package/src/components/BottomNav/BottomNav.tsx +2 -1
- package/src/components/BottomNavItem/BottomNavItem.tsx +159 -88
- package/src/components/Button/Button.tsx +228 -101
- package/src/components/ButtonGroup/ButtonGroup.tsx +2 -2
- package/src/components/Card/Card.tsx +2 -1
- package/src/components/CardCTA/CardCTA.tsx +2 -2
- package/src/components/CardProviderInfo/CardProviderInfo.tsx +2 -2
- package/src/components/Carousel/Carousel.tsx +3 -2
- package/src/components/Checkbox/Checkbox.tsx +2 -1
- package/src/components/ChipGroup/ChipGroup.tsx +2 -2
- package/src/components/ChipSelect/ChipSelect.tsx +2 -1
- package/src/components/DebitCard/DebitCard.tsx +2 -2
- package/src/components/Disclaimer/Disclaimer.tsx +2 -1
- package/src/components/Divider/Divider.tsx +2 -1
- package/src/components/Drawer/Drawer.tsx +2 -1
- package/src/components/EmptyState/EmptyState.tsx +2 -1
- package/src/components/FilterBar/FilterBar.tsx +2 -2
- package/src/components/Form/Form.tsx +2 -1
- package/src/components/FormField/FormField.tsx +3 -2
- package/src/components/HStack/HStack.tsx +2 -2
- package/src/components/HoldingsCard/HoldingsCard.tsx +2 -1
- package/src/components/IconButton/IconButton.tsx +154 -126
- package/src/components/IconCapsule/IconCapsule.tsx +73 -54
- package/src/components/InputSearch/InputSearch.tsx +19 -5
- package/src/components/LazyList/LazyList.tsx +2 -2
- package/src/components/LinearMeter/LinearMeter.tsx +3 -2
- package/src/components/ListGroup/ListGroup.tsx +4 -5
- package/src/components/ListItem/ListItem.tsx +257 -187
- package/src/components/MediaCard/MediaCard.tsx +2 -1
- package/src/components/MerchantProfile/MerchantProfile.tsx +2 -1
- package/src/components/MoneyValue/MoneyValue.tsx +2 -1
- package/src/components/NavArrow/NavArrow.tsx +91 -58
- package/src/components/NoteInput/NoteInput.tsx +2 -1
- package/src/components/Nudge/Nudge.tsx +2 -2
- package/src/components/Numpad/Numpad.tsx +2 -1
- package/src/components/OTP/OTP.tsx +2 -2
- package/src/components/PaymentFeedback/PaymentFeedback.tsx +2 -1
- package/src/components/Popup/Popup.tsx +2 -1
- package/src/components/ProductLabel/ProductLabel.tsx +2 -1
- package/src/components/ProgressBadge/ProgressBadge.tsx +2 -2
- package/src/components/RadioButton/RadioButton.tsx +2 -1
- package/src/components/RechargeCard/RechargeCard.tsx +2 -1
- package/src/components/Screen/Screen.tsx +2 -2
- package/src/components/Section/Section.tsx +323 -167
- package/src/components/SegmentedControl/SegmentedControl.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/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/Text/Text.tsx +2 -1
- package/src/components/TextInput/TextInput.tsx +3 -3
- 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/Toggle/Toggle.tsx +2 -1
- package/src/components/Tooltip/Tooltip.tsx +2 -1
- package/src/components/TransactionBubble/TransactionBubble.tsx +2 -2
- package/src/components/TransactionDetails/TransactionDetails.tsx +3 -3
- package/src/components/TransactionStatus/TransactionStatus.tsx +3 -2
- package/src/components/UpiHandle/UpiHandle.tsx +193 -125
- package/src/components/VStack/VStack.tsx +2 -2
- package/src/design-tokens/JFSThemeProvider.tsx +1 -37
- package/src/design-tokens/figma-variables-resolver.ts +21 -3
- package/src/icons/registry.ts +1 -1
- package/src/utils/react-utils.ts +29 -3
- package/lib/typescript/App.d.ts +0 -2
- package/lib/typescript/index.d.ts +0 -2
- package/lib/typescript/metro.config.d.ts +0 -78
- package/lib/typescript/react-native.config.d.ts +0 -4
|
@@ -1,83 +1,150 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import React, { useState, useRef, useCallback
|
|
3
|
+
import React, { useState, useMemo, useRef, useCallback } from 'react';
|
|
4
4
|
import { View, Text, Pressable, Platform } from 'react-native';
|
|
5
5
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
6
|
import NavArrow from '../NavArrow/NavArrow';
|
|
7
7
|
import { usePressableWebSupport } from '../../utils/web-platform-utils';
|
|
8
|
-
import { cloneChildrenWithModes, flattenChildren } from '../../utils/react-utils';
|
|
8
|
+
import { EMPTY_MODES, cloneChildrenWithModes, flattenChildren } from '../../utils/react-utils';
|
|
9
|
+
|
|
10
|
+
// Match Button: delay the press visual on iOS so a scroll-cancelled touch
|
|
11
|
+
// never applies the "pressed" style. See Button.tsx for the rationale.
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
13
|
+
const IS_WEB = Platform.OS === 'web';
|
|
14
|
+
const IS_IOS = Platform.OS === 'ios';
|
|
15
|
+
const HEADER_PRESS_DELAY = IS_IOS ? 130 : 0;
|
|
16
|
+
|
|
17
|
+
// Module-scope style constants — never re-allocated per render.
|
|
18
|
+
const headerWrapStyle = {
|
|
19
|
+
flexDirection: 'row',
|
|
20
|
+
alignItems: 'center',
|
|
21
|
+
justifyContent: 'space-between'
|
|
22
|
+
};
|
|
23
|
+
const headerHoverStyle = {
|
|
24
|
+
opacity: 0.95
|
|
25
|
+
};
|
|
26
|
+
const headerPressedStyle = {
|
|
27
|
+
opacity: 0.85
|
|
28
|
+
};
|
|
29
|
+
const headerFocusStyle = {
|
|
30
|
+
borderColor: '#222',
|
|
31
|
+
borderWidth: 1
|
|
32
|
+
};
|
|
9
33
|
|
|
10
34
|
// ---------------------------------------------------------------------------
|
|
11
|
-
// Shared grid layout: measures widest child
|
|
12
|
-
//
|
|
35
|
+
// Shared grid layout: measures the widest child once per item-count, then
|
|
36
|
+
// renders uniform-width cells laid out with `justify-content: space-between`.
|
|
37
|
+
// This preserves three visual invariants regardless of viewport width:
|
|
38
|
+
// 1. The first cell hugs the container's left edge.
|
|
39
|
+
// 2. The last cell hugs the container's right edge.
|
|
40
|
+
// 3. Cells in row N column K align with cells in row N+1 column K
|
|
41
|
+
// (uniform cell width across the whole grid).
|
|
42
|
+
// Pure flex sizing (e.g. `flexBasis: 0; flexGrow: 1`) cannot satisfy (1) and
|
|
43
|
+
// (2) on wide viewports — it distributes extra space inside each cell, which
|
|
44
|
+
// makes the icon+label content drift toward each cell's center and produces
|
|
45
|
+
// visible "dead" margins on the left and right of the grid.
|
|
46
|
+
//
|
|
47
|
+
// To avoid the blank-flash that the previous implementation suffered from
|
|
48
|
+
// (it hid the grid with `opacity: 0` until measurement completed, and reset
|
|
49
|
+
// every measurement when the item count changed):
|
|
50
|
+
// * Cells render at their *natural* widths during measurement instead of
|
|
51
|
+
// being hidden. With `space-between`, the first/last cells already hug
|
|
52
|
+
// the edges; only the column alignment can be off by a few pixels for
|
|
53
|
+
// the single frame between mount and the onLayout callback.
|
|
54
|
+
// * On item-count change (e.g. expand / collapse), we clear the per-cell
|
|
55
|
+
// samples but keep the rendered layout visible — we never blank out.
|
|
56
|
+
// * No 500ms safety timeout is needed because the grid is visible from the
|
|
57
|
+
// first frame.
|
|
13
58
|
// ---------------------------------------------------------------------------
|
|
14
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
15
59
|
const SLOT_GRID_MAX_COLUMNS = 4;
|
|
16
|
-
|
|
60
|
+
const slotGridRowStyle = {
|
|
61
|
+
flexDirection: 'row',
|
|
62
|
+
justifyContent: 'space-between'
|
|
63
|
+
};
|
|
64
|
+
const SlotGrid = /*#__PURE__*/React.memo(function SlotGrid({
|
|
17
65
|
items,
|
|
18
66
|
gap,
|
|
19
67
|
maxColumns = SLOT_GRID_MAX_COLUMNS
|
|
20
68
|
}) {
|
|
69
|
+
const totalItems = items.length;
|
|
21
70
|
const [maxItemWidth, setMaxItemWidth] = useState(null);
|
|
22
|
-
|
|
71
|
+
// Tracks the item-count that `maxItemWidth` corresponds to. When the
|
|
72
|
+
// current `totalItems` differs, the existing measurement is considered
|
|
73
|
+
// stale and cells fall back to natural widths until remeasurement.
|
|
74
|
+
const [measuredForCount, setMeasuredForCount] = useState(0);
|
|
23
75
|
const itemWidthsRef = useRef(new Map());
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
76
|
+
|
|
77
|
+
// Synchronously invalidate per-cell samples when the item count changes
|
|
78
|
+
// (e.g. show more / less). We deliberately do NOT touch `maxItemWidth` or
|
|
79
|
+
// `measuredForCount` state here — flipping them would force an extra render
|
|
80
|
+
// pass; instead we let the count mismatch (`measuredForCount !== totalItems`)
|
|
81
|
+
// gate the use of the stale value, and the next onLayout cycle will publish
|
|
82
|
+
// a fresh `maxItemWidth` for the new count.
|
|
83
|
+
const prevTotalRef = useRef(totalItems);
|
|
84
|
+
if (prevTotalRef.current !== totalItems) {
|
|
85
|
+
prevTotalRef.current = totalItems;
|
|
86
|
+
itemWidthsRef.current = new Map();
|
|
87
|
+
}
|
|
35
88
|
const handleItemLayout = useCallback((index, width) => {
|
|
36
|
-
itemWidthsRef.current
|
|
37
|
-
|
|
38
|
-
|
|
89
|
+
const widths = itemWidthsRef.current;
|
|
90
|
+
const previous = widths.get(index);
|
|
91
|
+
if (previous !== undefined && Math.abs(previous - width) < 0.5) return;
|
|
92
|
+
widths.set(index, width);
|
|
93
|
+
if (widths.size >= totalItems && totalItems > 0) {
|
|
94
|
+
let newMax = 0;
|
|
95
|
+
for (const w of widths.values()) {
|
|
96
|
+
if (w > newMax) newMax = w;
|
|
97
|
+
}
|
|
98
|
+
setMaxItemWidth(prev => prev !== null && Math.abs(prev - newMax) < 0.5 ? prev : newMax);
|
|
99
|
+
setMeasuredForCount(totalItems);
|
|
39
100
|
}
|
|
40
101
|
}, [totalItems]);
|
|
41
|
-
const
|
|
102
|
+
const hasFreshMeasurement = maxItemWidth !== null && measuredForCount === totalItems;
|
|
103
|
+
const cellWidth = hasFreshMeasurement ? maxItemWidth : undefined;
|
|
42
104
|
const columns = Math.min(maxColumns, totalItems || 1);
|
|
43
105
|
const rows = [];
|
|
44
106
|
for (let i = 0; i < items.length; i += columns) {
|
|
45
107
|
rows.push(items.slice(i, i + columns));
|
|
46
108
|
}
|
|
109
|
+
const containerStyle = useMemo(() => ({
|
|
110
|
+
gap
|
|
111
|
+
}), [gap]);
|
|
112
|
+
const measuredCellStyle = useMemo(() => cellWidth !== undefined ? {
|
|
113
|
+
width: cellWidth
|
|
114
|
+
} : undefined, [cellWidth]);
|
|
47
115
|
return /*#__PURE__*/_jsx(View, {
|
|
48
|
-
style:
|
|
49
|
-
gap,
|
|
50
|
-
...(isMeasured || measureTimedOut ? {} : {
|
|
51
|
-
opacity: 0
|
|
52
|
-
})
|
|
53
|
-
},
|
|
116
|
+
style: containerStyle,
|
|
54
117
|
children: rows.map((row, rowIndex) => {
|
|
55
118
|
const spacersNeeded = row.length < columns ? columns - row.length : 0;
|
|
56
119
|
return /*#__PURE__*/_jsxs(View, {
|
|
57
|
-
style:
|
|
58
|
-
flexDirection: 'row',
|
|
59
|
-
justifyContent: 'space-between'
|
|
60
|
-
},
|
|
120
|
+
style: slotGridRowStyle,
|
|
61
121
|
children: [row.map((child, colIndex) => {
|
|
62
122
|
const itemIndex = rowIndex * columns + colIndex;
|
|
63
123
|
return /*#__PURE__*/_jsx(View, {
|
|
64
|
-
onLayout:
|
|
65
|
-
style:
|
|
66
|
-
width: maxItemWidth
|
|
67
|
-
} : undefined,
|
|
124
|
+
onLayout: hasFreshMeasurement ? undefined : e => handleItemLayout(itemIndex, e.nativeEvent.layout.width),
|
|
125
|
+
style: measuredCellStyle,
|
|
68
126
|
children: child
|
|
69
127
|
}, itemIndex);
|
|
70
|
-
}),
|
|
128
|
+
}), hasFreshMeasurement && spacersNeeded > 0 && Array.from({
|
|
71
129
|
length: spacersNeeded
|
|
72
130
|
}, (_, i) => /*#__PURE__*/_jsx(View, {
|
|
73
|
-
style:
|
|
74
|
-
width: maxItemWidth
|
|
75
|
-
}
|
|
131
|
+
style: measuredCellStyle
|
|
76
132
|
}, `spacer-${i}`))]
|
|
77
133
|
}, rowIndex);
|
|
78
134
|
})
|
|
79
135
|
});
|
|
136
|
+
}, slotGridPropsAreEqual);
|
|
137
|
+
function slotGridPropsAreEqual(prev, next) {
|
|
138
|
+
if (prev.gap !== next.gap) return false;
|
|
139
|
+
if ((prev.maxColumns ?? SLOT_GRID_MAX_COLUMNS) !== (next.maxColumns ?? SLOT_GRID_MAX_COLUMNS)) return false;
|
|
140
|
+
if (prev.items === next.items) return true;
|
|
141
|
+
if (prev.items.length !== next.items.length) return false;
|
|
142
|
+
for (let i = 0; i < prev.items.length; i++) {
|
|
143
|
+
if (prev.items[i] !== next.items[i]) return false;
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
80
146
|
}
|
|
147
|
+
|
|
81
148
|
/**
|
|
82
149
|
* Section component that mirrors the Figma "Section" component.
|
|
83
150
|
*
|
|
@@ -102,96 +169,99 @@ function SlotGrid({
|
|
|
102
169
|
* @param {string} [props.accessibilityLabel] - Accessibility label for the section. If not provided, uses title
|
|
103
170
|
* @param {string} [props.accessibilityHint] - Additional accessibility hint for screen readers
|
|
104
171
|
*/
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
supportText = 'Section support text',
|
|
108
|
-
showSupportText = true,
|
|
109
|
-
slot,
|
|
110
|
-
slotDirection = 'row',
|
|
111
|
-
modes = {},
|
|
112
|
-
onPress,
|
|
113
|
-
style,
|
|
114
|
-
accessibilityLabel,
|
|
115
|
-
accessibilityHint,
|
|
116
|
-
webAccessibilityProps,
|
|
117
|
-
...rest
|
|
118
|
-
}) {
|
|
119
|
-
const [isHeaderFocused, setIsHeaderFocused] = useState(false);
|
|
120
|
-
const [isHeaderHovered, setIsHeaderHovered] = useState(false);
|
|
121
|
-
const [isHeaderPressed, setIsHeaderPressed] = useState(false);
|
|
122
|
-
const headerFocusStyle = isHeaderFocused ? {
|
|
123
|
-
borderColor: '#222',
|
|
124
|
-
borderWidth: 1
|
|
125
|
-
} : {};
|
|
126
|
-
const headerHoverStyle = isHeaderHovered ? {
|
|
127
|
-
opacity: 0.95
|
|
128
|
-
} : {};
|
|
129
|
-
const headerPressedStyle = isHeaderPressed ? {
|
|
130
|
-
opacity: 0.85
|
|
131
|
-
} : {};
|
|
132
|
-
// Resolve section container tokens
|
|
172
|
+
|
|
173
|
+
function resolveSectionTokens(modes) {
|
|
133
174
|
const backgroundColor = getVariableByName('section/background/color', modes) || '#ffffff';
|
|
134
175
|
const sectionGap = getVariableByName('section/gap', modes) || 12;
|
|
135
176
|
const slotGap = getVariableByName('slot/gap', modes) || 12;
|
|
136
177
|
const paddingHorizontal = getVariableByName('section/padding/horizontal', modes) || 12;
|
|
137
178
|
const paddingVertical = getVariableByName('section/padding/vertical', modes) || 16;
|
|
138
179
|
const radius = getVariableByName('section/radius', modes) || 12;
|
|
139
|
-
|
|
140
|
-
// Resolve section header tokens
|
|
141
180
|
const headerGap = getVariableByName('section/header/gap', modes) || 8;
|
|
142
181
|
const headerPaddingHorizontal = getVariableByName('section/header/padding/horizontal', modes) || 0;
|
|
143
182
|
const headerPaddingVertical = getVariableByName('section/header/padding/vertical', modes) || 0;
|
|
144
|
-
|
|
145
|
-
// Resolve section title tokens
|
|
146
183
|
const titleColor = getVariableByName('section/title/color', modes) || '#0f0d0a';
|
|
147
184
|
const titleFontSize = getVariableByName('section/title/fontSize', modes) || 18;
|
|
148
185
|
const titleLineHeight = getVariableByName('section/title/lineHeight', modes) || 20;
|
|
149
186
|
const titleFontFamily = getVariableByName('section/title/fontFamily', modes) || 'System';
|
|
150
187
|
const titleFontWeightRaw = getVariableByName('section/title/fontWeight', modes) || 800;
|
|
151
188
|
const titleFontWeight = typeof titleFontWeightRaw === 'number' ? titleFontWeightRaw.toString() : titleFontWeightRaw;
|
|
152
|
-
|
|
153
|
-
// Resolve section support text tokens
|
|
154
189
|
const supportTextColor = getVariableByName('section/supportText/color', modes) || '#1f1a14';
|
|
155
190
|
const supportTextFontSize = getVariableByName('section/supportText/fontSize', modes) || 14;
|
|
156
191
|
const supportTextLineHeight = getVariableByName('section/supportText/lineHeight', modes) || 18;
|
|
157
192
|
const supportTextFontFamily = getVariableByName('section/supportText/fontFamily', modes) || 'System';
|
|
158
193
|
const supportTextFontWeightRaw = getVariableByName('section/supportText/fontWeight', modes) || 500;
|
|
159
194
|
const supportTextFontWeight = typeof supportTextFontWeightRaw === 'number' ? supportTextFontWeightRaw.toString() : supportTextFontWeightRaw;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
fontWeight: supportTextFontWeight
|
|
195
|
+
return {
|
|
196
|
+
containerStyle: {
|
|
197
|
+
backgroundColor,
|
|
198
|
+
paddingHorizontal,
|
|
199
|
+
paddingVertical,
|
|
200
|
+
borderRadius: radius,
|
|
201
|
+
gap: sectionGap
|
|
202
|
+
},
|
|
203
|
+
headerStyle: {
|
|
204
|
+
paddingHorizontal: headerPaddingHorizontal,
|
|
205
|
+
paddingVertical: headerPaddingVertical,
|
|
206
|
+
gap: headerGap
|
|
207
|
+
},
|
|
208
|
+
titleStyle: {
|
|
209
|
+
flex: 1,
|
|
210
|
+
color: titleColor,
|
|
211
|
+
fontSize: titleFontSize,
|
|
212
|
+
lineHeight: titleLineHeight,
|
|
213
|
+
fontFamily: titleFontFamily,
|
|
214
|
+
fontWeight: titleFontWeight
|
|
215
|
+
},
|
|
216
|
+
supportTextStyle: {
|
|
217
|
+
color: supportTextColor,
|
|
218
|
+
fontSize: supportTextFontSize,
|
|
219
|
+
lineHeight: supportTextLineHeight,
|
|
220
|
+
fontFamily: supportTextFontFamily,
|
|
221
|
+
fontWeight: supportTextFontWeight
|
|
222
|
+
},
|
|
223
|
+
sectionGap,
|
|
224
|
+
slotGap
|
|
191
225
|
};
|
|
226
|
+
}
|
|
227
|
+
function Section({
|
|
228
|
+
title = 'Section title',
|
|
229
|
+
supportText = 'Section support text',
|
|
230
|
+
showSupportText = true,
|
|
231
|
+
slot,
|
|
232
|
+
slotDirection = 'row',
|
|
233
|
+
modes = EMPTY_MODES,
|
|
234
|
+
onPress,
|
|
235
|
+
style,
|
|
236
|
+
// accessibilityLabel is intentionally accepted on the type for API
|
|
237
|
+
// back-compat, but the inner Pressable/View deliberately pass
|
|
238
|
+
// `accessibilityLabel={undefined}` (the title Text carries the label
|
|
239
|
+
// instead). Prefix to satisfy the unused-var lint while keeping the prop
|
|
240
|
+
// shape unchanged.
|
|
241
|
+
accessibilityLabel: _accessibilityLabel,
|
|
242
|
+
accessibilityHint,
|
|
243
|
+
webAccessibilityProps,
|
|
244
|
+
...rest
|
|
245
|
+
}) {
|
|
246
|
+
// Focus and hover are still mirrored in React because they are visible,
|
|
247
|
+
// sustained states (web-only in practice). The setters are gated so they
|
|
248
|
+
// never fire on native — keeping the component render-free during touch.
|
|
249
|
+
// Press is handled imperatively via the `Pressable` style callback so a
|
|
250
|
+
// scroll-cancelled touch never schedules a React render.
|
|
251
|
+
const [isHeaderFocused, setIsHeaderFocused] = useState(false);
|
|
252
|
+
const [isHeaderHovered, setIsHeaderHovered] = useState(false);
|
|
192
253
|
|
|
193
|
-
//
|
|
194
|
-
|
|
254
|
+
// Mirror user handlers in a ref so our wrappers can stay referentially
|
|
255
|
+
// stable. Without this, every parent re-render would hand Pressable fresh
|
|
256
|
+
// function identities and re-bind every event.
|
|
257
|
+
const userHandlersRef = useRef({});
|
|
258
|
+
userHandlersRef.current.onPressIn = rest?.onPressIn;
|
|
259
|
+
userHandlersRef.current.onPressOut = rest?.onPressOut;
|
|
260
|
+
userHandlersRef.current.onHoverIn = rest?.onHoverIn;
|
|
261
|
+
userHandlersRef.current.onHoverOut = rest?.onHoverOut;
|
|
262
|
+
userHandlersRef.current.onFocus = rest?.onFocus;
|
|
263
|
+
userHandlersRef.current.onBlur = rest?.onBlur;
|
|
264
|
+
const tokens = useMemo(() => resolveSectionTokens(modes), [modes]);
|
|
195
265
|
|
|
196
266
|
// Get web platform support props (only used when onPress is defined)
|
|
197
267
|
const webProps = usePressableWebSupport({
|
|
@@ -205,7 +275,7 @@ function Section({
|
|
|
205
275
|
children: [/*#__PURE__*/_jsxs(View, {
|
|
206
276
|
style: headerWrapStyle,
|
|
207
277
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
208
|
-
style: titleStyle,
|
|
278
|
+
style: tokens.titleStyle,
|
|
209
279
|
numberOfLines: 1,
|
|
210
280
|
accessibilityElementsHidden: true,
|
|
211
281
|
importantForAccessibility: "no",
|
|
@@ -215,16 +285,49 @@ function Section({
|
|
|
215
285
|
modes: modes
|
|
216
286
|
})]
|
|
217
287
|
}), showSupportText && /*#__PURE__*/_jsx(Text, {
|
|
218
|
-
style: supportTextStyle,
|
|
288
|
+
style: tokens.supportTextStyle,
|
|
219
289
|
numberOfLines: 2,
|
|
220
290
|
accessibilityElementsHidden: true,
|
|
221
291
|
importantForAccessibility: "no",
|
|
222
292
|
children: supportText
|
|
223
293
|
})]
|
|
224
294
|
});
|
|
295
|
+
|
|
296
|
+
// Stable handler identities. User handlers are read through the ref so
|
|
297
|
+
// these wrappers don't need new identities each render.
|
|
298
|
+
const handlePressIn = useCallback(e => {
|
|
299
|
+
userHandlersRef.current.onPressIn?.(e);
|
|
300
|
+
}, []);
|
|
301
|
+
const handlePressOut = useCallback(e => {
|
|
302
|
+
userHandlersRef.current.onPressOut?.(e);
|
|
303
|
+
}, []);
|
|
304
|
+
const handleHoverIn = useCallback(e => {
|
|
305
|
+
if (IS_WEB) setIsHeaderHovered(true);
|
|
306
|
+
userHandlersRef.current.onHoverIn?.(e);
|
|
307
|
+
}, []);
|
|
308
|
+
const handleHoverOut = useCallback(e => {
|
|
309
|
+
if (IS_WEB) setIsHeaderHovered(false);
|
|
310
|
+
userHandlersRef.current.onHoverOut?.(e);
|
|
311
|
+
}, []);
|
|
312
|
+
const handleFocus = useCallback(e => {
|
|
313
|
+
if (IS_WEB) setIsHeaderFocused(true);
|
|
314
|
+
userHandlersRef.current.onFocus?.(e);
|
|
315
|
+
}, []);
|
|
316
|
+
const handleBlur = useCallback(e => {
|
|
317
|
+
if (IS_WEB) setIsHeaderFocused(false);
|
|
318
|
+
userHandlersRef.current.onBlur?.(e);
|
|
319
|
+
}, []);
|
|
320
|
+
|
|
321
|
+
// The pressed visual is applied by the host view directly through the
|
|
322
|
+
// Pressable style callback — no React render is scheduled. We still want
|
|
323
|
+
// the (constant) hover style on web so we keep it in the array.
|
|
324
|
+
const headerStyleCallback = useCallback(({
|
|
325
|
+
pressed
|
|
326
|
+
}) => [tokens.headerStyle, pressed ? headerPressedStyle : null, isHeaderHovered ? headerHoverStyle : null, isHeaderFocused ? headerFocusStyle : null], [tokens.headerStyle, isHeaderHovered, isHeaderFocused]);
|
|
327
|
+
const containerStyleArray = useMemo(() => [tokens.containerStyle, style], [tokens.containerStyle, style]);
|
|
225
328
|
return /*#__PURE__*/_jsxs(View, {
|
|
226
|
-
style:
|
|
227
|
-
...(
|
|
329
|
+
style: containerStyleArray,
|
|
330
|
+
...(IS_WEB ? {
|
|
228
331
|
accessibilityRole: 'region'
|
|
229
332
|
} : undefined),
|
|
230
333
|
accessibilityLabel: undefined,
|
|
@@ -233,52 +336,59 @@ function Section({
|
|
|
233
336
|
children: [onPress ? /*#__PURE__*/_jsx(Pressable, {
|
|
234
337
|
accessibilityRole: "button",
|
|
235
338
|
accessibilityLabel: undefined,
|
|
236
|
-
accessibilityHint: accessibilityHint ||
|
|
339
|
+
accessibilityHint: accessibilityHint || 'Opens section details',
|
|
237
340
|
onPress: onPress,
|
|
238
|
-
onPressIn:
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
onFocus: e => {
|
|
247
|
-
setIsHeaderFocused(true);
|
|
248
|
-
rest?.onFocus?.(e);
|
|
249
|
-
},
|
|
250
|
-
onBlur: e => {
|
|
251
|
-
setIsHeaderFocused(false);
|
|
252
|
-
rest?.onBlur?.(e);
|
|
253
|
-
},
|
|
254
|
-
onHoverIn: e => {
|
|
255
|
-
setIsHeaderHovered(true);
|
|
256
|
-
rest?.onHoverIn?.(e);
|
|
257
|
-
},
|
|
258
|
-
onHoverOut: e => {
|
|
259
|
-
setIsHeaderHovered(false);
|
|
260
|
-
rest?.onHoverOut?.(e);
|
|
261
|
-
},
|
|
262
|
-
style: ({
|
|
263
|
-
pressed
|
|
264
|
-
}) => [headerStyle, pressed ? headerPressedStyle : null, headerHoverStyle, headerFocusStyle],
|
|
341
|
+
onPressIn: handlePressIn,
|
|
342
|
+
onPressOut: handlePressOut,
|
|
343
|
+
onFocus: handleFocus,
|
|
344
|
+
onBlur: handleBlur,
|
|
345
|
+
onHoverIn: handleHoverIn,
|
|
346
|
+
onHoverOut: handleHoverOut,
|
|
347
|
+
unstable_pressDelay: HEADER_PRESS_DELAY,
|
|
348
|
+
style: headerStyleCallback,
|
|
265
349
|
...webProps,
|
|
266
350
|
children: headerContent
|
|
267
351
|
}) : /*#__PURE__*/_jsx(View, {
|
|
268
|
-
style: headerStyle,
|
|
352
|
+
style: tokens.headerStyle,
|
|
269
353
|
children: headerContent
|
|
270
|
-
}), slot &&
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
gap: slotGap
|
|
277
|
-
},
|
|
278
|
-
children: cloneChildrenWithModes(flattenChildren(slot), modes)
|
|
354
|
+
}), slot && /*#__PURE__*/_jsx(SectionSlot, {
|
|
355
|
+
slot: slot,
|
|
356
|
+
modes: modes,
|
|
357
|
+
direction: slotDirection,
|
|
358
|
+
rowGap: tokens.sectionGap,
|
|
359
|
+
columnGap: tokens.slotGap
|
|
279
360
|
})]
|
|
280
361
|
});
|
|
281
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Internal helper that processes the slot children once per (slot, modes) pair
|
|
365
|
+
* and dispatches to the row (SlotGrid) or column layout. Splitting this out of
|
|
366
|
+
* `Section` lets the parent re-render (e.g. for header press/hover state)
|
|
367
|
+
* without re-walking the slot tree via `cloneChildrenWithModes`.
|
|
368
|
+
*/
|
|
369
|
+
function SectionSlot({
|
|
370
|
+
slot,
|
|
371
|
+
modes,
|
|
372
|
+
direction,
|
|
373
|
+
rowGap,
|
|
374
|
+
columnGap
|
|
375
|
+
}) {
|
|
376
|
+
const processed = useMemo(() => cloneChildrenWithModes(flattenChildren(slot), modes), [slot, modes]);
|
|
377
|
+
const columnContainerStyle = useMemo(() => ({
|
|
378
|
+
flexDirection: 'column',
|
|
379
|
+
gap: columnGap
|
|
380
|
+
}), [columnGap]);
|
|
381
|
+
if (direction === 'row') {
|
|
382
|
+
return /*#__PURE__*/_jsx(SlotGrid, {
|
|
383
|
+
items: processed,
|
|
384
|
+
gap: rowGap
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
return /*#__PURE__*/_jsx(View, {
|
|
388
|
+
style: columnContainerStyle,
|
|
389
|
+
children: processed
|
|
390
|
+
});
|
|
391
|
+
}
|
|
282
392
|
/**
|
|
283
393
|
* Section.Bento component that mirrors the Figma "Section.Bento" component.
|
|
284
394
|
*
|
|
@@ -301,12 +411,17 @@ function Section({
|
|
|
301
411
|
* @param {string} [props.accessibilityLabel] - Accessibility label for the section
|
|
302
412
|
* @param {string} [props.accessibilityHint] - Additional accessibility hint for screen readers
|
|
303
413
|
*/
|
|
414
|
+
const sectionBentoUpiRowStyle = {
|
|
415
|
+
flexDirection: 'row',
|
|
416
|
+
gap: 8
|
|
417
|
+
};
|
|
304
418
|
function SectionBento({
|
|
305
419
|
navSlot,
|
|
306
420
|
upiSlot,
|
|
307
|
-
modes =
|
|
421
|
+
modes = EMPTY_MODES,
|
|
308
422
|
style,
|
|
309
|
-
|
|
423
|
+
// Same rationale as Section: accepted on the type but unused internally.
|
|
424
|
+
accessibilityLabel: _accessibilityLabel,
|
|
310
425
|
accessibilityHint,
|
|
311
426
|
...rest
|
|
312
427
|
}) {
|
|
@@ -316,15 +431,15 @@ function SectionBento({
|
|
|
316
431
|
const paddingHorizontal = getVariableByName('section/padding/horizontal', modes) || 12;
|
|
317
432
|
const paddingVertical = getVariableByName('section/padding/vertical', modes) || 16;
|
|
318
433
|
const radius = getVariableByName('section/radius', modes) || 12;
|
|
319
|
-
const containerStyle = {
|
|
434
|
+
const containerStyle = useMemo(() => ({
|
|
320
435
|
backgroundColor,
|
|
321
436
|
paddingHorizontal,
|
|
322
437
|
paddingVertical,
|
|
323
438
|
borderRadius: radius,
|
|
324
439
|
gap
|
|
325
|
-
};
|
|
326
|
-
const processedNavSlot = navSlot ? cloneChildrenWithModes(flattenChildren(navSlot), modes) : null;
|
|
327
|
-
const processedUpiSlot = upiSlot ? cloneChildrenWithModes(flattenChildren(upiSlot), modes) : null;
|
|
440
|
+
}), [backgroundColor, paddingHorizontal, paddingVertical, radius, gap]);
|
|
441
|
+
const processedNavSlot = useMemo(() => navSlot ? cloneChildrenWithModes(flattenChildren(navSlot), modes) : null, [navSlot, modes]);
|
|
442
|
+
const processedUpiSlot = useMemo(() => upiSlot ? cloneChildrenWithModes(flattenChildren(upiSlot), modes) : null, [upiSlot, modes]);
|
|
328
443
|
return /*#__PURE__*/_jsxs(View, {
|
|
329
444
|
style: [containerStyle, style],
|
|
330
445
|
...(Platform.OS === 'web' ? {
|
|
@@ -337,10 +452,7 @@ function SectionBento({
|
|
|
337
452
|
items: processedNavSlot,
|
|
338
453
|
gap: gap
|
|
339
454
|
}), processedUpiSlot && /*#__PURE__*/_jsx(View, {
|
|
340
|
-
style:
|
|
341
|
-
flexDirection: 'row',
|
|
342
|
-
gap: 8
|
|
343
|
-
},
|
|
455
|
+
style: sectionBentoUpiRowStyle,
|
|
344
456
|
children: processedUpiSlot
|
|
345
457
|
})]
|
|
346
458
|
});
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
import React, { useState, useCallback } from 'react';
|
|
4
4
|
import { View, Pressable, Text } from 'react-native';
|
|
5
5
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
|
+
import { EMPTY_MODES } from '../../utils/react-utils';
|
|
6
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
8
|
function SegmentedControlSegment({
|
|
8
9
|
label,
|
|
9
10
|
active,
|
|
10
11
|
onPress,
|
|
11
|
-
modes =
|
|
12
|
+
modes = EMPTY_MODES
|
|
12
13
|
}) {
|
|
13
14
|
const resolvedModes = {
|
|
14
15
|
...modes,
|
|
@@ -89,7 +90,7 @@ function SegmentedControl({
|
|
|
89
90
|
selectedKey: controlledSelectedKey,
|
|
90
91
|
defaultSelectedKey,
|
|
91
92
|
onSelectionChange,
|
|
92
|
-
modes =
|
|
93
|
+
modes = EMPTY_MODES,
|
|
93
94
|
style
|
|
94
95
|
}) {
|
|
95
96
|
const isControlled = controlledSelectedKey !== undefined;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { View, Text } from 'react-native';
|
|
5
5
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
|
+
import { EMPTY_MODES } from '../../utils/react-utils';
|
|
6
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
8
|
/**
|
|
8
9
|
* StatItem displays a label/value pair with the value in a large, bold style.
|
|
@@ -14,7 +15,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
14
15
|
function StatItem({
|
|
15
16
|
label = 'Purity verified by NABL',
|
|
16
17
|
value = '99.99%',
|
|
17
|
-
modes =
|
|
18
|
+
modes = EMPTY_MODES,
|
|
18
19
|
style
|
|
19
20
|
}) {
|
|
20
21
|
const gap = getVariableByName('statItem/gap', modes) ?? 2;
|
|
@@ -6,6 +6,7 @@ import { getVariableByName } from '../../design-tokens/figma-variables-resolver'
|
|
|
6
6
|
import { useTokens } from '../../design-tokens/JFSThemeProvider';
|
|
7
7
|
import IconCapsule from '../IconCapsule/IconCapsule';
|
|
8
8
|
import MoneyValue from '../MoneyValue/MoneyValue';
|
|
9
|
+
import { EMPTY_MODES } from '../../utils/react-utils';
|
|
9
10
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
11
|
/**
|
|
11
12
|
* StatusHero component that displays a hero section for payment/transaction status screens.
|
|
@@ -35,7 +36,7 @@ export default function StatusHero({
|
|
|
35
36
|
iconName = 'ic_confirm',
|
|
36
37
|
value = '50',
|
|
37
38
|
currency = 'INR',
|
|
38
|
-
modes: propModes =
|
|
39
|
+
modes: propModes = EMPTY_MODES,
|
|
39
40
|
style
|
|
40
41
|
}) {
|
|
41
42
|
const {
|
|
@@ -5,10 +5,11 @@ import { View, Text } from 'react-native';
|
|
|
5
5
|
import Svg, { Path } from 'react-native-svg';
|
|
6
6
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
7
7
|
import { StepLabel } from './StepLabel';
|
|
8
|
+
import { EMPTY_MODES } from '../../utils/react-utils';
|
|
8
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
10
|
export function Step({
|
|
10
11
|
children,
|
|
11
|
-
modes =
|
|
12
|
+
modes = EMPTY_MODES,
|
|
12
13
|
style,
|
|
13
14
|
index = 0,
|
|
14
15
|
connectorStyle,
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import { View, Text } from 'react-native';
|
|
5
5
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
|
+
import { EMPTY_MODES } from '../../utils/react-utils';
|
|
6
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
8
|
export function StepLabel({
|
|
8
9
|
title = 'Stepper Item',
|
|
9
10
|
supportingText,
|
|
10
|
-
modes =
|
|
11
|
+
modes = EMPTY_MODES,
|
|
11
12
|
style
|
|
12
13
|
}) {
|
|
13
14
|
// Title styles
|
|
@@ -5,11 +5,12 @@ import { View } from 'react-native';
|
|
|
5
5
|
import { getVariableByName } from '../../design-tokens/figma-variables-resolver';
|
|
6
6
|
import { Step } from './Step';
|
|
7
7
|
import { StepLabel } from './StepLabel';
|
|
8
|
+
import { EMPTY_MODES } from '../../utils/react-utils';
|
|
8
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
10
|
export { Step, StepLabel };
|
|
10
11
|
export default function Stepper({
|
|
11
12
|
children,
|
|
12
|
-
modes =
|
|
13
|
+
modes = EMPTY_MODES,
|
|
13
14
|
style
|
|
14
15
|
}) {
|
|
15
16
|
// Stepper container styles
|