@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.
- package/dist/package.json +1 -1
- package/dist/src/lib/Components/AmountDisplay/AmountDisplay.d.ts.map +1 -1
- package/dist/src/lib/Components/AmountDisplay/AmountDisplay.js +5 -1
- package/dist/src/lib/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/src/lib/Components/SegmentedControl/SegmentedControl.d.ts.map +1 -1
- package/dist/src/lib/Components/SegmentedControl/SegmentedControl.js +34 -61
- package/dist/src/lib/Components/SegmentedControl/SegmentedControlContext.d.ts +1 -0
- package/dist/src/lib/Components/SegmentedControl/SegmentedControlContext.d.ts.map +1 -1
- package/dist/src/lib/Components/SegmentedControl/types.d.ts +12 -2
- package/dist/src/lib/Components/SegmentedControl/types.d.ts.map +1 -1
- package/dist/src/lib/Components/SegmentedControl/usePillLayout.d.ts +19 -0
- package/dist/src/lib/Components/SegmentedControl/usePillLayout.d.ts.map +1 -0
- package/dist/src/lib/Components/SegmentedControl/usePillLayout.js +46 -0
- package/dist/src/lib/Components/TileButton/TileButton.js +2 -2
- package/jest.config.ts +0 -1
- package/package.json +1 -1
- package/src/lib/Components/AmountDisplay/AmountDisplay.tsx +8 -1
- package/src/lib/Components/SegmentedControl/SegmentedControl.mdx +1 -38
- package/src/lib/Components/SegmentedControl/SegmentedControl.stories.tsx +35 -19
- package/src/lib/Components/SegmentedControl/SegmentedControl.tsx +61 -77
- package/src/lib/Components/SegmentedControl/SegmentedControlContext.tsx +1 -0
- package/src/lib/Components/SegmentedControl/types.ts +12 -2
- package/src/lib/Components/SegmentedControl/usePillLayout.ts +76 -0
- package/src/lib/Components/TileButton/TileButton.tsx +2 -2
- package/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.tsx +1 -1
- package/tsconfig.json +3 -16
- package/tsconfig.lib.json +5 -0
- package/dist/src/lib/Animations/Pulse/Pulse.stories.d.ts +0 -9
- package/dist/src/lib/Animations/Pulse/Pulse.stories.d.ts.map +0 -1
- package/dist/src/lib/Animations/Pulse/Pulse.stories.js +0 -38
- package/dist/src/lib/Animations/Spin/Spin.stories.d.ts +0 -9
- package/dist/src/lib/Animations/Spin/Spin.stories.d.ts.map +0 -1
- package/dist/src/lib/Animations/Spin/Spin.stories.js +0 -27
- package/dist/src/lib/Components/AddressInput/AddressInput.stories.d.ts +0 -13
- package/dist/src/lib/Components/AddressInput/AddressInput.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/AddressInput/AddressInput.stories.js +0 -128
- package/dist/src/lib/Components/AmountDisplay/AmountDisplay.stories.d.ts +0 -10
- package/dist/src/lib/Components/AmountDisplay/AmountDisplay.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/AmountDisplay/AmountDisplay.stories.js +0 -127
- package/dist/src/lib/Components/AmountInput/AmountInput.stories.d.ts +0 -16
- package/dist/src/lib/Components/AmountInput/AmountInput.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/AmountInput/AmountInput.stories.js +0 -186
- package/dist/src/lib/Components/Avatar/Avatar.stories.d.ts +0 -22
- package/dist/src/lib/Components/Avatar/Avatar.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Avatar/Avatar.stories.js +0 -72
- package/dist/src/lib/Components/Banner/Banner.stories.d.ts +0 -16
- package/dist/src/lib/Components/Banner/Banner.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Banner/Banner.stories.js +0 -268
- package/dist/src/lib/Components/BottomSheet/BottomSheet.stories.d.ts +0 -87
- package/dist/src/lib/Components/BottomSheet/BottomSheet.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/BottomSheet/BottomSheet.stories.js +0 -266
- package/dist/src/lib/Components/Button/Button.stories.d.ts +0 -16
- package/dist/src/lib/Components/Button/Button.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Button/Button.stories.js +0 -143
- package/dist/src/lib/Components/CardButton/CardButton.stories.d.ts +0 -16
- package/dist/src/lib/Components/CardButton/CardButton.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/CardButton/CardButton.stories.js +0 -208
- package/dist/src/lib/Components/Checkbox/Checkbox.stories.d.ts +0 -14
- package/dist/src/lib/Components/Checkbox/Checkbox.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Checkbox/Checkbox.stories.js +0 -72
- package/dist/src/lib/Components/ContentBanner/ContentBanner.stories.d.ts +0 -11
- package/dist/src/lib/Components/ContentBanner/ContentBanner.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/ContentBanner/ContentBanner.stories.js +0 -91
- package/dist/src/lib/Components/Divider/Divider.stories.d.ts +0 -9
- package/dist/src/lib/Components/Divider/Divider.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Divider/Divider.stories.js +0 -51
- package/dist/src/lib/Components/Icon/Icon.stories.d.ts +0 -15
- package/dist/src/lib/Components/Icon/Icon.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Icon/Icon.stories.js +0 -137
- package/dist/src/lib/Components/IconButton/IconButton.stories.d.ts +0 -10
- package/dist/src/lib/Components/IconButton/IconButton.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/IconButton/IconButton.stories.js +0 -74
- package/dist/src/lib/Components/InteractiveIcon/InteractiveIcon.stories.d.ts +0 -11
- package/dist/src/lib/Components/InteractiveIcon/InteractiveIcon.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/InteractiveIcon/InteractiveIcon.stories.js +0 -90
- package/dist/src/lib/Components/Link/Link.stories.d.ts +0 -17
- package/dist/src/lib/Components/Link/Link.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Link/Link.stories.js +0 -275
- package/dist/src/lib/Components/ListItem/ListItem.stories.d.ts +0 -10
- package/dist/src/lib/Components/ListItem/ListItem.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/ListItem/ListItem.stories.js +0 -106
- package/dist/src/lib/Components/NavBar/NavBar.stories.d.ts +0 -10
- package/dist/src/lib/Components/NavBar/NavBar.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/NavBar/NavBar.stories.js +0 -72
- package/dist/src/lib/Components/PageIndicator/PageIndicator.stories.d.ts +0 -27
- package/dist/src/lib/Components/PageIndicator/PageIndicator.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/PageIndicator/PageIndicator.stories.js +0 -42
- package/dist/src/lib/Components/SearchInput/SearchInput.stories.d.ts +0 -12
- package/dist/src/lib/Components/SearchInput/SearchInput.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/SearchInput/SearchInput.stories.js +0 -98
- package/dist/src/lib/Components/SegmentedControl/SegmentedControl.stories.d.ts +0 -58
- package/dist/src/lib/Components/SegmentedControl/SegmentedControl.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/SegmentedControl/SegmentedControl.stories.js +0 -61
- package/dist/src/lib/Components/Select/Select.stories.d.ts +0 -11
- package/dist/src/lib/Components/Select/Select.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Select/Select.stories.js +0 -83
- package/dist/src/lib/Components/Skeleton/Skeleton.stories.d.ts +0 -11
- package/dist/src/lib/Components/Skeleton/Skeleton.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Skeleton/Skeleton.stories.js +0 -49
- package/dist/src/lib/Components/Spinner/Spinner.stories.d.ts +0 -9
- package/dist/src/lib/Components/Spinner/Spinner.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Spinner/Spinner.stories.js +0 -50
- package/dist/src/lib/Components/Spot/Spot.stories.d.ts +0 -12
- package/dist/src/lib/Components/Spot/Spot.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Spot/Spot.stories.js +0 -156
- package/dist/src/lib/Components/Stepper/Stepper.stories.d.ts +0 -9
- package/dist/src/lib/Components/Stepper/Stepper.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Stepper/Stepper.stories.js +0 -35
- package/dist/src/lib/Components/Subheader/Subheader.stories.d.ts +0 -10
- package/dist/src/lib/Components/Subheader/Subheader.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Subheader/Subheader.stories.js +0 -34
- package/dist/src/lib/Components/Switch/Switch.stories.d.ts +0 -14
- package/dist/src/lib/Components/Switch/Switch.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Switch/Switch.stories.js +0 -65
- package/dist/src/lib/Components/TabBar/TabBar.stories.d.ts +0 -50
- package/dist/src/lib/Components/TabBar/TabBar.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/TabBar/TabBar.stories.js +0 -60
- package/dist/src/lib/Components/Tag/Tag.stories.d.ts +0 -10
- package/dist/src/lib/Components/Tag/Tag.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Tag/Tag.stories.js +0 -45
- package/dist/src/lib/Components/TextInput/TextInput.stories.d.ts +0 -14
- package/dist/src/lib/Components/TextInput/TextInput.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/TextInput/TextInput.stories.js +0 -128
- package/dist/src/lib/Components/Tile/Tile.stories.d.ts +0 -14
- package/dist/src/lib/Components/Tile/Tile.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Tile/Tile.stories.js +0 -117
- package/dist/src/lib/Components/TileButton/TileButton.stories.d.ts +0 -12
- package/dist/src/lib/Components/TileButton/TileButton.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/TileButton/TileButton.stories.js +0 -63
- package/dist/src/lib/Components/Tooltip/Tooltip.stories.d.ts +0 -10
- package/dist/src/lib/Components/Tooltip/Tooltip.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Tooltip/Tooltip.stories.js +0 -50
- package/dist/src/lib/Components/Utility/Box/Box.stories.d.ts +0 -7
- package/dist/src/lib/Components/Utility/Box/Box.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Utility/Box/Box.stories.js +0 -42
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.d.ts +0 -11
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.js +0 -105
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.d.ts +0 -10
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.js +0 -101
- package/dist/src/lib/Components/Utility/Pressable/Pressable.stories.d.ts +0 -7
- package/dist/src/lib/Components/Utility/Pressable/Pressable.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Utility/Pressable/Pressable.stories.js +0 -47
- package/dist/src/lib/Components/Utility/Text/Text.stories.d.ts +0 -7
- package/dist/src/lib/Components/Utility/Text/Text.stories.d.ts.map +0 -1
- package/dist/src/lib/Components/Utility/Text/Text.stories.js +0 -33
package/dist/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AmountDisplay.d.ts","sourceRoot":"","sources":["../../../../../src/lib/Components/AmountDisplay/AmountDisplay.tsx"],"names":[],"mappings":"
|
|
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:
|
|
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":"
|
|
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
|
|
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
|
-
|
|
6
|
+
import { usePillLayout, useSegmentedControlSelectedIndex, } from './usePillLayout';
|
|
9
7
|
export function SegmentedControlButton({ value, children, icon: Icon, onPress, ...props }) {
|
|
10
|
-
const
|
|
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
|
-
|
|
15
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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.
|
|
103
|
-
backgroundColor: t.colors.bg.
|
|
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:
|
|
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 +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;
|
|
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).
|
|
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;
|
|
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.
|
|
24
|
+
backgroundColor: t.colors.bg.surface,
|
|
25
25
|
},
|
|
26
26
|
isFull && { width: t.sizes.full },
|
|
27
|
-
pressed && !disabled && { backgroundColor: t.colors.bg.
|
|
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
|
@@ -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
|
|
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'>() => 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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
+
};
|