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
package/CHANGELOG.md ADDED
@@ -0,0 +1,36 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+
7
+ ## [0.0.63] - 2026-04-20
8
+
9
+ ### Performance
10
+
11
+ - **Pressable / scroll flicker (native):** `Button`, `Section` (header), `ListItem`, `Avatar`, `IconCapsule`, `NavArrow`, `UpiHandle`, `IconButton`, and `BottomNavItem` no longer mirror transient press state in React. Pressed visuals use `Pressable`’s `style` callback (host-view updates). On iOS, `unstable_pressDelay={130}` reduces accidental “pressed” flashes when a parent `ScrollView` cancels the gesture.
12
+ - **Token resolution:** `getVariableByName` caches serialized mode keys per `modes` object via a `WeakMap` in `serializeModes`, avoiding repeated sort/join work when the same `modes` reference is used for many lookups in one render.
13
+ - **Stable default modes:** Shared frozen `EMPTY_MODES` from `src/utils/react-utils.ts` replaces inline `modes = {}` defaults across components so default props do not allocate a new object every render (better `React.memo` hits and resolver cache locality).
14
+ - **Memoization:** Heavy token reads are batched in `useMemo` where refactored; several interactive components are wrapped in `React.memo`.
15
+
16
+ ### Fixed
17
+
18
+ - Intermittent visual flicker on interactive rows (e.g. People / Setup style cards) during vertical scroll on native devices.
19
+
20
+ ### Changed
21
+
22
+ - **Breaking (none intended):** Public prop types and default behavior are preserved. Some components now ignore unused `accessibilityLabel` props on inner nodes (documented via `_accessibilityLabel` where applicable); screen-reader behavior should match prior intentional `accessibilityLabel={undefined}` usage.
23
+
24
+ ### Removed
25
+
26
+ - Dead code: duplicate `usePressableWebSupport` usage in `ListItem`; unused computed labels in a few components; redundant pressed-style paths in `IconButton`.
27
+
28
+ ### Repository / tooling
29
+
30
+ - Storybook and example app layout updates; addon and config changes as reflected in the repo.
31
+
32
+ ---
33
+
34
+ ## [0.0.62] and earlier
35
+
36
+ See git history for releases prior to this changelog.
@@ -50,7 +50,7 @@ function Accordion({
50
50
  onExpandedChange,
51
51
  disabled = false,
52
52
  children,
53
- modes = {},
53
+ modes = _reactUtils.EMPTY_MODES,
54
54
  style,
55
55
  accessibilityLabel,
56
56
  accessibilityHint,
@@ -40,7 +40,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
40
40
  */
41
41
  function ActionFooter({
42
42
  children,
43
- modes = {},
43
+ modes = _reactUtils.EMPTY_MODES,
44
44
  style,
45
45
  accessibilityLabel = undefined
46
46
  }) {
@@ -9,6 +9,7 @@ var _reactNative = require("react-native");
9
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
10
  var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
11
11
  var _IconCapsule = _interopRequireDefault(require("../IconCapsule/IconCapsule"));
12
+ var _reactUtils = require("../../utils/react-utils");
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
15
  /**
@@ -20,7 +21,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
20
21
  function ActionTile({
21
22
  label = 'Cards',
22
23
  icon,
23
- modes: propModes = {},
24
+ modes: propModes = _reactUtils.EMPTY_MODES,
24
25
  style,
25
26
  onPress
26
27
  }) {
@@ -10,6 +10,7 @@ var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resol
10
10
  var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
11
11
  var _MoneyValue = _interopRequireDefault(require("../MoneyValue/MoneyValue"));
12
12
  var _NoteInput = _interopRequireDefault(require("../NoteInput/NoteInput"));
13
+ var _reactUtils = require("../../utils/react-utils");
13
14
  var _jsxRuntime = require("react/jsx-runtime");
14
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
16
  /**
@@ -20,7 +21,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
20
21
  function AmountInput({
21
22
  moneyValueSlot,
22
23
  noteInputSlot,
23
- modes: propModes = {},
24
+ modes: propModes = _reactUtils.EMPTY_MODES,
24
25
  style
25
26
  }) {
26
27
  const {
@@ -17,7 +17,7 @@ function AppBar({
17
17
  leadingSlot,
18
18
  middleSlot,
19
19
  actionsSlot,
20
- modes: propModes = {},
20
+ modes: propModes = _reactUtils.EMPTY_MODES,
21
21
  onLeadingPress,
22
22
  style,
23
23
  accessibilityLabel,
@@ -4,22 +4,104 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
+ var _reactUtils = require("../../utils/react-utils");
10
11
  var _jsxRuntime = require("react/jsx-runtime");
11
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
12
13
  const avatarImage = require('./31595e70c4181263f9971590224b12934b280c9b.png');
13
14
 
15
+ // ---------------------------------------------------------------------------
16
+ // Module-scope constants — never re-allocated per render.
17
+ // ---------------------------------------------------------------------------
18
+
19
+ const IS_WEB = _reactNative.Platform.OS === 'web';
20
+ const IS_IOS = _reactNative.Platform.OS === 'ios';
21
+ const PRESS_DELAY = IS_IOS ? 130 : 0;
22
+
23
+ // Pressed visual is applied through Pressable's style callback so the host
24
+ // view updates without scheduling a React render.
25
+ const pressedOverlayStyle = {
26
+ transform: [{
27
+ scale: 0.98
28
+ }]
29
+ };
30
+ const focusOverlayStyle = {
31
+ borderColor: '#222',
32
+ borderWidth: 1
33
+ };
34
+ const imageContainerStyle = {
35
+ width: '100%',
36
+ height: '100%',
37
+ overflow: 'hidden'
38
+ };
39
+ const imageBaseStyle = {
40
+ width: '100%',
41
+ height: '100%'
42
+ };
43
+ const monogramContainerStyle = {
44
+ width: '100%',
45
+ height: '100%',
46
+ justifyContent: 'center',
47
+ alignItems: 'center',
48
+ paddingVertical: 7,
49
+ paddingHorizontal: 5
50
+ };
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Token resolution — collapsed into one useMemo per (modes, style) tuple.
54
+ // ---------------------------------------------------------------------------
55
+
56
+ function resolveAvatarTokens(modes, isMonogram) {
57
+ const size = (0, _figmaVariablesResolver.getVariableByName)('avatar/size', modes) || 29;
58
+ const radiusRaw = (0, _figmaVariablesResolver.getVariableByName)('avatar/radius', modes) || 9999;
59
+ const backgroundColor = (0, _figmaVariablesResolver.getVariableByName)('avatar/background', modes) || '#dbcfff';
60
+ const borderColor = (0, _figmaVariablesResolver.getVariableByName)('avatar/border/color', modes) || 'rgba(255,255,255,0)';
61
+ const borderSize = (0, _figmaVariablesResolver.getVariableByName)('avatar/border/size', modes) || 1;
62
+ const labelColor = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/color', modes) || '#5c00b5';
63
+ const labelFontSize = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/fontSize', modes) || 12;
64
+ const labelLineHeight = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/lineHeight', modes) || 14;
65
+ const labelFontWeightRaw = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/fontWeight', modes) || 500;
66
+ const labelFontWeight = typeof labelFontWeightRaw === 'number' ? labelFontWeightRaw.toString() : labelFontWeightRaw;
67
+ const labelFontFamily = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/fontFamily', modes) || 'Inter';
68
+
69
+ // 9999 is the design-token sentinel for "perfect circle"
70
+ const borderRadius = radiusRaw === 9999 ? size / 2 : radiusRaw;
71
+ return {
72
+ containerStyle: {
73
+ width: size,
74
+ height: size,
75
+ borderRadius,
76
+ borderWidth: borderSize,
77
+ borderColor: borderColor,
78
+ overflow: 'hidden',
79
+ ...(isMonogram ? {
80
+ backgroundColor: backgroundColor
81
+ } : {})
82
+ },
83
+ imageContainerStyle: {
84
+ ...imageContainerStyle,
85
+ borderRadius
86
+ },
87
+ imageStyle: {
88
+ ...imageBaseStyle,
89
+ borderRadius
90
+ },
91
+ monogramTextStyle: {
92
+ fontSize: labelFontSize,
93
+ lineHeight: labelLineHeight,
94
+ fontWeight: labelFontWeight,
95
+ fontFamily: labelFontFamily,
96
+ color: labelColor,
97
+ textAlign: 'center'
98
+ }
99
+ };
100
+ }
101
+
14
102
  /**
15
103
  * Avatar component that displays either an image or a monogram.
16
- *
17
- * This component supports two styles:
18
- * - Image: Displays a user's profile picture
19
- * - Monogram: Displays user initials in a circular background
20
- *
21
- * All styling values are resolved from Figma design tokens using the provided modes.
22
- *
104
+ *
23
105
  * @component
24
106
  * @param {Object} props - Component props
25
107
  * @param {string} [props.monogram="MS"] - The initials to display when style is "Monogram"
@@ -27,182 +109,122 @@ const avatarImage = require('./31595e70c4181263f9971590224b12934b280c9b.png');
27
109
  * @param {Object} [props.modes={}] - Mode configuration for design tokens (e.g., {"Avatar Size": "M"})
28
110
  * @param {string} [props.imageSource] - Optional image source for Image style (defaults to built-in image)
29
111
  * @param {string} [props.accessibilityLabel] - Accessibility label for screen readers. If not provided, uses monogram or "User avatar"
30
- *
31
- * @example
32
- * ```jsx
33
- * // Image style
34
- * <Avatar style="Image" modes={{"Avatar Size": "M"}} />
35
- *
36
- * // Monogram style
37
- * <Avatar style="Monogram" monogram="JD" modes={{"Avatar Size": "L"}} />
38
- * ```
112
+ *
113
+ * Performance notes:
114
+ * - All token reads are folded into a single `useMemo([modes, isMonogram])`.
115
+ * - Press visual goes through Pressable's `({ pressed })` style callback so
116
+ * a scroll-cancelled touch never schedules a React render. iOS gets
117
+ * `unstable_pressDelay={130}` for additional safety inside scrollables.
118
+ * - Focus state stays in React (it's a sustained visual) but the setter is
119
+ * gated to web only, where focus events actually fire.
39
120
  */
40
121
 
41
122
  function Avatar({
42
- monogram = "MS",
43
- style = "Image",
44
- modes = {},
123
+ monogram = 'MS',
124
+ style = 'Image',
125
+ modes = _reactUtils.EMPTY_MODES,
45
126
  imageSource,
46
- accessibilityLabel,
127
+ // accessibilityLabel is accepted on the type for API back-compat but the
128
+ // component intentionally renders `accessibilityLabel={undefined}` on the
129
+ // wrapper (the inner Text/Image carry the label instead).
130
+ accessibilityLabel: _accessibilityLabel,
47
131
  ...rest
48
132
  }) {
49
- // Resolve design tokens using the provided modes
50
- const size = (0, _figmaVariablesResolver.getVariableByName)('avatar/size', modes) || 29;
51
- const radius = (0, _figmaVariablesResolver.getVariableByName)('avatar/radius', modes) || 9999;
52
- const backgroundColor = (0, _figmaVariablesResolver.getVariableByName)('avatar/background', modes) || '#dbcfff';
53
- const borderColor = (0, _figmaVariablesResolver.getVariableByName)('avatar/border/color', modes) || 'rgba(255,255,255,0)';
54
- const borderSize = (0, _figmaVariablesResolver.getVariableByName)('avatar/border/size', modes) || 1;
55
- const labelColor = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/color', modes) || '#5c00b5';
56
- const labelFontSize = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/fontSize', modes) || 12;
57
- const labelLineHeight = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/lineHeight', modes) || 14;
58
- const labelFontWeight = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/fontWeight', modes) || 500;
59
- const labelFontFamily = (0, _figmaVariablesResolver.getVariableByName)('avatar/label/fontFamily', modes) || 'Inter';
133
+ const isMonogram = style === 'Monogram';
134
+ const tokens = (0, _react.useMemo)(() => resolveAvatarTokens(modes, isMonogram), [modes, isMonogram]);
60
135
 
61
- // Convert radius to React Native format (if 9999, use size/2 for perfect circle)
62
- const borderRadius = radius === 9999 ? size / 2 : radius;
63
-
64
- // Container style
65
- const containerStyle = {
66
- width: size,
67
- height: size,
68
- borderRadius: borderRadius,
69
- borderWidth: borderSize,
70
- borderColor: borderColor,
71
- overflow: 'hidden',
72
- ...(style === 'Monogram' ? {
73
- backgroundColor: backgroundColor
74
- } : {})
75
- };
136
+ // Focus is a sustained visible state keep mirroring on web; gate the
137
+ // setter so it never fires on native (where focus events don't fire on
138
+ // these elements anyway).
139
+ const [isFocused, setIsFocused] = (0, _react.useState)(false);
76
140
 
77
- // Image container style
78
- const imageContainerStyle = {
79
- width: '100%',
80
- height: '100%',
81
- borderRadius: borderRadius,
82
- overflow: 'hidden'
83
- };
84
-
85
- // Image style
86
- const imageStyle = {
87
- width: '100%',
88
- height: '100%',
89
- borderRadius: borderRadius
90
- };
141
+ // Mirror user handlers in a ref so our wrappers can stay referentially
142
+ // stable across renders.
143
+ const userHandlersRef = (0, _react.useRef)({});
144
+ userHandlersRef.current.onPressIn = rest?.onPressIn;
145
+ userHandlersRef.current.onPressOut = rest?.onPressOut;
146
+ userHandlersRef.current.onFocus = rest?.onFocus;
147
+ userHandlersRef.current.onBlur = rest?.onBlur;
148
+ const handlePressIn = (0, _react.useCallback)(e => {
149
+ userHandlersRef.current.onPressIn?.(e);
150
+ }, []);
151
+ const handlePressOut = (0, _react.useCallback)(e => {
152
+ userHandlersRef.current.onPressOut?.(e);
153
+ }, []);
154
+ const handleFocus = (0, _react.useCallback)(e => {
155
+ if (IS_WEB) setIsFocused(true);
156
+ userHandlersRef.current.onFocus?.(e);
157
+ }, []);
158
+ const handleBlur = (0, _react.useCallback)(e => {
159
+ if (IS_WEB) setIsFocused(false);
160
+ userHandlersRef.current.onBlur?.(e);
161
+ }, []);
162
+ const pressableStyle = (0, _react.useCallback)(({
163
+ pressed
164
+ }) => [tokens.containerStyle, pressed ? pressedOverlayStyle : null, isFocused ? focusOverlayStyle : null], [tokens.containerStyle, isFocused]);
165
+ const staticContainerStyle = (0, _react.useMemo)(() => [tokens.containerStyle, isFocused ? focusOverlayStyle : null], [tokens.containerStyle, isFocused]);
91
166
 
92
- // Monogram container style
93
- const monogramContainerStyle = {
94
- width: '100%',
95
- height: '100%',
96
- justifyContent: 'center',
97
- alignItems: 'center',
98
- paddingVertical: 7,
99
- paddingHorizontal: 5
100
- };
101
-
102
- // Monogram text style
103
- const monogramTextStyle = {
104
- fontSize: labelFontSize,
105
- lineHeight: labelLineHeight,
106
- fontWeight: labelFontWeight,
107
- fontFamily: labelFontFamily,
108
- color: labelColor,
109
- textAlign: 'center'
110
- };
111
-
112
- // Generate default accessibility label
113
- const defaultAccessibilityLabel = accessibilityLabel || (style === "Monogram" ? `Avatar with initials ${monogram}` : "User avatar");
114
- // Interaction placeholders for press/focus
115
- const [isPressed, setIsPressed] = _react.default.useState(false);
116
- const [isFocused, setIsFocused] = _react.default.useState(false);
117
- const pressedStyle = isPressed ? {
118
- transform: [{
119
- scale: 0.98
120
- }]
121
- } : null;
122
- const focusStyle = isFocused ? {
123
- borderColor: '#222',
124
- borderWidth: 1
125
- } : null;
126
- if (style === "Monogram") {
127
- const Wrapper = rest?.onPress ? _reactNative.Pressable : _reactNative.View;
128
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapper, {
129
- style: [containerStyle, pressedStyle, focusStyle],
167
+ // The inner content varies; everything else (wrapper, handlers, style) is shared.
168
+ const innerContent = isMonogram ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
169
+ style: monogramContainerStyle,
170
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
171
+ style: tokens.monogramTextStyle,
172
+ accessibilityElementsHidden: true,
173
+ importantForAccessibility: "no",
174
+ children: monogram
175
+ })
176
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(ImageContent, {
177
+ tokens: tokens,
178
+ imageSource: imageSource
179
+ });
180
+ const isPressable = !!rest?.onPress;
181
+ if (isPressable) {
182
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Pressable, {
183
+ style: pressableStyle,
130
184
  accessibilityRole: "image",
131
185
  accessibilityLabel: undefined,
132
- onPressIn: e => {
133
- setIsPressed(true);
134
- rest?.onPressIn?.(e);
135
- },
136
- onPressOut: e => {
137
- setIsPressed(false);
138
- rest?.onPressOut?.(e);
139
- },
140
- onFocus: e => {
141
- setIsFocused(true);
142
- rest?.onFocus?.(e);
143
- },
144
- onBlur: e => {
145
- setIsFocused(false);
146
- rest?.onBlur?.(e);
147
- },
186
+ onPressIn: handlePressIn,
187
+ onPressOut: handlePressOut,
188
+ onFocus: handleFocus,
189
+ onBlur: handleBlur,
190
+ unstable_pressDelay: PRESS_DELAY,
148
191
  ...rest,
149
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
150
- style: monogramContainerStyle,
151
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
152
- style: monogramTextStyle,
153
- accessibilityElementsHidden: true,
154
- importantForAccessibility: "no",
155
- children: monogram
156
- })
157
- })
192
+ children: innerContent
158
193
  });
