@ledgerhq/lumen-ui-rnative 0.1.4 → 0.1.6

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 (147) hide show
  1. package/dist/package.json +1 -1
  2. package/dist/src/lib/Components/AmountDisplay/AmountDisplay.d.ts.map +1 -1
  3. package/dist/src/lib/Components/AmountDisplay/AmountDisplay.js +5 -1
  4. package/dist/src/lib/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
  5. package/dist/src/lib/Components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  6. package/dist/src/lib/Components/SegmentedControl/SegmentedControl.js +34 -61
  7. package/dist/src/lib/Components/SegmentedControl/SegmentedControlContext.d.ts +1 -0
  8. package/dist/src/lib/Components/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
  9. package/dist/src/lib/Components/SegmentedControl/types.d.ts +12 -2
  10. package/dist/src/lib/Components/SegmentedControl/types.d.ts.map +1 -1
  11. package/dist/src/lib/Components/SegmentedControl/usePillLayout.d.ts +19 -0
  12. package/dist/src/lib/Components/SegmentedControl/usePillLayout.d.ts.map +1 -0
  13. package/dist/src/lib/Components/SegmentedControl/usePillLayout.js +46 -0
  14. package/dist/src/lib/Components/TileButton/TileButton.js +2 -2
  15. package/jest.config.ts +0 -1
  16. package/package.json +1 -1
  17. package/src/lib/Components/AmountDisplay/AmountDisplay.tsx +8 -1
  18. package/src/lib/Components/SegmentedControl/SegmentedControl.mdx +1 -38
  19. package/src/lib/Components/SegmentedControl/SegmentedControl.stories.tsx +35 -19
  20. package/src/lib/Components/SegmentedControl/SegmentedControl.tsx +61 -77
  21. package/src/lib/Components/SegmentedControl/SegmentedControlContext.tsx +1 -0
  22. package/src/lib/Components/SegmentedControl/types.ts +12 -2
  23. package/src/lib/Components/SegmentedControl/usePillLayout.ts +76 -0
  24. package/src/lib/Components/TileButton/TileButton.tsx +2 -2
  25. package/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.tsx +1 -1
  26. package/tsconfig.json +3 -16
  27. package/tsconfig.lib.json +5 -0
  28. package/dist/src/lib/Animations/Pulse/Pulse.stories.d.ts +0 -9
  29. package/dist/src/lib/Animations/Pulse/Pulse.stories.d.ts.map +0 -1
  30. package/dist/src/lib/Animations/Pulse/Pulse.stories.js +0 -38
  31. package/dist/src/lib/Animations/Spin/Spin.stories.d.ts +0 -9
  32. package/dist/src/lib/Animations/Spin/Spin.stories.d.ts.map +0 -1
  33. package/dist/src/lib/Animations/Spin/Spin.stories.js +0 -27
  34. package/dist/src/lib/Components/AddressInput/AddressInput.stories.d.ts +0 -13
  35. package/dist/src/lib/Components/AddressInput/AddressInput.stories.d.ts.map +0 -1
  36. package/dist/src/lib/Components/AddressInput/AddressInput.stories.js +0 -128
  37. package/dist/src/lib/Components/AmountDisplay/AmountDisplay.stories.d.ts +0 -10
  38. package/dist/src/lib/Components/AmountDisplay/AmountDisplay.stories.d.ts.map +0 -1
  39. package/dist/src/lib/Components/AmountDisplay/AmountDisplay.stories.js +0 -127
  40. package/dist/src/lib/Components/AmountInput/AmountInput.stories.d.ts +0 -16
  41. package/dist/src/lib/Components/AmountInput/AmountInput.stories.d.ts.map +0 -1
  42. package/dist/src/lib/Components/AmountInput/AmountInput.stories.js +0 -186
  43. package/dist/src/lib/Components/Avatar/Avatar.stories.d.ts +0 -22
  44. package/dist/src/lib/Components/Avatar/Avatar.stories.d.ts.map +0 -1
  45. package/dist/src/lib/Components/Avatar/Avatar.stories.js +0 -72
  46. package/dist/src/lib/Components/Banner/Banner.stories.d.ts +0 -16
  47. package/dist/src/lib/Components/Banner/Banner.stories.d.ts.map +0 -1
  48. package/dist/src/lib/Components/Banner/Banner.stories.js +0 -268
  49. package/dist/src/lib/Components/BottomSheet/BottomSheet.stories.d.ts +0 -87
  50. package/dist/src/lib/Components/BottomSheet/BottomSheet.stories.d.ts.map +0 -1
  51. package/dist/src/lib/Components/BottomSheet/BottomSheet.stories.js +0 -266
  52. package/dist/src/lib/Components/Button/Button.stories.d.ts +0 -16
  53. package/dist/src/lib/Components/Button/Button.stories.d.ts.map +0 -1
  54. package/dist/src/lib/Components/Button/Button.stories.js +0 -143
  55. package/dist/src/lib/Components/CardButton/CardButton.stories.d.ts +0 -16
  56. package/dist/src/lib/Components/CardButton/CardButton.stories.d.ts.map +0 -1
  57. package/dist/src/lib/Components/CardButton/CardButton.stories.js +0 -208
  58. package/dist/src/lib/Components/Checkbox/Checkbox.stories.d.ts +0 -14
  59. package/dist/src/lib/Components/Checkbox/Checkbox.stories.d.ts.map +0 -1
  60. package/dist/src/lib/Components/Checkbox/Checkbox.stories.js +0 -72
  61. package/dist/src/lib/Components/ContentBanner/ContentBanner.stories.d.ts +0 -11
  62. package/dist/src/lib/Components/ContentBanner/ContentBanner.stories.d.ts.map +0 -1
  63. package/dist/src/lib/Components/ContentBanner/ContentBanner.stories.js +0 -91
  64. package/dist/src/lib/Components/Divider/Divider.stories.d.ts +0 -9
  65. package/dist/src/lib/Components/Divider/Divider.stories.d.ts.map +0 -1
  66. package/dist/src/lib/Components/Divider/Divider.stories.js +0 -51
  67. package/dist/src/lib/Components/Icon/Icon.stories.d.ts +0 -15
  68. package/dist/src/lib/Components/Icon/Icon.stories.d.ts.map +0 -1
  69. package/dist/src/lib/Components/Icon/Icon.stories.js +0 -137
  70. package/dist/src/lib/Components/IconButton/IconButton.stories.d.ts +0 -10
  71. package/dist/src/lib/Components/IconButton/IconButton.stories.d.ts.map +0 -1
  72. package/dist/src/lib/Components/IconButton/IconButton.stories.js +0 -74
  73. package/dist/src/lib/Components/InteractiveIcon/InteractiveIcon.stories.d.ts +0 -11
  74. package/dist/src/lib/Components/InteractiveIcon/InteractiveIcon.stories.d.ts.map +0 -1
  75. package/dist/src/lib/Components/InteractiveIcon/InteractiveIcon.stories.js +0 -90
  76. package/dist/src/lib/Components/Link/Link.stories.d.ts +0 -17
  77. package/dist/src/lib/Components/Link/Link.stories.d.ts.map +0 -1
  78. package/dist/src/lib/Components/Link/Link.stories.js +0 -275
  79. package/dist/src/lib/Components/ListItem/ListItem.stories.d.ts +0 -10
  80. package/dist/src/lib/Components/ListItem/ListItem.stories.d.ts.map +0 -1
  81. package/dist/src/lib/Components/ListItem/ListItem.stories.js +0 -106
  82. package/dist/src/lib/Components/NavBar/NavBar.stories.d.ts +0 -10
  83. package/dist/src/lib/Components/NavBar/NavBar.stories.d.ts.map +0 -1
  84. package/dist/src/lib/Components/NavBar/NavBar.stories.js +0 -72
  85. package/dist/src/lib/Components/PageIndicator/PageIndicator.stories.d.ts +0 -27
  86. package/dist/src/lib/Components/PageIndicator/PageIndicator.stories.d.ts.map +0 -1
  87. package/dist/src/lib/Components/PageIndicator/PageIndicator.stories.js +0 -42
  88. package/dist/src/lib/Components/SearchInput/SearchInput.stories.d.ts +0 -12
  89. package/dist/src/lib/Components/SearchInput/SearchInput.stories.d.ts.map +0 -1
  90. package/dist/src/lib/Components/SearchInput/SearchInput.stories.js +0 -98
  91. package/dist/src/lib/Components/SegmentedControl/SegmentedControl.stories.d.ts +0 -58
  92. package/dist/src/lib/Components/SegmentedControl/SegmentedControl.stories.d.ts.map +0 -1
  93. package/dist/src/lib/Components/SegmentedControl/SegmentedControl.stories.js +0 -61
  94. package/dist/src/lib/Components/Select/Select.stories.d.ts +0 -11
  95. package/dist/src/lib/Components/Select/Select.stories.d.ts.map +0 -1
  96. package/dist/src/lib/Components/Select/Select.stories.js +0 -83
  97. package/dist/src/lib/Components/Skeleton/Skeleton.stories.d.ts +0 -11
  98. package/dist/src/lib/Components/Skeleton/Skeleton.stories.d.ts.map +0 -1
  99. package/dist/src/lib/Components/Skeleton/Skeleton.stories.js +0 -49
  100. package/dist/src/lib/Components/Spinner/Spinner.stories.d.ts +0 -9
  101. package/dist/src/lib/Components/Spinner/Spinner.stories.d.ts.map +0 -1
  102. package/dist/src/lib/Components/Spinner/Spinner.stories.js +0 -50
  103. package/dist/src/lib/Components/Spot/Spot.stories.d.ts +0 -12
  104. package/dist/src/lib/Components/Spot/Spot.stories.d.ts.map +0 -1
  105. package/dist/src/lib/Components/Spot/Spot.stories.js +0 -156
  106. package/dist/src/lib/Components/Stepper/Stepper.stories.d.ts +0 -9
  107. package/dist/src/lib/Components/Stepper/Stepper.stories.d.ts.map +0 -1
  108. package/dist/src/lib/Components/Stepper/Stepper.stories.js +0 -35
  109. package/dist/src/lib/Components/Subheader/Subheader.stories.d.ts +0 -10
  110. package/dist/src/lib/Components/Subheader/Subheader.stories.d.ts.map +0 -1
  111. package/dist/src/lib/Components/Subheader/Subheader.stories.js +0 -34
  112. package/dist/src/lib/Components/Switch/Switch.stories.d.ts +0 -14
  113. package/dist/src/lib/Components/Switch/Switch.stories.d.ts.map +0 -1
  114. package/dist/src/lib/Components/Switch/Switch.stories.js +0 -65
  115. package/dist/src/lib/Components/TabBar/TabBar.stories.d.ts +0 -50
  116. package/dist/src/lib/Components/TabBar/TabBar.stories.d.ts.map +0 -1
  117. package/dist/src/lib/Components/TabBar/TabBar.stories.js +0 -60
  118. package/dist/src/lib/Components/Tag/Tag.stories.d.ts +0 -10
  119. package/dist/src/lib/Components/Tag/Tag.stories.d.ts.map +0 -1
  120. package/dist/src/lib/Components/Tag/Tag.stories.js +0 -45
  121. package/dist/src/lib/Components/TextInput/TextInput.stories.d.ts +0 -14
  122. package/dist/src/lib/Components/TextInput/TextInput.stories.d.ts.map +0 -1
  123. package/dist/src/lib/Components/TextInput/TextInput.stories.js +0 -128
  124. package/dist/src/lib/Components/Tile/Tile.stories.d.ts +0 -14
  125. package/dist/src/lib/Components/Tile/Tile.stories.d.ts.map +0 -1
  126. package/dist/src/lib/Components/Tile/Tile.stories.js +0 -117
  127. package/dist/src/lib/Components/TileButton/TileButton.stories.d.ts +0 -12
  128. package/dist/src/lib/Components/TileButton/TileButton.stories.d.ts.map +0 -1
  129. package/dist/src/lib/Components/TileButton/TileButton.stories.js +0 -63
  130. package/dist/src/lib/Components/Tooltip/Tooltip.stories.d.ts +0 -10
  131. package/dist/src/lib/Components/Tooltip/Tooltip.stories.d.ts.map +0 -1
  132. package/dist/src/lib/Components/Tooltip/Tooltip.stories.js +0 -50
  133. package/dist/src/lib/Components/Utility/Box/Box.stories.d.ts +0 -7
  134. package/dist/src/lib/Components/Utility/Box/Box.stories.d.ts.map +0 -1
  135. package/dist/src/lib/Components/Utility/Box/Box.stories.js +0 -42
  136. package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.d.ts +0 -11
  137. package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.d.ts.map +0 -1
  138. package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.js +0 -105
  139. package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.d.ts +0 -10
  140. package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.d.ts.map +0 -1
  141. package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.js +0 -101
  142. package/dist/src/lib/Components/Utility/Pressable/Pressable.stories.d.ts +0 -7
  143. package/dist/src/lib/Components/Utility/Pressable/Pressable.stories.d.ts.map +0 -1
  144. package/dist/src/lib/Components/Utility/Pressable/Pressable.stories.js +0 -47
  145. package/dist/src/lib/Components/Utility/Text/Text.stories.d.ts +0 -7
  146. package/dist/src/lib/Components/Utility/Text/Text.stories.d.ts.map +0 -1
  147. package/dist/src/lib/Components/Utility/Text/Text.stories.js +0 -33
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/lumen-ui-rnative",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "license": "Apache-2.0",
5
5
  "keywords": [
6
6
  "react-native",
@@ -1 +1 @@
1
- {"version":3,"file":"AmountDisplay.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/AmountDisplay/AmountDisplay.tsx"],"names":[],"mappings":"AAaA,OAAO,EACL,kBAAkB,EAInB,MAAM,SAAS,CAAC;AA6IjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,aAAa;+DAOvB,kBAAkB;;CA8DpB,CAAC"}
1
+ {"version":3,"file":"AmountDisplay.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/AmountDisplay/AmountDisplay.tsx"],"names":[],"mappings":"AAcA,OAAO,EACL,kBAAkB,EAInB,MAAM,SAAS,CAAC;AAmJjB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,aAAa;+DAOvB,kBAAkB;;CA8DpB,CAAC"}
@@ -6,6 +6,7 @@ import Animated, { Easing, useAnimatedStyle, useSharedValue, withTiming, } from
6
6
  import { useCommonTranslation } from '../../../i18n';
