@coinbase/cds-mobile 8.60.0 → 8.62.0

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 (256) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dts/accordion/Accordion.d.ts +1 -9
  3. package/dts/accordion/Accordion.d.ts.map +1 -1
  4. package/dts/alpha/combobox/Combobox.d.ts.map +1 -1
  5. package/dts/alpha/select/Select.d.ts.map +1 -1
  6. package/dts/alpha/select-chip/SelectChip.d.ts.map +1 -1
  7. package/dts/alpha/tabbed-chips/TabbedChips.d.ts.map +1 -1
  8. package/dts/banner/Banner.d.ts.map +1 -1
  9. package/dts/buttons/AvatarButton.d.ts +6 -3
  10. package/dts/buttons/AvatarButton.d.ts.map +1 -1
  11. package/dts/buttons/Button.d.ts.map +1 -1
  12. package/dts/buttons/ButtonGroup.d.ts +3 -1
  13. package/dts/buttons/ButtonGroup.d.ts.map +1 -1
  14. package/dts/buttons/IconButton.d.ts.map +1 -1
  15. package/dts/buttons/IconCounterButton.d.ts.map +1 -1
  16. package/dts/buttons/SlideButton.d.ts.map +1 -1
  17. package/dts/cards/Card.d.ts +4 -0
  18. package/dts/cards/Card.d.ts.map +1 -1
  19. package/dts/cards/CardBody.d.ts +4 -0
  20. package/dts/cards/CardBody.d.ts.map +1 -1
  21. package/dts/cards/CardFooter.d.ts +4 -0
  22. package/dts/cards/CardFooter.d.ts.map +1 -1
  23. package/dts/cards/CardGroup.d.ts +12 -0
  24. package/dts/cards/CardGroup.d.ts.map +1 -1
  25. package/dts/cards/CardHeader.d.ts +8 -0
  26. package/dts/cards/CardHeader.d.ts.map +1 -1
  27. package/dts/cards/CardMedia.d.ts +8 -0
  28. package/dts/cards/CardMedia.d.ts.map +1 -1
  29. package/dts/cards/LikeButton.d.ts.map +1 -1
  30. package/dts/carousel/Carousel.d.ts.map +1 -1
  31. package/dts/cells/Cell.d.ts.map +1 -1
  32. package/dts/cells/ListCell.d.ts.map +1 -1
  33. package/dts/cells/ListCellFallback.d.ts.map +1 -1
  34. package/dts/chips/Chip.d.ts.map +1 -1
  35. package/dts/chips/ChipProps.d.ts +10 -8
  36. package/dts/chips/ChipProps.d.ts.map +1 -1
  37. package/dts/chips/InputChip.d.ts.map +1 -1
  38. package/dts/chips/MediaChip.d.ts +3 -2
  39. package/dts/chips/MediaChip.d.ts.map +1 -1
  40. package/dts/chips/TabbedChips.d.ts.map +1 -1
  41. package/dts/coachmark/Coachmark.d.ts.map +1 -1
  42. package/dts/collapsible/Collapsible.d.ts.map +1 -1
  43. package/dts/controls/Checkbox.d.ts.map +1 -1
  44. package/dts/controls/CheckboxCell.d.ts.map +1 -1
  45. package/dts/controls/Control.d.ts.map +1 -1
  46. package/dts/controls/ControlGroup.d.ts +13 -4
  47. package/dts/controls/ControlGroup.d.ts.map +1 -1
  48. package/dts/controls/InputStack.d.ts.map +1 -1
  49. package/dts/controls/Radio.d.ts.map +1 -1
  50. package/dts/controls/RadioCell.d.ts.map +1 -1
  51. package/dts/controls/SearchInput.d.ts.map +1 -1
  52. package/dts/controls/SelectOption.d.ts +3 -1
  53. package/dts/controls/SelectOption.d.ts.map +1 -1
  54. package/dts/controls/Switch.d.ts.map +1 -1
  55. package/dts/controls/TextInput.d.ts.map +1 -1
  56. package/dts/core/componentConfig.d.ts +166 -0
  57. package/dts/core/componentConfig.d.ts.map +1 -0
  58. package/dts/dates/Calendar.d.ts.map +1 -1
  59. package/dts/dates/DateInput.d.ts.map +1 -1
  60. package/dts/dates/DatePicker.d.ts.map +1 -1
  61. package/dts/dots/DotCount.d.ts +1 -11
  62. package/dts/dots/DotCount.d.ts.map +1 -1
  63. package/dts/dots/DotStatusColor.d.ts +1 -8
  64. package/dts/dots/DotStatusColor.d.ts.map +1 -1
  65. package/dts/dots/DotSymbol.d.ts +1 -17
  66. package/dts/dots/DotSymbol.d.ts.map +1 -1
  67. package/dts/hooks/useComponentConfig.d.ts +22 -0
  68. package/dts/hooks/useComponentConfig.d.ts.map +1 -0
  69. package/dts/icons/Icon.d.ts +11 -1
  70. package/dts/icons/Icon.d.ts.map +1 -1
  71. package/dts/index.d.ts +2 -0
  72. package/dts/index.d.ts.map +1 -1
  73. package/dts/layout/Divider.d.ts +3 -1
  74. package/dts/layout/Divider.d.ts.map +1 -1
  75. package/dts/layout/Fallback.d.ts +3 -1
  76. package/dts/layout/Fallback.d.ts.map +1 -1
  77. package/dts/media/Avatar.d.ts +1 -14
  78. package/dts/media/Avatar.d.ts.map +1 -1
  79. package/dts/media/RemoteImage.d.ts.map +1 -1
  80. package/dts/media/RemoteImageGroup.d.ts +3 -10
  81. package/dts/media/RemoteImageGroup.d.ts.map +1 -1
  82. package/dts/navigation/BrowserBar.d.ts +5 -14
  83. package/dts/navigation/BrowserBar.d.ts.map +1 -1
  84. package/dts/navigation/NavigationTitle.d.ts +4 -7
  85. package/dts/navigation/NavigationTitle.d.ts.map +1 -1
  86. package/dts/navigation/NavigationTitleSelect.d.ts +5 -11
  87. package/dts/navigation/NavigationTitleSelect.d.ts.map +1 -1
  88. package/dts/navigation/TopNavBar.d.ts +3 -13
  89. package/dts/navigation/TopNavBar.d.ts.map +1 -1
  90. package/dts/numbers/RollingNumber/RollingNumber.d.ts.map +1 -1
  91. package/dts/numpad/Numpad.d.ts +41 -38
  92. package/dts/numpad/Numpad.d.ts.map +1 -1
  93. package/dts/overlays/Alert.d.ts.map +1 -1
  94. package/dts/overlays/Toast.d.ts.map +1 -1
  95. package/dts/overlays/drawer/Drawer.d.ts.map +1 -1
  96. package/dts/overlays/modal/Modal.d.ts.map +1 -1
  97. package/dts/overlays/modal/ModalBody.d.ts.map +1 -1
  98. package/dts/overlays/modal/ModalFooter.d.ts +3 -8
  99. package/dts/overlays/modal/ModalFooter.d.ts.map +1 -1
  100. package/dts/overlays/modal/ModalHeader.d.ts.map +1 -1
  101. package/dts/overlays/overlay/Overlay.d.ts +7 -3
  102. package/dts/overlays/overlay/Overlay.d.ts.map +1 -1
  103. package/dts/overlays/tooltip/Tooltip.d.ts +2 -20
  104. package/dts/overlays/tooltip/Tooltip.d.ts.map +1 -1
  105. package/dts/overlays/tray/Tray.d.ts.map +1 -1
  106. package/dts/page/PageFooter.d.ts.map +1 -1
  107. package/dts/page/PageHeader.d.ts.map +1 -1
  108. package/dts/perf/component-config/Button.component-config.perf-test.d.ts +2 -0
  109. package/dts/perf/component-config/Button.component-config.perf-test.d.ts.map +1 -0
  110. package/dts/perf/component-config/ComponentConfigProvider.perf-test.d.ts +2 -0
  111. package/dts/perf/component-config/ComponentConfigProvider.perf-test.d.ts.map +1 -0
  112. package/dts/perf/component-config/ComponentConfigStickerSheet.perf-test.d.ts +2 -0
  113. package/dts/perf/component-config/ComponentConfigStickerSheet.perf-test.d.ts.map +1 -0
  114. package/dts/stepper/Stepper.d.ts.map +1 -1
  115. package/dts/system/ComponentConfigProvider.d.ts +26 -0
  116. package/dts/system/ComponentConfigProvider.d.ts.map +1 -0
  117. package/dts/system/index.d.ts +1 -0
  118. package/dts/system/index.d.ts.map +1 -1
  119. package/dts/tabs/SegmentedTab.d.ts +6 -3
  120. package/dts/tabs/SegmentedTab.d.ts.map +1 -1
  121. package/dts/tabs/SegmentedTabs.d.ts +6 -3
  122. package/dts/tabs/SegmentedTabs.d.ts.map +1 -1
  123. package/dts/tabs/Tabs.d.ts +25 -24
  124. package/dts/tabs/Tabs.d.ts.map +1 -1
  125. package/dts/tag/Tag.d.ts.map +1 -1
  126. package/dts/tour/Tour.d.ts +42 -41
  127. package/dts/tour/Tour.d.ts.map +1 -1
  128. package/dts/typography/Link.d.ts +1 -14
  129. package/dts/typography/Link.d.ts.map +1 -1
  130. package/dts/utils/mergeComponentProps.d.ts +34 -0
  131. package/dts/utils/mergeComponentProps.d.ts.map +1 -0
  132. package/dts/visualizations/ProgressBar.d.ts.map +1 -1
  133. package/dts/visualizations/ProgressBarWithFixedLabels.d.ts +5 -3
  134. package/dts/visualizations/ProgressBarWithFixedLabels.d.ts.map +1 -1
  135. package/dts/visualizations/ProgressBarWithFloatLabel.d.ts +3 -1
  136. package/dts/visualizations/ProgressBarWithFloatLabel.d.ts.map +1 -1
  137. package/dts/visualizations/ProgressCircle.d.ts.map +1 -1
  138. package/esm/accordion/Accordion.js +5 -3
  139. package/esm/alpha/combobox/Combobox.js +8 -6
  140. package/esm/alpha/select/Select.js +6 -4
  141. package/esm/alpha/select-chip/SelectChip.js +6 -4
  142. package/esm/alpha/tabbed-chips/TabbedChips.js +6 -4
  143. package/esm/banner/Banner.js +6 -4
  144. package/esm/buttons/AvatarButton.js +6 -4
  145. package/esm/buttons/Button.js +25 -10
  146. package/esm/buttons/ButtonGroup.js +5 -3
  147. package/esm/buttons/IconButton.js +14 -11
  148. package/esm/buttons/IconCounterButton.js +6 -4
  149. package/esm/buttons/SlideButton.js +10 -8
  150. package/esm/buttons/__stories__/Button.stories.js +32 -0
  151. package/esm/buttons/__stories__/IconButton.stories.js +32 -0
  152. package/esm/cards/Card.js +5 -0
  153. package/esm/cards/CardBody.js +5 -0
  154. package/esm/cards/CardFooter.js +4 -0
  155. package/esm/cards/CardGroup.js +14 -0
  156. package/esm/cards/CardHeader.js +9 -0
  157. package/esm/cards/CardMedia.js +10 -0
  158. package/esm/cards/LikeButton.js +6 -4
  159. package/esm/carousel/Carousel.js +10 -8
  160. package/esm/cells/Cell.js +6 -4
  161. package/esm/cells/ListCell.js +6 -4
  162. package/esm/cells/ListCellFallback.js +6 -4
  163. package/esm/chips/Chip.js +6 -4
  164. package/esm/chips/InputChip.js +6 -4
  165. package/esm/chips/MediaChip.js +6 -4
  166. package/esm/chips/TabbedChips.js +6 -4
  167. package/esm/coachmark/Coachmark.js +6 -4
  168. package/esm/collapsible/Collapsible.js +10 -8
  169. package/esm/controls/Checkbox.js +6 -4
  170. package/esm/controls/CheckboxCell.js +6 -4
  171. package/esm/controls/Control.js +8 -6
  172. package/esm/controls/ControlGroup.js +6 -4
  173. package/esm/controls/InputStack.js +6 -4
  174. package/esm/controls/Radio.js +6 -4
  175. package/esm/controls/RadioCell.js +6 -4
  176. package/esm/controls/SearchInput.js +6 -4
  177. package/esm/controls/SelectOption.js +6 -4
  178. package/esm/controls/Switch.js +6 -4
  179. package/esm/controls/TextInput.js +6 -4
  180. package/esm/core/componentConfig.js +1 -0
  181. package/esm/dates/Calendar.js +8 -6
  182. package/esm/dates/DateInput.js +6 -4
  183. package/esm/dates/DatePicker.js +9 -6
  184. package/esm/dots/DotCount.js +6 -4
  185. package/esm/dots/DotStatusColor.js +6 -4
  186. package/esm/dots/DotSymbol.js +6 -4
  187. package/esm/hooks/useComponentConfig.js +27 -0
  188. package/esm/icons/Icon.js +10 -8
  189. package/esm/index.js +2 -0
  190. package/esm/layout/Divider.js +6 -4
  191. package/esm/layout/Fallback.js +6 -4
  192. package/esm/media/Avatar.js +6 -4
  193. package/esm/media/RemoteImage.js +6 -4
  194. package/esm/media/RemoteImageGroup.js +6 -4
  195. package/esm/navigation/BrowserBar.js +6 -4
  196. package/esm/navigation/NavigationTitle.js +6 -4
  197. package/esm/navigation/NavigationTitleSelect.js +8 -6
  198. package/esm/navigation/TopNavBar.js +5 -3
  199. package/esm/numbers/RollingNumber/RollingNumber.js +6 -4
  200. package/esm/numpad/Numpad.js +8 -6
  201. package/esm/overlays/Alert.js +7 -5
  202. package/esm/overlays/Toast.js +10 -8
  203. package/esm/overlays/drawer/Drawer.js +12 -10
  204. package/esm/overlays/modal/Modal.js +4 -1
  205. package/esm/overlays/modal/ModalBody.js +8 -6
  206. package/esm/overlays/modal/ModalFooter.js +8 -6
  207. package/esm/overlays/modal/ModalHeader.js +6 -4
  208. package/esm/overlays/overlay/Overlay.js +6 -4
  209. package/esm/overlays/tooltip/Tooltip.js +5 -3
  210. package/esm/overlays/tray/Tray.js +13 -11
  211. package/esm/page/PageFooter.js +6 -4
  212. package/esm/page/PageHeader.js +6 -4
  213. package/esm/perf/component-config/Button.component-config.perf-test.js +35 -0
  214. package/esm/perf/component-config/ComponentConfigProvider.perf-test.js +147 -0
  215. package/esm/perf/component-config/ComponentConfigStickerSheet.perf-test.js +326 -0
  216. package/esm/perf/component-config/README.md +8 -0
  217. package/esm/stepper/Stepper.js +11 -9
  218. package/esm/system/ComponentConfigProvider.js +39 -0
  219. package/esm/system/__stories__/ComponentConfigProvider.stories.js +12 -0
  220. package/esm/system/__stories__/ComponentConfigProviderCustom.stories.js +22 -0
  221. package/esm/system/__stories__/componentConfigStickerSheet/Container.js +27 -0
  222. package/esm/system/__stories__/componentConfigStickerSheet/StickerSheet.js +94 -0
  223. package/esm/system/__stories__/componentConfigStickerSheet/customComponentConfig.js +116 -0
  224. package/esm/system/__stories__/componentConfigStickerSheet/customTheme.js +520 -0
  225. package/esm/system/__stories__/componentConfigStickerSheet/examples/Accordion.js +67 -0
  226. package/esm/system/__stories__/componentConfigStickerSheet/examples/Avatar.js +48 -0
  227. package/esm/system/__stories__/componentConfigStickerSheet/examples/Banner.js +43 -0
  228. package/esm/system/__stories__/componentConfigStickerSheet/examples/Button.js +77 -0
  229. package/esm/system/__stories__/componentConfigStickerSheet/examples/Coachmark.js +15 -0
  230. package/esm/system/__stories__/componentConfigStickerSheet/examples/Controls.js +29 -0
  231. package/esm/system/__stories__/componentConfigStickerSheet/examples/DatePicker.js +15 -0
  232. package/esm/system/__stories__/componentConfigStickerSheet/examples/DotCount.js +28 -0
  233. package/esm/system/__stories__/componentConfigStickerSheet/examples/Icon.js +57 -0
  234. package/esm/system/__stories__/componentConfigStickerSheet/examples/InputChip.js +17 -0
  235. package/esm/system/__stories__/componentConfigStickerSheet/examples/ListCell.js +48 -0
  236. package/esm/system/__stories__/componentConfigStickerSheet/examples/Search.js +20 -0
  237. package/esm/system/__stories__/componentConfigStickerSheet/examples/SegmentedTabs.js +12 -0
  238. package/esm/system/__stories__/componentConfigStickerSheet/examples/Select.js +24 -0
  239. package/esm/system/__stories__/componentConfigStickerSheet/examples/SelectChip.js +22 -0
  240. package/esm/system/__stories__/componentConfigStickerSheet/examples/Tag.js +35 -0
  241. package/esm/system/__stories__/componentConfigStickerSheet/examples/TextInput.js +46 -0
  242. package/esm/system/__stories__/componentConfigStickerSheet/examples/constants.js +33 -0
  243. package/esm/system/__stories__/componentConfigStickerSheet/themeVars.js +2 -0
  244. package/esm/system/index.js +1 -0
  245. package/esm/tabs/SegmentedTab.js +7 -5
  246. package/esm/tabs/SegmentedTabs.js +9 -4
  247. package/esm/tabs/Tabs.js +12 -10
  248. package/esm/tag/Tag.js +6 -4
  249. package/esm/tour/Tour.js +5 -3
  250. package/esm/typography/Link.js +6 -4
  251. package/esm/utils/mergeComponentProps.js +35 -0
  252. package/esm/visualizations/ProgressBar.js +7 -5
  253. package/esm/visualizations/ProgressBarWithFixedLabels.js +5 -3
  254. package/esm/visualizations/ProgressBarWithFloatLabel.js +5 -3
  255. package/esm/visualizations/ProgressCircle.js +7 -5
  256. package/package.json +4 -3
