@bigbinary/neetoui-rn 0.0.125 → 0.0.128
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/assets/fonts/SFProText-Bold.ttf +0 -0
- package/assets/fonts/SFProText-Medium.ttf +0 -0
- package/assets/fonts/SFProText-Regular.ttf +0 -0
- package/assets/fonts/SFProText-Semibold.ttf +0 -0
- package/assets/icons/apple-logo.svg +3 -0
- package/assets/icons/error.svg +4 -0
- package/assets/icons/google-logo.svg +6 -0
- package/assets/icons/info.svg +7 -0
- package/assets/icons/success.svg +3 -0
- package/assets/icons/warning.svg +5 -0
- package/lib/components/Alert.js +1 -1
- package/lib/components/Avatar.js +1 -1
- package/lib/components/Badge.js +1 -1
- package/lib/components/BottomSheet.js +1 -1
- package/lib/components/Button.js +1 -1
- package/lib/components/Carousel.js +1 -0
- package/lib/components/CheckBox.js +1 -1
- package/lib/components/Chip.js +1 -1
- package/lib/components/Input.js +1 -1
- package/lib/components/ListItem.js +1 -0
- package/lib/components/MultiSelect.js +1 -1
- package/lib/components/OnBoarding.js +1 -0
- package/lib/components/OtpInputs.js +1 -1
- package/lib/components/Popover.js +1 -1
- package/lib/components/RadioButton.js +1 -1
- package/lib/components/SearchBar.js +1 -0
- package/lib/components/SegmentPicker.js +1 -0
- package/lib/components/Select.js +1 -1
- package/lib/components/SocialButton.js +1 -0
- package/lib/components/Toast.js +1 -1
- package/lib/components/ToggleSwitch.js +1 -1
- package/lib/components/index.js +1 -1
- package/lib/config/toasterConfig.js +1 -1
- package/lib/hooks/index.js +1 -1
- package/lib/hooks/useDebounce.js +1 -0
- package/lib/theme/index.js +1 -1
- package/package.json +5 -3
- package/src/components/Alert.js +5 -5
- package/src/components/Avatar.js +1 -1
- package/src/components/Badge.js +1 -1
- package/src/components/BottomSheet.js +113 -74
- package/src/components/Button.js +152 -61
- package/src/components/Carousel.js +112 -0
- package/src/components/CheckBox.js +87 -81
- package/src/components/Chip.js +1 -1
- package/src/components/Input.js +147 -241
- package/src/components/ListItem.js +66 -0
- package/src/components/MultiSelect.js +6 -6
- package/src/components/OnBoarding.js +116 -0
- package/src/components/OtpInputs.js +1 -1
- package/src/components/Popover.js +13 -1
- package/src/components/RadioButton.js +88 -114
- package/src/components/SearchBar.js +134 -0
- package/src/components/SegmentPicker.js +210 -0
- package/src/components/Select.js +5 -5
- package/src/components/SocialButton.js +89 -0
- package/src/components/Toast.js +85 -30
- package/src/components/ToggleSwitch.js +49 -97
- package/src/components/Typography.js +2 -2
- package/src/components/index.js +6 -0
- package/src/config/toasterConfig.js +2 -2
- package/src/hooks/index.js +1 -0
- package/src/hooks/useDebounce.js +16 -0
- package/src/theme/index.js +68 -34
- package/assets/fonts/Inter-Bold.ttf +0 -0
- package/assets/fonts/Inter-Regular.ttf +0 -0
|
@@ -45,7 +45,19 @@ PopOverItem.propTypes = {
|
|
|
45
45
|
fontFamily: PropTypes.string,
|
|
46
46
|
fontSize: PropTypes.oneOfType([
|
|
47
47
|
PropTypes.number,
|
|
48
|
-
PropTypes.oneOf([
|
|
48
|
+
PropTypes.oneOf([
|
|
49
|
+
"3xs",
|
|
50
|
+
"2xs",
|
|
51
|
+
"xs",
|
|
52
|
+
"s",
|
|
53
|
+
"m",
|
|
54
|
+
"l",
|
|
55
|
+
"xl",
|
|
56
|
+
"2xl",
|
|
57
|
+
"3xl",
|
|
58
|
+
"4xl",
|
|
59
|
+
"5xl",
|
|
60
|
+
]),
|
|
49
61
|
]),
|
|
50
62
|
};
|
|
51
63
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import
|
|
1
|
+
import React, { useContext } from "react";
|
|
2
|
+
import Proptypes from "prop-types";
|
|
3
|
+
import { ThemeContext } from "styled-components/native";
|
|
3
4
|
|
|
4
|
-
import { Container,
|
|
5
|
-
const labelPositions = ["left", "right"];
|
|
6
|
-
|
|
7
|
-
const LabelComponent = ({ label, labelComponent, labelProp }) => {
|
|
8
|
-
return labelComponent || <Typography {...labelProp}>{label}</Typography>;
|
|
9
|
-
};
|
|
5
|
+
import { Container, Typography, Touchable } from "@components";
|
|
10
6
|
|
|
11
7
|
/**
|
|
8
|
+
*
|
|
9
|
+
* <div class="screenshots">
|
|
10
|
+
* <img src="screenshots/radioButton/radioButton.png" />
|
|
11
|
+
* </div>
|
|
12
12
|
*
|
|
13
13
|
* This component supports below props categories from [styled-system ](/styled-system).
|
|
14
14
|
* <ul>
|
|
@@ -26,149 +26,123 @@ const LabelComponent = ({ label, labelComponent, labelProp }) => {
|
|
|
26
26
|
* import { Container, RadioButton } from "@bigbinary/neetoui-rn";
|
|
27
27
|
*
|
|
28
28
|
* export default function Main() {
|
|
29
|
-
* const [
|
|
29
|
+
* const [selected1, setSelected1] = useState(true);
|
|
30
|
+
* const [selected2, setSelected2] = useState(false);
|
|
30
31
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
32
|
+
* return (
|
|
33
|
+
* <Container>
|
|
33
34
|
* <RadioButton
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* mt={2}
|
|
36
|
+
* selected={selected1}
|
|
37
|
+
* onSelect={() => setSelected1(prev => !prev)}
|
|
38
|
+
* label={`Radio button marked as ${!selected1 ? "un" : ""}selected`}
|
|
38
39
|
* />
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* <RadioButton
|
|
41
|
+
* mt={3}
|
|
42
|
+
* selected={selected2}
|
|
43
|
+
* onSelect={() => setSelected2(prev => !prev)}
|
|
44
|
+
* label={`Radio button marked as ${!selected2 ? "un" : ""}selected`}
|
|
45
|
+
* />
|
|
46
|
+
* <RadioButton mt={3} disabled label="Disabled Radio button" />
|
|
47
|
+
* </Container>
|
|
48
|
+
* );
|
|
49
|
+
* }
|
|
42
50
|
* ```
|
|
43
51
|
*
|
|
44
52
|
*/
|
|
45
53
|
|
|
46
54
|
export const RadioButton = ({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
selected = null,
|
|
54
|
-
density = 5,
|
|
55
|
-
label = "Option",
|
|
56
|
-
labelComponent = null,
|
|
57
|
-
labelProp = {},
|
|
58
|
-
labelPosition = "right",
|
|
59
|
-
disabled = false,
|
|
55
|
+
selected,
|
|
56
|
+
onSelect,
|
|
57
|
+
disabled,
|
|
58
|
+
label,
|
|
59
|
+
radioButtonStyle,
|
|
60
|
+
labelStyle,
|
|
60
61
|
...rest
|
|
61
62
|
}) => {
|
|
63
|
+
const theme = useContext(ThemeContext);
|
|
64
|
+
const disabledProps = {
|
|
65
|
+
borderColor: theme.colors.border.secondary,
|
|
66
|
+
labelProps: {
|
|
67
|
+
color: theme.colors.font.grey400,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
const selectedProps = {
|
|
71
|
+
borderWidth: 4,
|
|
72
|
+
borderColor: theme.colors.background.base,
|
|
73
|
+
labelProps: {
|
|
74
|
+
fontFamily: theme.fonts.sf500,
|
|
75
|
+
color: theme.colors.font.primary,
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
const unselectedProps = {
|
|
79
|
+
borderWidth: 2,
|
|
80
|
+
borderColor: theme.colors.border.secondary,
|
|
81
|
+
labelProps: {
|
|
82
|
+
fontFamily: theme.fonts.sf400,
|
|
83
|
+
color: theme.colors.font.secondary,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
62
86
|
return (
|
|
63
87
|
<Touchable
|
|
64
88
|
disabled={disabled}
|
|
65
|
-
opacity={disabled ? 0.5 : 1}
|
|
66
89
|
onPress={onSelect}
|
|
67
90
|
flexDirection="row"
|
|
68
91
|
alignItems="center"
|
|
69
|
-
py={1}
|
|
70
92
|
{...rest}
|
|
71
93
|
>
|
|
72
|
-
{labelPosition === labelPositions[0] ? (
|
|
73
|
-
<LabelComponent
|
|
74
|
-
label={label}
|
|
75
|
-
labelComponent={labelComponent}
|
|
76
|
-
labelProp={{ mr: 2, ...labelProp }}
|
|
77
|
-
/>
|
|
78
|
-
) : null}
|
|
79
94
|
<Container
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
height={16}
|
|
96
|
+
width={16}
|
|
97
|
+
borderRadius={8}
|
|
98
|
+
bg={theme.colors.background.white}
|
|
99
|
+
{...(selected && selectedProps)}
|
|
100
|
+
{...(!selected && unselectedProps)}
|
|
101
|
+
{...(disabled && disabledProps)}
|
|
102
|
+
{...radioButtonStyle}
|
|
103
|
+
/>
|
|
104
|
+
<Typography
|
|
105
|
+
ml={2}
|
|
106
|
+
fontSize="m"
|
|
107
|
+
{...(selected && selectedProps.labelProps)}
|
|
108
|
+
{...(!selected && unselectedProps.labelProps)}
|
|
109
|
+
{...(disabled && disabledProps.labelProps)}
|
|
110
|
+
{...labelStyle}
|
|
86
111
|
>
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
width={radioButtonSelectedWidth + density}
|
|
90
|
-
borderRadius={(radioButtonSelectedWidth + density) / 2}
|
|
91
|
-
bg="background.white"
|
|
92
|
-
justifyContent="center"
|
|
93
|
-
alignItems="center"
|
|
94
|
-
>
|
|
95
|
-
<Container
|
|
96
|
-
bg={selected ? innerActiveBg : innerInActiveBg}
|
|
97
|
-
height={radioButtonSelectedWidth}
|
|
98
|
-
width={radioButtonSelectedWidth}
|
|
99
|
-
borderRadius={radioButtonSelectedWidth / 2}
|
|
100
|
-
m={1}
|
|
101
|
-
/>
|
|
102
|
-
</Container>
|
|
103
|
-
</Container>
|
|
104
|
-
{labelPosition === labelPositions[1] ? (
|
|
105
|
-
<LabelComponent
|
|
106
|
-
label={label}
|
|
107
|
-
labelComponent={labelComponent}
|
|
108
|
-
labelProp={{ ml: 2, ...labelProp }}
|
|
109
|
-
/>
|
|
110
|
-
) : null}
|
|
112
|
+
{label}
|
|
113
|
+
</Typography>
|
|
111
114
|
</Touchable>
|
|
112
115
|
);
|
|
113
116
|
};
|
|
114
117
|
|
|
115
118
|
RadioButton.propTypes = {
|
|
116
119
|
/**
|
|
117
|
-
*
|
|
118
|
-
*/
|
|
119
|
-
onSelect: PropTypes.func.isRequired,
|
|
120
|
-
/**
|
|
121
|
-
* Whether radio is selected.
|
|
122
|
-
*/
|
|
123
|
-
selected: PropTypes.any.isRequired,
|
|
124
|
-
/**
|
|
125
|
-
* Text label to be shown with radio button.
|
|
120
|
+
* Whether radio button is selected or not.
|
|
126
121
|
*/
|
|
127
|
-
|
|
122
|
+
selected: Proptypes.bool.isRequired,
|
|
128
123
|
/**
|
|
129
|
-
*
|
|
130
|
-
*/
|
|
131
|
-
labelProp: PropTypes.object,
|
|
132
|
-
/**
|
|
133
|
-
* Label can passed as a component as well.
|
|
134
|
-
*/
|
|
135
|
-
labelComponent: PropTypes.element,
|
|
136
|
-
/**
|
|
137
|
-
* Position of label relative to the radio button. It can be either `left` or `right`
|
|
138
|
-
*/
|
|
139
|
-
labelPosition: PropTypes.oneOf(labelPositions),
|
|
140
|
-
/**
|
|
141
|
-
* Whether radio is disabled.
|
|
142
|
-
*/
|
|
143
|
-
disabled: PropTypes.bool,
|
|
144
|
-
/**
|
|
145
|
-
* Size of radio button.
|
|
146
|
-
*/
|
|
147
|
-
radioButtonWidth: PropTypes.number,
|
|
148
|
-
/**
|
|
149
|
-
* Size of radio button when selected.
|
|
124
|
+
* Function to execute on press.
|
|
150
125
|
*/
|
|
151
|
-
|
|
126
|
+
onSelect: Proptypes.func.isRequired,
|
|
152
127
|
/**
|
|
153
|
-
*
|
|
128
|
+
* To disable the component.
|
|
154
129
|
*/
|
|
155
|
-
|
|
130
|
+
disabled: Proptypes.bool,
|
|
156
131
|
/**
|
|
157
|
-
*
|
|
132
|
+
* Text label to be shown with radio button.
|
|
158
133
|
*/
|
|
159
|
-
|
|
134
|
+
label: Proptypes.string,
|
|
160
135
|
/**
|
|
161
|
-
*
|
|
136
|
+
* Customize radio button style.
|
|
162
137
|
*/
|
|
163
|
-
|
|
138
|
+
radioButtonStyle: Proptypes.object,
|
|
164
139
|
/**
|
|
165
|
-
*
|
|
140
|
+
* Customize label style.
|
|
166
141
|
*/
|
|
167
|
-
|
|
142
|
+
labelStyle: Proptypes.object,
|
|
168
143
|
};
|
|
169
144
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
labelProp: PropTypes.object,
|
|
145
|
+
RadioButton.defaultProps = {
|
|
146
|
+
selected: false,
|
|
147
|
+
onSelect: () => {},
|
|
174
148
|
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { TextInput, Animated, StyleSheet } from "react-native";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import Icon from "react-native-remix-icon";
|
|
5
|
+
|
|
6
|
+
import { Container, Button } from "@components";
|
|
7
|
+
import { useDebounce } from "@hooks";
|
|
8
|
+
import { theme } from "@theme";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* SearchBars are used to search or filter items.
|
|
12
|
+
*
|
|
13
|
+
* ## Usage
|
|
14
|
+
* ```js
|
|
15
|
+
* import * as React from 'react';
|
|
16
|
+
* import { Container, SearchBar } from '@bigbinary/neetoui-rn';
|
|
17
|
+
*
|
|
18
|
+
* export default function Main() {
|
|
19
|
+
* return (
|
|
20
|
+
* <Container>
|
|
21
|
+
* <SearchBar placeholder="Search" onChangeText={() => {}} />
|
|
22
|
+
* </Container>
|
|
23
|
+
* );
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export const SearchBar = props => {
|
|
29
|
+
const {
|
|
30
|
+
placeholder = "Search",
|
|
31
|
+
onChangeText = () => {},
|
|
32
|
+
debounceDelay = 1000,
|
|
33
|
+
...rest
|
|
34
|
+
} = props;
|
|
35
|
+
const inputRef = useRef();
|
|
36
|
+
const [searchText, setSearchText] = useState("");
|
|
37
|
+
const debouncedSearchTextValue = useDebounce(
|
|
38
|
+
searchText,
|
|
39
|
+
Number(debounceDelay)
|
|
40
|
+
);
|
|
41
|
+
const searchAnimationController = useRef(new Animated.Value(0)).current;
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
onChangeText(debouncedSearchTextValue);
|
|
45
|
+
}, [debouncedSearchTextValue, onChangeText]);
|
|
46
|
+
|
|
47
|
+
const animateSearchInput = val => {
|
|
48
|
+
Animated.timing(searchAnimationController, {
|
|
49
|
+
toValue: val,
|
|
50
|
+
duration: 350,
|
|
51
|
+
useNativeDriver: false,
|
|
52
|
+
}).start();
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const searchInputWidth = searchAnimationController.interpolate({
|
|
56
|
+
inputRange: [0, 1],
|
|
57
|
+
outputRange: ["100%", "85%"],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const onCancelHandle = () => {
|
|
61
|
+
animateSearchInput(0);
|
|
62
|
+
setSearchText("");
|
|
63
|
+
inputRef.current.blur();
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<Container flexDirection="row" alignItems="center">
|
|
68
|
+
<Animated.View
|
|
69
|
+
style={{
|
|
70
|
+
...styles.inputContainerStyles,
|
|
71
|
+
width: searchInputWidth,
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
<Container px={10}>
|
|
75
|
+
<Icon
|
|
76
|
+
name="ri-search-line"
|
|
77
|
+
size={20}
|
|
78
|
+
color={theme.colors.font.grey600}
|
|
79
|
+
/>
|
|
80
|
+
</Container>
|
|
81
|
+
<TextInput
|
|
82
|
+
ref={inputRef}
|
|
83
|
+
value={searchText}
|
|
84
|
+
onChangeText={setSearchText}
|
|
85
|
+
onFocus={() => {
|
|
86
|
+
animateSearchInput(1);
|
|
87
|
+
}}
|
|
88
|
+
onBlur={() => {
|
|
89
|
+
if (!searchText) animateSearchInput(0);
|
|
90
|
+
}}
|
|
91
|
+
placeholder={placeholder}
|
|
92
|
+
fontSize={16}
|
|
93
|
+
flex={1}
|
|
94
|
+
placeholderTextColor={theme.colors.font.grey600}
|
|
95
|
+
color="font.primary"
|
|
96
|
+
{...rest.searchbarProps}
|
|
97
|
+
/>
|
|
98
|
+
</Animated.View>
|
|
99
|
+
<Animated.View
|
|
100
|
+
style={{
|
|
101
|
+
opacity: searchAnimationController,
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
<Button variant="text" label="Cancel" onPress={onCancelHandle} />
|
|
105
|
+
</Animated.View>
|
|
106
|
+
</Container>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const styles = StyleSheet.create({
|
|
111
|
+
inputContainerStyles: {
|
|
112
|
+
height: 42,
|
|
113
|
+
borderWidth: 1,
|
|
114
|
+
borderColor: theme.colors.border.grey400,
|
|
115
|
+
borderRadius: 8,
|
|
116
|
+
flexDirection: "row",
|
|
117
|
+
alignItems: "center",
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
SearchBar.propTypes = {
|
|
122
|
+
/**
|
|
123
|
+
* Set the placeholder text
|
|
124
|
+
*/
|
|
125
|
+
placeholder: PropTypes.string,
|
|
126
|
+
/**
|
|
127
|
+
* Method to fire when text is changed
|
|
128
|
+
*/
|
|
129
|
+
onChangeText: PropTypes.func.isRequired,
|
|
130
|
+
/**
|
|
131
|
+
* Takes numeric value which is used to set the debounce delay
|
|
132
|
+
*/
|
|
133
|
+
debounceDelay: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
134
|
+
};
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import PropTypes from "prop-types";
|
|
2
|
+
import React, { useEffect, useCallback } from "react";
|
|
3
|
+
import { Dimensions, StyleSheet } from "react-native";
|
|
4
|
+
import Animated, {
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
useSharedValue,
|
|
7
|
+
withSpring,
|
|
8
|
+
} from "react-native-reanimated";
|
|
9
|
+
import { Typography, Touchable } from "@components";
|
|
10
|
+
|
|
11
|
+
const defaultShadowStyle = {
|
|
12
|
+
shadowColor: "#000",
|
|
13
|
+
shadowOffset: {
|
|
14
|
+
width: 0,
|
|
15
|
+
height: 2,
|
|
16
|
+
},
|
|
17
|
+
shadowOpacity: 0.23,
|
|
18
|
+
shadowRadius: 2.62,
|
|
19
|
+
|
|
20
|
+
elevation: 4,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// eslint-disable-next-line neeto/no-dangling-constants
|
|
24
|
+
const DEFAULT_SPRING_CONFIG = {
|
|
25
|
+
stiffness: 150,
|
|
26
|
+
damping: 20,
|
|
27
|
+
mass: 1,
|
|
28
|
+
overshootClamping: false,
|
|
29
|
+
restSpeedThreshold: 0.001,
|
|
30
|
+
restDisplacementThreshold: 0.001,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// So that it stretches in landscape mode.
|
|
34
|
+
const width = Dimensions.get("screen").width - 32;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* A Segment Picker component that provides toggling between two or more views.
|
|
39
|
+
*
|
|
40
|
+
* <div class="screenshots">
|
|
41
|
+
* <img src="screenshots/segmentPicker/segmentpickers.png" />
|
|
42
|
+
* </div>
|
|
43
|
+
*
|
|
44
|
+
* ## Usage
|
|
45
|
+
* ```js
|
|
46
|
+
* import * as React from 'react';
|
|
47
|
+
* import { Container, SegmentPicker } from '@bigbinary/neetoui-rn';
|
|
48
|
+
*
|
|
49
|
+
* export default function Main(){
|
|
50
|
+
* const [tabIndex, setTabIndex] = useState(1);
|
|
51
|
+
*
|
|
52
|
+
* return (
|
|
53
|
+
* <Container flex={1} alignItems="center" justifyContent="center">
|
|
54
|
+
* <Container my={3}>
|
|
55
|
+
* <SegmentPicker
|
|
56
|
+
* tabs={["On", "Off"]}
|
|
57
|
+
* currentIndex={tabIndex}
|
|
58
|
+
* onChange={setTabIndex}
|
|
59
|
+
* />
|
|
60
|
+
* </Container>
|
|
61
|
+
* </Container>
|
|
62
|
+
* );
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
export const SegmentPicker = ({
|
|
68
|
+
tabs,
|
|
69
|
+
onChange,
|
|
70
|
+
currentIndex,
|
|
71
|
+
inactiveSegmentStyle,
|
|
72
|
+
activeSegmentStyle,
|
|
73
|
+
activeTextStyle,
|
|
74
|
+
inactiveTextStyle,
|
|
75
|
+
py,
|
|
76
|
+
}) => {
|
|
77
|
+
const translateValue = (width - 4) / tabs?.length;
|
|
78
|
+
const tabTranslateValue = useSharedValue(0);
|
|
79
|
+
|
|
80
|
+
// useCallBack with an empty array as input, which will call inner lambda only once and memoize the reference for future calls
|
|
81
|
+
const memoizedTabPressCallback = useCallback(
|
|
82
|
+
index => {
|
|
83
|
+
onChange(index);
|
|
84
|
+
},
|
|
85
|
+
[onChange]
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
tabTranslateValue.value = withSpring(
|
|
90
|
+
currentIndex * (translateValue * 1),
|
|
91
|
+
DEFAULT_SPRING_CONFIG
|
|
92
|
+
);
|
|
93
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
94
|
+
}, [currentIndex]);
|
|
95
|
+
|
|
96
|
+
const tabTranslateAnimatedStyles = useAnimatedStyle(() => {
|
|
97
|
+
return {
|
|
98
|
+
transform: [{ translateX: tabTranslateValue.value }],
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Animated.View
|
|
104
|
+
style={[styles.defaultSegmentedControlWrapper, inactiveSegmentStyle]}
|
|
105
|
+
>
|
|
106
|
+
<Animated.View
|
|
107
|
+
style={[
|
|
108
|
+
styles.movingSegmentStyle,
|
|
109
|
+
activeSegmentStyle,
|
|
110
|
+
defaultShadowStyle,
|
|
111
|
+
StyleSheet.absoluteFill,
|
|
112
|
+
{
|
|
113
|
+
width: width / tabs?.length,
|
|
114
|
+
},
|
|
115
|
+
tabTranslateAnimatedStyles,
|
|
116
|
+
]}
|
|
117
|
+
/>
|
|
118
|
+
|
|
119
|
+
{tabs.map((label, index) => {
|
|
120
|
+
const currentIndexTextStyle =
|
|
121
|
+
currentIndex === index ? activeTextStyle : inactiveTextStyle;
|
|
122
|
+
return (
|
|
123
|
+
<Touchable
|
|
124
|
+
key={index}
|
|
125
|
+
flex={1}
|
|
126
|
+
elevation={6}
|
|
127
|
+
onPress={() => memoizedTabPressCallback(index)}
|
|
128
|
+
py={py}
|
|
129
|
+
activeOpacity={0.7}
|
|
130
|
+
>
|
|
131
|
+
<Typography
|
|
132
|
+
fontSize="xs"
|
|
133
|
+
textAlign="center"
|
|
134
|
+
color="font.grey800"
|
|
135
|
+
fontFamily="sf500"
|
|
136
|
+
{...currentIndexTextStyle}
|
|
137
|
+
>
|
|
138
|
+
{label}
|
|
139
|
+
</Typography>
|
|
140
|
+
</Touchable>
|
|
141
|
+
);
|
|
142
|
+
})}
|
|
143
|
+
</Animated.View>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const styles = StyleSheet.create({
|
|
148
|
+
segmentedControlWrapper: {
|
|
149
|
+
display: "flex",
|
|
150
|
+
flexDirection: "row",
|
|
151
|
+
alignItems: "center",
|
|
152
|
+
borderRadius: 8,
|
|
153
|
+
width: width,
|
|
154
|
+
},
|
|
155
|
+
defaultSegmentedControlWrapper: {
|
|
156
|
+
position: "relative",
|
|
157
|
+
display: "flex",
|
|
158
|
+
flexDirection: "row",
|
|
159
|
+
alignItems: "center",
|
|
160
|
+
borderRadius: 8,
|
|
161
|
+
backgroundColor: "#E5E5EA",
|
|
162
|
+
width: width,
|
|
163
|
+
},
|
|
164
|
+
movingSegmentStyle: {
|
|
165
|
+
top: 0,
|
|
166
|
+
marginVertical: 2,
|
|
167
|
+
marginHorizontal: 2,
|
|
168
|
+
borderRadius: 6,
|
|
169
|
+
backgroundColor: "#FFFFFF",
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
SegmentPicker.propTypes = {
|
|
174
|
+
/**
|
|
175
|
+
* Array of texts for the labels of each Segment/Tab.
|
|
176
|
+
*/
|
|
177
|
+
tabs: PropTypes.arrayOf(PropTypes.string).isRequired,
|
|
178
|
+
/**
|
|
179
|
+
* Callback called with the new value when it changes.
|
|
180
|
+
*/
|
|
181
|
+
onChange: PropTypes.func.isRequired,
|
|
182
|
+
/**
|
|
183
|
+
* Index value of the currently selected Segment/Tab.
|
|
184
|
+
*/
|
|
185
|
+
currentIndex: PropTypes.number.isRequired,
|
|
186
|
+
/**
|
|
187
|
+
* To change the inactive segment container style.
|
|
188
|
+
*/
|
|
189
|
+
inactiveSegmentStyle: PropTypes.object,
|
|
190
|
+
/**
|
|
191
|
+
* To change the active segment container style.
|
|
192
|
+
*/
|
|
193
|
+
activeSegmentStyle: PropTypes.object,
|
|
194
|
+
/**
|
|
195
|
+
* To change the inactive segment font style.
|
|
196
|
+
*/
|
|
197
|
+
inactiveTextStyle: PropTypes.object,
|
|
198
|
+
/**
|
|
199
|
+
* To change the active segment font style.
|
|
200
|
+
*/
|
|
201
|
+
activeTextStyle: PropTypes.object,
|
|
202
|
+
py: PropTypes.number,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
SegmentPicker.defaultProps = {
|
|
206
|
+
tabs: [],
|
|
207
|
+
onChange: () => {},
|
|
208
|
+
currentIndex: 0,
|
|
209
|
+
py: 12,
|
|
210
|
+
};
|
package/src/components/Select.js
CHANGED
|
@@ -37,7 +37,7 @@ const DropdownItem = ({
|
|
|
37
37
|
{...(isSelectedItem && selectedItemContainerStyle)}
|
|
38
38
|
>
|
|
39
39
|
<Typography
|
|
40
|
-
fontFamily="
|
|
40
|
+
fontFamily="sf400"
|
|
41
41
|
fontSize="s"
|
|
42
42
|
color={isSelectedItem ? "font.white" : "font.grey"}
|
|
43
43
|
{...itemLabelStyle}
|
|
@@ -215,7 +215,7 @@ export const Select = ({
|
|
|
215
215
|
return (
|
|
216
216
|
<Container {...containerStyle}>
|
|
217
217
|
<Typography
|
|
218
|
-
fontFamily="
|
|
218
|
+
fontFamily="sf400"
|
|
219
219
|
mb={1}
|
|
220
220
|
fontSize="s"
|
|
221
221
|
color="font.base"
|
|
@@ -237,7 +237,7 @@ export const Select = ({
|
|
|
237
237
|
{...inputContainerStyle}
|
|
238
238
|
{...rest}
|
|
239
239
|
>
|
|
240
|
-
<Typography fontFamily="
|
|
240
|
+
<Typography fontFamily="sf400" fontSize="s" color="font.grey">
|
|
241
241
|
{selectedOptionLabel || placeholder}
|
|
242
242
|
</Typography>
|
|
243
243
|
{isLoading ? (
|
|
@@ -287,7 +287,7 @@ export const Select = ({
|
|
|
287
287
|
{...emptyOptionsContainerStyle}
|
|
288
288
|
>
|
|
289
289
|
<Typography
|
|
290
|
-
fontFamily="
|
|
290
|
+
fontFamily="sf400"
|
|
291
291
|
fontSize="s"
|
|
292
292
|
color="font.grey"
|
|
293
293
|
{...emptyOptionsLabelStyle}
|
|
@@ -311,7 +311,7 @@ export const Select = ({
|
|
|
311
311
|
/>
|
|
312
312
|
) : (
|
|
313
313
|
<Typography
|
|
314
|
-
fontFamily="
|
|
314
|
+
fontFamily="sf400"
|
|
315
315
|
fontSize="s"
|
|
316
316
|
color="font.grey"
|
|
317
317
|
{...createSearchedOptionLabelStyle}
|