This commit is contained in:
2026-01-13 15:10:13 +08:00
parent 38f0885a85
commit 45d5debead
134 changed files with 16980 additions and 1 deletions

View File

@@ -0,0 +1,57 @@
import React from "react";
import { StyleSheet } from "react-native";
import PropTypes from 'prop-types';
import { Button } from "galio-framework";
import argonTheme from "../constants/Theme";
class ArButton extends React.Component {
render() {
const { small, shadowless, children, color, style, fontSize, ...props } = this.props;
const colorStyle = color && argonTheme.COLORS[color.toUpperCase()];
const buttonStyles = [
small && styles.smallButton,
color && { backgroundColor: colorStyle },
!shadowless && styles.shadow,
{...style}
];
return (
<Button
style={buttonStyles}
shadowless
textStyle={{ fontSize: fontSize || 12, fontWeight: '700' }}
{...props}
>
{children}
</Button>
);
}
}
ArButton.propTypes = {
small: PropTypes.bool,
shadowless: PropTypes.bool,
color: PropTypes.oneOfType([
PropTypes.string,
PropTypes.oneOf(['default', 'primary', 'secondary', 'info', 'error', 'success', 'warning'])
])
}
const styles = StyleSheet.create({
smallButton: {
width: 75,
height: 28
},
shadow: {
shadowColor: 'black',
shadowOffset: { width: 0, height: 4 },
shadowRadius: 4,
shadowOpacity: 0.1,
elevation: 2,
},
});
export default ArButton;

View File

@@ -0,0 +1,141 @@
import React from "react";
import { useNavigation } from '@react-navigation/native';
import PropTypes from "prop-types";
import {
StyleSheet,
Image,
TouchableWithoutFeedback
} from "react-native";
import { Block, Text, theme } from "galio-framework";
import { argonTheme } from "../constants";
const Card = ({
item,
horizontal,
full,
style,
ctaColor,
imageStyle,
ctaRight
}) => {
const navigation = useNavigation();
const imageStyles = [
full ? styles.fullImage : styles.horizontalImage,
imageStyle
];
const cardContainer = [styles.card, styles.shadow, style];
const imgContainer = [
styles.imageContainer,
horizontal ? styles.horizontalStyles : styles.verticalStyles,
styles.shadow
];
return (
<Block row={horizontal} card flex style={cardContainer}>
<TouchableWithoutFeedback
onPress={() => navigation.navigate("Product", { product: item })}
>
<Block flex style={imgContainer}>
<Image source={{ uri: item.image }} style={imageStyles} />
</Block>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback
onPress={() => navigation.navigate("Product", { product: item })}
>
<Block flex space="between" style={styles.cardDescription}>
<Block flex>
<Text
style={{ fontFamily: 'open-sans-regular' }}
size={14}
style={styles.cardTitle}
color={argonTheme.COLORS.TEXT}
>
{item.title}
</Text>
{item.body ? (
<Block flex left>
<Text style={{ fontFamily: 'open-sans-regular' }} size={12} color={argonTheme.COLORS.TEXT}>
{item.body}
</Text>
</Block>
) : (
<Block />
)}
</Block>
<Block right={ctaRight ? true : false}>
<Text
style={{ fontFamily: 'open-sans-bold' }}
size={12}
muted={!ctaColor}
color={ctaColor || argonTheme.COLORS.ACTIVE}
bold
>
{item.cta}
</Text>
</Block>
</Block>
</TouchableWithoutFeedback>
</Block>
);
};
Card.propTypes = {
item: PropTypes.object,
horizontal: PropTypes.bool,
full: PropTypes.bool,
ctaColor: PropTypes.string,
imageStyle: PropTypes.any,
ctaRight: PropTypes.bool
};
const styles = StyleSheet.create({
card: {
backgroundColor: theme.COLORS.WHITE,
marginVertical: theme.SIZES.BASE,
borderWidth: 0,
minHeight: 114,
marginBottom: 4,
},
cardTitle: {
// flex: 1,
// flexWrap: "wrap",
paddingBottom: 6
},
cardDescription: {
padding: theme.SIZES.BASE / 2
},
imageContainer: {
borderRadius: 3,
elevation: 1,
overflow: "hidden"
},
image: {
// borderRadius: 3,
},
horizontalImage: {
height: 122,
width: "auto"
},
horizontalStyles: {
borderTopRightRadius: 0,
borderBottomRightRadius: 0
},
verticalStyles: {
borderBottomRightRadius: 0,
borderBottomLeftRadius: 0
},
fullImage: {
height: 215
},
shadow: {
shadowColor: "#8898AA",
shadowOffset: { width: 0, height: 1 },
shadowRadius: 6,
shadowOpacity: 0.1,
elevation: 2
}
});
export default Card;

