Skip to content

Commit f5259c9

Browse files
initial commit
0 parents  commit f5259c9

19 files changed

+6074
-0
lines changed

.eslintrc.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
root: true,
3+
extends: '@react-native-community',
4+
};

.gitignore

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Logs
2+
*.log
3+
npm-debug.log
4+
5+
# Runtime data
6+
tmp
7+
build
8+
dist
9+
10+
# Dependency directory
11+
node_modules

.prettierrc.js

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
bracketSpacing: false,
3+
jsxBracketSameLine: true,
4+
singleQuote: true,
5+
trailingComma: 'all',
6+
printWidth: 100,
7+
};

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Hossein Shabani
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# React Native Modern Datepicker 📆
2+
3+
A customizable calendar, time & month picker for React Native (including Persian Jalaali calendar & locale). For more information, please visit [website](https://github.com/HosseinShabani/react-native-modern-datepicker)

package.json

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"name": "react-native-modern-datepicker",
3+
"version": "1.0.0-beta.0",
4+
"description": "A customizable calendar, time & month picker for React Native (including Persian Jalaali calendar & locale)",
5+
"main": "src/index.js",
6+
"scripts": {
7+
"playground": "cd playground && react-native start"
8+
},
9+
"files": [
10+
"src"
11+
],
12+
"author": "Hossein Shabani",
13+
"homepage": "https://github.com/HosseinShabani/react-native-modern-datepicker",
14+
"repository": {
15+
"type": "git",
16+
"url": "https://github.com/HosseinShabani/react-native-modern-datepicker.git"
17+
},
18+
"bugs": {
19+
"url": "https://github.com/HosseinShabani/react-native-modern-datepicker/issues"
20+
},
21+
"license": "MIT",
22+
"keywords": [
23+
"react",
24+
"react-native",
25+
"react-native-datepicker",
26+
"datepicker",
27+
"calendar",
28+
"react-native-calendar",
29+
"react-native-calendars",
30+
"react-native-persian-calendar",
31+
"react-native-jalaali-calendar",
32+
"time-picker",
33+
"react-native-time-picker",
34+
"month-picker",
35+
"react-native-month-picker",
36+
"persian",
37+
"jalaali",
38+
"react-native-jalaali",
39+
"persian-calendar",
40+
"customizable-datepicker"
41+
],
42+
"dependencies": {
43+
"moment-jalaali": "^0.8.3",
44+
"prop-types": "^15.7.2"
45+
},
46+
"peerDependencies": {
47+
"react-native": ">=0.59"
48+
},
49+
"devDependencies": {
50+
"husky": ">=1",
51+
"lint-staged": ">=8",
52+
"prettier": "^1.18.2",
53+
"@babel/core": "^7.5.5",
54+
"@babel/runtime": "^7.5.5",
55+
"@react-native-community/eslint-config": "^0.0.5",
56+
"eslint": "^6.3.0",
57+
"metro-react-native-babel-preset": "^0.56.0"
58+
},
59+
"husky": {
60+
"hooks": {
61+
"pre-commit": "lint-staged"
62+
}
63+
},
64+
"lint-staged": {
65+
"*.js": [
66+
"eslint --fix",
67+
"git add"
68+
]
69+
}
70+
}

src/assets/IRANYekanMobileBold.ttf

57.4 KB
Binary file not shown.

src/assets/IRANYekanMobileRegular.ttf

58.1 KB
Binary file not shown.

src/assets/arrow.png

2.6 KB
Loading

