From d092d669f26fa8900785085bcc951032207c7b3f Mon Sep 17 00:00:00 2001 From: neverland Date: Fri, 19 Feb 2021 19:46:46 +0800 Subject: [PATCH] types(Calendar): use tsx (#8180) --- src/calendar/README.zh-CN.md | 2 +- src/calendar/components/{Day.js => Day.tsx} | 37 ++++++-- .../components/{Header.js => Header.tsx} | 0 .../components/{Month.js => Month.tsx} | 61 ++++++++----- src/calendar/{index.js => index.tsx} | 89 ++++++++++--------- 5 files changed, 120 insertions(+), 69 deletions(-) rename src/calendar/components/{Day.js => Day.tsx} (77%) rename src/calendar/components/{Header.js => Header.tsx} (100%) rename src/calendar/components/{Month.js => Month.tsx} (80%) rename src/calendar/{index.js => index.tsx} (84%) diff --git a/src/calendar/README.zh-CN.md b/src/calendar/README.zh-CN.md index d4710d487..a74c02f01 100644 --- a/src/calendar/README.zh-CN.md +++ b/src/calendar/README.zh-CN.md @@ -251,7 +251,7 @@ export default { | 参数 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | -| type | 选择类型:
`single`表示选择单个日期,
`multiple`表示选择多个日期,
`range`表示选择日期区间 | _string_ | `single` | +| type | 选择类型:
`single` 表示选择单个日期,
`multiple` 表示选择多个日期,
`range` 表示选择日期区间 | _string_ | `single` | | title | 日历标题 | _string_ | `日期选择` | | color | 主题色,对底部按钮和选中日期生效 | _string_ | `#ee0a24` | | min-date | 可选择的最小日期 | _Date_ | 当前日期 | diff --git a/src/calendar/components/Day.js b/src/calendar/components/Day.tsx similarity index 77% rename from src/calendar/components/Day.js rename to src/calendar/components/Day.tsx index f27091037..f59fd9b79 100644 --- a/src/calendar/components/Day.js +++ b/src/calendar/components/Day.tsx @@ -1,16 +1,43 @@ +import { computed, CSSProperties, PropType } from 'vue'; import { createNamespace } from '../../utils'; import { bem } from '../utils'; -import { computed } from 'vue'; 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({ props: { - item: Object, color: String, index: Number, - offset: Number, rowHeight: String, + offset: { + type: Number, + default: 0, + }, + item: { + type: Object as PropType, + required: true, + }, }, emits: ['click'], @@ -18,7 +45,7 @@ export default createComponent({ setup(props, { emit }) { const style = computed(() => { const { item, index, color, offset, rowHeight } = props; - const style = { + const style: CSSProperties = { height: rowHeight, }; @@ -92,7 +119,7 @@ export default createComponent({ role="gridcell" style={style.value} class={[bem('day', type), className]} - tabindex={type === 'disabled' ? null : -1} + tabindex={type === 'disabled' ? undefined : -1} onClick={onClick} > {renderContent()} diff --git a/src/calendar/components/Header.js b/src/calendar/components/Header.tsx similarity index 100% rename from src/calendar/components/Header.js rename to src/calendar/components/Header.tsx diff --git a/src/calendar/components/Month.js b/src/calendar/components/Month.tsx similarity index 80% rename from src/calendar/components/Month.js rename to src/calendar/components/Month.tsx index 9af7decce..b2bb67e82 100644 --- a/src/calendar/components/Month.js +++ b/src/calendar/components/Month.tsx @@ -1,4 +1,4 @@ -import { ref, computed } from 'vue'; +import { ref, computed, PropType } from 'vue'; // Utils import { addUnit, setScrollTop, createNamespace } from '../../utils'; @@ -18,26 +18,37 @@ import { useExpose } from '../../composables/use-expose'; import { useHeight } from '../../composables/use-height'; // Components -import Day from './Day'; +import Day, { DayItem, DayType } from './Day'; const [createComponent] = createNamespace('calendar-month'); +export type CalendarType = 'single' | 'range' | 'multiple'; + export default createComponent({ props: { - date: Date, - type: String, + type: String as PropType, color: String, - minDate: Date, - maxDate: Date, showMark: Boolean, rowHeight: [Number, String], - formatter: Function, + formatter: Function as PropType<(item: DayItem) => DayItem>, lazyRender: Boolean, - currentDate: [Date, Array], + currentDate: [Date, Array] as PropType, allowSameDay: Boolean, showSubtitle: Boolean, showMonthTitle: Boolean, firstDayOfWeek: Number, + date: { + type: Date as PropType, + required: true, + }, + minDate: { + type: Date as PropType, + required: true, + }, + maxDate: { + type: Date as PropType, + required: true, + }, }, emits: ['click', 'update-height'], @@ -67,7 +78,7 @@ export default createComponent({ const getTitle = () => title.value; - const scrollIntoView = (body) => { + const scrollIntoView = (body: Element) => { const el = props.showSubtitle ? daysRef.value : monthRef.value; const scrollTop = @@ -78,9 +89,11 @@ export default createComponent({ setScrollTop(body, scrollTop); }; - const getMultipleDayType = (day) => { - const isSelected = (date) => - props.currentDate.some((item) => compareDay(item, date) === 0); + const getMultipleDayType = (day: Date) => { + const isSelected = (date: Date) => + (props.currentDate as Date[]).some( + (item) => compareDay(item, date) === 0 + ); if (isSelected(day)) { const prevDay = getPrevDay(day); @@ -103,8 +116,8 @@ export default createComponent({ return ''; }; - const getRangeDayType = (day) => { - const [startDay, endDay] = props.currentDate; + const getRangeDayType = (day: Date) => { + const [startDay, endDay] = props.currentDate as Date[]; if (!startDay) { return ''; @@ -130,9 +143,11 @@ export default createComponent({ if (compareToStart > 0 && compareToEnd < 0) { return 'middle'; } + + return ''; }; - const getDayType = (day) => { + const getDayType = (day: Date): DayType => { const { type, minDate, maxDate, currentDate } = props; if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) { @@ -140,7 +155,7 @@ export default createComponent({ } if (currentDate === null) { - return; + return ''; } if (Array.isArray(currentDate)) { @@ -151,11 +166,13 @@ export default createComponent({ return getRangeDayType(day); } } 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 (dayType === 'start' || dayType === 'end') { return t(dayType); @@ -179,7 +196,7 @@ export default createComponent({ }; const placeholders = computed(() => { - const rows = []; + const rows: DayItem[] = []; const count = Math.ceil((totalDay.value + offset.value) / 7); for (let day = 1; day <= count; day++) { rows.push({ type: 'placeholder' }); @@ -188,7 +205,7 @@ export default createComponent({ }); const days = computed(() => { - const days = []; + const days: DayItem[] = []; const year = props.date.getFullYear(); const month = props.date.getMonth(); @@ -196,7 +213,7 @@ export default createComponent({ const date = new Date(year, month, day); const type = getDayType(date); - let config = { + let config: DayItem = { date, type, text: day, @@ -213,7 +230,7 @@ export default createComponent({ return days; }); - const renderDay = (item, index) => ( + const renderDay = (item: DayItem, index: number) => ( , + formatter: Function as PropType<(item: DayItem) => DayItem>, rowHeight: [Number, String], confirmText: 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, confirmDisabledText: String, type: { - type: String, + type: String as PropType, default: 'single', }, round: { @@ -52,7 +57,7 @@ export default createComponent({ default: true, }, position: { - type: String, + type: String as PropType, default: 'bottom', }, poppable: { @@ -96,14 +101,14 @@ export default createComponent({ default: true, }, minDate: { - type: Date, + type: Date as PropType, validator: isDate, default: () => new Date(), }, maxDate: { - type: Date, + type: Date as PropType, validator: isDate, - default() { + default: () => { const now = new Date(); return new Date(now.getFullYear(), now.getMonth() + 6, now.getDate()); }, @@ -111,7 +116,7 @@ export default createComponent({ firstDayOfWeek: { type: [Number, String], 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 }) { const limitDateRange = ( - date, + date: Date, minDate = props.minDate, maxDate = props.maxDate ) => { @@ -167,7 +172,7 @@ export default createComponent({ return limitDateRange(defaultDate); }; - let bodyHeight; + let bodyHeight: number; const bodyRef = ref(); @@ -176,10 +181,10 @@ export default createComponent({ currentDate: getInitialDate(), }); - const [monthRefs, setMonthRefs] = useRefs(); + const [monthRefs, setMonthRefs] = useRefs(); const dayOffset = computed(() => - props.firstDayOfWeek ? props.firstDayOfWeek % 7 : 0 + props.firstDayOfWeek ? +props.firstDayOfWeek % 7 : 0 ); const months = computed(() => { @@ -201,10 +206,10 @@ export default createComponent({ if (currentDate) { if (props.type === 'range') { - return !currentDate[0] || !currentDate[1]; + return !(currentDate as Date[])[0] || !(currentDate as Date[])[1]; } 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(() => { months.value.some((month, index) => { if (compareMonth(month, targetDate) === 0) { @@ -291,7 +296,7 @@ export default createComponent({ const { currentDate } = state; if (currentDate) { const targetDate = - props.type === 'single' ? currentDate : currentDate[0]; + props.type === 'single' ? currentDate : (currentDate as Date[])[0]; scrollToDate(targetDate); } else { raf(onScroll); @@ -316,7 +321,7 @@ export default createComponent({ scrollIntoView(); }; - const checkRange = (date) => { + const checkRange = (date: [Date, Date]) => { const { maxRange, rangePrompt } = props; if (maxRange && calcDateNum(date) > maxRange) { @@ -331,21 +336,21 @@ export default createComponent({ emit('confirm', copyDates(state.currentDate)); }; - const select = (date, complete) => { - const setCurrentDate = (date) => { + const select = (date: Date | Date[], complete?: boolean) => { + const setCurrentDate = (date: Date | Date[]) => { state.currentDate = date; emit('select', copyDates(state.currentDate)); }; if (complete && props.type === 'range') { - const valid = checkRange(date); + const valid = checkRange(date as [Date, Date]); if (!valid) { // auto selected to max range if showConfirm if (props.showConfirm) { setCurrentDate([ - date[0], - getDayByOffset(date[0], props.maxRange - 1), + (date as Date[])[0], + getDayByOffset((date as Date[])[0], +props.maxRange - 1), ]); } else { setCurrentDate(date); @@ -361,8 +366,8 @@ export default createComponent({ } }; - const onClickDay = (item) => { - if (props.readonly) { + const onClickDay = (item: DayItem) => { + if (props.readonly || !item.date) { return; } @@ -372,7 +377,7 @@ export default createComponent({ if (type === 'range') { if (!currentDate) { - select([date, null]); + select([date]); return; } @@ -384,12 +389,12 @@ export default createComponent({ if (compareToStart === 1) { select([startDay, date], true); } else if (compareToStart === -1) { - select([date, null]); + select([date]); } else if (props.allowSameDay) { select([date, date], true); } } else { - select([date, null]); + select([date]); } } else if (type === 'multiple') { if (!currentDate) { @@ -398,13 +403,15 @@ export default createComponent({ } let selectedIndex; - const selected = state.currentDate.some((dateItem, index) => { - const equal = compareDay(dateItem, date) === 0; - if (equal) { - selectedIndex = index; + const selected = state.currentDate.some( + (dateItem: Date, index: number) => { + const equal = compareDay(dateItem, date) === 0; + if (equal) { + selectedIndex = index; + } + return equal; } - return equal; - }); + ); if (selected) { const [unselectedDate] = currentDate.splice(selectedIndex, 1); @@ -419,11 +426,11 @@ export default createComponent({ } }; - const togglePopup = (val) => { - emit('update:show', val); + const togglePopup = (value: boolean) => { + emit('update:show', value); }; - const renderMonth = (date, index) => { + const renderMonth = (date: Date, index: number) => { const showMonthTitle = index !== 0 || !props.showSubtitle; return (