Skip to content

Commit

Permalink
feat: languageItemProps for proper prop drilling
Browse files Browse the repository at this point in the history
  • Loading branch information
WrathChaos committed Oct 16, 2022
1 parent c71ae4b commit cd3f0ff
Show file tree
Hide file tree
Showing 18 changed files with 270 additions and 22 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const data: ILanguagePicker[] = [
| itemContainer | default | default | change the language item container style |
| imageComponent | default | React.ReactNode / React.ReactNode[] | change the language image component |
| checkComponent | default | React.ReactNode / React.ReactNode[] | change the check component |
| languageItemProps | default | ILanguageItemProps | change the language item props |

## Future Plans

Expand Down
13 changes: 9 additions & 4 deletions example/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const App = () => {
alignItems: 'center',
paddingTop: 50,
backgroundColor: '#EFEFEF',
}}>
}}
>
<Text
style={{
textAlign: 'center',
Expand All @@ -51,7 +52,8 @@ const App = () => {
color: '#454A62',
marginTop: 32,
marginBottom: 30,
}}>
}}
>
Language
</Text>
<Text
Expand All @@ -62,13 +64,16 @@ const App = () => {
fontSize: 13,
color: '#2F3452',
marginBottom: 40,
}}>
}}
>
You can choose the language and costumise your application in the
language you want
</Text>
<LanguagePicker
initialIndex={1}
activeBorderColor="red"
languageItemProps={{
activeBorderColor: 'red',
}}
data={data}
onSelect={(selectedItem: ILanguagePicker) => {
console.log(selectedItem);
Expand Down
11 changes: 11 additions & 0 deletions example/lib/LanguagePicker.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Dimensions, StyleSheet } from "react-native";

const windowWidth = Dimensions.get("window").width;
const windowHeight = Dimensions.get("window").height;

export const _container = (width: number, height: number) => ({
width: width,
height: height,
});

export default StyleSheet.create({});
67 changes: 67 additions & 0 deletions example/lib/LanguagePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, {useState} from 'react';
import {Dimensions, FlatList, ViewStyle} from 'react-native';
/**
* ? Local Imports
*/
import {_container} from './LanguagePicker.style';
import LanguageItem, {ILanguageItemProps} from './language-item/LanguageItem';

const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;

export interface ILanguagePicker {
title: string;
imageSource: any;
language?: string;
}

export interface ILanguagePickerProps {
data: ILanguagePicker[];
flatListStyle?: ViewStyle;
containerWidth?: number;
containerHeight?: number;
initialIndex?: number;
languageItemProps?: ILanguageItemProps;
onSelect?: (selectedItem: ILanguagePicker) => void;
}

const LanguagePicker: React.FC<ILanguagePickerProps> = ({
data,
flatListStyle,
initialIndex = -1,
containerWidth = windowWidth * 0.9,
containerHeight = windowHeight * 0.7,
onSelect,
languageItemProps,
...rest
}) => {
const [selectedItem, setSelectedItem] = useState<ILanguagePicker | undefined>(
data[initialIndex],
);

const handleOnSelectItem = (item: ILanguagePicker) => {
setSelectedItem(item);
onSelect && onSelect(item);
};

const renderItem = (item: ILanguagePicker) => (
<LanguageItem
{...languageItemProps}
onSelect={handleOnSelectItem}
isActive={selectedItem === item}
item={item}
/>
);

return (
<FlatList
{...rest}
data={data}
style={[_container(containerWidth, containerHeight), flatListStyle]}
renderItem={({item}) => renderItem(item)}
keyExtractor={item => item.title}
/>
);
};

export default LanguagePicker;
42 changes: 42 additions & 0 deletions example/lib/language-item/LanguageItem.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { StyleSheet, Dimensions, ViewStyle, TextStyle } from "react-native";
const windowWidth = Dimensions.get("window").width;
const windowHeight = Dimensions.get("window").height;

export const _itemContainer = (
backgroundColor: string,
borderColor: string,
width: number,
height: number,
): ViewStyle => ({
borderColor: borderColor,
backgroundColor: backgroundColor,
borderWidth: 2,
borderRadius: 20,
height: height,
width: width,
marginBottom: 12,
flexDirection: "row",
alignItems: "center",
paddingLeft: 24,
});

export const _titleStyle = (color: string): TextStyle => ({
fontWeight: "600",
color: color,
fontSize: 16,
});

export default StyleSheet.create({
imageStyle: {
width: 40,
height: 40,
marginRight: 18,
},
checkImageStyle: {
position: "absolute",
right: 24,
width: 20,
height: 20,
color: "red",
},
});
74 changes: 74 additions & 0 deletions example/lib/language-item/LanguageItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react';
import {
Dimensions,
Image,
ImageSourcePropType,
Text,
ViewStyle,
} from 'react-native';
import RNBounceable from '@freakycoder/react-native-bounceable';
/**
* ? Local Imports
*/
import {ILanguagePicker} from '../LanguagePicker';
import styles, {_itemContainer, _titleStyle} from './LanguageItem.style';

const windowWidth = Dimensions.get('window').width;

interface ILanguageItemRequiredProps extends ILanguageItemProps {
item: ILanguagePicker;
isActive: boolean;
}

export interface ILanguageItemProps {
width?: number;
height?: number;
backgroundColor?: string;
activeBorderColor?: string;
textColor?: string;
itemContainer?: ViewStyle;
imageComponent?: React.ReactNode | React.ReactNode[];
checkComponent?: React.ReactNode | React.ReactNode[];
rightImageSource?: ImageSourcePropType;
onSelect?: (selectedItem: ILanguagePicker) => void;
}

const LanguageItem: React.FC<ILanguageItemRequiredProps> = ({
itemContainer,
item,
width = windowWidth * 0.9,
height = 80,
isActive,
backgroundColor = '#FFFFFF',
textColor = '#2F3452',
imageComponent,
checkComponent,
activeBorderColor = '#504ED9',
rightImageSource,
onSelect,
}) => {
const borderColor = isActive ? activeBorderColor : backgroundColor;
return (
<RNBounceable
style={[
_itemContainer(backgroundColor, borderColor, width, height),
itemContainer,
]}
onPress={() => onSelect && onSelect(item)}
>
{imageComponent || (
<Image source={item.imageSource} style={styles.imageStyle} />
)}
<Text style={_titleStyle(textColor)}>{item.title}</Text>
{isActive &&
(checkComponent || (
<Image
source={rightImageSource || require('../local-assets/check.png')}
style={styles.checkImageStyle}
/>
))}
</RNBounceable>
);
};

export default LanguageItem;
Binary file added example/lib/local-assets/america.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/lib/local-assets/check.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/lib/local-assets/germany.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/lib/local-assets/italy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/lib/local-assets/japan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/lib/local-assets/sweden.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/lib/local-assets/turkey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 36 additions & 7 deletions example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,39 @@
// prettier-ignore
{
"extends": "@tsconfig/react-native/tsconfig.json", /* Recommended React Native TSConfig base */
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */

/* Completeness */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
"target": "esnext",
"module": "es6",
"lib": ["es6"],
"allowJs": true,
"jsx": "react-native",
"noImplicitAny": false,
"incremental": true /* Enable incremental compilation */,
"isolatedModules": true,
"strict": true,
"moduleResolution": "node",
"baseUrl": "./",
"outDir": "build/dist",
"noEmitHelpers": true,
"alwaysStrict": true,
"strictFunctionTypes": true,
"resolveJsonModule": true,
"importHelpers": false,
"experimentalDecorators": true,
"strictPropertyInitialization": false,
"allowSyntheticDefaultImports": true,
"strictNullChecks": true,
"skipDefaultLibCheck": true,
"skipLibCheck": true,
"esModuleInterop": true,
"typeRoots": ["./node_modules/@types", "./@types"],
"declaration": true /* Generates corresponding '.d.ts' file. */,
"sourceMap": true /* Generates corresponding '.map' file. */
},
"exclude": [
"example",
"example-manual-state",
"node_modules",
"babel.config.js",
"metro.config.js",
"jest.config.js"
]
}
7 changes: 5 additions & 2 deletions lib/LanguagePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Dimensions, FlatList, ViewStyle } from "react-native";
* ? Local Imports
*/
import { _container } from "./LanguagePicker.style";
import LanguageItem from "./language-item/LanguageItem";
import LanguageItem, { ILanguageItemProps } from "./language-item/LanguageItem";