src/datePicker/DatePicker.js

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import React, {createContext, useReducer, useContext, useState} from 'react';
2+
import {View, StyleSheet} from 'react-native';
3+
import PropTypes from 'prop-types';
4+
5+
import {Calendar, SelectMonth, SelectTime} from './components';
6+
import {utils} from '../utils';
7+
8+
const options = {
9+
backgroundColor: '#fff',
10+
textHeaderColor: '#212c35',
11+
textDefaultColor: '#2d4150',
12+
selectedTextColor: '#fff',
13+
mainColor: '#0eca2d',
14+
textSecondaryColor: '#7a92a5',
15+
borderColor: 'rgba(122, 146, 165, 0.1)',
16+
defaultFont: 'System',
17+
headerFont: 'System',
18+
textFontSize: 15,
19+
textHeaderFontSize: 17,
20+
headerAnimationDistance: 50,
21+
daysAnimationDistance: 200,
22+
};
23+
24+
const reducer = (state, action) => {
25+
switch (action.type) {
26+
case 'set':
27+
return {...state, ...action};
28+
case 'toggleMonth':
29+
return {...state, monthOpen: !state.monthOpen};
30+
case 'toggleTime':
31+
return {...state, timeOpen: !state.timeOpen};
32+
default:
33+
throw new Error('Unexpected action');
34+
}
35+
};
36+
37+
const CalendarContext = createContext();
38+
39+
const useCalendar = () => {
40+
const contextValue = useContext(CalendarContext);
41+
return contextValue;
42+
};
43+
44+
const DatePicker = props => {
45+
const calendarUtils = new utils(props);
46+
const contextValue = {
47+
...props,
48+
options: {...options, ...props.options},
49+
utils: calendarUtils,
50+
state: useReducer(reducer, {
51+
activeDate: props.current || calendarUtils.getToday(),
52+
selectedDate: '',
53+
monthOpen: props.mode === 'monthYear',
54+
timeOpen: props.mode === 'time',
55+
}),
56+
};
57+
const [minHeight, setMinHeight] = useState(0);
58+
const style = styles(contextValue.options);
59+
60+
const renderBody = () => {
61+
switch (contextValue.mode) {
62+
default:
63+
case 'datepicker':
64+
return (
65+
<React.Fragment>
66+
<Calendar />
67+
<SelectMonth />
68+
<SelectTime />
69+
</React.Fragment>
70+
);
71+
case 'calendar':
72+
return (
73+
<React.Fragment>
74+
<Calendar />
75+
<SelectMonth />
76+
</React.Fragment>
77+
);
78+
case 'monthYear':
79+
return <SelectMonth />;
80+
case 'time':
81+
return <SelectTime />;
82+
}
83+
};
84+
85+
return (
86+
<CalendarContext.Provider value={contextValue}>
87+
<View
88+
style={[style.container, {minHeight}, props.style]}
89+
onLayout={({nativeEvent}) => setMinHeight(nativeEvent.layout.width * 0.9 + 50)}>
90+
{renderBody()}
91+
</View>
92+
</CalendarContext.Provider>
93+
);
94+
};
95+
96+
const styles = theme =>
97+
StyleSheet.create({
98+
container: {
99+
backgroundColor: theme.backgroundColor,
100+
position: 'relative',
101+
width: '100%',
102+
overflow: 'hidden',
103+
},
104+
});
105+
106+
const optionsShape = {
107+
backgroundColor: PropTypes.string,
108+
textHeaderColor: PropTypes.string,
109+
textDefaultColor: PropTypes.string,
110+
selectedTextColor: PropTypes.string,
111+
mainColor: PropTypes.string,
112+
textSecondaryColor: PropTypes.string,
113+
borderColor: PropTypes.string,
114+
defaultFont: PropTypes.string,
115+
headerFont: PropTypes.string,
116+
textFontSize: PropTypes.number,
117+
textHeaderFontSize: PropTypes.number,
118+
headerAnimationDistance: PropTypes.number,
119+
daysAnimationDistance: PropTypes.number,
120+
};
121+
const modeArray = ['datepicker', 'calendar', 'monthYear', 'time'];
122+
const minuteIntervalArray = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60];
123+
124+
DatePicker.defaultProps = {
125+
onSelectedChange: () => null,
126+
onMonthYearChange: () => null,
127+
onTimeChange: () => null,
128+
onDateChange: () => null,
129+
current: '',
130+
minimumDate: '',
131+
maximumDate: '',
132+
selectorStartingYear: 0,
133+
selectorEndingYear: 3000,
134+
disableDateChange: false,
135+
isGregorian: true,
136+
options: {},
137+
mode: 'datepicker',
138+
minuteInterval: 5,
139+
style: {},
140+
};
141+
142+
DatePicker.propTypes = {
143+
onSelectedChange: PropTypes.func,
144+
onMonthYearChange: PropTypes.func,
145+
onTimeChange: PropTypes.func,
146+
onDateChange: PropTypes.func,
147+
current: PropTypes.string,
148+
minimumDate: PropTypes.string,
149+
maximumDate: PropTypes.string,
150+
selectorStartingYear: PropTypes.number,
151+
selectorEndingYear: PropTypes.number,
152+
disableDateChange: PropTypes.bool,
153+
isGregorian: PropTypes.bool,
154+
options: PropTypes.shape(optionsShape),
155+
mode: PropTypes.oneOf(modeArray),
156+
minuteInterval: PropTypes.oneOf(minuteIntervalArray),
157+
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
158+
};
159+
160+
export {DatePicker, CalendarContext, useCalendar};

src/datePicker/components/Calendar.js

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import React, {useEffect} from 'react';
2+
import {View, StyleSheet, Text, Animated} from 'react-native';
3+
4+
import {Header, Days} from '.';
5+
import {useCalendar} from '../DatePicker';
6+
7+
const Calendar = () => {
8+
const {options, state, utils, onSelectedChange} = useCalendar();
9+
const [mainState] = state;
10+
const style = styles(options);
11+
const [{shownAnimation}, changeMonthAnimation] = utils.useMonthAnimation(
12+
mainState.activeDate,
13+
options.daysAnimationDistance,
14+
);
15+
16+
useEffect(() => {
17+
mainState.selectedDate && onSelectedChange(mainState.selectedDate);
18+
}, [mainState.selectedDate, onSelectedChange]);
19+
20+
return (
21+
<View style={style.container}>
22+
<Header changeMonth={changeMonthAnimation} />
23+
<View style={style.daysName}>
24+
{utils.config.dayNamesShort.map(item => (
25+
<Text key={item} style={style.daysNameText}>
26+
{item}
27+
</Text>
28+
))}
29+
</View>
30+
<View style={style.daysContainer}>
31+
<Animated.View style={[style.days, shownAnimation]}>
32+
<Days />
33+
</Animated.View>
34+
</View>
35+
</View>
36+
);
37+
};
38+
39+
const styles = theme =>
40+
StyleSheet.create({
41+
container: {
42+
flexDirection: 'column',
43+
flex: 1,
44+
},
45+
daysName: {
46+
paddingBottom: 10,
47+
marginBottom: 0,
48+
alignItems: 'center',
49+
flexDirection: 'row-reverse',
50+
justifyContent: 'space-around',
51+
borderBottomColor: theme.borderColor,
52+
borderBottomWidth: 1,
53+
marginHorizontal: 15,
54+
},
55+
daysNameText: {
56+
fontFamily: theme.defaultFont,
57+
color: theme.textSecondaryColor,
58+
fontSize: theme.textFontSize,
59+
},
60+
daysContainer: {
61+
flex: 1,
62+
position: 'relative',
63+
overflow: 'hidden',
64+
margin: 15,
65+
marginTop: 5,
66+
marginBottom: 0,
67+
},
68+
days: {
69+
position: 'absolute',
70+
width: '100%',
71+
height: '100%',
72+
top: 0,
73+
right: 0,
74+
},
75+
});
76+
77+
export {Calendar};

0 commit comments

Comments
 (0)