@@ -0,0 +1,326 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React from 'react';
3
+ import { Pressable } from 'react-native';
4
+ import { fireEvent, screen } from '@testing-library/react-native';
5
+ import { measurePerformance } from 'reassure';
6
+ import { Button } from '../../buttons/Button';
7
+ import { IconButton } from '../../buttons/IconButton';
8
+ import { ListCell } from '../../cells/ListCell';
9
+ import { Chip } from '../../chips/Chip';
10
+ import { SearchInput } from '../../controls/SearchInput';
11
+ import { TextInput } from '../../controls/TextInput';
12
+ import { DotCount } from '../../dots/DotCount';
13
+ import { Icon } from '../../icons/Icon';
14
+ import { HStack } from '../../layout/HStack';
15
+ import { VStack } from '../../layout/VStack';
16
+ import { Avatar } from '../../media/Avatar';
17
+ import { ComponentConfigProvider } from '../../system/ComponentConfigProvider';
18
+ import { ThemeProvider } from '../../system/ThemeProvider';
19
+ import { Tag } from '../../tag/Tag';
20
+ import { defaultTheme } from '../../themes/defaultTheme';
21
+ import { Text } from '../../typography/Text';
22
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
23
+ const updateIterations = 50;
24
+ const customPerfTheme = _extends({}, defaultTheme, {
25
+ id: 'component-config-mobile-perf-theme',
26
+ lightColor: _extends({}, defaultTheme.lightColor, {
27
+ bgAlternate: defaultTheme.lightColor.bgSecondary
28
+ }),
29
+ darkColor: _extends({}, defaultTheme.darkColor, {
30
+ bgAlternate: defaultTheme.darkColor.bgSecondary
31
+ })
32
+ });
33
+ const customComponentConfig = {
34
+ Button: props => ({
35
+ borderRadius: 200,
36
+ height: props.compact ? 24 : 32,
37
+ font: props.compact ? 'label1' : 'headline'
38
+ }),
39
+ IconButton: props => ({
40
+ borderRadius: 200,
41
+ height: props.compact ? 24 : 32,
42
+ width: props.compact ? 24 : 32
43
+ }),
44
+ TextInput: props => ({
45
+ bordered: false,
46
+ inputBackground: 'bgAlternate',
47
+ font: props.compact ? 'label2' : 'body',
48
+ variant: 'foregroundMuted',
49
+ focusedBorderWidth: 100
50
+ }),
51
+ SearchInput: props => ({
52
+ borderRadius: 200,
53
+ height: props.compact ? 24 : 32
54
+ }),
55
+ Chip: {
56
+ borderRadius: 200
57
+ },
58
+ ListCell: {
59
+ spacingVariant: 'condensed'
60
+ }
61
+ };
62
+ const ComplexStickerSheetLike = _ref => {
63
+ let {
64
+ tick = 0
65
+ } = _ref;
66
+ return /*#__PURE__*/_jsx(VStack, {
67
+ alignItems: "center",
68
+ background: "bgAlternate",
69
+ gap: 2,
70
+ padding: 2,
71
+ children: /*#__PURE__*/_jsxs(HStack, {
72
+ gap: 2,
73
+ children: [/*#__PURE__*/_jsxs(VStack, {
74
+ gap: 2,
75
+ width: 420,
76
+ children: [/*#__PURE__*/_jsx(HStack, {
77
+ gap: 1,
78
+ children: Array.from({
79
+ length: 12
80
+ }, (_, i) => /*#__PURE__*/_jsx(Button, {
81
+ variant: tick % 2 === 0 ? 'primary' : 'secondary',
82
+ children: "Primary"
83
+ }, "primary-" + i))
84
+ }), /*#__PURE__*/_jsx(HStack, {
85
+ gap: 1,
86
+ children: Array.from({
87
+ length: 12
88
+ }, (_, i) => /*#__PURE__*/_jsx(Button, {
89
+ compact: true,
90
+ variant: "secondary",
91
+ children: "Secondary"
92
+ }, "secondary-" + i))
93
+ }), /*#__PURE__*/_jsx(VStack, {
94
+ gap: 1,
95
+ children: Array.from({
96
+ length: 8
97
+ }, (_, i) => /*#__PURE__*/_jsx(TextInput, {
98
+ label: "Label " + i,
99
+ onChangeText: () => {},
100
+ value: ""
101
+ }, "input-" + i))
102
+ }), /*#__PURE__*/_jsx(VStack, {
103
+ gap: 1,
104
+ children: Array.from({
105
+ length: 8
106
+ }, (_, i) => /*#__PURE__*/_jsx(SearchInput, {
107
+ label: "Search " + i,
108
+ onChangeText: () => {},
109
+ value: ""
110
+ }, "search-" + i))
111
+ }), /*#__PURE__*/_jsx(VStack, {
112
+ gap: 1,
113
+ children: Array.from({
114
+ length: 8
115
+ }, (_, i) => /*#__PURE__*/_jsx(ListCell, {
116
+ accessibilityLabel: "List row " + i,
117
+ description: "$100",
118
+ media: /*#__PURE__*/_jsx(Avatar, {
119
+ name: "A",
120
+ size: "m"
121
+ }),
122
+ onPress: () => {},
123
+ subtitle: "Subtitle",
124
+ title: "Row " + i
125
+ }, "cell-" + i))
126
+ })]
127
+ }), /*#__PURE__*/_jsxs(VStack, {
128
+ gap: 2,
129
+ width: 600,
130
+ children: [/*#__PURE__*/_jsx(HStack, {
131
+ gap: 1,
132
+ children: Array.from({
133
+ length: 16
134
+ }, (_, i) => /*#__PURE__*/_jsx(IconButton, {
135
+ accessibilityLabel: "Icon button " + i,
136
+ name: "add",
137
+ variant: "tertiary"
138
+ }, "icon-" + i))
139
+ }), /*#__PURE__*/_jsx(HStack, {
140
+ flexWrap: "wrap",
141
+ gap: 1,
142
+ children: Array.from({
143
+ length: 24
144
+ }, (_, i) => /*#__PURE__*/_jsxs(Chip, {
145
+ accessibilityLabel: "Chip " + i,
146
+ onPress: () => {},
147
+ children: ["Chip ", i]
148
+ }, "chip-" + i))
149
+ }), /*#__PURE__*/_jsx(HStack, {
150
+ gap: 1,
151
+ children: Array.from({
152
+ length: 20
153
+ }, (_, i) => /*#__PURE__*/_jsxs(Tag, {
154
+ intent: i % 2 === 0 ? 'informational' : 'promotional',
155
+ children: ["Tag ", i]
156
+ }, "tag-" + i))
157
+ }), /*#__PURE__*/_jsx(HStack, {
158
+ gap: 1,
159
+ children: Array.from({
160
+ length: 10
161
+ }, (_, i) => /*#__PURE__*/_jsx(DotCount, {
162
+ count: i + 1,
163
+ children: /*#__PURE__*/_jsx(Icon, {
164
+ name: "bell",
165
+ size: "l"
166
+ })
167
+ }, "dot-" + i))
168
+ }), /*#__PURE__*/_jsxs(Text, {
169
+ font: "title3",
170
+ children: ["Complex story-like surface tick=", tick]
171
+ })]
172
+ })]
173
+ })
174
+ });
175
+ };
176
+ const BaselineHarness = () => /*#__PURE__*/_jsx(ThemeProvider, {
177
+ activeColorScheme: "light",
178
+ theme: defaultTheme,
179
+ children: /*#__PURE__*/_jsx(ComplexStickerSheetLike, {})
180
+ });
181
+ const CustomHarness = () => /*#__PURE__*/_jsx(ThemeProvider, {
182
+ activeColorScheme: "dark",
183
+ theme: customPerfTheme,
184
+ children: /*#__PURE__*/_jsx(ComponentConfigProvider, {
185
+ value: customComponentConfig,
186
+ children: /*#__PURE__*/_jsx(ComplexStickerSheetLike, {})
187
+ })
188
+ });
189
+ const UnrelatedConfigUpdateHarness = () => {
190
+ const [tick, setTick] = React.useState(0);
191
+ const value = React.useMemo(() => _extends({}, customComponentConfig, {
192
+ Tour: tick % 2 === 0 ? {} : {}
193
+ }), [tick]);
194
+ return /*#__PURE__*/_jsxs(_Fragment, {
195
+ children: [/*#__PURE__*/_jsx(Pressable, {
196
+ onPress: () => setTick(v => v + 1),
197
+ testID: "update-unrelated-config"
198
+ }), /*#__PURE__*/_jsx(ThemeProvider, {
199
+ activeColorScheme: "dark",
200
+ theme: customPerfTheme,
201
+ children: /*#__PURE__*/_jsx(ComponentConfigProvider, {
202
+ value: value,
203
+ children: /*#__PURE__*/_jsx(ComplexStickerSheetLike, {})
204
+ })
205
+ })]
206
+ });
207
+ };
208
+ const TargetedConfigUpdateHarness = () => {
209
+ const [tick, setTick] = React.useState(0);
210
+ const value = React.useMemo(() => _extends({}, customComponentConfig, {
211
+ Button: props => ({
212
+ borderRadius: tick % 2 === 0 ? 200 : 300,
213
+ height: props.compact ? 24 : 32,
214
+ font: props.compact ? 'label1' : 'headline'
215
+ })
216
+ }), [tick]);
217
+ return /*#__PURE__*/_jsxs(_Fragment, {
218
+ children: [/*#__PURE__*/_jsx(Pressable, {
219
+ onPress: () => setTick(v => v + 1),
220
+ testID: "update-targeted-config"
221
+ }), /*#__PURE__*/_jsx(ThemeProvider, {
222
+ activeColorScheme: "dark",
223
+ theme: customPerfTheme,
224
+ children: /*#__PURE__*/_jsx(ComponentConfigProvider, {
225
+ value: value,
226
+ children: /*#__PURE__*/_jsx(ComplexStickerSheetLike, {})
227
+ })
228
+ })]
229
+ });
230
+ };
231
+ const RandomStateUpdateHarness = () => {
232
+ const [tick, setTick] = React.useState(0);
233
+ return /*#__PURE__*/_jsxs(_Fragment, {
234
+ children: [/*#__PURE__*/_jsx(Pressable, {
235
+ onPress: () => setTick(v => v + 1),
236
+ testID: "update-random-state"
237
+ }), /*#__PURE__*/_jsx(ThemeProvider, {
238
+ activeColorScheme: "dark",
239
+ theme: customPerfTheme,
240
+ children: /*#__PURE__*/_jsx(ComponentConfigProvider, {
241
+ value: customComponentConfig,
242
+ children: /*#__PURE__*/_jsx(ComplexStickerSheetLike, {
243
+ tick: tick
244
+ })
245
+ })
246
+ })]
247
+ });
248
+ };
249
+ const CustomThemeNoProviderHarness = () => /*#__PURE__*/_jsx(ThemeProvider, {
250
+ activeColorScheme: "dark",
251
+ theme: customPerfTheme,
252
+ children: /*#__PURE__*/_jsx(ComplexStickerSheetLike, {})
253
+ });
254
+ const CustomThemeNoProviderStateUpdateHarness = () => {
255
+ const [tick, setTick] = React.useState(0);
256
+ return /*#__PURE__*/_jsxs(_Fragment, {
257
+ children: [/*#__PURE__*/_jsx(Pressable, {
258
+ onPress: () => setTick(v => v + 1),
259
+ testID: "update-page-state-no-provider"
260
+ }), /*#__PURE__*/_jsx(ThemeProvider, {
261
+ activeColorScheme: "dark",
262
+ theme: customPerfTheme,
263
+ children: /*#__PURE__*/_jsx(ComplexStickerSheetLike, {
264
+ tick: tick
265
+ })
266
+ })]
267
+ });
268
+ };
269
+ describe('ComponentConfig StickerSheet performance tests (mobile)', () => {
270
+ jest.setTimeout(90000);
271
+ beforeAll(() => {
272
+ jest.spyOn(console, 'error').mockImplementation(() => {});
273
+ });
274
+ afterAll(() => {
275
+ jest.restoreAllMocks();
276
+ });
277
+ it('renders StickerSheet baseline (no provider)', async () => {
278
+ await measurePerformance(/*#__PURE__*/_jsx(BaselineHarness, {}));
279
+ });
280
+ it('renders StickerSheet custom story (theme + component config)', async () => {
281
+ await measurePerformance(/*#__PURE__*/_jsx(CustomHarness, {}));
282
+ });
283
+ it('updates unrelated config key 50 times', async () => {
284
+ const scenario = async () => {
285
+ for (let i = 0; i < updateIterations; i += 1) {
286
+ fireEvent.press(screen.getByTestId('update-unrelated-config'));
287
+ }
288
+ };
289
+ await measurePerformance(/*#__PURE__*/_jsx(UnrelatedConfigUpdateHarness, {}), {
290
+ scenario
291
+ });
292
+ });
293
+ it('updates targeted config key 50 times', async () => {
294
+ const scenario = async () => {
295
+ for (let i = 0; i < updateIterations; i += 1) {
296
+ fireEvent.press(screen.getByTestId('update-targeted-config'));
297
+ }
298
+ };
299
+ await measurePerformance(/*#__PURE__*/_jsx(TargetedConfigUpdateHarness, {}), {
300
+ scenario
301
+ });
302
+ });
303
+ it('updates random local state 50 times (provider enabled)', async () => {
304
+ const scenario = async () => {
305
+ for (let i = 0; i < updateIterations; i += 1) {
306
+ fireEvent.press(screen.getByTestId('update-random-state'));
307
+ }
308
+ };
309
+ await measurePerformance(/*#__PURE__*/_jsx(RandomStateUpdateHarness, {}), {
310
+ scenario
311
+ });
312
+ });
313
+ it('renders custom theme with no provider', async () => {
314
+ await measurePerformance(/*#__PURE__*/_jsx(CustomThemeNoProviderHarness, {}));
315
+ });
316
+ it('updates page state 50 times with custom theme and no provider', async () => {
317
+ const scenario = async () => {
318
+ for (let i = 0; i < updateIterations; i += 1) {
319
+ fireEvent.press(screen.getByTestId('update-page-state-no-provider'));
320
+ }
321
+ };
322
+ await measurePerformance(/*#__PURE__*/_jsx(CustomThemeNoProviderStateUpdateHarness, {}), {
323
+ scenario
324
+ });
325
+ });
326
+ });
@@ -0,0 +1,8 @@
1
+ # Component Config Perf Tests
2
+
3
+ This folder contains manual performance benchmarks for component config behavior.
4
+
5
+ ## Run
6
+
7
+ - Web + mobile together:
8
+ - `yarn perf:component-config`
@@ -7,6 +7,7 @@ import { useHasMounted } from '@coinbase/cds-common/hooks/useHasMounted';
7
7
  import { usePreviousValue } from '@coinbase/cds-common/hooks/usePreviousValue';
