jfs-components 0.0.62 → 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.
Files changed (255) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/lib/commonjs/components/Accordion/Accordion.js +1 -1
  3. package/lib/commonjs/components/ActionFooter/ActionFooter.js +1 -1
  4. package/lib/commonjs/components/ActionTile/ActionTile.js +2 -1
  5. package/lib/commonjs/components/AmountInput/AmountInput.js +2 -1
  6. package/lib/commonjs/components/AppBar/AppBar.js +1 -1
  7. package/lib/commonjs/components/Avatar/Avatar.js +184 -162
  8. package/lib/commonjs/components/AvatarGroup/AvatarGroup.js +1 -1
  9. package/lib/commonjs/components/Badge/Badge.js +2 -1
  10. package/lib/commonjs/components/Balance/Balance.js +2 -1
  11. package/lib/commonjs/components/BottomNav/BottomNav.js +2 -1
  12. package/lib/commonjs/components/BottomNavItem/BottomNavItem.js +106 -86
  13. package/lib/commonjs/components/Button/Button.js +190 -93
  14. package/lib/commonjs/components/ButtonGroup/ButtonGroup.js +1 -1
  15. package/lib/commonjs/components/Card/Card.js +2 -1
  16. package/lib/commonjs/components/CardCTA/CardCTA.js +1 -1
  17. package/lib/commonjs/components/CardProviderInfo/CardProviderInfo.js +1 -1
  18. package/lib/commonjs/components/Carousel/Carousel.js +3 -2
  19. package/lib/commonjs/components/Checkbox/Checkbox.js +2 -1
  20. package/lib/commonjs/components/ChipGroup/ChipGroup.js +1 -1
  21. package/lib/commonjs/components/ChipSelect/ChipSelect.js +2 -1
  22. package/lib/commonjs/components/DebitCard/DebitCard.js +1 -1
  23. package/lib/commonjs/components/Disclaimer/Disclaimer.js +2 -1
  24. package/lib/commonjs/components/Divider/Divider.js +2 -1
  25. package/lib/commonjs/components/Drawer/Drawer.js +2 -1
  26. package/lib/commonjs/components/EmptyState/EmptyState.js +2 -1
  27. package/lib/commonjs/components/FilterBar/FilterBar.js +1 -1
  28. package/lib/commonjs/components/Form/Form.js +2 -1
  29. package/lib/commonjs/components/FormField/FormField.js +3 -2
  30. package/lib/commonjs/components/HStack/HStack.js +1 -1
  31. package/lib/commonjs/components/HoldingsCard/HoldingsCard.js +2 -1
  32. package/lib/commonjs/components/IconButton/IconButton.js +118 -128
  33. package/lib/commonjs/components/IconCapsule/IconCapsule.js +61 -57
  34. package/lib/commonjs/components/InputSearch/InputSearch.js +7 -3
  35. package/lib/commonjs/components/LazyList/LazyList.js +1 -1
  36. package/lib/commonjs/components/LinearMeter/LinearMeter.js +3 -2
  37. package/lib/commonjs/components/ListGroup/ListGroup.js +1 -1
  38. package/lib/commonjs/components/ListItem/ListItem.js +190 -142
  39. package/lib/commonjs/components/MediaCard/MediaCard.js +3 -3
  40. package/lib/commonjs/components/MerchantProfile/MerchantProfile.js +2 -1
  41. package/lib/commonjs/components/MoneyValue/MoneyValue.js +2 -1
  42. package/lib/commonjs/components/NavArrow/NavArrow.js +82 -59
  43. package/lib/commonjs/components/NoteInput/NoteInput.js +2 -1
  44. package/lib/commonjs/components/Nudge/Nudge.js +1 -1
  45. package/lib/commonjs/components/Numpad/Numpad.js +2 -1
  46. package/lib/commonjs/components/OTP/OTP.js +1 -1
  47. package/lib/commonjs/components/PaymentFeedback/PaymentFeedback.js +2 -1
  48. package/lib/commonjs/components/Popup/Popup.js +2 -1
  49. package/lib/commonjs/components/ProductLabel/ProductLabel.js +2 -1
  50. package/lib/commonjs/components/ProgressBadge/ProgressBadge.js +2 -1
  51. package/lib/commonjs/components/RadioButton/RadioButton.js +2 -1
  52. package/lib/commonjs/components/RechargeCard/RechargeCard.js +2 -1
  53. package/lib/commonjs/components/Screen/Screen.js +1 -1
  54. package/lib/commonjs/components/Section/Section.js +268 -156
  55. package/lib/commonjs/components/SegmentedControl/SegmentedControl.js +3 -2
  56. package/lib/commonjs/components/StatItem/StatItem.js +2 -1
  57. package/lib/commonjs/components/StatusHero/StatusHero.js +2 -1
  58. package/lib/commonjs/components/Stepper/Step.js +2 -1
  59. package/lib/commonjs/components/Stepper/StepLabel.js +2 -1
  60. package/lib/commonjs/components/Stepper/Stepper.js +2 -1
  61. package/lib/commonjs/components/SupportText/SupportText.js +2 -1
  62. package/lib/commonjs/components/SupportText/SupportTextIcon.js +2 -1
  63. package/lib/commonjs/components/SwappableAmount/SwappableAmount.js +2 -1
  64. package/lib/commonjs/components/Tabs/TabItem.js +2 -1
  65. package/lib/commonjs/components/Tabs/Tabs.js +2 -1
  66. package/lib/commonjs/components/Text/Text.js +2 -1
  67. package/lib/commonjs/components/TextInput/TextInput.js +2 -2
  68. package/lib/commonjs/components/ThreadHero/ThreadHero.js +2 -1
  69. package/lib/commonjs/components/Title/Title.js +2 -1
  70. package/lib/commonjs/components/Toast/Toast.js +2 -1
  71. package/lib/commonjs/components/Toggle/Toggle.js +2 -1
  72. package/lib/commonjs/components/Tooltip/Tooltip.js +2 -1
  73. package/lib/commonjs/components/TransactionBubble/TransactionBubble.js +1 -1
  74. package/lib/commonjs/components/TransactionDetails/TransactionDetails.js +2 -2
  75. package/lib/commonjs/components/TransactionStatus/TransactionStatus.js +3 -2
  76. package/lib/commonjs/components/UpiHandle/UpiHandle.js +144 -110
  77. package/lib/commonjs/components/VStack/VStack.js +1 -1
  78. package/lib/commonjs/design-tokens/figma-variables-resolver.js +21 -3
  79. package/lib/commonjs/icons/registry.js +1 -1
  80. package/lib/commonjs/utils/react-utils.js +17 -0
  81. package/lib/module/components/Accordion/Accordion.js +2 -2
  82. package/lib/module/components/ActionFooter/ActionFooter.js +2 -2
  83. package/lib/module/components/ActionTile/ActionTile.js +2 -1
  84. package/lib/module/components/AmountInput/AmountInput.js +2 -1
  85. package/lib/module/components/AppBar/AppBar.js +2 -2
  86. package/lib/module/components/Avatar/Avatar.js +184 -162
  87. package/lib/module/components/AvatarGroup/AvatarGroup.js +2 -2
  88. package/lib/module/components/Badge/Badge.js +2 -1
  89. package/lib/module/components/Balance/Balance.js +2 -1
  90. package/lib/module/components/BottomNav/BottomNav.js +2 -1
  91. package/lib/module/components/BottomNavItem/BottomNavItem.js +108 -88
  92. package/lib/module/components/Button/Button.js +192 -95
  93. package/lib/module/components/ButtonGroup/ButtonGroup.js +2 -2
  94. package/lib/module/components/Card/Card.js +2 -1
  95. package/lib/module/components/CardCTA/CardCTA.js +2 -2
  96. package/lib/module/components/CardProviderInfo/CardProviderInfo.js +2 -2
  97. package/lib/module/components/Carousel/Carousel.js +3 -2
  98. package/lib/module/components/Checkbox/Checkbox.js +2 -1
  99. package/lib/module/components/ChipGroup/ChipGroup.js +2 -2
  100. package/lib/module/components/ChipSelect/ChipSelect.js +2 -1
  101. package/lib/module/components/DebitCard/DebitCard.js +2 -2
  102. package/lib/module/components/Disclaimer/Disclaimer.js +2 -1
  103. package/lib/module/components/Divider/Divider.js +2 -1
  104. package/lib/module/components/Drawer/Drawer.js +2 -1
  105. package/lib/module/components/EmptyState/EmptyState.js +2 -1
  106. package/lib/module/components/FilterBar/FilterBar.js +2 -2
  107. package/lib/module/components/Form/Form.js +2 -1
  108. package/lib/module/components/FormField/FormField.js +3 -2
  109. package/lib/module/components/HStack/HStack.js +2 -2
  110. package/lib/module/components/HoldingsCard/HoldingsCard.js +2 -1
  111. package/lib/module/components/IconButton/IconButton.js +120 -130
  112. package/lib/module/components/IconCapsule/IconCapsule.js +60 -57
  113. package/lib/module/components/InputSearch/InputSearch.js +7 -3
  114. package/lib/module/components/LazyList/LazyList.js +2 -2
  115. package/lib/module/components/LinearMeter/LinearMeter.js +3 -2
  116. package/lib/module/components/ListGroup/ListGroup.js +2 -2
  117. package/lib/module/components/ListItem/ListItem.js +194 -146
  118. package/lib/module/components/MediaCard/MediaCard.js +4 -2
  119. package/lib/module/components/MerchantProfile/MerchantProfile.js +2 -1
  120. package/lib/module/components/MoneyValue/MoneyValue.js +2 -1
  121. package/lib/module/components/NavArrow/NavArrow.js +82 -58
  122. package/lib/module/components/NoteInput/NoteInput.js +2 -1
  123. package/lib/module/components/Nudge/Nudge.js +2 -2
  124. package/lib/module/components/Numpad/Numpad.js +2 -1
  125. package/lib/module/components/OTP/OTP.js +2 -2
  126. package/lib/module/components/PaymentFeedback/PaymentFeedback.js +2 -1
  127. package/lib/module/components/Popup/Popup.js +2 -1
  128. package/lib/module/components/ProductLabel/ProductLabel.js +2 -1
  129. package/lib/module/components/ProgressBadge/ProgressBadge.js +2 -1
  130. package/lib/module/components/RadioButton/RadioButton.js +2 -1
  131. package/lib/module/components/RechargeCard/RechargeCard.js +2 -1
  132. package/lib/module/components/Screen/Screen.js +2 -2
  133. package/lib/module/components/Section/Section.js +271 -159
  134. package/lib/module/components/SegmentedControl/SegmentedControl.js +3 -2
  135. package/lib/module/components/StatItem/StatItem.js +2 -1
  136. package/lib/module/components/StatusHero/StatusHero.js +2 -1
  137. package/lib/module/components/Stepper/Step.js +2 -1
  138. package/lib/module/components/Stepper/StepLabel.js +2 -1
  139. package/lib/module/components/Stepper/Stepper.js +2 -1
  140. package/lib/module/components/SupportText/SupportText.js +2 -1
  141. package/lib/module/components/SupportText/SupportTextIcon.js +2 -1
  142. package/lib/module/components/SwappableAmount/SwappableAmount.js +2 -1
  143. package/lib/module/components/Tabs/TabItem.js +2 -1
  144. package/lib/module/components/Tabs/Tabs.js +2 -1
  145. package/lib/module/components/Text/Text.js +2 -1
  146. package/lib/module/components/TextInput/TextInput.js +3 -3
  147. package/lib/module/components/ThreadHero/ThreadHero.js +2 -1
  148. package/lib/module/components/Title/Title.js +2 -1
  149. package/lib/module/components/Toast/Toast.js +2 -1
  150. package/lib/module/components/Toggle/Toggle.js +2 -1
  151. package/lib/module/components/Tooltip/Tooltip.js +2 -1
  152. package/lib/module/components/TransactionBubble/TransactionBubble.js +2 -2
  153. package/lib/module/components/TransactionDetails/TransactionDetails.js +3 -3
  154. package/lib/module/components/TransactionStatus/TransactionStatus.js +3 -2
  155. package/lib/module/components/UpiHandle/UpiHandle.js +147 -113
  156. package/lib/module/components/VStack/VStack.js +2 -2
  157. package/lib/module/design-tokens/figma-variables-resolver.js +21 -3
  158. package/lib/module/icons/registry.js +1 -1
  159. package/lib/module/utils/react-utils.js +16 -0
  160. package/lib/typescript/src/components/Avatar/Avatar.d.ts +11 -17
  161. package/lib/typescript/src/components/BottomNavItem/BottomNavItem.d.ts +12 -8
  162. package/lib/typescript/src/components/Button/Button.d.ts +18 -1
  163. package/lib/typescript/src/components/IconButton/IconButton.d.ts +12 -29
  164. package/lib/typescript/src/components/IconCapsule/IconCapsule.d.ts +10 -18
  165. package/lib/typescript/src/components/InputSearch/InputSearch.d.ts +8 -3
  166. package/lib/typescript/src/components/ListItem/ListItem.d.ts +14 -1
  167. package/lib/typescript/src/components/NavArrow/NavArrow.d.ts +12 -11
  168. package/lib/typescript/src/components/Section/Section.d.ts +2 -48
  169. package/lib/typescript/src/components/UpiHandle/UpiHandle.d.ts +13 -12
  170. package/lib/typescript/src/icons/registry.d.ts +1 -1
  171. package/lib/typescript/src/utils/react-utils.d.ts +15 -0
  172. package/package.json +4 -6
  173. package/src/components/Accordion/Accordion.tsx +2 -2
  174. package/src/components/ActionFooter/ActionFooter.tsx +2 -2
  175. package/src/components/ActionTile/ActionTile.tsx +2 -1
  176. package/src/components/AmountInput/AmountInput.tsx +2 -1
  177. package/src/components/AppBar/AppBar.tsx +2 -2
  178. package/src/components/Avatar/Avatar.tsx +229 -158
  179. package/src/components/AvatarGroup/AvatarGroup.tsx +2 -2
  180. package/src/components/Badge/Badge.tsx +2 -1
  181. package/src/components/Balance/Balance.tsx +2 -1
  182. package/src/components/BottomNav/BottomNav.tsx +2 -1
  183. package/src/components/BottomNavItem/BottomNavItem.tsx +159 -88
  184. package/src/components/Button/Button.tsx +228 -101
  185. package/src/components/ButtonGroup/ButtonGroup.tsx +2 -2
  186. package/src/components/Card/Card.tsx +2 -1
  187. package/src/components/CardCTA/CardCTA.tsx +2 -2
  188. package/src/components/CardProviderInfo/CardProviderInfo.tsx +2 -2
  189. package/src/components/Carousel/Carousel.tsx +3 -2
  190. package/src/components/Checkbox/Checkbox.tsx +2 -1
  191. package/src/components/ChipGroup/ChipGroup.tsx +2 -2
  192. package/src/components/ChipSelect/ChipSelect.tsx +2 -1
  193. package/src/components/DebitCard/DebitCard.tsx +2 -2
  194. package/src/components/Disclaimer/Disclaimer.tsx +2 -1
  195. package/src/components/Divider/Divider.tsx +2 -1
  196. package/src/components/Drawer/Drawer.tsx +2 -1
  197. package/src/components/EmptyState/EmptyState.tsx +2 -1
  198. package/src/components/FilterBar/FilterBar.tsx +2 -2
  199. package/src/components/Form/Form.tsx +2 -1
  200. package/src/components/FormField/FormField.tsx +3 -2
  201. package/src/components/HStack/HStack.tsx +2 -2
  202. package/src/components/HoldingsCard/HoldingsCard.tsx +2 -1
  203. package/src/components/IconButton/IconButton.tsx +154 -126
  204. package/src/components/IconCapsule/IconCapsule.tsx +73 -54
  205. package/src/components/InputSearch/InputSearch.tsx +19 -5
  206. package/src/components/LazyList/LazyList.tsx +2 -2
  207. package/src/components/LinearMeter/LinearMeter.tsx +3 -2
  208. package/src/components/ListGroup/ListGroup.tsx +2 -2
  209. package/src/components/ListItem/ListItem.tsx +257 -187
  210. package/src/components/MediaCard/MediaCard.tsx +2 -1
  211. package/src/components/MerchantProfile/MerchantProfile.tsx +2 -1
  212. package/src/components/MoneyValue/MoneyValue.tsx +2 -1
  213. package/src/components/NavArrow/NavArrow.tsx +91 -58
  214. package/src/components/NoteInput/NoteInput.tsx +2 -1
  215. package/src/components/Nudge/Nudge.tsx +2 -2
  216. package/src/components/Numpad/Numpad.tsx +2 -1
  217. package/src/components/OTP/OTP.tsx +2 -2
  218. package/src/components/PaymentFeedback/PaymentFeedback.tsx +2 -1
  219. package/src/components/Popup/Popup.tsx +2 -1
  220. package/src/components/ProductLabel/ProductLabel.tsx +2 -1
  221. package/src/components/ProgressBadge/ProgressBadge.tsx +2 -2
  222. package/src/components/RadioButton/RadioButton.tsx +2 -1
  223. package/src/components/RechargeCard/RechargeCard.tsx +2 -1
  224. package/src/components/Screen/Screen.tsx +2 -2
  225. package/src/components/Section/Section.tsx +323 -167
  226. package/src/components/SegmentedControl/SegmentedControl.tsx +3 -2
  227. package/src/components/StatItem/StatItem.tsx +2 -1
  228. package/src/components/StatusHero/StatusHero.tsx +2 -1
  229. package/src/components/Stepper/Step.tsx +2 -1
  230. package/src/components/Stepper/StepLabel.tsx +2 -1
  231. package/src/components/Stepper/Stepper.tsx +2 -1
  232. package/src/components/SupportText/SupportText.tsx +2 -1
  233. package/src/components/SupportText/SupportTextIcon.tsx +2 -1
  234. package/src/components/SwappableAmount/SwappableAmount.tsx +2 -1
  235. package/src/components/Tabs/TabItem.tsx +2 -1
  236. package/src/components/Tabs/Tabs.tsx +2 -1
  237. package/src/components/Text/Text.tsx +2 -1
  238. package/src/components/TextInput/TextInput.tsx +3 -3
  239. package/src/components/ThreadHero/ThreadHero.tsx +2 -1
  240. package/src/components/Title/Title.tsx +2 -1
  241. package/src/components/Toast/Toast.tsx +2 -1
  242. package/src/components/Toggle/Toggle.tsx +2 -1
  243. package/src/components/Tooltip/Tooltip.tsx +2 -1
  244. package/src/components/TransactionBubble/TransactionBubble.tsx +2 -2
  245. package/src/components/TransactionDetails/TransactionDetails.tsx +3 -3
  246. package/src/components/TransactionStatus/TransactionStatus.tsx +3 -2
  247. package/src/components/UpiHandle/UpiHandle.tsx +193 -125
  248. package/src/components/VStack/VStack.tsx +2 -2
  249. package/src/design-tokens/figma-variables-resolver.ts +21 -3
  250. package/src/icons/registry.ts +1 -1
  251. package/src/utils/react-utils.ts +16 -0
  252. package/lib/typescript/App.d.ts +0 -2
  253. package/lib/typescript/index.d.ts +0 -2
  254. package/lib/typescript/metro.config.d.ts +0 -78
  255. 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, useEffect } from 'react';
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, enforces uniform width,
12
- // chunks into fixed rows of up to maxColumns, space-between per row.
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
- function SlotGrid({
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
- const [measureTimedOut, setMeasureTimedOut] = useState(false);
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
- const totalItems = items.length;
25
- useEffect(() => {
26
- itemWidthsRef.current.clear();
27
- setMaxItemWidth(null);
28
- setMeasureTimedOut(false);
29
- }, [totalItems]);
30
- useEffect(() => {
31
- if (maxItemWidth !== null) return;
32
- const timer = setTimeout(() => setMeasureTimedOut(true), 500);
33
- return () => clearTimeout(timer);
34
- }, [maxItemWidth, totalItems]);
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.set(index, width);
37
- if (itemWidthsRef.current.size >= totalItems && totalItems > 0) {
38
- setMaxItemWidth(Math.max(...itemWidthsRef.current.values()));
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 isMeasured = maxItemWidth !== null;
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: !isMeasured ? e => handleItemLayout(itemIndex, e.nativeEvent.layout.width) : undefined,
65
- style: isMeasured ? {
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
- }), isMeasured && spacersNeeded > 0 && Array.from({
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
- function Section({
106
- title = 'Section title',
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
- const containerStyle = {
161
- backgroundColor,
162
- paddingHorizontal,
163
- paddingVertical,
164
- borderRadius: radius,
165
- gap: sectionGap
166
- };
167
- const headerStyle = {
168
- paddingHorizontal: headerPaddingHorizontal,
169
- paddingVertical: headerPaddingVertical,
170
- gap: headerGap
171
- };
172
- const headerWrapStyle = {
173
- flexDirection: 'row',
174
- alignItems: 'center',
175
- justifyContent: 'space-between'
176
- };
177
- const titleStyle = {
178
- flex: 1,
179
- color: titleColor,
180
- fontSize: titleFontSize,
181
- lineHeight: titleLineHeight,
182
- fontFamily: titleFontFamily,
183
- fontWeight: titleFontWeight
184
- };
185
- const supportTextStyle = {
186
- color: supportTextColor,
187
- fontSize: supportTextFontSize,
188
- lineHeight: supportTextLineHeight,
189
- fontFamily: supportTextFontFamily,
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
- // Generate default accessibility label from title and supportText
194
- const defaultAccessibilityLabel = accessibilityLabel || (showSupportText ? `${title}. ${supportText}` : title);
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: [containerStyle, style],
227
- ...(Platform.OS === 'web' ? {
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 || "Opens section details",
339
+ accessibilityHint: accessibilityHint || 'Opens section details',
237
340
  onPress: onPress,
238
- onPressIn: e => {
239
- setIsHeaderPressed(true);
240
- rest?.onPressIn?.(e);
241
- },
242
- onPressOut: e => {
243
- setIsHeaderPressed(false);
244
- rest?.onPressOut?.(e);
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 && slotDirection === 'row' && /*#__PURE__*/_jsx(SlotGrid, {
271
- items: cloneChildrenWithModes(flattenChildren(slot), modes),
272
- gap: sectionGap
273
- }), slot && slotDirection === 'column' && /*#__PURE__*/_jsx(View, {
274
- style: {
275
- flexDirection: 'column',
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
- accessibilityLabel = undefined,
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