const windowWidth = Dimensions.get("window").width;
const windowHeight = Dimensions.get("window").height;
Expand All @@ -15,12 +15,13 @@ export interface ILanguagePicker {
language?: string;
}

interface ILanguagePickerProps {
export interface ILanguagePickerProps {
data: ILanguagePicker[];
flatListStyle?: ViewStyle;
containerWidth?: number;
containerHeight?: number;
initialIndex?: number;
languageItemProps?: ILanguageItemProps;
onSelect?: (selectedItem: ILanguagePicker) => void;
}

Expand All @@ -31,6 +32,7 @@ const LanguagePicker: React.FC<ILanguagePickerProps> = ({
containerWidth = windowWidth * 0.9,
containerHeight = windowHeight * 0.7,
onSelect,
languageItemProps,
...rest
}) => {
const [selectedItem, setSelectedItem] = useState<ILanguagePicker | undefined>(
Expand All @@ -44,6 +46,7 @@ const LanguagePicker: React.FC<ILanguagePickerProps> = ({

const renderItem = (item: ILanguagePicker) => (
<LanguageItem
{...languageItemProps}
onSelect={handleOnSelectItem}
isActive={selectedItem === item}
item={item}
Expand Down
10 changes: 7 additions & 3 deletions lib/language-item/LanguageItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ import { ILanguagePicker } from "../LanguagePicker";
import styles, { _itemContainer, _titleStyle } from "./LanguageItem.style";

const windowWidth = Dimensions.get("window").width;
interface ILanguageItem {

interface ILanguageItemRequiredProps extends ILanguageItemProps {
item: ILanguagePicker;
isActive: boolean;
}

export interface ILanguageItemProps {
width?: number;
height?: number;
isActive: boolean;
backgroundColor?: string;
activeBorderColor?: string;
textColor?: string;
Expand All @@ -29,7 +33,7 @@ interface ILanguageItem {
onSelect?: (selectedItem: ILanguagePicker) => void;
}

const LanguageItem: React.FC<ILanguageItem> = ({
const LanguageItem: React.FC<ILanguageItemRequiredProps> = ({
itemContainer,
item,
width = windowWidth * 0.9,
Expand Down
Loading

0 comments on commit cd3f0ff

Please sign in to comment.