refactor: calendar by ts

pull/2992/head
tanjinzhou 2020-10-13 19:02:03 +08:00
parent 8e1678cc70
commit efc7db1b69
7 changed files with 77 additions and 68 deletions

View File

@ -13,12 +13,6 @@ export interface Route {
children?: Omit<Route, 'children'>[]; children?: Omit<Route, 'children'>[];
} }
const Route = PropTypes.shape({
path: PropTypes.string,
breadcrumbName: PropTypes.string,
children: PropTypes.array,
}).loose;
const BreadcrumbProps = { const BreadcrumbProps = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
routes: {type: Array as PropType<Route[]>}, routes: {type: Array as PropType<Route[]>},

View File

@ -1,9 +1,9 @@
import { inject } from 'vue'; import { defineComponent, inject, PropType } from 'vue';
import Select from '../select'; import Select from '../select';
import { Group, Button } from '../radio'; import { Group, Button } from '../radio';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import { initDefaultProps } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import { VueNode } from 'components/_util/type';
const { Option } = Select; const { Option } = Select;
@ -17,7 +17,13 @@ function getMonthsLocale(value) {
} }
return months; return months;
} }
export interface RenderHeader {
value: moment.Moment;
onChange?: (value: moment.Moment) => void;
type: string;
onTypeChange: (type: string) => void;
}
export type HeaderRender = (headerRender: RenderHeader) => VueNode;
export const HeaderProps = { export const HeaderProps = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
locale: PropTypes.any, locale: PropTypes.any,
@ -25,28 +31,34 @@ export const HeaderProps = {
yearSelectOffset: PropTypes.number, yearSelectOffset: PropTypes.number,
yearSelectTotal: PropTypes.number, yearSelectTotal: PropTypes.number,
type: PropTypes.string, type: PropTypes.string,
value: PropTypes.any, value: {
validRange: PropTypes.array, type: Object as PropType<moment.Moment>
},
validRange: {
type: Array as PropType<moment.Moment[]>
},
headerRender: PropTypes.func, headerRender: PropTypes.func,
onValueChange: PropTypes.func, onValueChange: PropTypes.func,
onTypeChange: PropTypes.func, onTypeChange: PropTypes.func,
}; };
export default { export default defineComponent({
name: 'CalendarHeader', name: 'CalendarHeader',
inheritAttrs: false, inheritAttrs: false,
props: initDefaultProps(HeaderProps, { props: {
yearSelectOffset: 10, ...HeaderProps,
yearSelectTotal: 20, yearSelectOffset: PropTypes.number.def(10),
}), yearSelectTotal: PropTypes.number.def(20),
},
setup() { setup() {
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
calendarHeaderNode: undefined
}; };
}, },
// private calendarHeaderNode: HTMLDivElement; // private calendarHeaderNode: HTMLDivElement;
methods: { methods: {
getYearSelectElement(prefixCls, year) { getYearSelectElement(prefixCls: string, year: number) {
const { yearSelectOffset, yearSelectTotal, locale = {}, fullscreen, validRange } = this; const { yearSelectOffset, yearSelectTotal, locale = {}, fullscreen, validRange } = this;
let start = year - yearSelectOffset; let start = year - yearSelectOffset;
let end = start + yearSelectTotal; let end = start + yearSelectTotal;
@ -74,7 +86,7 @@ export default {
); );
}, },
getMonthSelectElement(prefixCls, month, months) { getMonthSelectElement(prefixCls: string, month: number, months: number[]) {
const { fullscreen, validRange, value } = this; const { fullscreen, validRange, value } = this;
const options = []; const options = [];
let start = 0; let start = 0;
@ -167,10 +179,10 @@ export default {
triggerValueChange() { triggerValueChange() {
this.$emit('valueChange', ...arguments); this.$emit('valueChange', ...arguments);
}, },
saveCalendarHeaderNode(node) { saveCalendarHeaderNode(node: HTMLElement) {
this.calendarHeaderNode = node; this.calendarHeaderNode = node;
}, },
headerRenderCustom(headerRender) { headerRenderCustom(headerRender: HeaderRender) {
const { type, value } = this.$props; const { type, value } = this.$props;
return headerRender({ return headerRender({
value, value,
@ -190,11 +202,11 @@ export default {
return headerRender ? ( return headerRender ? (
this.headerRenderCustom(headerRender) this.headerRenderCustom(headerRender)
) : ( ) : (
<div class={`${prefixCls}-header`} ref={this.saveCalendarHeaderNode}> <div class={`${prefixCls}-header`} ref={this.saveCalendarHeaderNode as any}>
{yearReactNode} {yearReactNode}
{monthReactNode} {monthReactNode}
{typeSwitch} {typeSwitch}
</div> </div>
); );
}, },
}; });

View File

@ -1,7 +1,7 @@
import { inject } from 'vue'; import { App, defineComponent, inject, PropType } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import { getOptionProps, hasProp, initDefaultProps } from '../_util/props-util'; import { getOptionProps, hasProp } from '../_util/props-util';
import moment from 'moment'; import moment from 'moment';
import FullCalendar from '../vc-calendar/src/FullCalendar'; import FullCalendar from '../vc-calendar/src/FullCalendar';
import Header from './Header'; import Header from './Header';
@ -10,6 +10,7 @@ import interopDefault from '../_util/interopDefault';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
import enUS from './locale/en_US'; import enUS from './locale/en_US';
import { checkValidate, stringToMoment, momentToString, TimeType } from '../_util/moment-util'; import { checkValidate, stringToMoment, momentToString, TimeType } from '../_util/moment-util';
import { tuple } from '../_util/type';
function noop() { function noop() {
return null; return null;
@ -21,12 +22,11 @@ function zerofixed(v) {
} }
return `${v}`; return `${v}`;
} }
function isMomentArray(value) {
return Array.isArray(value) && !!value.find(val => moment.isMoment(val));
}
export const CalendarMode = PropTypes.oneOf(['month', 'year']);
export const CalendarProps = () => ({ const CalendarModeTypes = tuple('month', 'year');
export type CalendarMode = typeof CalendarModeTypes[number];
export const CalendarProps = {
monthCellRender: PropTypes.func, monthCellRender: PropTypes.func,
dateCellRender: PropTypes.func, dateCellRender: PropTypes.func,
monthFullCellRender: PropTypes.func, monthFullCellRender: PropTypes.func,
@ -34,30 +34,30 @@ export const CalendarProps = () => ({
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
value: TimeType, value: TimeType,
defaultValue: TimeType, defaultValue: TimeType,
mode: CalendarMode, mode: PropTypes.oneOf(CalendarModeTypes),
fullscreen: PropTypes.looseBool, fullscreen: PropTypes.looseBool.def(true),
locale: PropTypes.object, locale: PropTypes.object.def({}),
disabledDate: PropTypes.func, disabledDate: PropTypes.func,
validRange: PropTypes.custom(isMomentArray), validRange: {
type: Array as PropType<moment.Moment[]>,
},
headerRender: PropTypes.func, headerRender: PropTypes.func,
valueFormat: PropTypes.string, valueFormat: PropTypes.string,
onPanelChange: PropTypes.func, onPanelChange: PropTypes.func,
onSelect: PropTypes.func, onSelect: PropTypes.func,
onChange: PropTypes.func, onChange: PropTypes.func,
'onUpdate:value': PropTypes.func, 'onUpdate:value': PropTypes.func,
}); };
const Calendar = { const Calendar = defineComponent({
name: 'ACalendar', name: 'ACalendar',
inheritAttrs: false, inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
props: initDefaultProps(CalendarProps(), { props: CalendarProps,
locale: {},
fullscreen: true,
}),
setup() { setup() {
return { return {
configProvider: inject('configProvider', defaultConfigProvider), configProvider: inject('configProvider', defaultConfigProvider),
sPrefixCls: undefined
}; };
}, },
data() { data() {
@ -65,7 +65,6 @@ const Calendar = {
const sValue = value || defaultValue || interopDefault(moment)(); const sValue = value || defaultValue || interopDefault(moment)();
checkValidate('Calendar', defaultValue, 'defaultValue', valueFormat); checkValidate('Calendar', defaultValue, 'defaultValue', valueFormat);
checkValidate('Calendar', value, 'value', valueFormat); checkValidate('Calendar', value, 'value', valueFormat);
this._sPrefixCls = undefined;
return { return {
sValue: stringToMoment(sValue, valueFormat), sValue: stringToMoment(sValue, valueFormat),
sMode: this.mode || 'month', sMode: this.mode || 'month',
@ -85,14 +84,14 @@ const Calendar = {
}, },
}, },
methods: { methods: {
onHeaderValueChange(value) { onHeaderValueChange(value: moment.Moment) {
this.setValue(value, 'changePanel'); this.setValue(value, 'changePanel');
}, },
onHeaderTypeChange(mode) { onHeaderTypeChange(mode: CalendarMode) {
this.sMode = mode; this.sMode = mode;
this.triggerPanelChange(this.sValue, mode); this.triggerPanelChange(this.sValue, mode);
}, },
triggerPanelChange(value, mode) { triggerPanelChange(value: moment.Moment, mode: CalendarMode | undefined) {
const val = this.valueFormat ? momentToString(value, this.valueFormat) : value; const val = this.valueFormat ? momentToString(value, this.valueFormat) : value;
this.$emit('panelChange', val, mode); this.$emit('panelChange', val, mode);
if (value !== this.sValue) { if (value !== this.sValue) {
@ -101,10 +100,10 @@ const Calendar = {
} }
}, },
triggerSelect(value) { triggerSelect(value: moment.Moment) {
this.setValue(value, 'select'); this.setValue(value, 'select');
}, },
setValue(value, way) { setValue(value: moment.Moment, way: 'select' | 'changePanel') {
const prevValue = this.value ? stringToMoment(this.value, this.valueFormat) : this.sValue; const prevValue = this.value ? stringToMoment(this.value, this.valueFormat) : this.sValue;
const { sMode: mode, valueFormat } = this; const { sMode: mode, valueFormat } = this;
if (!hasProp(this, 'value')) { if (!hasProp(this, 'value')) {
@ -122,8 +121,11 @@ const Calendar = {
this.triggerPanelChange(value, mode); this.triggerPanelChange(value, mode);
} }
}, },
getDateRange(validRange, disabledDate) { getDateRange(
return current => { validRange: [moment.Moment, moment.Moment],
disabledDate?: (current: moment.Moment) => boolean,
) {
return (current: moment.Moment) => {
if (!current) { if (!current) {
return false; return false;
} }
@ -147,29 +149,29 @@ const Calendar = {
return result; return result;
}, },
monthCellRender2({ current: value }) { monthCellRender2({ current: value }) {
const { _sPrefixCls, $slots } = this; const { sPrefixCls, $slots } = this;
const monthCellRender = this.monthCellRender || $slots.monthCellRender || noop; const monthCellRender: Function = this.monthCellRender || $slots.monthCellRender || noop;
return ( return (
<div class={`${_sPrefixCls}-month`}> <div class={`${sPrefixCls}-month`}>
<div class={`${_sPrefixCls}-value`}>{value.localeData().monthsShort(value)}</div> <div class={`${sPrefixCls}-value`}>{value.localeData().monthsShort(value)}</div>
<div class={`${_sPrefixCls}-content`}>{monthCellRender({ current: value })}</div> <div class={`${sPrefixCls}-content`}>{monthCellRender({ current: value })}</div>
</div> </div>
); );
}, },
dateCellRender2({ current: value }) { dateCellRender2({ current: value }) {
const { _sPrefixCls, $slots } = this; const { sPrefixCls, $slots } = this;
const dateCellRender = this.dateCellRender || $slots.dateCellRender || noop; const dateCellRender: Function = this.dateCellRender || $slots.dateCellRender || noop;
return ( return (
<div class={`${_sPrefixCls}-date`}> <div class={`${sPrefixCls}-date`}>
<div class={`${_sPrefixCls}-value`}>{zerofixed(value.date())}</div> <div class={`${sPrefixCls}-value`}>{zerofixed(value.date())}</div>
<div class={`${_sPrefixCls}-content`}>{dateCellRender({ current: value })}</div> <div class={`${sPrefixCls}-content`}>{dateCellRender({ current: value })}</div>
</div> </div>
); );
}, },
renderCalendar(locale, localeCode) { renderCalendar(locale: any, localeCode: string) {
const props = { ...getOptionProps(this), ...this.$attrs }; const props: any = { ...getOptionProps(this), ...this.$attrs };
const { sValue: value, sMode: mode, $slots } = this; const { sValue: value, sMode: mode, $slots } = this;
if (value && localeCode) { if (value && localeCode) {
value.locale(localeCode); value.locale(localeCode);
@ -189,7 +191,7 @@ const Calendar = {
// To support old version react. // To support old version react.
// Have to add prefixCls on the instance. // Have to add prefixCls on the instance.
// https://github.com/facebook/react/issues/12397 // https://github.com/facebook/react/issues/12397
this._sPrefixCls = prefixCls; this.sPrefixCls = prefixCls;
let cls = className || ''; let cls = className || '';
if (fullscreen) { if (fullscreen) {
@ -248,10 +250,10 @@ const Calendar = {
/> />
); );
}, },
}; });
/* istanbul ignore next */ /* istanbul ignore next */
Calendar.install = function(app) { Calendar.install = function(app: App) {
app.component(Calendar.name, Calendar); app.component(Calendar.name, Calendar);
}; };
export { HeaderProps } from './Header'; export { HeaderProps } from './Header';

View File

@ -1,11 +1,11 @@
import { provide, inject, nextTick } from 'vue'; import { provide, inject, nextTick, defineComponent } from 'vue';
import classNames from '../_util/classNames'; import classNames from '../_util/classNames';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import Radio from './Radio'; import Radio from './Radio';
import { getOptionProps, filterEmpty, hasProp, getSlot } from '../_util/props-util'; import { getOptionProps, filterEmpty, hasProp, getSlot } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
export default { export default defineComponent({
name: 'ARadioGroup', name: 'ARadioGroup',
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
@ -121,4 +121,4 @@ export default {
return <div class={classString}>{children}</div>; return <div class={classString}>{children}</div>;
}, },
}; });

View File

@ -1,9 +1,9 @@
import { inject } from 'vue'; import { defineComponent, inject } from 'vue';
import Radio from './Radio'; import Radio from './Radio';
import { getOptionProps, getSlot } from '../_util/props-util'; import { getOptionProps, getSlot } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider'; import { defaultConfigProvider } from '../config-provider';
export default { export default defineComponent({
name: 'ARadioButton', name: 'ARadioButton',
props: { props: {
...Radio.props, ...Radio.props,
@ -31,4 +31,4 @@ export default {
} }
return <Radio {...radioProps}>{getSlot(this)}</Radio>; return <Radio {...radioProps}>{getSlot(this)}</Radio>;
}, },
}; });

View File

@ -39,6 +39,7 @@ const AbstractSelectProps = () => ({
defaultOpen: PropTypes.looseBool, defaultOpen: PropTypes.looseBool,
autoClearSearchValue: PropTypes.looseBool, autoClearSearchValue: PropTypes.looseBool,
dropdownRender: PropTypes.func, dropdownRender: PropTypes.func,
onChange: PropTypes.func,
loading: PropTypes.looseBool, loading: PropTypes.looseBool,
}); });
const Value = PropTypes.shape({ const Value = PropTypes.shape({