7
7
  import { useStyleSheet } from '../../../styles';
8
8
  import { Pulse } from '../../Animations/Pulse';
9
+ import { RuntimeConstants } from '../../utils';
9
10
  import { Box } from '../Utility';
10
11
  import { DIGITS, } from './types';
11
12
  const INTEGER_DIGIT_WIDTHS = {
@@ -91,7 +92,10 @@ const DigitStrip = memo(({ value, textStyle, animate, type }) => {
91
92
  const animatedStyle = useAnimatedStyle(() => ({
92
93
  transform: [{ translateY: translateY.value }],
93
94
  }), [translateY]);
94
- return (_jsx(Animated.View, { style: { height: lineHeight, overflow: 'hidden', width: width }, accessibilityValue: { text: String(value) }, children: _jsx(Animated.View, { style: [animatedStyle, { alignItems: 'center' }], children: DIGITS.map((d) => (_jsx(Text, { style: textStyle, children: d }, d))) }) }));
95
+ return (_jsx(Animated.View, { style: { height: lineHeight, overflow: 'hidden', width: width }, accessibilityValue: { text: String(value) }, children: _jsx(Animated.View, { style: [animatedStyle, { alignItems: 'center' }], children: DIGITS.map((d) => (_jsx(Text, { style: [
96
+ textStyle,
97
+ RuntimeConstants.isAndroid && { height: lineHeight },
98
+ ], children: d }, d))) }) }));
95
99
  });
96
100
  const DigitStripList = memo(({ items, textStyle, animate, type }) => {
97
101
  return items.map((item, index) => {
@@ -3,7 +3,7 @@ export declare function SegmentedControlButton({ value, children, icon: Icon, on
3
3
  export declare namespace SegmentedControlButton {
4
4
  var displayName: string;
5
5
  }
6
- export declare function SegmentedControl({ selectedValue, onSelectedChange, accessibilityLabel, children, ...props }: SegmentedControlProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function SegmentedControl({ selectedValue, onSelectedChange, accessibilityLabel, children, disabled, appearance, ...props }: SegmentedControlProps): import("react/jsx-runtime").JSX.Element;
7
7
  export declare namespace SegmentedControl {
8
8
  var displayName: string;
9
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControl.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/SegmentedControl/SegmentedControl.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,2BAA2B,EAC3B,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAIjB,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,QAAQ,EACR,IAAI,EAAE,IAAI,EACV,OAAO,EACP,GAAG,KAAK,EACT,EAAE,2BAA2B,2CAkC7B;yBAxCe,sBAAsB;;;AA4EtC,wBAAgB,gBAAgB,CAAC,EAC/B,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,qBAAqB,2CAwEvB;yBA9Ee,gBAAgB"}
1
+ {"version":3,"file":"SegmentedControl.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/SegmentedControl/SegmentedControl.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,2BAA2B,EAC3B,qBAAqB,EACtB,MAAM,SAAS,CAAC;AAMjB,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,QAAQ,EACR,IAAI,EAAE,IAAI,EACV,OAAO,EACP,GAAG,KAAK,EACT,EAAE,2BAA2B,2CAqC7B;yBA3Ce,sBAAsB;;;AA2FtC,wBAAgB,gBAAgB,CAAC,EAC/B,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,QAAQ,EACR,QAAQ,EACR,UAAyB,EACzB,GAAG,KAAK,EACT,EAAE,qBAAqB,2CAkCvB;yBA1Ce,gBAAgB"}
@@ -1,24 +1,24 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useCallback, useEffect, useRef } from 'react';
3
- import Animated, { useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated';
2
+ import Animated from 'react-native-reanimated';
4
3
  import { useStyleSheet } from '../../../styles';
5
- import { durations, easingCurves } from '../../Animations/constants';
6
4
  import { Box, Pressable, Text } from '../Utility';
7
5
  import { SegmentedControlContextProvider, useSegmentedControlContext, } from './SegmentedControlContext';
8
- const ICON_SIZE = 16;
6
+ import { usePillLayout, useSegmentedControlSelectedIndex, } from './usePillLayout';
9
7
  export function SegmentedControlButton({ value, children, icon: Icon, onPress, ...props }) {
10
- const styles = useButtonStyles();
11
- const { selectedValue, onSelectedChange } = useSegmentedControlContext();
8
+ const { selectedValue, onSelectedChange, disabled } = useSegmentedControlContext();
12
9
  const selected = selectedValue === value;
10
+ const styles = useButtonStyles({ selected, disabled });
13
11
  function handlePress() {
14
- onSelectedChange(value);
15
- onPress?.();
12
+ if (!disabled) {
13
+ onSelectedChange(value);
14
+ onPress?.();
15
+ }
16
16
  }
17
- return (_jsx(Pressable, { onPress: handlePress, accessibilityState: { selected }, style: styles.button, ...props, children: _jsxs(Box, { style: styles.content, children: [Icon && (_jsx(Box, { style: styles.iconWrap, children: _jsx(Icon, { size: ICON_SIZE }) })), _jsx(Text, { typography: selected ? 'body2SemiBold' : 'body2', lx: { color: 'base' }, style: styles.label, children: children })] }) }));
17
+ return (_jsx(Pressable, { onPress: handlePress, disabled: disabled, accessibilityState: { selected, disabled }, style: styles.button, ...props, children: _jsxs(Box, { style: styles.content, children: [Icon && (_jsx(Box, { style: styles.iconWrap, children: _jsx(Icon, { size: 16, color: styles.textColor }) })), _jsx(Text, { typography: styles.typography, lx: { color: styles.textColor }, style: styles.label, children: children })] }) }));
18
18
  }
19
19
  SegmentedControlButton.displayName = 'SegmentedControlButton';
20
- function useButtonStyles() {
21
- return useStyleSheet((t) => ({
20
+ function useButtonStyles({ selected, disabled, }) {
21
+ const styles = useStyleSheet((t) => ({
22
22
  button: {
23
23
  flex: 1,
24
24
  flexDirection: 'row',
@@ -44,71 +44,44 @@ function useButtonStyles() {
44
44
  alignItems: 'center',
45
45
  },
46
46
  }), []);
47
+ const typography = selected
48
+ ? 'body2SemiBold'
49
+ : 'body2';
50
+ const textColor = selected && !disabled ? 'base' : 'muted';
51
+ return { ...styles, typography, textColor };
47
52
  }
48
- export function SegmentedControl({ selectedValue, onSelectedChange, accessibilityLabel, children, ...props }) {
49
- const styles = useRootStyles();
50
- const pillTranslateX = useSharedValue(0);
51
- const pillWidth = useSharedValue(0);
52
- const pillHeight = useSharedValue(0);
53
- const hasLayoutRef = useRef(false);
54
- const getSelectedIndex = useCallback(() => {
55
- return React.Children.toArray(children).findIndex((child) => {
56
- if (React.isValidElement(child) && child.props != null) {
57
- return child.props.value === selectedValue;
58
- }
59
- return false;
60
- });
61
- }, [selectedValue, children]);
62
- function onLayout(e) {
63
- const { width, height } = e.nativeEvent.layout;
64
- const count = React.Children.count(children);
65
- const slotWidth = count > 0 ? width / count : 0;
66
- pillWidth.value = slotWidth;
67
- pillHeight.value = height;
68
- if (!hasLayoutRef.current) {
69
- hasLayoutRef.current = true;
70
- const index = getSelectedIndex();
71
- if (index >= 0) {
72
- pillTranslateX.value = index * slotWidth;
73
- }
74
- }
75
- }
76
- useEffect(() => {
77
- if (!hasLayoutRef.current)
78
- return;
79
- const index = getSelectedIndex();
80
- if (index >= 0 && pillWidth.value > 0) {
81
- pillTranslateX.value = withTiming(index * pillWidth.value, {
82
- duration: durations['250'],
83
- easing: easingCurves.bezier.default,
84
- });
85
- }
86
- }, [pillWidth, pillTranslateX, getSelectedIndex]);
87
- const animatedPillStyle = useAnimatedStyle(() => ({
88
- transform: [{ translateX: pillTranslateX.value }],
89
- width: pillWidth.value,
90
- height: pillHeight.value,
91
- }), [pillTranslateX, pillWidth, pillHeight]);
92
- return (_jsx(SegmentedControlContextProvider, { value: { selectedValue, onSelectedChange }, children: _jsxs(Box, { accessibilityRole: 'radiogroup', accessibilityLabel: accessibilityLabel, onLayout: onLayout, style: styles.container, ...props, children: [children, _jsx(Animated.View, { style: [styles.pill, animatedPillStyle], pointerEvents: 'none' })] }) }));
53
+ export function SegmentedControl({ selectedValue, onSelectedChange, accessibilityLabel, children, disabled, appearance = 'background', ...props }) {
54
+ const styles = useRootStyles({
55
+ disabled: Boolean(disabled),
56
+ appearance,
57
+ });
58
+ const selectedIndex = useSegmentedControlSelectedIndex(selectedValue, children);
59
+ const { onLayout, animatedPillStyle } = usePillLayout({
60
+ selectedIndex,
61
+ children,
62
+ });
63
+ return (_jsx(SegmentedControlContextProvider, { value: { selectedValue, onSelectedChange, disabled }, children: _jsxs(Box, { accessibilityRole: 'radiogroup', accessibilityLabel: accessibilityLabel, accessibilityState: { disabled }, onLayout: onLayout, style: styles.container, ...props, children: [children, _jsx(Animated.View, { style: [styles.pill, animatedPillStyle], pointerEvents: 'none' })] }) }));
93
64
  }
94
65
  SegmentedControl.displayName = 'SegmentedControl';
95
- function useRootStyles() {
66
+ function useRootStyles({ disabled, appearance, }) {
96
67
  return useStyleSheet((t) => ({
97
68
  container: {
98
69
  flexDirection: 'row',
99
70
  alignItems: 'center',
100
71
  position: 'relative',
101
72
  width: '100%',
102
- borderRadius: t.borderRadius.full,
103
- backgroundColor: t.colors.bg.baseTransparent,
73
+ borderRadius: t.borderRadius.md,
74
+ backgroundColor: appearance === 'background' ? t.colors.bg.surface : 'transparent',
104
75
  },
105
76
  pill: {
106
77
  position: 'absolute',
107
78
  top: 0,
108
79
  left: 0,
109
80
  borderRadius: t.borderRadius.sm,
110
- backgroundColor: t.colors.bg.muted,
81
+ backgroundColor: disabled
82
+ ? t.colors.bg.baseTransparentPressed
83
+ : t.colors.bg.mutedTransparent,
111
84
  zIndex: 0,
112
85
  },
113
- }), []);
86
+ }), [disabled, appearance]);
114
87
  }
@@ -1,6 +1,7 @@
1
1
  export type SegmentedControlContextValue = {
2
2
  selectedValue: string;
3
3
  onSelectedChange: (value: string) => void;
4
+ disabled?: boolean;
4
5
  };
5
6
  declare const SegmentedControlContextProvider: import("react").FC<{
6
7
  children: import("react").ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"SegmentedControlContext.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/SegmentedControl/SegmentedControlContext.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,4BAA4B,GAAG;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEF,QAAA,MAAO,+BAA+B;;;EAC+B,CAAC;AAEtE,eAAO,MAAM,0BAA0B,oCAInC,CAAC;AAEL,OAAO,EAAE,+BAA+B,EAAE,CAAC"}
1
+ {"version":3,"file":"SegmentedControlContext.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/SegmentedControl/SegmentedControlContext.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,4BAA4B,GAAG;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,QAAA,MAAO,+BAA+B;;;EAC+B,CAAC;AAEtE,eAAO,MAAM,0BAA0B,oCAInC,CAAC;AAEL,OAAO,EAAE,+BAA+B,EAAE,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { ComponentType, ReactNode } from 'react';
2
- import { StyledPressableProps } from '../../../styles';
2
+ import { LumenTextStyle, StyledPressableProps } from '../../../styles';
3
3
  import { IconSize } from '../Icon';
4
4
  import { BoxProps } from '../Utility';
5
5
  export type SegmentedControlProps = {
@@ -11,17 +11,27 @@ export type SegmentedControlProps = {
11
11
  * Callback when the selected segment value changes.
12
12
  */
13
13
  onSelectedChange: (value: string) => void;
14
+ /**
15
+ * When true, the entire control is disabled (no interaction, selected uses muted styling).
16
+ */
17
+ disabled?: boolean;
18
+ /**
19
+ * Visual style of the control container: "background" shows the surface bg, "no-background" is transparent.
20
+ * @default 'background'
21
+ */
22
+ appearance?: 'background' | 'no-background';
14
23
  /**
15
24
  * Accessible label for the control (e.g. "File view").
16
25
  */
17
26
  accessibilityLabel?: string;
18
27
  /**
19
- * Segment buttons (SegmentedControlButton). Can be wrapped (e.g. in Tooltip).
28
+ * Segment buttons (SegmentedControlButton).
20
29
  */
21
30
  children: ReactNode;
22
31
  } & Omit<BoxProps, 'children'>;
23
32
  type IconComponent = ComponentType<{
24
33
  size?: IconSize;
34
+ color?: LumenTextStyle['color'];
25
35
  }>;
26
36
  export type SegmentedControlButtonProps = {
27
37
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/SegmentedControl/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AAE/B,KAAK,aAAa,GAAG,aAAa,CAAC;IACjC,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB,CAAC,CAAC;AAEH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,GAAG,IAAI,CAAC,oBAAoB,EAAE,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/SegmentedControl/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,MAAM,qBAAqB,GAAG;IAClC;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,YAAY,GAAG,eAAe,CAAC;IAC5C;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB,GAAG,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AAE/B,KAAK,aAAa,GAAG,aAAa,CAAC;IACjC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IACpB;;OAEG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,GAAG,IAAI,CAAC,oBAAoB,EAAE,UAAU,CAAC,CAAC"}
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { LayoutChangeEvent } from 'react-native';
3
+ export declare function useSegmentedControlSelectedIndex(selectedValue: string, children: React.ReactNode): number;
4
+ type UsePillLayoutParams = {
5
+ selectedIndex: number;
6
+ children: React.ReactNode;
7
+ };
8
+ export declare function usePillLayout({ selectedIndex, children, }: UsePillLayoutParams): {
9
+ onLayout: (e: LayoutChangeEvent) => void;
10
+ animatedPillStyle: {
11
+ transform: {
12
+ translateX: number;
13
+ }[];
14
+ width: number;
15
+ height: number;
16
+ };
17
+ };
18
+ export {};
19
+ //# sourceMappingURL=usePillLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePillLayout.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/SegmentedControl/usePillLayout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAQjD,wBAAgB,gCAAgC,CAC9C,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,KAAK,CAAC,SAAS,GACxB,MAAM,CAWR;AAED,KAAK,mBAAmB,GAAG;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAC5B,aAAa,EACb,QAAQ,GACT,EAAE,mBAAmB;kBAMC,iBAAiB,KAAG,IAAI;;;;;;;;EAoC9C"}
@@ -0,0 +1,46 @@
1
+ import React, { useEffect, useMemo, useRef } from 'react';
2
+ import { useAnimatedStyle, useSharedValue, withTiming, } from 'react-native-reanimated';
3
+ import { durations, easingCurves } from '../../Animations/constants';
4
+ export function useSegmentedControlSelectedIndex(selectedValue, children) {
5
+ return useMemo(() => React.Children.toArray(children).findIndex((child) => {
6
+ if (React.isValidElement(child) && child.props != null) {
7
+ return child.props.value === selectedValue;
8
+ }
9
+ return false;
10
+ }), [selectedValue, children]);
11
+ }
12
+ export function usePillLayout({ selectedIndex, children, }) {
13
+ const pillTranslateX = useSharedValue(0);
14
+ const pillWidth = useSharedValue(0);
15
+ const pillHeight = useSharedValue(0);
16
+ const hasLayoutRef = useRef(false);
17
+ const onLayout = (e) => {
18
+ const { width, height } = e.nativeEvent.layout;
19
+ const count = React.Children.count(children);
20
+ const slotWidth = count > 0 ? width / count : 0;
21
+ pillWidth.value = slotWidth;
22
+ pillHeight.value = height;
23
+ if (!hasLayoutRef.current) {
24
+ hasLayoutRef.current = true;
25
+ if (selectedIndex >= 0) {
26
+ pillTranslateX.value = selectedIndex * slotWidth;
27
+ }
28
+ }
29
+ };
30
+ useEffect(() => {
31
+ if (!hasLayoutRef.current)
32
+ return;
33
+ if (selectedIndex >= 0 && pillWidth.value > 0) {
34
+ pillTranslateX.value = withTiming(selectedIndex * pillWidth.value, {
35
+ duration: durations['250'],
36
+ easing: easingCurves.bezier.default,
37
+ });
38
+ }
39
+ }, [selectedIndex, pillWidth, pillTranslateX]);
40
+ const animatedPillStyle = useAnimatedStyle(() => ({
41
+ transform: [{ translateX: pillTranslateX.value }],
42
+ width: pillWidth.value,
43
+ height: pillHeight.value,
44
+ }), [pillTranslateX, pillWidth, pillHeight]);
45
+ return { onLayout, animatedPillStyle };
46
+ }
@@ -21,10 +21,10 @@ const useStyles = ({ disabled, pressed, isFull, }) => {
21
21
  gap: t.spacings.s8,
22
22
  padding: t.spacings.s12,
23
23
  borderRadius: t.borderRadius.md,
24
- backgroundColor: t.colors.bg.muted,
24
+ backgroundColor: t.colors.bg.surface,
25
25
  },
26
26
  isFull && { width: t.sizes.full },
27
- pressed && !disabled && { backgroundColor: t.colors.bg.mutedPressed },
27
+ pressed && !disabled && { backgroundColor: t.colors.bg.surfacePressed },
28
28
  disabled && { backgroundColor: t.colors.bg.disabled },
29
29
  ]),
30
30
  label: StyleSheet.flatten([
package/jest.config.ts CHANGED
@@ -13,7 +13,6 @@ export default {
13
13
  displayName: '@ledgerhq/lumen-ui-rnative',
14
14
  preset: 'react-native',
15
15
  setupFiles: ['<rootDir>/jest.setup.ts'],
16
- setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'],
17
16
  transformIgnorePatterns: [
18
17
  `node_modules/(?!(.pnpm|${transformIncludePatterns.join('|')})/)`,
19
18
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/lumen-ui-rnative",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "license": "Apache-2.0",
5
5
  "keywords": [
6
6
  "react-native",
@@ -10,6 +10,7 @@ import Animated, {
10
10
  import { useCommonTranslation } from '../../../i18n';
11
11
  import { useStyleSheet } from '../../../styles';
12
12
  import { Pulse } from '../../Animations/Pulse';
13
+ import { RuntimeConstants } from '../../utils';
13
14
  import { Box } from '../Utility';
14
15
  import {
15
16
  AmountDisplayProps,
@@ -123,7 +124,13 @@ const DigitStrip = memo(
123
124
  >
124
125
  <Animated.View style={[animatedStyle, { alignItems: 'center' }]}>
125
126
  {DIGITS.map((d) => (
126
- <Text key={d} style={textStyle}>
127
+ <Text
128
+ key={d}
129
+ style={[
130
+ textStyle,
131
+ RuntimeConstants.isAndroid && { height: lineHeight },
132
+ ]}
133
+ >
127
134
  {d}
128
135
  </Text>
129
136
  ))}
@@ -25,6 +25,7 @@ SegmentedControl is a tab bar–style component for switching between mutually e
25
25
  - **Segments**: Individual options the user can select.
26
26
  - **Selected state**: The active segment (sliding pill + semi-bold label).
27
27
  - **Optional icon**: Icon to the left of the label (from Symbols).
28
+ - **Appearance**: Use `appearance="background"` (default) for a surface background, or `appearance="no-background"` for a transparent container.
28
29
 
29
30
  ## Properties
30
31
 
@@ -55,44 +56,6 @@ SegmentedControl lays out segments in a horizontal row with equal width per segm
55
56
 
56
57
  Use the library as part of `@ledgerhq/lumen-ui-rnative`. See the [Setup Guide →](?path=/docs/getting-started-setup--docs).
57
58
 
58
- ## SegmentedControlButton
59
-
60
- Use as a direct child of SegmentedControl (or inside wrappers such as Tooltip). Required: value (string) and children (label). Optional: icon (component from symbols), onPress (runs in addition to parent onSelectedChange).
61
-
62
- <div className='my-24 overflow-hidden rounded-lg'>
63
- <table className='w-full'>
64
- <thead>
65
- <tr className='border-b border-muted bg-muted'>
66
- <th className='p-12 text-left text-on-accent body-2'>Prop</th>
67
- <th className='p-12 text-left text-on-accent body-2'>Type</th>
68
- <th className='p-12 text-left text-on-accent body-2'>Description</th>
69
- </tr>
70
- </thead>
71
- <tbody className='bg-canvas'>
72
- <tr className='border-b border-muted'>
73
- <td className='text-accent p-12'>value</td>
74
- <td className='p-12 text-muted'>string</td>
75
- <td className='p-12 text-muted'>Unique value for this segment (e.g. "send", "receive")</td>
76
- </tr>
77
- <tr className='border-b border-muted'>
78
- <td className='text-accent p-12'>children</td>
79
- <td className='p-12 text-muted'>ReactNode</td>
80
- <td className='p-12 text-muted'>Button label (e.g. "Send", "Tokens")</td>
81
- </tr>
82
- <tr className='border-b border-muted'>
83
- <td className='text-accent p-12'>icon</td>
84
- <td className='p-12 text-muted'>ComponentType</td>
85
- <td className='p-12 text-muted'>Optional icon to the left of the label (from Symbols)</td>
86
- </tr>
87
- <tr>
88
- <td className='text-accent p-12'>onPress</td>
89
- <td className='p-12 text-muted'>() =&gt; void</td>
90
- <td className='p-12 text-muted'>Optional callback when the button is pressed (in addition to parent onSelectedChange)</td>
91
- </tr>
92
- </tbody>
93
- </table>
94
- </div>
95
-
96
59
  ## Basic Usage
97
60
 
98
61
  Control selected value in state at the top level and pass it to SegmentedControl. Buttons use value to identify themselves; selected state is derived from context.
@@ -17,34 +17,27 @@ const meta = {
17
17
  argTypes: {
18
18
  onSelectedChange: {
19
19
  action: 'change',
20
- description: 'Callback when the selected value changes',
21
- table: {
22
- type: { summary: '(value: string) => void' },
23
- },
20
+ },
21
+ disabled: {
22
+ control: 'boolean',
23
+ },
24
+ appearance: {
25
+ options: ['background', 'no-background'],
26
+ control: 'radio',
24
27
  },
25
28
  accessibilityLabel: {
26
29
  control: 'text',
27
- description: 'Accessible label for the control',
28
- table: {
29
- type: { summary: 'string' },
30
- },
31
30
  },
32
31
  selectedValue: {
33
32
  control: 'text',
34
- description:
35
- 'The value of the currently selected segment (drives the sliding pill)',
36
- table: {
37
- type: { summary: 'string' },
38
- },
39
33
  },
40
34
  children: {
41
35
  control: false,
42
- description: 'SegmentedControlButton elements',
43
- table: {
44
- type: { summary: 'ReactNode' },
45
- },
46
36
  },
47
37
  },
38
+ args: {
39
+ appearance: 'background',
40
+ },
48
41
  } satisfies Meta<typeof SegmentedControl>;
49
42
 
50
43
  export default meta;
@@ -52,12 +45,13 @@ type Story = StoryObj<typeof meta>;
52
45
 
53
46
  export const Base: Story = {
54
47
  args: {} as React.ComponentProps<typeof SegmentedControl>,
55
- render: () => {
48
+ render: (args) => {
56
49
  const [state, setState] = useState('send');
57
50
 
58
51
  return (
59
52
  <Box lx={{ width: 's256' }}>
60
53
  <SegmentedControl
54
+ {...args}
61
55
  selectedValue={state}
62
56
  onSelectedChange={setState}
63
57
  accessibilityLabel='Transaction type'
@@ -75,11 +69,12 @@ export const Base: Story = {
75
69
 
76
70
  export const WithIcons: Story = {
77
71
  args: {} as React.ComponentProps<typeof SegmentedControl>,
78
- render: () => {
72
+ render: (args) => {
79
73
  const [state, setState] = useState('tokens');
80
74
 
81
75
  return (
82
76
  <SegmentedControl
77
+ {...args}
83
78
  selectedValue={state}
84
79
  onSelectedChange={setState}
85
80
  accessibilityLabel='Asset section'
@@ -100,3 +95,24 @@ export const WithIcons: Story = {
100
95
  );
101
96
  },
102
97
  };
98
+
99
+ export const Disabled: Story = {
100
+ args: {} as React.ComponentProps<typeof SegmentedControl>,
101
+ render: (args) => (
102
+ <Box lx={{ width: 's256' }}>
103
+ <SegmentedControl
104
+ {...args}
105
+ selectedValue='receive'
106
+ onSelectedChange={() => {
107
+ /* empty */
108
+ }}
109
+ accessibilityLabel='Transaction type (disabled)'
110
+ disabled
111
+ >
112
+ <SegmentedControlButton value='send'>Send</SegmentedControlButton>
113
+ <SegmentedControlButton value='receive'>Receive</SegmentedControlButton>
114
+ <SegmentedControlButton value='buy'>Buy</SegmentedControlButton>
115
+ </SegmentedControl>
116
+ </Box>
117
+ ),
118
+ };