Skip to content

Commit

Permalink
Merge pull request #53 from farhoudshapouran/calendar-modes
Browse files Browse the repository at this point in the history
calendar modes
  • Loading branch information
farhoudshapouran authored Jan 27, 2024
2 parents f3617e6 + 191538e commit bc776a8
Show file tree
Hide file tree
Showing 22 changed files with 927 additions and 264 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "@react-native-community",
"ignorePatterns": [".*.js", ".*.ts", "node_modules/", "lib/", "example/"]
}
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function App() {
<View style={styles.container}>
<DateTimePicker
value={value}
onValueChange={(date) => setValue(date)}
onChange={(date) => setValue(date)}
/>
</View>
)
Expand All @@ -61,11 +61,11 @@ For more, take a look at the `/example` directory.
| Name | Type | Default | Description |
| ------------------------ | --------------- | --------------- | -------------------------------------------------------------------------------------- |
| value | `DateType` | `Dayjs` | DatePicker value to display selected date |
| onValueChange | `func` | `() => {}` | Called when the new date selected from DatePicker |
| onChange | `Function` | `() => {}` | Called when the new date selected from DatePicker |
| mode | `string` | `'datetime'` | Defines the DatePicker mode `['datetime', 'date', 'time']` |
| locale | `string` | `'en'` | Defines the DatePicker locale |
| minimumDate | `DateType` | `null` | Defines DatePicker minimum selectable date |
| maximumDate | `DateType` | `null` | Defines DatePicker maximum selectable date |
| minDate | `DateType` | `null` | Defines DatePicker minimum selectable date |
| maxDate | `DateType` | `null` | Defines DatePicker maximum selectable date |
| firstDayOfWeek | `number` | `0` | Defines the starting day of week, number 0-6, 0 - Sunday, 6 - Saturday |
| displayFullDays | `boolean` | `false` | Defines show previous and next month's days in the current calendar view |
| calendarTextStyle | `TextStyle` | `null` | Defines all text styles inside the calendar (Days, Months, Years, Hours, and Minutes) |
Expand Down
1 change: 1 addition & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.6",
"react-native-bouncy-checkbox": "^3.0.7",
"react-native-web": "~0.19.6"
},
"devDependencies": {
Expand Down
277 changes: 241 additions & 36 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useCallback, useState } from 'react';
import {
StyleSheet,
View,
Expand All @@ -7,8 +7,10 @@ import {
Image,
Linking,
SafeAreaView,
TouchableOpacity,
} from 'react-native';
import DateTimePicker, { DateType } from 'react-native-ui-datepicker';
import BouncyCheckbox from 'react-native-bouncy-checkbox';
import DateTimePicker, { DateType, ModeType } from 'react-native-ui-datepicker';
import dayjs from 'dayjs';
import 'dayjs/locale/en';
import 'dayjs/locale/de';
Expand All @@ -35,10 +37,42 @@ const Themes: ITheme[] = [
const Locales = ['en', 'de', 'es', 'fr', 'tr'];

export default function App() {
const [value, setValue] = useState<DateType>(dayjs());
const [mode, setMode] = useState<ModeType>('single');
const [timePicker, setTimePicker] = useState(false);

const [date, setDate] = useState<DateType | undefined>();
const [range, setRange] = React.useState<{
startDate: DateType;
endDate: DateType;
}>({ startDate: undefined, endDate: undefined });
const [dates, setDates] = useState<DateType[] | undefined>();

const [theme, setTheme] = useState<ITheme | undefined>(Themes[0]);
const [locale, setLocale] = useState('en');

const onChangeMode = useCallback(
(value: ModeType) => {
setDate(undefined);
setRange({ startDate: undefined, endDate: undefined });
setDates(undefined);
setMode(value);
},
[setMode, setDate, setRange, setDates]
);

const onChange = useCallback(
(params) => {
if (mode === 'single') {
setDate(params.date);
} else if (mode === 'range') {
setRange(params);
} else if (mode === 'multiple') {
setDates(params.dates);
}
},
[mode]
);

return (
<SafeAreaView style={styles.container}>
<View style={styles.body}>
Expand All @@ -63,6 +97,14 @@ export default function App() {
))}
</View>
<View style={styles.localeContainer}>
<Text
style={{
// eslint-disable-next-line react-native/no-inline-styles
marginRight: 8,
}}
>
Locale:
</Text>
{Locales.map((item, index) => (
<Pressable
key={index}
Expand Down Expand Up @@ -91,16 +133,119 @@ export default function App() {
</Pressable>
))}
</View>
<View style={styles.modesContainer}>
<Text
style={{
// eslint-disable-next-line react-native/no-inline-styles
marginRight: 8,
}}
>
Mode:
</Text>
<TouchableOpacity
style={[
styles.modeSelect,
{
// eslint-disable-next-line react-native/no-inline-styles
backgroundColor:
mode === 'single' ? theme?.mainColor : undefined,
},
]}
onPress={() => onChangeMode('single')}
>
<Text
style={[
styles.modeSelectText,
mode === 'single' && { color: theme?.activeTextColor },
]}
>
Single
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.modeSelect,
// eslint-disable-next-line react-native/no-inline-styles
{
backgroundColor:
mode === 'range' ? theme?.mainColor : undefined,
},
]}
onPress={() => onChangeMode('range')}
>
<Text
style={[
styles.modeSelectText,
mode === 'range' && { color: theme?.activeTextColor },
]}
>
Range
</Text>
</TouchableOpacity>
<TouchableOpacity
style={[
styles.modeSelect,
// eslint-disable-next-line react-native/no-inline-styles
{
backgroundColor:
mode === 'multiple' ? theme?.mainColor : undefined,
},
]}
onPress={() => onChangeMode('multiple')}
>
<Text
style={[
styles.modeSelectText,
mode === 'multiple' && { color: theme?.activeTextColor },
]}
>
Multiple
</Text>
</TouchableOpacity>
</View>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
gap: 10,
marginBottom: 20,
}}
>
<BouncyCheckbox
size={20}
text="Time Picker"
fillColor={theme?.mainColor}
textStyle={{
fontSize: 14,
color: '#000',
marginLeft: -8,
textDecorationLine: 'none',
}}
useNativeDriver={false}
isChecked={timePicker}
disableBuiltInState
onPress={() => setTimePicker(!timePicker)}
disabled={mode !== 'single'}
/>
<Text style={{ fontSize: 13, color: 'gray' }}>
(Works in Single mode)
</Text>
</View>
<View style={styles.datePickerContainer}>
<View style={styles.datePicker}>
<DateTimePicker
value={value}
//minimumDate={dayjs().startOf('day')}
//maximumDate={dayjs().add(3, 'day').endOf('day')}
//firstDayOfWeek={1}
displayFullDays={true}
mode={mode}
date={date}
locale={locale}
onValueChange={(date) => setValue(date)}
startDate={range.startDate}
endDate={range.endDate}
dates={dates}
//minDate={dayjs().startOf('day')}
//maxDate={dayjs().add(3, 'day').endOf('day')}
//firstDayOfWeek={1}
displayFullDays
timePicker={timePicker}
onChange={onChange}
headerButtonColor={theme?.mainColor}
selectedItemColor={theme?.mainColor}
// eslint-disable-next-line react-native/no-inline-styles
Expand All @@ -112,35 +257,77 @@ export default function App() {
todayContainerStyle={{
borderWidth: 1,
}}
mode="datetime"
/>
<View style={styles.footerContainer}>
<Text>
{dayjs(value).locale(locale).format('MMMM, DD, YYYY - HH:mm')}
</Text>
<Pressable
onPress={() => {
setValue(dayjs());
}}
accessibilityRole="button"
accessibilityLabel="Today"
>
<View
style={[
styles.todayButton,
{ backgroundColor: theme?.mainColor },
]}
>
<Text
style={[
styles.todayButtonText,
{ color: theme?.activeTextColor },
]}
<View style={styles.footer}>
{mode === 'single' ? (
<View style={styles.footerContainer}>
<Text>
{date
? dayjs(date)
.locale(locale)
.format(
timePicker
? 'MMMM, DD, YYYY - HH:mm'
: 'MMMM, DD, YYYY'
)
: '...'}
</Text>
<Pressable
onPress={() => setDate(dayjs())}
accessibilityRole="button"
accessibilityLabel="Today"
>
Today
<View
style={[
styles.todayButton,
{ backgroundColor: theme?.mainColor },
]}
>
<Text
style={[
styles.todayButtonText,
{ color: theme?.activeTextColor },
]}
>
Today
</Text>
</View>
</Pressable>
</View>
) : mode === 'range' ? (
<View style={{ gap: 3 }}>
<Text>
<Text style={{ marginRight: 5, fontWeight: 'bold' }}>
Start Date:
</Text>
{range.startDate
? dayjs(range.startDate)
.locale(locale)
.format('MMMM, DD, YYYY')
: '...'}
</Text>
<Text>
<Text style={{ marginRight: 5, fontWeight: 'bold' }}>
End Date:
</Text>
{range.endDate
? dayjs(range.endDate)
.locale(locale)
.format('MMMM, DD, YYYY')
: '...'}
</Text>
</View>
) : mode === 'multiple' ? (
<View style={{ gap: 3 }}>
<Text style={{ fontWeight: 'bold' }}>Selected Dates:</Text>
{dates &&
dates.map((d, index) => (
<Text key={index}>
{dayjs(d).locale(locale).format('MMMM, DD, YYYY')}
</Text>
))}
</View>
</Pressable>
) : null}
</View>
</View>
</View>
Expand Down Expand Up @@ -219,6 +406,21 @@ const styles = StyleSheet.create({
localeButtonText: {
fontSize: 15,
},
modesContainer: {
flexDirection: 'row',
alignItems: 'center',
gap: 6,
marginBottom: 20,
},
modeSelect: {
paddingHorizontal: 15,
paddingVertical: 8,
borderRadius: 20,
},
modeSelectText: {
fontSize: 13,
fontWeight: 'bold',
},
datePickerContainer: {
alignItems: 'center',
},
Expand All @@ -232,12 +434,15 @@ const styles = StyleSheet.create({
shadowOpacity: 0.1,
shadowOffset: { width: 0, height: 0 },
},
footer: {
paddingHorizontal: 5,
paddingVertical: 5,
marginTop: 15,
},
footerContainer: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 5,
paddingVertical: 5,
},
todayButton: {
paddingHorizontal: 16,
Expand Down
5 changes: 5 additions & 0 deletions example/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6979,6 +6979,11 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==

react-native-bouncy-checkbox@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/react-native-bouncy-checkbox/-/react-native-bouncy-checkbox-3.0.7.tgz#011aef92b4fbde2a1f223165626c56a9ffe637fb"
integrity sha512-776TgMGt9wTpOQA1TcvFjL5VUn6o945wFYf3Ztqva62/vT2o3JAezLiP7hYh2Svd+PewfWBYSPMs4jeaSoS8Sg==

react-native-web@~0.19.6:
version "0.19.9"
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.19.9.tgz#6ee43e6c64d886b1d739f100fed07927541ee003"
Expand Down
Loading

0 comments on commit bc776a8

Please sign in to comment.