159
194
  }
195
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
196
+ style: staticContainerStyle,
197
+ accessibilityRole: "image",
198
+ accessibilityLabel: undefined,
199
+ ...rest,
200
+ children: innerContent
201
+ });
202
+ }
160
203
 
161
- // Normalize imageSource: if it's a string (URL), convert to { uri: string } format
162
- // Otherwise, use it as-is (could be require() result or already { uri: ... } object)
163
- const normalizedImageSource = _react.default.useMemo(() => {
204
+ // Memoize the image normalization so a string URL that doesn't change
205
+ // doesn't keep producing a new `{ uri }` object every render.
206
+ function ImageContent({
207
+ tokens,
208
+ imageSource
209
+ }) {
210
+ const normalizedImageSource = (0, _react.useMemo)(() => {
164
211
  if (!imageSource) return avatarImage;
165
212
  if (typeof imageSource === 'string') {
166
- // If it's a string, treat it as a URL
167
213
  return {
168
214
  uri: imageSource
169
215
  };
170
216
  }
171
- // Otherwise, use it as-is (could be require() result or { uri: ... } object)
172
217
  return imageSource;
173
218
  }, [imageSource]);
174
- const Wrapper = rest?.onPress ? _reactNative.Pressable : _reactNative.View;
175
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapper, {
176
- style: [containerStyle, pressedStyle, focusStyle],
177
- accessibilityRole: "image",
178
- accessibilityLabel: undefined,
179
- onPressIn: e => {
180
- setIsPressed(true);
181
- rest?.onPressIn?.(e);
182
- },
183
- onPressOut: e => {
184
- setIsPressed(false);
185
- rest?.onPressOut?.(e);
186
- },
187
- onFocus: e => {
188
- setIsFocused(true);
189
- rest?.onFocus?.(e);
190
- },
191
- onBlur: e => {
192
- setIsFocused(false);
193
- rest?.onBlur?.(e);
194
- },
195
- ...rest,
196
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
197
- style: imageContainerStyle,
198
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
199
- source: normalizedImageSource,
200
- resizeMode: "cover",
201
- style: imageStyle,
202
- accessibilityElementsHidden: true,
203
- importantForAccessibility: "no"
204
- })
219
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
220
+ style: tokens.imageContainerStyle,
221
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Image, {
222
+ source: normalizedImageSource,
223
+ resizeMode: "cover",
224
+ style: tokens.imageStyle,
225
+ accessibilityElementsHidden: true,
226
+ importantForAccessibility: "no"
205
227
  })
206
228
  });
