From 041fd349a4d0f84ba122c423696d8a984ee53fe5 Mon Sep 17 00:00:00 2001 From: tangjinzhou <415800467@qq.com> Date: Fri, 16 Mar 2018 11:19:02 +0800 Subject: [PATCH] fix date-picker --- components/date-picker/WeekPicker.vue | 1 + components/date-picker/createPicker.js | 194 +++++++++++++++++ components/date-picker/createPicker.tsx | 196 ------------------ components/date-picker/index.js | 9 +- components/date-picker/interface.js | 80 +++++++ components/date-picker/interface.tsx | 90 -------- .../{wrapPicker.vue => wrapPicker.js} | 5 +- components/time-picker/index.vue | 8 +- 8 files changed, 286 insertions(+), 297 deletions(-) create mode 100644 components/date-picker/createPicker.js delete mode 100644 components/date-picker/createPicker.tsx create mode 100644 components/date-picker/interface.js delete mode 100644 components/date-picker/interface.tsx rename components/date-picker/{wrapPicker.vue => wrapPicker.js} (98%) diff --git a/components/date-picker/WeekPicker.vue b/components/date-picker/WeekPicker.vue index 3020b9a62..40ef26348 100644 --- a/components/date-picker/WeekPicker.vue +++ b/components/date-picker/WeekPicker.vue @@ -18,6 +18,7 @@ export default { // }; // private input: any; + name: 'WeekPicker', mixins: [BaseMixin], data () { const value = this.value || this.defaultValue diff --git a/components/date-picker/createPicker.js b/components/date-picker/createPicker.js new file mode 100644 index 000000000..fd63c3c2f --- /dev/null +++ b/components/date-picker/createPicker.js @@ -0,0 +1,194 @@ + +import * as moment from 'moment' +import MonthCalendar from '../vc-calendar/src/MonthCalendar' +import VcDatePicker from '../vc-calendar/src/Picker' +import classNames from 'classnames' +import Icon from '../icon' +import callMoment from '../_util/callMoment' +import BaseMixin from '../_util/BaseMixin' +import { hasProp, getOptionProps } from '../_util/props-util' + +// export const PickerProps = { +// value?: moment.Moment; +// prefixCls: string; +// } +function noop () {} +export default function createPicker (TheCalendar) { + return { + // static defaultProps = { + // prefixCls: 'ant-calendar', + // allowClear: true, + // showToday: true, + // }; + + // private input: any; + mixins: [BaseMixin], + data () { + const value = this.value || this.defaultValue + if (value && !moment.isMoment(value)) { + throw new Error( + 'The value/defaultValue of DatePicker or MonthPicker must be ' + + 'a moment object', + ) + } + return { + sValue: value, + showDate: value, + } + }, + watch: { + value (val) { + this.setState({ + sValue: val, + showDate: val, + }) + }, + }, + methods: { + renderFooter (...args) { + const { prefixCls, renderExtraFooter } = this + return renderExtraFooter ? ( + + ) : null + }, + + clearSelection (e) { + e.preventDefault() + e.stopPropagation() + this.handleChange(null) + }, + + handleChange (value) { + if (!hasProp(this, 'value')) { + this.setState({ + sValue: value, + showDate: value, + }) + } + this.$emit('change', value, (value && value.format(this.format)) || '') + }, + + handleCalendarChange (value) { + this.setState({ showDate: value }) + }, + + focus () { + this.$refs.input.focus() + }, + + blur () { + this.$refs.input.blur() + }, + }, + + render () { + const { sValue: value, showDate, $listeners } = this + const { panelChange = noop, focus = noop, blur = noop, ok = noop } = $listeners + const props = getOptionProps(this) + const { prefixCls, locale, localeCode } = props + + const placeholder = ('placeholder' in props) + ? props.placeholder : locale.lang.placeholder + + const disabledTime = props.showTime ? props.disabledTime : null + + const calendarClassName = classNames({ + [`${prefixCls}-time`]: props.showTime, + [`${prefixCls}-month`]: MonthCalendar === TheCalendar, + }) + + if (value && localeCode) { + value.locale(localeCode) + } + + const pickerProps = { props: {}, on: {}} + const calendarProps = { props: {}, on: {}} + if (props.showTime) { + // fix https://github.com/ant-design/ant-design/issues/1902 + calendarProps.on.select = this.handleChange + } else { + pickerProps.on.change = this.handleChange + } + if ('mode' in props) { + calendarProps.props.mode = props.mode + } + + const calendar = ( + + ) + + const clearIcon = (!props.disabled && props.allowClear && value) ? ( + + ) : null + + const input = ({ value: inputValue }) => ( +
+ + {clearIcon} + +
+ ) + const vcDatePickerProps = { + props: { + ...props, + ...pickerProps.props, + calendar, + value, + prefixCls: `${prefixCls}-picker-container`, + }, + on: { + ...$listeners, + ...pickerProps.on, + }, + style: props.popupStyle, + } + return ( + + + {input} + + + ) + }, + } +} diff --git a/components/date-picker/createPicker.tsx b/components/date-picker/createPicker.tsx deleted file mode 100644 index 71ccfaac3..000000000 --- a/components/date-picker/createPicker.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import * as React from 'react'; -import * as moment from 'moment'; -import MonthCalendar from 'rc-calendar/lib/MonthCalendar'; -import RcDatePicker from 'rc-calendar/lib/Picker'; -import classNames from 'classnames'; -import omit from 'omit.js'; -import Icon from '../icon'; -import warning from '../_util/warning'; -import callMoment from '../_util/callMoment'; - -export interface PickerProps { - value?: moment.Moment; - prefixCls: string; -} - -export default function createPicker(TheCalendar: React.ComponentClass): any { - return class CalenderWrapper extends React.Component { - static defaultProps = { - prefixCls: 'ant-calendar', - allowClear: true, - showToday: true, - }; - - private input: any; - - constructor(props: any) { - super(props); - const value = props.value || props.defaultValue; - if (value && !moment.isMoment(value)) { - throw new Error( - 'The value/defaultValue of DatePicker or MonthPicker must be ' + - 'a moment object after `antd@2.0`, see: https://u.ant.design/date-picker-value', - ); - } - this.state = { - value, - showDate: value, - }; - } - - componentWillReceiveProps(nextProps: PickerProps) { - if ('value' in nextProps) { - this.setState({ - value: nextProps.value, - showDate: nextProps.value, - }); - } - } - - renderFooter = (...args: any[]) => { - const { prefixCls, renderExtraFooter } = this.props; - return renderExtraFooter ? ( -
- {renderExtraFooter(...args)} -
- ) : null; - } - - clearSelection = (e: React.MouseEvent) => { - e.preventDefault(); - e.stopPropagation(); - this.handleChange(null); - } - - handleChange = (value: moment.Moment | null) => { - const props = this.props; - if (!('value' in props)) { - this.setState({ - value, - showDate: value, - }); - } - props.onChange(value, (value && value.format(props.format)) || ''); - } - - handleCalendarChange = (value: moment.Moment) => { - this.setState({ showDate: value }); - } - - focus() { - this.input.focus(); - } - - blur() { - this.input.blur(); - } - - saveInput = (node: any) => { - this.input = node; - } - - render() { - const { value, showDate } = this.state; - const props = omit(this.props, ['onChange']); - const { prefixCls, locale, localeCode } = props; - - const placeholder = ('placeholder' in props) - ? props.placeholder : locale.lang.placeholder; - - const disabledTime = props.showTime ? props.disabledTime : null; - - const calendarClassName = classNames({ - [`${prefixCls}-time`]: props.showTime, - [`${prefixCls}-month`]: MonthCalendar === TheCalendar, - }); - - if (value && localeCode) { - value.locale(localeCode); - } - - let pickerProps: Object = {}; - let calendarProps: any = {}; - if (props.showTime) { - calendarProps = { - // fix https://github.com/ant-design/ant-design/issues/1902 - onSelect: this.handleChange, - }; - } else { - pickerProps = { - onChange: this.handleChange, - }; - } - if ('mode' in props) { - calendarProps.mode = props.mode; - } - - warning(!('onOK' in props), 'It should be `DatePicker[onOk]` or `MonthPicker[onOk]`, instead of `onOK`!'); - const calendar = ( - - ); - - const clearIcon = (!props.disabled && props.allowClear && value) ? ( - - ) : null; - - const input = ({ value: inputValue }: { value: moment.Moment | null }) => ( -
- - {clearIcon} - -
- ); - - return ( - - - {input} - - - ); - } - }; -} diff --git a/components/date-picker/index.js b/components/date-picker/index.js index 626226f75..9880306e6 100755 --- a/components/date-picker/index.js +++ b/components/date-picker/index.js @@ -4,15 +4,16 @@ import createPicker from './createPicker' import wrapPicker from './wrapPicker' import RangePicker from './RangePicker' import WeekPicker from './WeekPicker' +import { DatePickerProps, MonthPickerProps, WeexPickerProps, RangePickerProps } from './interface' -const DatePicker = wrapPicker(createPicker(VcCalendar)) +const DatePicker = wrapPicker(createPicker(VcCalendar), DatePickerProps()) -const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'YYYY-MM') +const MonthPicker = wrapPicker(createPicker(MonthCalendar), MonthPickerProps(), 'YYYY-MM') Object.assign(DatePicker, { - RangePicker: wrapPicker(RangePicker), + RangePicker: wrapPicker(RangePicker, RangePickerProps()), MonthPicker, - WeekPicker: wrapPicker(WeekPicker, 'YYYY-wo'), + WeekPicker: wrapPicker(WeekPicker, WeexPickerProps(), 'YYYY-wo'), }) export default DatePicker diff --git a/components/date-picker/interface.js b/components/date-picker/interface.js new file mode 100644 index 000000000..963a89c5d --- /dev/null +++ b/components/date-picker/interface.js @@ -0,0 +1,80 @@ +import * as moment from 'moment' +import { TimePickerProps } from '../time-picker' +import PropTypes from '../_util/vue-types' + +export const MomentType = { + type: Object, + validator: function (value) { + return moment.isMoment(value) + }, +} + +export const PickerProps = () => ({ + prefixCls: PropTypes.string, + inputPrefixCls: PropTypes.string, + format: PropTypes.string, + disabled: PropTypes.boolean, + allowClear: PropTypes.boolean, + popupStyle: PropTypes.object, + locale: PropTypes.any, + size: PropTypes.oneOf(['large', 'small', 'default']), + getCalendarContainer: PropTypes.func, + open: PropTypes.boolean, + // onOpenChange: PropTypes.(status: boolean) => void, + disabledDate: PropTypes.func, + renderExtraFooter: PropTypes.any, + dateRender: PropTypes.any, // (current: moment.Moment, today: moment.Moment) => React.ReactNode, +}) + +export const SinglePickerProps = () => ({ + value: MomentType, + defaultValue: MomentType, + defaultPickerValue: MomentType, + // onChange?: (date: moment.Moment, dateString: string) => void; +}) + +export const DatePickerProps = () => ({ + ...PickerProps(), ...SinglePickerProps(), + showTime: PropTypes.oneOfType([PropTypes.shape(TimePickerProps()).loose, PropTypes.bool]), + showToday: PropTypes.bool, + open: PropTypes.bool, + disabledTime: PropTypes.func, + // onOpenChange?: (status: boolean) => void; + // onOk?: (selectedTime: moment.Moment) => void; + placeholder: PropTypes.string, +}) + +export const MonthPickerProps = () => ({ + ...PickerProps(), ...SinglePickerProps(), + placeholder: PropTypes.string, +}) + +export const RangePickerValue = PropTypes.arrayOf(PropTypes.oneOfType([undefined, MomentType])) +export const RangePickerPresetRange = PropTypes.oneOfType([RangePickerValue, PropTypes.func]) + +export const RangePickerProps = () => ({ + ...PickerProps(), + value: RangePickerValue, + defaultValue: RangePickerValue, + defaultPickerValue: RangePickerValue, + // onChange?: (dates: RangePickerValue, dateStrings: [string, string]) => void; + // onCalendarChange?: (dates: RangePickerValue, dateStrings: [string, string]) => void; + // onOk?: (selectedTime: moment.Moment) => void; + showTime: PropTypes.oneOfType([PropTypes.shape(TimePickerProps()).loose, PropTypes.bool]), + ranges: PropTypes.objectOf(String), + placeholder: PropTypes.oneOfType(String), + mode: PropTypes.oneOfType([PropTypes.string, PropTypes.oneOfType(String)]), + disabledTime: PropTypes.func, + // onPanelChange?: (value?: RangePickerValue, mode?: string | string[]) => void; +}) + +export const WeexPickerProps = () => ({ + ...PickerProps(), ...SinglePickerProps(), + placeholder: PropTypes.string, +}) + +// export interface DatePickerDecorator extends React.ClassicComponentClass { +// RangePicker: React.ClassicComponentClass; +// MonthPicker: React.ClassicComponentClass; +// WeekPicker: React.ClassicComponentClass; +// } diff --git a/components/date-picker/interface.tsx b/components/date-picker/interface.tsx deleted file mode 100644 index 3665fc2a1..000000000 --- a/components/date-picker/interface.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import * as React from 'react'; -import * as moment from 'moment'; -import { TimePickerProps } from '../time-picker'; - -export interface PickerProps { - id?: number | string; - prefixCls?: string; - inputPrefixCls?: string; - format?: string; - disabled?: boolean; - allowClear?: boolean; - className?: string; - style?: React.CSSProperties; - popupStyle?: React.CSSProperties; - locale?: any; - size?: 'large' | 'small' | 'default'; - getCalendarContainer?: (triggerNode: Element) => HTMLElement; - open?: boolean; - onOpenChange?: (status: boolean) => void; - disabledDate?: (current: moment.Moment) => boolean; - renderExtraFooter?: () => React.ReactNode; - dateRender?: (current: moment.Moment, today: moment.Moment) => React.ReactNode; -} - -export interface SinglePickerProps { - value?: moment.Moment; - defaultValue?: moment.Moment; - defaultPickerValue?: moment.Moment; - onChange?: (date: moment.Moment, dateString: string) => void; -} - -export interface DatePickerProps extends PickerProps, SinglePickerProps { - className?: string; - showTime?: TimePickerProps | boolean; - showToday?: boolean; - open?: boolean; - disabledTime?: (current: moment.Moment) => { - disabledHours?: () => number[], - disabledMinutes?: () => number[], - disabledSeconds?: () => number[], - }; - onOpenChange?: (status: boolean) => void; - onOk?: (selectedTime: moment.Moment) => void; - placeholder?: string; -} - -export interface MonthPickerProps extends PickerProps, SinglePickerProps { - className?: string; - placeholder?: string; -} - -export type RangePickerValue = - undefined[] | - [moment.Moment] | - [undefined, moment.Moment] | - [moment.Moment, moment.Moment]; -export type RangePickerPresetRange = RangePickerValue | (() => RangePickerValue); - -export interface RangePickerProps extends PickerProps { - className?: string; - value?: RangePickerValue; - defaultValue?: RangePickerValue; - defaultPickerValue?: RangePickerValue; - onChange?: (dates: RangePickerValue, dateStrings: [string, string]) => void; - onCalendarChange?: (dates: RangePickerValue, dateStrings: [string, string]) => void; - onOk?: (selectedTime: moment.Moment) => void; - showTime?: TimePickerProps | boolean; - ranges?: { - [range: string]: RangePickerPresetRange, - }; - placeholder?: [string, string]; - mode?: string | string[]; - disabledTime?: (current: moment.Moment, type: string) => { - disabledHours?: () => number[], - disabledMinutes?: () => number[], - disabledSeconds?: () => number[], - }; - onPanelChange?: (value?: RangePickerValue, mode?: string | string[]) => void; -} - -export interface WeexPickerProps extends PickerProps, SinglePickerProps { - className?: string; - placeholder?: string; -} - -export interface DatePickerDecorator extends React.ClassicComponentClass { - RangePicker: React.ClassicComponentClass; - MonthPicker: React.ClassicComponentClass; - WeekPicker: React.ClassicComponentClass; -} diff --git a/components/date-picker/wrapPicker.vue b/components/date-picker/wrapPicker.js similarity index 98% rename from components/date-picker/wrapPicker.vue rename to components/date-picker/wrapPicker.js index e5225f63f..963c3ddbc 100644 --- a/components/date-picker/wrapPicker.vue +++ b/components/date-picker/wrapPicker.js @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/components/time-picker/index.vue b/components/time-picker/index.vue index acdf41474..ebccf8b13 100644 --- a/components/time-picker/index.vue +++ b/components/time-picker/index.vue @@ -20,7 +20,7 @@ export function generateShowHourMinuteSecond (format) { } } -export const TimePickerProps = { +export const TimePickerProps = () => ({ size: PropTypes.oneOf(['large', 'default', 'small']), value: PropTypes.object, defaultValue: PropTypes.object, @@ -46,11 +46,11 @@ export const TimePickerProps = { align: PropTypes.object, placement: PropTypes.any, transitionName: PropTypes.string, -} +}) export default { mixins: [BaseMixin], - props: initDefaultProps(TimePickerProps, { + props: initDefaultProps(TimePickerProps(), { prefixCls: 'ant-time-picker', align: { offset: [0, -2], @@ -163,4 +163,4 @@ export default { ) }, } - \ No newline at end of file +