8
8
  import { containsStep, flattenSteps, isStepVisited } from '@coinbase/cds-common/stepper/utils';
9
9
  import { useSprings } from '@react-spring/native';
10
+ import { useComponentConfig } from '../hooks/useComponentConfig';
10
11
  import { Box } from '../layout/Box';
11
12
  import { VStack } from '../layout/VStack';
12
13
  import { DefaultStepperHeaderHorizontal } from './DefaultStepperHeaderHorizontal';
@@ -34,9 +35,10 @@ export const defaultProgressSpringConfig = {
34
35
  tension: 100,
35
36
  clamp: true
36
37
  };
37
- const StepperBase = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
38
+ const StepperBase = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_props, ref) => {
38
39
  var _usePreviousValue, _usePreviousValue2;
39
- let {
40
+ const mergedProps = useComponentConfig('Stepper', _props);
41
+ const {
40
42
  direction,
41
43
  activeStepId,
42
44
  steps,
@@ -56,8 +58,8 @@ const StepperBase = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
56
58
  progressSpringConfig = defaultProgressSpringConfig,
57
59
  animate = true,
58
60
  disableAnimateOnMount
59
- } = _ref,
60
- props = _objectWithoutPropertiesLoose(_ref, _excluded);
61
+ } = mergedProps,
62
+ props = _objectWithoutPropertiesLoose(mergedProps, _excluded);
61
63
  const hasMounted = useHasMounted();
62
64
  const flatStepIds = useMemo(() => flattenSteps(steps).map(step => step.id), [steps]);
63
65
 
@@ -72,11 +74,11 @@ const StepperBase = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
72
74
  rootStyle,
73
75
  stepStyles
74
76
  } = useMemo(() => {
75
- const _ref2 = styles != null ? styles : {},
77
+ const _ref = styles != null ? styles : {},
76
78
  {
77
79
  root
78
- } = _ref2,
79
- stepStyles = _objectWithoutPropertiesLoose(_ref2, _excluded2);
80
+ } = _ref,
81
+ stepStyles = _objectWithoutPropertiesLoose(_ref, _excluded2);
80
82
  const rootStyle = [style, root];
81
83
  return {
82
84
  rootStyle,
@@ -84,12 +86,12 @@ const StepperBase = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
84
86
  };
85
87
  }, [styles, style]);