View File

@@ -0,0 +1,143 @@
import React from "react";
import { StyleSheet, TouchableOpacity, Linking } from "react-native";
import { Block, Text, theme } from "galio-framework";
import Icon from "./Icon";
import argonTheme from "../constants/Theme";
class DrawerItem extends React.Component {
renderIcon = () => {
const { title, focused } = this.props;
switch (title) {
case "Home":
return (
<Icon
name="shop"
family="ArgonExtra"
size={14}
color={focused ? "white" : argonTheme.COLORS.PRIMARY}
/>
);
case "Elements":
return (
<Icon
name="map-big"
family="ArgonExtra"
size={14}
color={focused ? "white" : argonTheme.COLORS.ERROR}
/>
);
case "Articles":
return (
<Icon
name="spaceship"
family="ArgonExtra"
size={14}
color={focused ? "white" : argonTheme.COLORS.PRIMARY}
/>
);
case "Profile":
return (
<Icon
name="chart-pie-35"
family="ArgonExtra"
size={14}
color={focused ? "white" : argonTheme.COLORS.WARNING}
/>
);
case "Account":
return (
<Icon
name="calendar-date"
family="ArgonExtra"
size={14}
color={focused ? "white" : argonTheme.COLORS.INFO}
/>
);
case "Settings":
return (
<Icon
name="calendar-date"
family="ArgonExtra"
size={14}
color={focused ? "white" : argonTheme.COLORS.DEFAULT}
/>
);
case "Getting Started":
return (
<Icon
name="spaceship"
family="ArgonExtra"
size={14}
color={focused ? "white" : "rgba(0,0,0,0.5)"}
/>
);
case "Log out":
return <Icon />;
default:
return null;
}
};
render() {
const { focused, title, navigation, navigateTo } = this.props;
const containerStyles = [
styles.defaultStyle,
focused ? [styles.activeStyle, styles.shadow] : null,
];
return (
<TouchableOpacity
style={{ height: 60 }}
onPress={() =>
title == "Getting Started"
? Linking.openURL(
"https://demos.creative-tim.com/argon-pro-react-native/docs/"
).catch((err) => console.error("An error occurred", err))
: navigation.navigate(navigateTo)
}
>
<Block flex row style={containerStyles}>
<Block middle flex={0.1} style={{ marginRight: 5 }}>
{this.renderIcon()}
</Block>
<Block row center flex={0.9}>
<Text
style={{ fontFamily: "open-sans-regular" }}
size={15}
bold={focused ? true : false}
color={focused ? "white" : "rgba(0,0,0,0.5)"}
>
{title}
</Text>
</Block>
</Block>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
defaultStyle: {
paddingVertical: 16,
paddingHorizontal: 16,
marginBottom: 2,
},
activeStyle: {
backgroundColor: argonTheme.COLORS.ACTIVE,
borderRadius: 4,
},
shadow: {
shadowColor: theme.COLORS.BLACK,
shadowOffset: {
width: 0,
height: 2,
},
shadowRadius: 8,
shadowOpacity: 0.1,
},
});
export default DrawerItem;

View File

@@ -0,0 +1,255 @@
import React from 'react';
import { TouchableOpacity, StyleSheet, Platform, Dimensions, Keyboard } from 'react-native';
import { Button, Block, NavBar, Text, theme } from 'galio-framework';
import { CommonActions } from '@react-navigation/native';
import Icon from './Icon';
import Input from './Input';
import Tabs from './Tabs';
import argonTheme from '../constants/Theme';
const { height, width } = Dimensions.get('window');
const iPhoneX = () => Platform.OS === 'ios' && (height === 812 || width === 812 || height === 896 || width === 896);
const BellButton = ({isWhite, style, navigation}) => (
<TouchableOpacity style={[styles.button, style]} onPress={() => navigation.navigate('Notifications')}>
<Icon
family="ArgonExtra"
size={16}
name="bell"
color={argonTheme.COLORS[isWhite ? 'WHITE' : 'ICON']}
/>
<Block middle style={styles.notify} />
</TouchableOpacity>
);
const BasketButton = ({isWhite, style, navigation}) => (
<TouchableOpacity style={[styles.button, style]} onPress={() => navigation.navigate('Cart')}>
<Icon
family="ArgonExtra"
size={16}
name="basket"
color={argonTheme.COLORS[isWhite ? 'WHITE' : 'ICON']}
/>
</TouchableOpacity>
);
const SearchButton = ({isWhite, style, navigation}) => (
<TouchableOpacity style={[styles.button, style]} onPress={() => navigation.navigate('Search')}>
<Icon
size={16}
family="Galio"
name="search-zoom-in"
color={theme.COLORS[isWhite ? 'WHITE' : 'ICON']}
/>
</TouchableOpacity>
);
class Header extends React.Component {
handleLeftPress = () => {
const { back, navigation, scene } = this.props;
return (back ? navigation.dispatch(CommonActions.goBack()) : navigation.openDrawer());
}
renderRight = () => {
const { white, title, navigation } = this.props;
// const { routeName } = navigation.state;
if (title === 'Title') {
return [
<BellButton key='chat-title' navigation={navigation} isWhite={white} />,
<BasketButton key='basket-title' navigation={navigation} isWhite={white} />
]
}
switch (title) {
case 'Home':
case 'Deals':
case 'Categories':
case 'Category':
case 'Profile':
case 'Product':
case 'Search':
case 'Settings':
return ([
<BellButton key='chat-categories' navigation={navigation} isWhite={white}/>,
<BasketButton key='basket-categories' navigation={navigation} isWhite={white}/>
]);
default:
break;
}
}
renderSearch = () => {
const { navigation } = this.props;
return (
<Input
right
color="black"
style={styles.search}
placeholder="What are you looking for?"
placeholderTextColor={'#8898AA'}
onFocus={() => {Keyboard.dismiss(); navigation.navigate('Search');}}
iconContent={<Icon size={16} color={theme.COLORS.MUTED} name="search-zoom-in" family="ArgonExtra" />}
/>
);
}
renderOptions = () => {
const { navigation, optionLeft, optionRight } = this.props;
return (
<Block row style={styles.options}>
<Button shadowless style={[styles.tab, styles.divider]} onPress={() => navigation.navigate('Beauty')}>
<Block row middle>
<Icon name="diamond" family="ArgonExtra" style={{ paddingRight: 8 }} color={argonTheme.COLORS.ICON} />
<Text style={{ fontFamily: 'open-sans-regular' }} size={16} style={styles.tabTitle}>{optionLeft || 'Beauty'}</Text>
</Block>
</Button>
<Button shadowless style={styles.tab} onPress={() => navigation.navigate('Fashion')}>
<Block row middle>
<Icon size={16} name="bag-17" family="ArgonExtra" style={{ paddingRight: 8 }} color={argonTheme.COLORS.ICON}/>
<Text style={{ fontFamily: 'open-sans-regular' }} size={16} style={styles.tabTitle}>{optionRight || 'Fashion'}</Text>
</Block>
</Button>
</Block>
);
}
renderTabs = () => {
const { tabs, tabIndex, navigation } = this.props;
const defaultTab = tabs && tabs[0] && tabs[0].id;
if (!tabs) return null;
return (
<Tabs
data={tabs || []}
initialIndex={tabIndex || defaultTab}
onChange={id => navigation.setParams({ tabId: id })} />
)
}
renderHeader = () => {
const { search, options, tabs } = this.props;
if (search || tabs || options) {
return (
<Block center>
{search ? this.renderSearch() : null}
{options ? this.renderOptions() : null}
{tabs ? this.renderTabs() : null}
</Block>
);
}
}
render() {
const { back, title, white, transparent, bgColor, iconColor, titleColor, navigation, ...props } = this.props;
// const { routeName } = navigation.state;
const noShadow = ['Search', 'Categories', 'Deals', 'Pro', 'Profile'].includes(title);
const headerStyles = [
!noShadow ? styles.shadow : null,
transparent ? { backgroundColor: 'rgba(0,0,0,0)' } : null,
];
const navbarStyles = [
styles.navbar,
bgColor && { backgroundColor: bgColor }
];
return (
<Block style={headerStyles}>
<NavBar
back={false}
title={title}
style={navbarStyles}
transparent={transparent}
right={this.renderRight()}
rightStyle={{ alignItems: 'center' }}
onLeftPress={this.handleLeftPress}
left={
<Icon
name={back ? 'chevron-left' : "menu"} family="entypo"
// name={back ? 'nav-left' : "menu-8"} family="ArgonExtra"
size={back ? 20 : 20} onPress={this.handleLeftPress}
color={iconColor || (white ? argonTheme.COLORS.WHITE : argonTheme.COLORS.ICON)}
style={{ marginTop: 2 }}
/>
}
leftStyle={{ paddingVertical: 12, flex: 0.2 }}
titleStyle={[
styles.title,
{ color: argonTheme.COLORS[white ? 'WHITE' : 'HEADER'] },
titleColor && { color: titleColor }
]}
{...props}
/>
{this.renderHeader()}
</Block>
);
}
}
const styles = StyleSheet.create({
button: {
padding: 12,
position: 'relative',
},
title: {
width: '100%',
fontSize: 16,
fontWeight: 'bold',
},
navbar: {
paddingVertical: 0,
paddingBottom: theme.SIZES.BASE * 1.5,
paddingTop: iPhoneX ? theme.SIZES.BASE * 4 : theme.SIZES.BASE,
zIndex: 5,
},
shadow: {
backgroundColor: theme.COLORS.WHITE,
shadowColor: 'black',
shadowOffset: { width: 0, height: 2 },
shadowRadius: 6,
shadowOpacity: 0.2,
elevation: 3,
},
notify: {
backgroundColor: argonTheme.COLORS.LABEL,
borderRadius: 4,
height: theme.SIZES.BASE / 2,
width: theme.SIZES.BASE / 2,
position: 'absolute',
top: 9,
right: 12,
},
header: {
backgroundColor: theme.COLORS.WHITE,
},
divider: {
borderRightWidth: 0.3,
borderRightColor: theme.COLORS.ICON,
},
search: {
height: 48,
width: width - 32,
marginHorizontal: 16,
borderWidth: 1,
borderRadius: 3,
borderColor: argonTheme.COLORS.BORDER
},
options: {
marginBottom: 24,
marginTop: 10,
elevation: 4,
},
tab: {
backgroundColor: theme.COLORS.TRANSPARENT,
width: width * 0.35,
borderRadius: 0,
borderWidth: 0,
height: 24,
elevation: 0,
},
tabTitle: {
lineHeight: 19,
fontWeight: '400',
color: argonTheme.COLORS.HEADER
},
});
export default Header;

View File

@@ -0,0 +1,34 @@
import React from 'react';
import * as Font from 'expo-font';
import { createIconSetFromIcoMoon } from '@expo/vector-icons';
import { Icon } from 'galio-framework';
import argonConfig from '../assets/config/argon.json';
const ArgonExtra = require('../assets/font/argon.ttf');
const IconArgonExtra = createIconSetFromIcoMoon(argonConfig, 'ArgonExtra');
class IconExtra extends React.Component {
state = {
fontLoaded: false,
}
async componentDidMount() {
await Font.loadAsync({ ArgonExtra: ArgonExtra });
this.setState({ fontLoaded: true });
}
render() {
const { name, family, ...rest } = this.props;
if (name && family && this.state.fontLoaded) {
if (family === 'ArgonExtra') {
return <IconArgonExtra name={name} family={family} {...rest} />;
}
return <Icon name={name} family={family} {...rest} />;
}
return null;
}
}
export default IconExtra;

View File

@@ -0,0 +1,76 @@
import React from "react";
import { StyleSheet } from "react-native";
import PropTypes from 'prop-types';
import { Input } from "galio-framework";
import Icon from './Icon';
import { argonTheme } from "../constants";
class ArInput extends React.Component {
render() {
const { shadowless, success, error } = this.props;
const inputStyles = [
styles.input,
!shadowless && styles.shadow,
success && styles.success,
error && styles.error,
{...this.props.style}
];
return (
<Input
placeholder="write something here"
placeholderTextColor={argonTheme.COLORS.MUTED}
style={inputStyles}
color={argonTheme.COLORS.HEADER}
iconContent={
<Icon
size={14}
color={argonTheme.COLORS.ICON}
name="link"
family="AntDesign"
/>
}
{...this.props}
/>
);
}
}
ArInput.defaultProps = {
shadowless: false,
success: false,
error: false
};
ArInput.propTypes = {
shadowless: PropTypes.bool,
success: PropTypes.bool,
error: PropTypes.bool
}
const styles = StyleSheet.create({
input: {
borderRadius: 4,
borderColor: argonTheme.COLORS.BORDER,
height: 44,
backgroundColor: '#FFFFFF'
},
success: {
borderColor: argonTheme.COLORS.INPUT_SUCCESS,
},
error: {
borderColor: argonTheme.COLORS.INPUT_ERROR,
},
shadow: {
shadowColor: argonTheme.COLORS.BLACK,
shadowOffset: { width: 0, height: 0.5 },
shadowRadius: 1,
shadowOpacity: 0.13,
elevation: 2,
}
});
export default ArInput;

View File

@@ -0,0 +1,157 @@
import React from "react";
import { StyleSheet, TouchableWithoutFeedback } from "react-native";
import PropTypes from "prop-types";
import { Block, Text } from "galio-framework";
import Icon from "./Icon";
import { argonTheme } from "../constants";
export default class Notification extends React.Component {
render() {
const {
body,
color,
iconColor,
iconFamily,
iconName,
iconSize,
onPress,
style,
system,
time,
title,
transparent
} = this.props;
const iconContainer = [
styles.iconContainer,
{ backgroundColor: color || argonTheme.COLORS.PRIMARY },
system && { width: 34, height: 34 },
!system && styles.iconShadow
];
const container = [
styles.card,
!transparent && { backgroundColor: argonTheme.COLORS.WHITE },
!transparent && styles.cardShadow,
system && { height: 78 },
style
];
return (
<Block style={container} middle>
<TouchableWithoutFeedback onPress={onPress}>
<Block row style={{ width: "95%" }}>
<Block top flex={system ? 0.12 : 0.2} middle>
<Block middle style={iconContainer}>
<Icon
name={iconName}
family={iconFamily}
size={iconSize || system ? 16 : 22}
color={
iconColor || system ? argonTheme.COLORS.DEFAULT : argonTheme.COLORS.WHITE
}
/>
</Block>
</Block>
<Block flex style={{ paddingRight: 3, paddingLeft: 12 }}>
{system && (
<Block row space="between" style={{ height: 18 }}>
<Text color={argonTheme.COLORS.MUTED} style={{ fontFamily: 'open-sans-bold' }} size={13}>{title}</Text>
<Block row style={{ marginTop: 3 }}>
<Icon
family="material-community"
name="clock"
size={12}
color={argonTheme.COLORS.MUTED}
/>
<Text
color={argonTheme.COLORS.MUTED}
style={{
fontFamily: "open-sans-regular",
marginLeft: 3,
marginTop: -3
}}
size={12}
>
{time}
</Text>
</Block>
</Block>
)}
<Text
color={argonTheme.COLORS.TEXT}
size={system ? 13 : 14}
style={{ fontFamily: system ? "open-sans-bold" : "open-sans-regular" }}
>
{body}
</Text>
</Block>
{!system && (
<Block row flex={0.2} style={{ marginTop: 3 }}>
<Icon
family="material-community"
name="clock"
size={12}
color={argonTheme.COLORS.MUTED}
/>
<Text
color={argonTheme.COLORS.MUTED}
style={{
fontFamily: "open-sans-regular",
marginLeft: 3,
marginTop: -2
}}
size={12}
>
{time}
</Text>
</Block>
)}
</Block>
</TouchableWithoutFeedback>
</Block>
);
}
}
Notification.propTypes = {
body: PropTypes.string,
color: PropTypes.string,
iconColor: PropTypes.string,
iconFamily: PropTypes.string,
iconName: PropTypes.string,
iconSize: PropTypes.number,
onPress: PropTypes.func,
style: PropTypes.object,
system: PropTypes.bool,
time: PropTypes.string,
title: PropTypes.string,
transparent: PropTypes.bool,
};
const styles = StyleSheet.create({
iconContainer: {
width: 46,
height: 46,
borderRadius: 23,
marginTop: 2
},
iconShadow: {
shadowColor: "black",
shadowOffset: { width: 0, height: 4 },
shadowRadius: 4,
shadowOpacity: 0.1,
elevation: 2
},
card: {
zIndex: 2,
height: 127,
borderRadius: 6
},
cardShadow: {
shadowColor: argonTheme.COLORS.BLACK,
shadowOffset: { width: 0, height: 2 },
shadowRadius: 4,
shadowOpacity: 0.1,
elevation: 2
}
});

View File

@@ -0,0 +1,85 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import ModalDropdown from 'react-native-modal-dropdown';
import { Block, Text } from 'galio-framework';
import Icon from './Icon';
import { argonTheme } from '../constants';
class DropDown extends React.Component {
state = {
value: 1,
}
handleOnSelect = (index, value) => {
const { onSelect } = this.props;
this.setState({ value: value });
onSelect && onSelect(index, value);
}
render() {
const { onSelect, iconName, iconFamily, iconSize, iconColor, color, textStyle, style, ...props } = this.props;
const modalStyles = [
styles.qty,
color && { backgroundColor: color },
style
];
const textStyles = [
styles.text,
textStyle
];
return (
<ModalDropdown
style={modalStyles}
onSelect={this.handleOnSelect}
dropdownStyle={styles.dropdown}
dropdownTextStyle={{paddingLeft:16, fontSize:12}}
{...props}>
<Block flex row middle space="between">
<Text size={12} style={textStyles}>{this.state.value}</Text>
<Icon name={iconName || "nav-down"} family={iconFamily || "ArgonExtra"} size={iconSize || 10} color={iconColor || argonTheme.COLORS.WHITE} />
</Block>
</ModalDropdown>
)
}
}
DropDown.propTypes = {
onSelect: PropTypes.func,
iconName: PropTypes.string,
iconFamily: PropTypes.string,
iconSize: PropTypes.number,
color: PropTypes.string,
textStyle: PropTypes.any,
};
const styles = StyleSheet.create({
qty: {
width: 100,
backgroundColor: argonTheme.COLORS.DEFAULT,
paddingHorizontal: 16,
paddingTop: 10,
paddingBottom:9.5,
borderRadius: 4,
shadowColor: "rgba(0, 0, 0, 0.1)",
shadowOffset: { width: 0, height: 2 },
shadowRadius: 4,
shadowOpacity: 1,
},
text: {
color: argonTheme.COLORS.WHITE,
fontWeight: '600'
},
dropdown: {
marginTop: 8,
marginLeft: -16,
width: 100,
},
});
export default DropDown;

View File

@@ -0,0 +1,24 @@
import React from 'react';
import { Switch, Platform } from 'react-native';
import argonTheme from '../constants/Theme';
class MkSwitch extends React.Component {
render() {
const { value, ...props } = this.props;
const thumbColor = Platform.OS === 'ios' ? null :
Platform.OS === 'android' && value ? argonTheme.COLORS.SWITCH_ON : argonTheme.COLORS.SWITCH_OFF;
return (
<Switch
value={value}
thumbColor={thumbColor}
ios_backgroundColor={argonTheme.COLORS.SWITCH_OFF}
trackColor={{ false: argonTheme.COLORS.SWITCH_ON, true: argonTheme.COLORS.SWITCH_ON }}
{...props}
/>
);
}
}
export default MkSwitch;

View File

@@ -0,0 +1,162 @@
import React from 'react';
import { StyleSheet, Dimensions, FlatList, Animated } from 'react-native';
import { Block, theme } from 'galio-framework';
const { width } = Dimensions.get('screen');
import argonTheme from '../constants/Theme';
const defaultMenu = [
{ id: 'music', title: 'Music', },
{ id: 'beauty', title: 'Beauty', },
{ id: 'fashion', title: 'Fashion', },
{ id: 'motocycles', title: 'Motocycles', },
];
export default class Tabs extends React.Component {
static defaultProps = {
data: defaultMenu,
initialIndex: null,
}
state = {
active: null,
}
componentDidMount() {
const { initialIndex } = this.props;
initialIndex && this.selectMenu(initialIndex);
}
animatedValue = new Animated.Value(1);
animate() {
this.animatedValue.setValue(0);
Animated.timing(this.animatedValue, {
toValue: 1,
duration: 300,
useNativeDriver: false, // color not supported
}).start()
}
menuRef = React.createRef();
onScrollToIndexFailed = () => {
this.menuRef.current.scrollToIndex({
index: 0,
viewPosition: 0.5
});
}
selectMenu = (id) => {
this.setState({ active: id });
this.menuRef.current.scrollToIndex({
index: this.props.data.findIndex(item => item.id === id),
viewPosition: 0.5
});
this.animate();
this.props.onChange && this.props.onChange(id);
}
renderItem = (item) => {
const isActive = this.state.active === item.id;
const textColor = this.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [argonTheme.COLORS.TEXT, isActive ? argonTheme.COLORS.WHITE : argonTheme.COLORS.TEXT],
extrapolate: 'clamp',
});
const containerStyles = [
styles.titleContainer,
!isActive && { backgroundColor: argonTheme.COLORS.SECONDARY },
isActive && styles.containerShadow
];
return (
<Block style={containerStyles}>
<Animated.Text
style={[
styles.menuTitle,
{ color: textColor },
{ fontFamily: 'open-sans-bold' },
]}
onPress={() => this.selectMenu(item.id)}>
{item.title}
</Animated.Text>
</Block>
)
}
renderMenu = () => {
const { data, ...props } = this.props;
return (
<FlatList
{...props}
data={data}
horizontal={true}
ref={this.menuRef}
extraData={this.state}
keyExtractor={(item) => item.id}
showsHorizontalScrollIndicator={false}
onScrollToIndexFailed={this.onScrollToIndexFailed}
renderItem={({ item }) => this.renderItem(item)}
contentContainerStyle={styles.menu}
/>
)
}
render() {
return (
<Block style={styles.container}>
{this.renderMenu()}
</Block>
)
}
}
const styles = StyleSheet.create({
container: {
width: width,
backgroundColor: theme.COLORS.WHITE,
zIndex: 2,
},
shadow: {
shadowColor: theme.COLORS.BLACK,
shadowOffset: { width: 0, height: 2 },
shadowRadius: 8,
shadowOpacity: 0.2,
elevation: 4,
},
menu: {
paddingHorizontal: theme.SIZES.BASE * 2.5,
paddingTop: 8,
paddingBottom: 16,
},
titleContainer: {
alignItems: 'center',
backgroundColor: argonTheme.COLORS.ACTIVE,
borderRadius: 4,
marginRight: 9,
paddingHorizontal: 10,
paddingVertical: 3,
},
containerShadow: {
shadowColor: 'black',
shadowOffset: { width: 0, height: 2 },
shadowRadius: 4,
shadowOpacity: 0.1,
elevation: 1,
},
menuTitle: {
fontWeight: '600',
fontSize: 14,
// lineHeight: 28,
paddingVertical: 8,
paddingHorizontal: 12,
color: argonTheme.COLORS.MUTED
},
});

View File

@@ -0,0 +1,21 @@
import Button from './Button';
import Card from './Card';
import DrawerItem from './DrawerItem';
import Icon from './Icon';
import Header from './Header';
import Input from './Input';
import Switch from './Switch';
import Select from './Select';
import Notification from './Notification';
export {
Button,
Card,
DrawerItem,
Icon,
Input,
Header,
Switch,
Select,
Notification
};