207
229
  }
208
- var _default = exports.default = Avatar;
230
+ var _default = exports.default = /*#__PURE__*/_react.default.memo(Avatar);
@@ -14,7 +14,7 @@ var _jsxRuntime = require("react/jsx-runtime");
14
14
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
15
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
16
  function AvatarGroup({
17
- modes = {},
17
+ modes = _reactUtils.EMPTY_MODES,
18
18
  children,
19
19
  style,
20
20
  ...rest
@@ -7,11 +7,12 @@ exports.default = void 0;
7
7
  var _react = _interopRequireDefault(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
+ var _reactUtils = require("../../utils/react-utils");
10
11
  var _jsxRuntime = require("react/jsx-runtime");
11
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
12
13
  function Badge({
13
14
  label = 'Label',
14
- modes = {},
15
+ modes = _reactUtils.EMPTY_MODES,
15
16
  onPress,
16
17
  accessibilityLabel,
17
18
  style,
@@ -8,6 +8,7 @@ var _react = _interopRequireDefault(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
10
  var _MoneyValue = _interopRequireDefault(require("../MoneyValue/MoneyValue"));
11
+ var _reactUtils = require("../../utils/react-utils");
11
12
  var _jsxRuntime = require("react/jsx-runtime");
12
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
14
  /**
@@ -23,7 +24,7 @@ function Balance({
23
24
  title = "Total owed to people",
24
25
  amount = "500",
25
26
  currency = "₹",
26
- modes = {},
27
+ modes = _reactUtils.EMPTY_MODES,
27
28
  style,
28
29
  children
29
30
  }) {
@@ -9,6 +9,7 @@ var _reactNative = require("react-native");
9
9
  var _figmaVariablesResolver = require("../../design-tokens/figma-variables-resolver");
10
10
  var _JFSThemeProvider = require("../../design-tokens/JFSThemeProvider");
11
11
  var _BottomNavItem = _interopRequireDefault(require("../BottomNavItem/BottomNavItem"));
12
+ var _reactUtils = require("../../utils/react-utils");
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
15
  /**
@@ -26,7 +27,7 @@ function BottomNav({
26
27
  value,
27
28
  onChange,
28
29
  children,
29
- modes: propModes = {},
30
+ modes: propModes = _reactUtils.EMPTY_MODES,
30
31
  style,
31
32
  accessibilityLabel = undefined,
32
33
  accessibilityHint,