1
0
mirror of https://gitee.com/vant-contrib/vant.git synced 2025-04-06 03:57:59 +08:00

types(Calendar): use tsx ()

This commit is contained in:
neverland 2021-02-19 19:46:46 +08:00 committed by GitHub
parent 8696f4ee70
commit d092d669f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 120 additions and 69 deletions

@ -251,7 +251,7 @@ export default {
| 参数 | 说明 | 类型 | 默认值 | | 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| type | 选择类型:<br>`single`表示选择单个日期,<br>`multiple`表示选择多个日期,<br>`range`表示选择日期区间 | _string_ | `single` | | type | 选择类型:<br>`single` 表示选择单个日期,<br>`multiple` 表示选择多个日期,<br>`range` 表示选择日期区间 | _string_ | `single` |
| title | 日历标题 | _string_ | `日期选择` | | title | 日历标题 | _string_ | `日期选择` |
| color | 主题色,对底部按钮和选中日期生效 | _string_ | `#ee0a24` | | color | 主题色,对底部按钮和选中日期生效 | _string_ | `#ee0a24` |
| min-date | 可选择的最小日期 | _Date_ | 当前日期 | | min-date | 可选择的最小日期 | _Date_ | 当前日期 |

@ -1,16 +1,43 @@
import { computed, CSSProperties, PropType } from 'vue';
import { createNamespace } from '../../utils'; import { createNamespace } from '../../utils';
import { bem } from '../utils'; import { bem } from '../utils';
import { computed } from 'vue';
const [createComponent] = createNamespace('calendar-day'); const [createComponent] = createNamespace('calendar-day');
export type DayType =
| ''
| 'start'
| 'start-end'
| 'middle'
| 'end'
| 'selected'
| 'multiple-middle'
| 'multiple-selected'
| 'disabled'
| 'placeholder';
export type DayItem = {
date?: Date;
text?: string | number;
type?: DayType;
topInfo?: string;
className?: unknown;
bottomInfo?: string;
};
export default createComponent({ export default createComponent({
props: { props: {
item: Object,
color: String, color: String,
index: Number, index: Number,
offset: Number,
rowHeight: String, rowHeight: String,
offset: {
type: Number,
default: 0,
},
item: {
type: Object as PropType<DayItem>,
required: true,
},
}, },
emits: ['click'], emits: ['click'],
@ -18,7 +45,7 @@ export default createComponent({
setup(props, { emit }) { setup(props, { emit }) {
const style = computed(() => { const style = computed(() => {
const { item, index, color, offset, rowHeight } = props; const { item, index, color, offset, rowHeight } = props;
const style = { const style: CSSProperties = {
height: rowHeight, height: rowHeight,
}; };
@ -92,7 +119,7 @@ export default createComponent({
role="gridcell" role="gridcell"
style={style.value} style={style.value}
class={[bem('day', type), className]} class={[bem('day', type), className]}
tabindex={type === 'disabled' ? null : -1} tabindex={type === 'disabled' ? undefined : -1}
onClick={onClick} onClick={onClick}
> >
{renderContent()} {renderContent()}

@ -1,4 +1,4 @@
import { ref, computed } from 'vue'; import { ref, computed, PropType } from 'vue';
// Utils // Utils
import { addUnit, setScrollTop, createNamespace } from '../../utils'; import { addUnit, setScrollTop, createNamespace } from '../../utils';
@ -18,26 +18,37 @@ import { useExpose } from '../../composables/use-expose';
import { useHeight } from '../../composables/use-height'; import { useHeight } from '../../composables/use-height';
// Components // Components
import Day from './Day'; import Day, { DayItem, DayType } from './Day';
const [createComponent] = createNamespace('calendar-month'); const [createComponent] = createNamespace('calendar-month');
export type CalendarType = 'single' | 'range' | 'multiple';
export default createComponent({ export default createComponent({
props: { props: {
date: Date, type: String as PropType<CalendarType>,
type: String,
color: String, color: String,
minDate: Date,
maxDate: Date,
showMark: Boolean, showMark: Boolean,
rowHeight: [Number, String], rowHeight: [Number, String],
formatter: Function, formatter: Function as PropType<(item: DayItem) => DayItem>,
lazyRender: Boolean, lazyRender: Boolean,
currentDate: [Date, Array], currentDate: [Date, Array] as PropType<Date | Date[]>,
allowSameDay: Boolean, allowSameDay: Boolean,
showSubtitle: Boolean, showSubtitle: Boolean,
showMonthTitle: Boolean, showMonthTitle: Boolean,
firstDayOfWeek: Number, firstDayOfWeek: Number,
date: {
type: Date as PropType<Date>,
required: true,
},
minDate: {
type: Date as PropType<Date>,
required: true,
},
maxDate: {
type: Date as PropType<Date>,
required: true,
},
}, },
emits: ['click', 'update-height'], emits: ['click', 'update-height'],
@ -67,7 +78,7 @@ export default createComponent({
const getTitle = () => title.value; const getTitle = () => title.value;
const scrollIntoView = (body) => { const scrollIntoView = (body: Element) => {
const el = props.showSubtitle ? daysRef.value : monthRef.value; const el = props.showSubtitle ? daysRef.value : monthRef.value;
const scrollTop = const scrollTop =
@ -78,9 +89,11 @@ export default createComponent({
setScrollTop(body, scrollTop); setScrollTop(body, scrollTop);
}; };
const getMultipleDayType = (day) => { const getMultipleDayType = (day: Date) => {
const isSelected = (date) => const isSelected = (date: Date) =>
props.currentDate.some((item) => compareDay(item, date) === 0); (props.currentDate as Date[]).some(
(item) => compareDay(item, date) === 0
);
if (isSelected(day)) { if (isSelected(day)) {
const prevDay = getPrevDay(day); const prevDay = getPrevDay(day);
@ -103,8 +116,8 @@ export default createComponent({
return ''; return '';
}; };
const getRangeDayType = (day) => { const getRangeDayType = (day: Date) => {
const [startDay, endDay] = props.currentDate; const [startDay, endDay] = props.currentDate as Date[];
if (!startDay) { if (!startDay) {
return ''; return '';
@ -130,9 +143,11 @@ export default createComponent({
if (compareToStart > 0 && compareToEnd < 0) { if (compareToStart > 0 && compareToEnd < 0) {
return 'middle'; return 'middle';
} }
return '';
}; };
const getDayType = (day) => { const getDayType = (day: Date): DayType => {
const { type, minDate, maxDate, currentDate } = props; const { type, minDate, maxDate, currentDate } = props;
if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) { if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) {
@ -140,7 +155,7 @@ export default createComponent({
} }
if (currentDate === null) { if (currentDate === null) {
return; return '';
} }
if (Array.isArray(currentDate)) { if (Array.isArray(currentDate)) {
@ -151,11 +166,13 @@ export default createComponent({
return getRangeDayType(day); return getRangeDayType(day);
} }
} else if (type === 'single') { } else if (type === 'single') {
return compareDay(day, currentDate) === 0 ? 'selected' : ''; return compareDay(day, currentDate as Date) === 0 ? 'selected' : '';
} }
return '';
}; };
const getBottomInfo = (dayType) => { const getBottomInfo = (dayType: DayType) => {
if (props.type === 'range') { if (props.type === 'range') {
if (dayType === 'start' || dayType === 'end') { if (dayType === 'start' || dayType === 'end') {
return t(dayType); return t(dayType);
@ -179,7 +196,7 @@ export default createComponent({
}; };
const placeholders = computed(() => { const placeholders = computed(() => {
const rows = []; const rows: DayItem[] = [];
const count = Math.ceil((totalDay.value + offset.value) / 7); const count = Math.ceil((totalDay.value + offset.value) / 7);
for (let day = 1; day <= count; day++) { for (let day = 1; day <= count; day++) {
rows.push({ type: 'placeholder' }); rows.push({ type: 'placeholder' });
@ -188,7 +205,7 @@ export default createComponent({
}); });
const days = computed(() => { const days = computed(() => {
const days = []; const days: DayItem[] = [];
const year = props.date.getFullYear(); const year = props.date.getFullYear();
const month = props.date.getMonth(); const month = props.date.getMonth();
@ -196,7 +213,7 @@ export default createComponent({
const date = new Date(year, month, day); const date = new Date(year, month, day);
const type = getDayType(date); const type = getDayType(date);
let config = { let config: DayItem = {
date, date,
type, type,
text: day, text: day,
@ -213,7 +230,7 @@ export default createComponent({
return days; return days;
}); });
const renderDay = (item, index) => ( const renderDay = (item: DayItem, index: number) => (
<Day <Day
item={item} item={item}
index={index} index={index}

@ -1,7 +1,7 @@
import { ref, watch, reactive, computed } from 'vue'; import { ref, watch, reactive, computed, PropType, TeleportProps } from 'vue';
// Utils // Utils
import { pick, getScrollTop } from '../utils'; import { pick, getScrollTop, ComponentInstance } from '../utils';
import { isDate } from '../utils/validate/date'; import { isDate } from '../utils/validate/date';
import { import {
t, t,
@ -23,28 +23,33 @@ import { useRefs } from '../composables/use-refs';
import { useExpose } from '../composables/use-expose'; import { useExpose } from '../composables/use-expose';
// Components // Components
import Popup from '../popup'; import Popup, { PopupPosition } from '../popup';
import Button from '../button'; import Button from '../button';
import Toast from '../toast'; import Toast from '../toast';
import Month from './components/Month'; import Month, { CalendarType } from './components/Month';
import Header from './components/Header'; import Header from './components/Header';
// Types
import type { DayItem } from './components/Day';
export default createComponent({ export default createComponent({
props: { props: {
show: Boolean, show: Boolean,
title: String, title: String,
color: String, color: String,
readonly: Boolean, readonly: Boolean,
teleport: [String, Object], teleport: [String, Object] as PropType<TeleportProps['to']>,
formatter: Function, formatter: Function as PropType<(item: DayItem) => DayItem>,
rowHeight: [Number, String], rowHeight: [Number, String],
confirmText: String, confirmText: String,
rangePrompt: String, rangePrompt: String,
defaultDate: [Date, Array], // TODO: remove any
// see: https://github.com/vuejs/vue-next/issues/2668
defaultDate: [Date, Array] as any,
allowSameDay: Boolean, allowSameDay: Boolean,
confirmDisabledText: String, confirmDisabledText: String,
type: { type: {
type: String, type: String as PropType<CalendarType>,
default: 'single', default: 'single',
}, },
round: { round: {
@ -52,7 +57,7 @@ export default createComponent({
default: true, default: true,
}, },
position: { position: {
type: String, type: String as PropType<PopupPosition>,
default: 'bottom', default: 'bottom',
}, },
poppable: { poppable: {
@ -96,14 +101,14 @@ export default createComponent({
default: true, default: true,
}, },
minDate: { minDate: {
type: Date, type: Date as PropType<Date>,
validator: isDate, validator: isDate,
default: () => new Date(), default: () => new Date(),
}, },
maxDate: { maxDate: {
type: Date, type: Date as PropType<Date>,
validator: isDate, validator: isDate,
default() { default: () => {
const now = new Date(); const now = new Date();
return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()); return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate());
}, },
@ -111,7 +116,7 @@ export default createComponent({
firstDayOfWeek: { firstDayOfWeek: {
type: [Number, String], type: [Number, String],
default: 0, default: 0,
validator: (val) => val >= 0 && val <= 6, validator: (val: number) => val >= 0 && val <= 6,
}, },
}, },
@ -119,7 +124,7 @@ export default createComponent({
setup(props, { emit, slots }) { setup(props, { emit, slots }) {
const limitDateRange = ( const limitDateRange = (
date, date: Date,
minDate = props.minDate, minDate = props.minDate,
maxDate = props.maxDate maxDate = props.maxDate
) => { ) => {
@ -167,7 +172,7 @@ export default createComponent({
return limitDateRange(defaultDate); return limitDateRange(defaultDate);
}; };
let bodyHeight; let bodyHeight: number;
const bodyRef = ref(); const bodyRef = ref();
@ -176,10 +181,10 @@ export default createComponent({
currentDate: getInitialDate(), currentDate: getInitialDate(),
}); });
const [monthRefs, setMonthRefs] = useRefs(); const [monthRefs, setMonthRefs] = useRefs<ComponentInstance>();
const dayOffset = computed(() => const dayOffset = computed(() =>
props.firstDayOfWeek ? props.firstDayOfWeek % 7 : 0 props.firstDayOfWeek ? +props.firstDayOfWeek % 7 : 0
); );
const months = computed(() => { const months = computed(() => {
@ -201,10 +206,10 @@ export default createComponent({
if (currentDate) { if (currentDate) {
if (props.type === 'range') { if (props.type === 'range') {
return !currentDate[0] || !currentDate[1]; return !(currentDate as Date[])[0] || !(currentDate as Date[])[1];
} }
if (props.type === 'multiple') { if (props.type === 'multiple') {
return !currentDate.length; return !(currentDate as Date[]).length;
} }
} }
@ -267,7 +272,7 @@ export default createComponent({
} }
}; };
const scrollToDate = (targetDate) => { const scrollToDate = (targetDate: Date) => {
raf(() => { raf(() => {
months.value.some((month, index) => { months.value.some((month, index) => {
if (compareMonth(month, targetDate) === 0) { if (compareMonth(month, targetDate) === 0) {
@ -291,7 +296,7 @@ export default createComponent({
const { currentDate } = state; const { currentDate } = state;
if (currentDate) { if (currentDate) {
const targetDate = const targetDate =
props.type === 'single' ? currentDate : currentDate[0]; props.type === 'single' ? currentDate : (currentDate as Date[])[0];
scrollToDate(targetDate); scrollToDate(targetDate);
} else { } else {
raf(onScroll); raf(onScroll);
@ -316,7 +321,7 @@ export default createComponent({
scrollIntoView(); scrollIntoView();
}; };
const checkRange = (date) => { const checkRange = (date: [Date, Date]) => {
const { maxRange, rangePrompt } = props; const { maxRange, rangePrompt } = props;
if (maxRange && calcDateNum(date) > maxRange) { if (maxRange && calcDateNum(date) > maxRange) {
@ -331,21 +336,21 @@ export default createComponent({
emit('confirm', copyDates(state.currentDate)); emit('confirm', copyDates(state.currentDate));
}; };
const select = (date, complete) => { const select = (date: Date | Date[], complete?: boolean) => {
const setCurrentDate = (date) => { const setCurrentDate = (date: Date | Date[]) => {
state.currentDate = date; state.currentDate = date;
emit('select', copyDates(state.currentDate)); emit('select', copyDates(state.currentDate));
}; };
if (complete && props.type === 'range') { if (complete && props.type === 'range') {
const valid = checkRange(date); const valid = checkRange(date as [Date, Date]);
if (!valid) { if (!valid) {
// auto selected to max range if showConfirm // auto selected to max range if showConfirm
if (props.showConfirm) { if (props.showConfirm) {
setCurrentDate([ setCurrentDate([
date[0], (date as Date[])[0],
getDayByOffset(date[0], props.maxRange - 1), getDayByOffset((date as Date[])[0], +props.maxRange - 1),
]); ]);
} else { } else {
setCurrentDate(date); setCurrentDate(date);
@ -361,8 +366,8 @@ export default createComponent({
} }
}; };
const onClickDay = (item) => { const onClickDay = (item: DayItem) => {
if (props.readonly) { if (props.readonly || !item.date) {
return; return;
} }
@ -372,7 +377,7 @@ export default createComponent({
if (type === 'range') { if (type === 'range') {
if (!currentDate) { if (!currentDate) {
select([date, null]); select([date]);
return; return;
} }
@ -384,12 +389,12 @@ export default createComponent({
if (compareToStart === 1) { if (compareToStart === 1) {
select([startDay, date], true); select([startDay, date], true);
} else if (compareToStart === -1) { } else if (compareToStart === -1) {
select([date, null]); select([date]);
} else if (props.allowSameDay) { } else if (props.allowSameDay) {
select([date, date], true); select([date, date], true);
} }
} else { } else {
select([date, null]); select([date]);
} }
} else if (type === 'multiple') { } else if (type === 'multiple') {
if (!currentDate) { if (!currentDate) {
@ -398,13 +403,15 @@ export default createComponent({
} }
let selectedIndex; let selectedIndex;
const selected = state.currentDate.some((dateItem, index) => { const selected = state.currentDate.some(
const equal = compareDay(dateItem, date) === 0; (dateItem: Date, index: number) => {
if (equal) { const equal = compareDay(dateItem, date) === 0;
selectedIndex = index; if (equal) {
selectedIndex = index;
}
return equal;
} }
return equal; );
});
if (selected) { if (selected) {
const [unselectedDate] = currentDate.splice(selectedIndex, 1); const [unselectedDate] = currentDate.splice(selectedIndex, 1);
@ -419,11 +426,11 @@ export default createComponent({
} }
}; };
const togglePopup = (val) => { const togglePopup = (value: boolean) => {
emit('update:show', val); emit('update:show', value);
}; };
const renderMonth = (date, index) => { const renderMonth = (date: Date, index: number) => {
const showMonthTitle = index !== 0 || !props.showSubtitle; const showMonthTitle = index !== 0 || !props.showSubtitle;
return ( return (
<Month <Month