feat: update time-picker

pull/2682/head
tanjinzhou 2020-07-21 16:46:39 +08:00
parent cd80ce622b
commit 6ab243ffaa
9 changed files with 90 additions and 72 deletions

@ -1 +1 @@
Subproject commit c2521df74700792b5cd6c353cf9fce91fbd40e19 Subproject commit aae9db4ae607a00f4c8482c159bfaf71fe982595

View File

@ -1,4 +1,5 @@
import omit from 'omit.js'; import omit from 'omit.js';
import { inject, provide } from 'vue';
import VcTimePicker from '../vc-time-picker'; import VcTimePicker from '../vc-time-picker';
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import LocaleReceiver from '../locale-provider/LocaleReceiver';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
@ -13,11 +14,9 @@ import {
getOptionProps, getOptionProps,
getComponent, getComponent,
isValidElement, isValidElement,
getListeners,
} from '../_util/props-util'; } from '../_util/props-util';
import { cloneElement } from '../_util/vnode'; import { cloneElement } from '../_util/vnode';
import { ConfigConsumerProps } from '../config-provider'; import { ConfigConsumerProps } from '../config-provider';
import Base from '../base';
import { import {
checkValidate, checkValidate,
stringToMoment, stringToMoment,
@ -69,10 +68,21 @@ export const TimePickerProps = () => ({
clearIcon: PropTypes.any, clearIcon: PropTypes.any,
locale: PropTypes.object, locale: PropTypes.object,
valueFormat: PropTypes.string, valueFormat: PropTypes.string,
onChange: PropTypes.func,
onAmPmChange: PropTypes.func,
onOpen: PropTypes.func,
onClose: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
onKeydown: PropTypes.func,
onOpenChange: PropTypes.func,
'onUpdate:value': PropTypes.func,
'onUpdate:open': PropTypes.func,
}); });
const TimePicker = { const TimePicker = {
name: 'ATimePicker', name: 'ATimePicker',
inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
props: initDefaultProps(TimePickerProps(), { props: initDefaultProps(TimePickerProps(), {
align: { align: {
@ -88,18 +98,15 @@ const TimePicker = {
focusOnOpen: true, focusOnOpen: true,
allowClear: true, allowClear: true,
}), }),
model: { created() {
prop: 'value', provide('savePopupRef', this.savePopupRef);
event: 'change',
}, },
provide() { setup() {
return { return {
savePopupRef: this.savePopupRef, configProvider: inject('configProvider', ConfigConsumerProps),
}; };
}, },
inject: {
configProvider: { default: () => ConfigConsumerProps },
},
data() { data() {
const { value, defaultValue, valueFormat } = this; const { value, defaultValue, valueFormat } = this;
@ -148,16 +155,17 @@ const TimePicker = {
savePopupRef(ref) { savePopupRef(ref) {
this.popupRef = ref; this.popupRef = ref;
}, },
saveTimePicker(timePickerRef) {
this.timePickerRef = timePickerRef;
},
handleChange(value) { handleChange(value) {
if (!hasProp(this, 'value')) { if (!hasProp(this, 'value')) {
this.setState({ sValue: value }); this.setState({ sValue: value });
} }
const { format = 'HH:mm:ss' } = this; const { format = 'HH:mm:ss' } = this;
this.$emit( const val = this.valueFormat ? momentToString(value, this.valueFormat) : value;
'change', this.$emit('update:value', val);
this.valueFormat ? momentToString(value, this.valueFormat) : value, this.$emit('change', val, (value && value.format(format)) || '');
(value && value.format(format)) || '',
);
}, },
handleOpenClose({ open }) { handleOpenClose({ open }) {
@ -166,11 +174,11 @@ const TimePicker = {
}, },
focus() { focus() {
this.$refs.timePicker.focus(); this.timePickerRef.focus();
}, },
blur() { blur() {
this.$refs.timePicker.blur(); this.timePickerRef.blur();
}, },
renderInputIcon(prefixCls) { renderInputIcon(prefixCls) {
@ -201,13 +209,14 @@ const TimePicker = {
renderTimePicker(locale) { renderTimePicker(locale) {
let props = getOptionProps(this); let props = getOptionProps(this);
props = omit(props, ['defaultValue', 'suffixIcon', 'allowEmpty', 'allowClear']); props = omit(props, ['defaultValue', 'suffixIcon', 'allowEmpty', 'allowClear']);
const { class: className } = this.$attrs;
const { prefixCls: customizePrefixCls, getPopupContainer, placeholder, size } = props; const { prefixCls: customizePrefixCls, getPopupContainer, placeholder, size } = props;
const getPrefixCls = this.configProvider.getPrefixCls; const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('time-picker', customizePrefixCls); const prefixCls = getPrefixCls('time-picker', customizePrefixCls);
const format = this.getDefaultFormat(); const format = this.getDefaultFormat();
const pickerClassName = { const pickerClassName = {
[className]: className,
[`${prefixCls}-${size}`]: !!size, [`${prefixCls}-${size}`]: !!size,
}; };
const tempAddon = getComponent(this, 'addon', {}, false); const tempAddon = getComponent(this, 'addon', {}, false);
@ -222,9 +231,9 @@ const TimePicker = {
const clearIcon = this.renderClearIcon(prefixCls); const clearIcon = this.renderClearIcon(prefixCls);
const { getPopupContainer: getContextPopupContainer } = this.configProvider; const { getPopupContainer: getContextPopupContainer } = this.configProvider;
const timeProps = { const timeProps = {
props: {
...generateShowHourMinuteSecond(format), ...generateShowHourMinuteSecond(format),
...props, ...props,
...this.$attrs,
allowEmpty: this.getAllowClear(), allowEmpty: this.getAllowClear(),
prefixCls, prefixCls,
getPopupContainer: getPopupContainer || getContextPopupContainer, getPopupContainer: getPopupContainer || getContextPopupContainer,
@ -234,15 +243,11 @@ const TimePicker = {
addon: pickerAddon, addon: pickerAddon,
inputIcon, inputIcon,
clearIcon, clearIcon,
},
class: pickerClassName, class: pickerClassName,
ref: 'timePicker', ref: this.saveTimePicker,
on: { onChange: this.handleChange,
...getListeners(this), onOpen: this.handleOpenClose,
change: this.handleChange, onClose: this.handleOpenClose,
open: this.handleOpenClose,
close: this.handleOpenClose,
},
}; };
return <VcTimePicker {...timeProps} />; return <VcTimePicker {...timeProps} />;
}, },
@ -253,16 +258,15 @@ const TimePicker = {
<LocaleReceiver <LocaleReceiver
componentName="TimePicker" componentName="TimePicker"
defaultLocale={this.getDefaultLocale()} defaultLocale={this.getDefaultLocale()}
scopedSlots={{ default: this.renderTimePicker }} children={this.renderTimePicker}
/> />
); );
}, },
}; };
/* istanbul ignore next */ /* istanbul ignore next */
TimePicker.install = function(Vue) { TimePicker.install = function(app) {
Vue.use(Base); app.component(TimePicker.name, TimePicker);
Vue.component(TimePicker.name, TimePicker);
}; };
export default TimePicker; export default TimePicker;

View File

@ -20,6 +20,7 @@ const formatOption = (option, disabledOptions) => {
}; };
const Combobox = { const Combobox = {
inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
name: 'Combobox', name: 'Combobox',
props: { props: {

View File

@ -3,6 +3,8 @@ import BaseMixin from '../_util/BaseMixin';
import moment from 'moment'; import moment from 'moment';
const Header = { const Header = {
inheritAttrs: false,
name: 'Header',
mixins: [BaseMixin], mixins: [BaseMixin],
props: { props: {
format: PropTypes.string, format: PropTypes.string,
@ -41,8 +43,8 @@ const Header = {
// Wait one frame for the panel to be positioned before focusing // Wait one frame for the panel to be positioned before focusing
const requestAnimationFrame = window.requestAnimationFrame || window.setTimeout; const requestAnimationFrame = window.requestAnimationFrame || window.setTimeout;
requestAnimationFrame(() => { requestAnimationFrame(() => {
this.$refs.input.focus(); this.refInput.focus();
this.$refs.input.select(); this.refInput.select();
}); });
} }
}, },
@ -160,19 +162,14 @@ const Header = {
return ( return (
<input <input
class={`${prefixCls}-input ${invalidClass}`} class={`${prefixCls}-input ${invalidClass}`}
ref="input" ref={ref => {
this.refInput = ref;
}}
onKeydown={this.onKeyDown} onKeydown={this.onKeyDown}
value={str} value={str}
placeholder={placeholder} placeholder={placeholder}
onInput={this.onInputChange} onInput={this.onInputChange}
readonly={!!inputReadOnly} readonly={!!inputReadOnly}
{...{
directives: [
{
name: 'ant-input',
},
],
}}
/> />
); );
}, },

View File

@ -1,9 +1,10 @@
import moment from 'moment'; import moment from 'moment';
import classNames from 'classnames';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import Header from './Header'; import Header from './Header';
import Combobox from './Combobox'; import Combobox from './Combobox';
import { getComponent, getListeners } from '../_util/props-util'; import { getComponent } from '../_util/props-util';
function noop() {} function noop() {}
@ -31,6 +32,8 @@ function toNearestValidTime(time, hourOptions, minuteOptions, secondOptions) {
} }
const Panel = { const Panel = {
name: 'Panel',
inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
props: { props: {
clearText: PropTypes.string, clearText: PropTypes.string,
@ -144,8 +147,8 @@ const Panel = {
sValue, sValue,
currentSelectPanel, currentSelectPanel,
} = this; } = this;
const { class: className, onEsc = noop, onKeydown = noop } = this.$attrs;
const clearIcon = getComponent(this, 'clearIcon'); const clearIcon = getComponent(this, 'clearIcon');
const { esc = noop, keydown = noop } = getListeners(this);
const disabledHourOptions = this.disabledHours2(); const disabledHourOptions = this.disabledHours2();
const disabledMinuteOptions = disabledMinutes(sValue ? sValue.hour() : null); const disabledMinuteOptions = disabledMinutes(sValue ? sValue.hour() : null);
@ -173,14 +176,14 @@ const Panel = {
secondOptions, secondOptions,
); );
return ( return (
<div class={`${prefixCls}-inner`}> <div className={classNames(className, `${prefixCls}-inner`)}>
<Header <Header
clearText={clearText} clearText={clearText}
prefixCls={prefixCls} prefixCls={prefixCls}
defaultOpenValue={validDefaultOpenValue} defaultOpenValue={validDefaultOpenValue}
value={sValue} value={sValue}
currentSelectPanel={currentSelectPanel} currentSelectPanel={currentSelectPanel}
onEsc={esc} onEsc={onEsc}
format={format} format={format}
placeholder={placeholder} placeholder={placeholder}
hourOptions={hourOptions} hourOptions={hourOptions}
@ -191,7 +194,7 @@ const Panel = {
disabledSeconds={disabledSeconds} disabledSeconds={disabledSeconds}
onChange={this.onChange} onChange={this.onChange}
focusOnOpen={focusOnOpen} focusOnOpen={focusOnOpen}
onKeydown={keydown} onKeydown={onKeydown}
inputReadOnly={inputReadOnly} inputReadOnly={inputReadOnly}
clearIcon={clearIcon} clearIcon={clearIcon}
/> />

View File

@ -23,7 +23,9 @@ const scrollTo = (element, to, duration) => {
}; };
const Select = { const Select = {
name: 'Select',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
props: { props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
options: PropTypes.array, options: PropTypes.array,
@ -101,6 +103,10 @@ const Select = {
this.setState({ active: false }); this.setState({ active: false });
}, },
saveList(node) {
this.list = node;
},
scrollToSelected(duration) { scrollToSelected(duration) {
// move to selected item // move to selected item
const select = this.$el; const select = this.$el;
@ -131,7 +137,7 @@ const Select = {
return ( return (
<div class={cls} onMouseenter={this.handleMouseEnter} onMouseleave={this.handleMouseLeave}> <div class={cls} onMouseenter={this.handleMouseEnter} onMouseleave={this.handleMouseLeave}>
<ul ref="list">{this.getOptions()}</ul> <ul ref={this.saveList}>{this.getOptions()}</ul>
</div> </div>
); );
}, },

View File

@ -15,10 +15,14 @@ import Panel from './Panel';
import placements from './placements'; import placements from './placements';
function noop() {} function noop() {}
function refFn(field, component) {
this[field] = component;
}
export default { export default {
name: 'VcTimePicker', name: 'VcTimePicker',
mixins: [BaseMixin], mixins: [BaseMixin],
inheritAttrs: false,
props: initDefaultProps( props: initDefaultProps(
{ {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
@ -93,6 +97,8 @@ export default {
}, },
), ),
data() { data() {
this.saveInputRef = refFn.bind(this, 'picker');
this.savePanelRef = refFn.bind(this, 'panelInstance');
const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = this; const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = this;
return { return {
sOpen: open, sOpen: open,
@ -210,7 +216,7 @@ export default {
<Panel <Panel
clearText={clearText} clearText={clearText}
prefixCls={`${prefixCls}-panel`} prefixCls={`${prefixCls}-panel`}
ref="panel" ref={this.savePanelRef}
value={sValue} value={sValue}
inputReadOnly={inputReadOnly} inputReadOnly={inputReadOnly}
onChange={this.onPanelChange} onChange={this.onPanelChange}
@ -278,11 +284,11 @@ export default {
}, },
focus() { focus() {
this.$refs.picker.focus(); this.picker.focus();
}, },
blur() { blur() {
this.$refs.picker.blur(); this.picker.blur();
}, },
onFocus(e) { onFocus(e) {
this.__emit('focus', e); this.__emit('focus', e);
@ -298,14 +304,12 @@ export default {
} }
const clearIcon = getComponent(this, 'clearIcon'); const clearIcon = getComponent(this, 'clearIcon');
if (isValidElement(clearIcon)) { if (isValidElement(clearIcon)) {
const { click } = getEvents(clearIcon) || {}; const { onClick } = getEvents(clearIcon) || {};
return cloneElement(clearIcon, { return cloneElement(clearIcon, {
on: { onClick: (...args) => {
click: (...args) => { if (onClick) onClick(...args);
if (click) click(...args);
this.onClear(...args); this.onClear(...args);
}, },
},
}); });
} }
@ -343,6 +347,7 @@ export default {
onBlur, onBlur,
popupStyle, popupStyle,
} = this; } = this;
const { class: className, style } = this.$attrs;
const popupClassName = this.getPopupClassName(); const popupClassName = this.getPopupClassName();
const inputIcon = getComponent(this, 'inputIcon'); const inputIcon = getComponent(this, 'inputIcon');
return ( return (
@ -359,12 +364,12 @@ export default {
popupTransitionName={transitionName} popupTransitionName={transitionName}
popupVisible={sOpen} popupVisible={sOpen}
onPopupVisibleChange={this.onVisibleChange} onPopupVisibleChange={this.onVisibleChange}
popup={this.getPanelElement()}
> >
<template slot="popup">{this.getPanelElement()}</template> <span class={classNames(prefixCls, className)} style={style}>
<span class={`${prefixCls}`}>
<input <input
class={`${prefixCls}-input`} class={`${prefixCls}-input`}
ref="picker" ref={this.saveInputRef}
type="text" type="text"
placeholder={placeholder} placeholder={placeholder}
name={name} name={name}

View File

@ -4,7 +4,7 @@
</div> </div>
</template> </template>
<script> <script>
import demo from '../antdv-demo/docs/slider/demo/basic'; import demo from '../antdv-demo/docs/time-picker/demo/basic';
export default { export default {
components: { components: {

View File

@ -33,6 +33,7 @@ import {
Transfer, Transfer,
Slider, Slider,
Carousel, Carousel,
TimePicker,
notification, notification,
message, message,
} from 'ant-design-vue'; } from 'ant-design-vue';
@ -83,4 +84,5 @@ app
.use(Transfer) .use(Transfer)
.use(Slider) .use(Slider)
.use(Carousel) .use(Carousel)
.use(TimePicker)
.mount('#app'); .mount('#app');