Skip to content

Commit 6839d29

Browse files
Amber-Nan杨楠
andauthored
feat(Calendar): 新增日历组件 & 添加文档 #334
* fix(Divider):优化 gutter属性不生效问题 * feat(Divider): 增加分割线标题的位置调整功能 & 更新文档 * feat(Rating):增加自定义每项的提示信息 & 更新文档 * feat(Rating):增加只读功能 & 文档更新 * feat(Timeline): 增加改变时间轴内容相对位置功能 & 文档更新 * style(Timeline):Update Readme.md img * feat(Timeline):增加自定义图标 & 文档更新 * feat(Timeline):优化自定义图标 & 文档更新 * feat:新增Calendar 日历组件 * doc(website): Update Calendar Readme.md Co-authored-by: 杨楠 <yangnan@nihaosi.com>
1 parent 531ba11 commit 6839d29

File tree

9 files changed

+515
-0
lines changed

9 files changed

+515
-0
lines changed

example/examples/src/routes.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,4 +458,12 @@ export const stackPageData: Routes[] = [
458458
header: () => null,
459459
},
460460
},
461+
{
462+
name: 'Calendar',
463+
component: require('./routes/Calendar').default,
464+
params: {
465+
title: 'Calendar 日历',
466+
description: '展示日历',
467+
},
468+
},
461469
];
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import React from 'react';
2+
import {Text, View} from 'react-native';
3+
import {Calendar, Spacing} from '@uiw/react-native';
4+
import {ComProps} from '../../routes';
5+
import Layout, {Container} from '../../Layout';
6+
7+
const {Header, Body, Card, Footer} = Layout;
8+
9+
export interface CalendarViewProps extends ComProps {}
10+
11+
export default class CalendarView extends React.Component<CalendarViewProps> {
12+
render() {
13+
const {route} = this.props;
14+
const description = route.params.description;
15+
const title = route.params.title;
16+
return (
17+
<Container>
18+
<Layout>
19+
<Header title={title} description={description} />
20+
<Body>
21+
<Calendar />
22+
<Spacing size={'large'} />
23+
<Calendar color="red" />
24+
</Body>
25+
<Footer />
26+
</Layout>
27+
</Container>
28+
);
29+
}
30+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
Calendar 日历
2+
---
3+
4+
展示日历
5+
6+
### 基础示例
7+
8+
<img src='https://user-images.githubusercontent.com/66067296/141421928-d46ffd84-2349-49ac-8b6f-4e8455a017eb.gif' alt='Calendar' style='zoom:33%;' />
9+
10+
### 基础示例
11+
12+
```jsx
13+
import React from 'react';
14+
import { Text, View } from 'react-native';
15+
import { Calendar } from '@uiw/react-native';
16+
import { ComProps } from '../../routes';
17+
import Layout, { Container } from '../../Layout';
18+
19+
const { Header, Body, Card, Footer } = Layout;
20+
21+
export interface CalendarViewProps extends ComProps { }
22+
23+
export default class CalendarView extends React.Component<CalendarViewProps> {
24+
render() {
25+
const { route } = this.props;
26+
const description = route.params.description;
27+
const title = route.params.title;
28+
return (
29+
<Container>
30+
<Layout>
31+
<Header title={title} description={description} />
32+
<Body>
33+
<Calendar />
34+
</Body>
35+
<Footer />
36+
</Layout>
37+
</Container>
38+
);
39+
}
40+
}
41+
```
42+
43+
### 自定义日历颜色
44+
45+
```jsx
46+
import React from 'react';
47+
import { Text, View } from 'react-native';
48+
import { Calendar } from '@uiw/react-native';
49+
import { ComProps } from '../../routes';
50+
import Layout, { Container } from '../../Layout';
51+
52+
const { Header, Body, Card, Footer } = Layout;
53+
54+
export interface CalendarViewProps extends ComProps { }
55+
56+
export default class CalendarView extends React.Component<CalendarViewProps> {
57+
render() {
58+
const { route } = this.props;
59+
const description = route.params.description;
60+
const title = route.params.title;
61+
return (
62+
<Container>
63+
<Layout>
64+
<Header title={title} description={description} />
65+
<Body>
66+
<Calendar color="red" />
67+
</Body>
68+
<Footer />
69+
</Layout>
70+
</Container>
71+
);
72+
}
73+
}
74+
```
75+
76+
### props
77+
78+
| 参数 | 说明 | 类型 | 默认值 |
79+
|------|------|-----|------|
80+
| `color` | 设置日历颜色 | String | "#329BCB" |
Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { View, Text, ViewProps, TextProps, StyleSheet, TouchableOpacity, Dimensions } from 'react-native';
3+
import { color } from 'src/utils';
4+
import Icon from '../Icon';
5+
import { getMonths, getWeeksArray, daysArrProps } from './utils';
6+
7+
export let MainWidth = Dimensions.get('window').width;
8+
export let newDates = new Date();
9+
export let toYear = newDates.getFullYear();
10+
export let toMonth = newDates.getMonth();
11+
export let toDays = newDates.getDate();
12+
13+
export interface CalendarProps extends ViewProps {
14+
// 日历颜色
15+
color: string;
16+
}
17+
const Calendar = (props: CalendarProps) => {
18+
const { color = '#329BCB' } = props;
19+
20+
const [currentYear, setCurrentYear] = useState<number>(toYear);
21+
const [currentMonth, setCurrentMonth] = useState<number>(toMonth);
22+
const [currentDays, setCurrentDays] = useState<number>(toDays);
23+
const [dayData, setDayData] = useState<number[]>([]);
24+
const [lastData, setLastData] = useState<number[]>([]);
25+
const [nextData, setNextData] = useState<number[]>([]);
26+
27+
useEffect(() => {
28+
let toMonths = getMonths(currentYear, currentMonth);
29+
setLastData(toMonths[0]);
30+
setDayData(toMonths[1]);
31+
setNextData(toMonths[2]);
32+
}, [currentYear, currentMonth]);
33+
34+
const renderWeekDays = () => {
35+
let weekdays = ['日', '一', '二', '三', '四', '五', '六'];
36+
return weekdays.map((day) => {
37+
return (
38+
<Text key={day} style={styles.calendarWedText}>
39+
{day.toLocaleUpperCase()}
40+
</Text>
41+
);
42+
});
43+
};
44+
45+
const renderWeeks = () => {
46+
let groupedDays = getWeeksArray(lastData, dayData, nextData);
47+
return groupedDays.map((weekDays, index) => {
48+
return (
49+
<View key={index} style={styles.weekDays}>
50+
{renderDays(weekDays)}
51+
</View>
52+
);
53+
});
54+
};
55+
const renderDays = (weekDays: daysArrProps[]) => {
56+
return weekDays.map((day, index) => {
57+
let type = 0;
58+
if (day.type === 'last' || day.type === 'next') {
59+
type = 1;
60+
} else if (
61+
currentYear === toYear &&
62+
currentMonth === toMonth &&
63+
day.monthDays === currentDays &&
64+
currentDays === toDays
65+
) {
66+
type = 2;
67+
} else if (day.monthDays === currentDays) {
68+
type = 3;
69+
} else {
70+
type = 0;
71+
}
72+
return (
73+
<TouchableOpacity
74+
key={index}
75+
style={
76+
type === 1
77+
? styles.otherMonth
78+
: type === 2
79+
? [styles.currentMonth, { backgroundColor: color }]
80+
: type === 3
81+
? [styles.selectMonth, { borderColor: color }]
82+
: styles.day
83+
}
84+
onPress={() => goSelectDay(day)}
85+
>
86+
<Text style={[styles.dayText, { color: type === 1 ? '#B5B5B5' : type === 2 ? '#fff' : '#000' }]}>
87+
{day.monthDays}
88+
</Text>
89+
</TouchableOpacity>
90+
);
91+
});
92+
};
93+
const goSelectDay = (day: daysArrProps) => {
94+
if (day.type === 'current') {
95+
setCurrentDays(day.monthDays);
96+
} else if (day.type === 'last') {
97+
setCurrentDays(day.monthDays);
98+
getCurrentMonth('last');
99+
} else {
100+
setCurrentDays(day.monthDays);
101+
getCurrentMonth('next');
102+
}
103+
};
104+
const getCurrentYear = (type: string) => {
105+
if (type === 'last') {
106+
let year = currentYear - 1;
107+
setCurrentYear(year);
108+
} else {
109+
let year = currentYear + 1;
110+
setCurrentYear(year);
111+
}
112+
};
113+
const getCurrentMonth = (type: string) => {
114+
if (type === 'last') {
115+
let month = currentMonth - 1;
116+
if (month < 0) {
117+
getCurrentYear('last');
118+
setCurrentMonth(11);
119+
} else {
120+
setCurrentMonth(month);
121+
}
122+
} else {
123+
let month = currentMonth + 1;
124+
if (month > 11) {
125+
getCurrentYear('next');
126+
setCurrentMonth(0);
127+
} else {
128+
setCurrentMonth(month);
129+
}
130+
}
131+
};
132+
const goToday = () => {
133+
setCurrentYear(toYear);
134+
setCurrentMonth(toMonth);
135+
setCurrentDays(toDays);
136+
};
137+
const goCurrentDay = (day: number) => {
138+
setCurrentDays(day);
139+
};
140+
141+
return (
142+
<View style={{ flex: 1, backgroundColor: '#fff' }}>
143+
<View style={[styles.header, { backgroundColor: color }]}>
144+
<TouchableOpacity>
145+
<View style={styles.headerBtn}>
146+
<Icon name="left" size={20} color={'#fff'} />
147+
<Text style={styles.headerText}>Menu</Text>
148+
</View>
149+
</TouchableOpacity>
150+
<View>
151+
<Text style={styles.headerText}>Calendar</Text>
152+
</View>
153+
<TouchableOpacity onPress={() => goToday()}>
154+
<Text style={styles.headerText}>Today</Text>
155+
</TouchableOpacity>
156+
</View>
157+
158+
<View style={styles.calendarHeader}>
159+
<View style={styles.calendarHeaderItem}>
160+
<TouchableOpacity onPress={() => getCurrentYear('last')}>
161+
<Icon name="left" size={20} color={'#333'} />
162+
</TouchableOpacity>
163+
<Text style={styles.calendarHeaderText}>{currentYear}</Text>
164+
<TouchableOpacity onPress={() => getCurrentYear('next')}>
165+
<Icon name="right" size={20} color={'#333'} />
166+
</TouchableOpacity>
167+
</View>
168+
169+
<View style={styles.calendarHeaderItem}>
170+
<TouchableOpacity onPress={() => getCurrentMonth('last')}>
171+
<Icon name="left" size={20} color={'#333'} />
172+
</TouchableOpacity>
173+
<Text style={styles.calendarHeaderText}>{currentMonth + 1}</Text>
174+
<TouchableOpacity onPress={() => getCurrentMonth('next')}>
175+
<Icon name="right" size={20} color={'#333'} />
176+
</TouchableOpacity>
177+
</View>
178+
</View>
179+
180+
<View style={styles.calendarWeekdays}>{renderWeekDays()}</View>
181+
<View style={styles.calendarDays}>{renderWeeks()}</View>
182+
</View>
183+
);
184+
};
185+
const styles = StyleSheet.create({
186+
header: {
187+
backgroundColor: '#329BCB',
188+
flexDirection: 'row',
189+
padding: 10,
190+
justifyContent: 'space-between',
191+
},
192+
headerBtn: {
193+
flexDirection: 'row',
194+
alignItems: 'center',
195+
},
196+
headerText: {
197+
fontSize: 20,
198+
color: '#fff',
199+
},
200+
calendarHeader: {
201+
flexDirection: 'row',
202+
padding: 10,
203+
justifyContent: 'space-between',
204+
},
205+
calendarHeaderItem: {
206+
flexDirection: 'row',
207+
justifyContent: 'space-between',
208+
alignItems: 'center',
209+
paddingTop: 10,
210+
},
211+
calendarHeaderText: {
212+
paddingHorizontal: 30,
213+
fontSize: 20,
214+
fontWeight: '500',
215+
color: '#000',
216+
},
217+
calendarWeekdays: {
218+
flexDirection: 'row',
219+
justifyContent: 'space-between',
220+
alignItems: 'center',
221+
paddingHorizontal: MainWidth / 7 - 33,
222+
paddingTop: 10,
223+
},
224+
calendarWedText: {
225+
color: '#616161',
226+
textAlign: 'center',
227+
},
228+
229+
calendarDays: {
230+
marginVertical: 10,
231+
},
232+
weekDays: {
233+
flexDirection: 'row',
234+
paddingHorizontal: 2,
235+
},
236+
currentMonth: {
237+
backgroundColor: '#329BCB',
238+
borderRadius: 50,
239+
marginHorizontal: 2,
240+
width: MainWidth / 7 - 4.5,
241+
height: MainWidth / 7 - 4.5,
242+
},
243+
selectMonth: {
244+
borderWidth: 1,
245+
borderColor: '#329BCB',
246+
borderRadius: 50,
247+
marginHorizontal: 2,
248+
width: MainWidth / 7 - 4.5,
249+
height: MainWidth / 7 - 4.5,
250+
},
251+
otherMonth: {
252+
borderRadius: 50,
253+
marginHorizontal: 2,
254+
width: MainWidth / 7 - 4.5,
255+
height: MainWidth / 7 - 4.5,
256+
},
257+
day: {
258+
marginHorizontal: 2,
259+
width: MainWidth / 7 - 4.5,
260+
height: MainWidth / 7 - 4.5,
261+
},
262+
dayText: {
263+
textAlign: 'center',
264+
fontSize: 17,
265+
lineHeight: MainWidth / 7 - 4.5,
266+
fontWeight: '500',
267+
},
268+
});
269+
270+
export default Calendar;

0 commit comments

Comments
 (0)