86
88
  const accessibilityLabel = useMemo(() => {
87
- var _ref3, _activeStep$accessibi;
89
+ var _ref2, _activeStep$accessibi;
88
90
  if (accessibilityLabelProp) return accessibilityLabelProp;
89
91
  if (!activeStep) return 'No active step';
90
92
  const pagination = activeFlatStepIndex + 1 + " of " + flatStepIds.length;
91
93
  const stepLabel = typeof activeStep.label === 'string' ? activeStep.label : null;
92
- const baseLabel = (_ref3 = (_activeStep$accessibi = activeStep.accessibilityLabel) != null ? _activeStep$accessibi : stepLabel) != null ? _ref3 : "Step " + (activeFlatStepIndex + 1);
94
+ const baseLabel = (_ref2 = (_activeStep$accessibi = activeStep.accessibilityLabel) != null ? _activeStep$accessibi : stepLabel) != null ? _ref2 : "Step " + (activeFlatStepIndex + 1);
93
95
  return baseLabel + " " + pagination;
94
96
  }, [activeStep, activeFlatStepIndex, flatStepIds.length, accessibilityLabelProp]);
95
97
 
@@ -0,0 +1,39 @@
1
+ import React, { createContext, useContext, useRef } from 'react';
2
+ import { createStore } from 'zustand';
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ export const ComponentConfigContext = /*#__PURE__*/createContext(undefined);
5
+ const createComponentConfigStoreState = config => {
6
+ return {
7
+ components: config
8
+ };
9
+ };
10
+ /**
11
+ * Provides component-level default props via a zustand store.
12
+ * Each component subscribes to only its own config slice, preventing cross-component re-renders.
13
+ * Supports nesting with isolated scopes: a child provider only applies its own config map.
14
+ */
15
+ export const ComponentConfigProvider = _ref => {
16
+ let {
17
+ value,
18
+ children
19
+ } = _ref;
20
+ const storeRef = useRef(null);
21
+ if (!storeRef.current) {
22
+ storeRef.current = createStore(() => createComponentConfigStoreState(value));
23
+ }
24
+ const newState = createComponentConfigStoreState(value);
25
+ storeRef.current.setState(newState, true);
26
+ return /*#__PURE__*/_jsx(ComponentConfigContext.Provider, {
27
+ value: storeRef.current,
28
+ children: children
29
+ });
30
+ };
31
+
32
+ /** Singleton empty store used when no ComponentConfigProvider exists in the tree. */
33
+ const emptyComponentConfigStore = createStore(() => ({}));
34
+
35
+ /** Returns the nearest ComponentConfigProvider's zustand store, or an empty fallback. */
36
+ export const useComponentConfigStore = () => {
37
+ const context = useContext(ComponentConfigContext);
38
+ return context != null ? context : emptyComponentConfigStore;
39
+ };
@@ -0,0 +1,12 @@
1
+ import { Example, ExampleScreen } from '../../examples/ExampleScreen';
2
+ import { StickerSheet } from './componentConfigStickerSheet/StickerSheet';
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ const ComponentConfigProviderStory = () => {
5
+ return /*#__PURE__*/_jsx(ExampleScreen, {
6
+ children: /*#__PURE__*/_jsx(Example, {
7
+ title: "ComponentConfigProvider",
8
+ children: /*#__PURE__*/_jsx(StickerSheet, {})
9
+ })
10
+ });
11
+ };
12
+ export default ComponentConfigProviderStory;
@@ -0,0 +1,22 @@
1
+ import { Example, ExampleScreen } from '../../examples/ExampleScreen';
2
+ import { ComponentConfigProvider, ThemeProvider } from '..';
3
+ import { customComponentConfig } from './componentConfigStickerSheet/customComponentConfig';
4
+ import { customTheme } from './componentConfigStickerSheet/customTheme';
5
+ import { StickerSheet } from './componentConfigStickerSheet/StickerSheet';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ const ComponentConfigProviderCustomStory = () => {
8
+ return /*#__PURE__*/_jsx(ExampleScreen, {
9
+ children: /*#__PURE__*/_jsx(Example, {
10
+ title: "ComponentConfigProviderCustom",
11
+ children: /*#__PURE__*/_jsx(ThemeProvider, {
12
+ activeColorScheme: "dark",
13
+ theme: customTheme,
14
+ children: /*#__PURE__*/_jsx(ComponentConfigProvider, {
15
+ value: customComponentConfig,
16
+ children: /*#__PURE__*/_jsx(StickerSheet, {})
17
+ })
18
+ })
19
+ })
20
+ });
21
+ };
22
+ export default ComponentConfigProviderCustomStory;
@@ -0,0 +1,27 @@
1
+ const _excluded = ["paddingX", "gap", "title", "children"];
2
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
3
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
4
+ import { memo } from 'react';
5
+ import { VStack } from '../../../layout/VStack';
6
+ import { Text } from '../../../typography/Text';
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ export const Container = /*#__PURE__*/memo(_ref => {
9
+ let {
10
+ paddingX = 2,
11
+ gap = 2,
12
+ title,
13
+ children
14
+ } = _ref,
15
+ props = _objectWithoutPropertiesLoose(_ref, _excluded);
16
+ return /*#__PURE__*/_jsxs(VStack, _extends({
17
+ gap: gap,
18
+ maxWidth: "100%",
19
+ paddingX: paddingX
20
+ }, props, {
21
+ children: [title && /*#__PURE__*/_jsx(Text, {
22
+ font: "title3",
23
+ width: "100%",
24
+ children: title
25
+ }), children]
26
+ }));
27
+ });
@@ -0,0 +1,94 @@
1
+ import React, { memo } from 'react';
2
+ import { HStack } from '../../../layout/HStack';
3
+ import { VStack } from '../../../layout/VStack';
4
+ import { AccordionExample } from './examples/Accordion';
5
+ import { AvatarExample } from './examples/Avatar';
6
+ import { BannerExample } from './examples/Banner';
7
+ import { ButtonExample } from './examples/Button';
8
+ import { CoachmarkExample } from './examples/Coachmark';
9
+ import { ControlsExample } from './examples/Controls';
10
+ import { DatePickerExample } from './examples/DatePicker';
11
+ import { DotCountExample } from './examples/DotCount';
12
+ import { IconExample } from './examples/Icon';
13
+ import { InputChipExample } from './examples/InputChip';
14
+ import { ListCellExample } from './examples/ListCell';
15
+ import { SearchExample } from './examples/Search';
16
+ import { SegmentedTabsExample } from './examples/SegmentedTabs';
17
+ import { SelectExample } from './examples/Select';
18
+ import { SelectChipExample } from './examples/SelectChip';
19
+ import { TagExample } from './examples/Tag';
20
+ import { TextInputExample } from './examples/TextInput';
21
+ import { Container } from './Container';
22
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
23
+ export const StickerSheet = /*#__PURE__*/memo(() => {
24
+ return /*#__PURE__*/_jsx(VStack, {
25
+ alignItems: "center",
26
+ background: "bg",
27
+ gap: 2,
28
+ padding: 2,
29
+ children: /*#__PURE__*/_jsxs(HStack, {
30
+ alignItems: "flex-start",
31
+ flexWrap: "wrap",
32
+ gap: 2,
33
+ children: [/*#__PURE__*/_jsxs(VStack, {
34
+ gap: 2,
35
+ children: [/*#__PURE__*/_jsx(Container, {
36
+ title: "Switch / Checkbox / Radio",
37
+ children: /*#__PURE__*/_jsx(ControlsExample, {})
38
+ }), /*#__PURE__*/_jsx(Container, {
39
+ title: "Segmented Tabs",
40
+ children: /*#__PURE__*/_jsx(SegmentedTabsExample, {})
41
+ }), /*#__PURE__*/_jsx(Container, {
42
+ title: "Select Input (SelectOption)",
43
+ children: /*#__PURE__*/_jsx(SelectExample, {})
44
+ }), /*#__PURE__*/_jsx(Container, {
45
+ title: "SearchInput",
46
+ children: /*#__PURE__*/_jsx(SearchExample, {})
47
+ }), /*#__PURE__*/_jsx(Container, {
48
+ title: "SelectChip / InputChip",
49
+ children: /*#__PURE__*/_jsxs(HStack, {
50
+ flexWrap: "wrap",
51
+ gap: 1,
52
+ children: [/*#__PURE__*/_jsx(SelectChipExample, {}), /*#__PURE__*/_jsx(InputChipExample, {})]
53
+ })
54
+ }), /*#__PURE__*/_jsx(Container, {
55
+ title: "Accordion",
56
+ children: /*#__PURE__*/_jsx(AccordionExample, {})
57
+ }), /*#__PURE__*/_jsx(Container, {
58
+ title: "DatePicker",
59
+ children: /*#__PURE__*/_jsx(DatePickerExample, {})
60
+ })]
61
+ }), /*#__PURE__*/_jsxs(VStack, {
62
+ gap: 2,
63
+ children: [/*#__PURE__*/_jsx(Container, {
64
+ title: "Tag",
65
+ children: /*#__PURE__*/_jsx(TagExample, {})
66
+ }), /*#__PURE__*/_jsx(Container, {
67
+ title: "Icon",
68
+ children: /*#__PURE__*/_jsx(IconExample, {})
69
+ }), /*#__PURE__*/_jsx(Container, {
70
+ title: "Button / IconButton",
71
+ children: /*#__PURE__*/_jsx(ButtonExample, {})
72
+ }), /*#__PURE__*/_jsx(Container, {
73
+ title: "Avatar",
74
+ children: /*#__PURE__*/_jsx(AvatarExample, {})
75
+ }), /*#__PURE__*/_jsx(Container, {
76
+ title: "TextInput",
77
+ children: /*#__PURE__*/_jsx(TextInputExample, {})
78
+ }), /*#__PURE__*/_jsx(Container, {
79
+ title: "ListCell",
80
+ children: /*#__PURE__*/_jsx(ListCellExample, {})
81
+ }), /*#__PURE__*/_jsx(Container, {
82
+ title: "Banner",
83
+ children: /*#__PURE__*/_jsx(BannerExample, {})
84
+ }), /*#__PURE__*/_jsx(Container, {
85
+ title: "DotCount",
86
+ children: /*#__PURE__*/_jsx(DotCountExample, {})
87
+ }), /*#__PURE__*/_jsx(Container, {
88
+ title: "Coachmark",
89
+ children: /*#__PURE__*/_jsx(CoachmarkExample, {})
90
+ })]
91
+ })]
92
+ })
93
+ });
94
+ });