ant-design-vue/components/vc-time-picker/TimePicker.jsx

387 lines
9.5 KiB
Vue
Raw Normal View History

2019-03-04 13:00:08 +00:00
import moment from 'moment';
2019-01-12 03:33:27 +00:00
import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin';
2019-05-28 03:37:38 +00:00
import {
initDefaultProps,
hasProp,
getComponentFromProp,
isValidElement,
getEvents,
} from '../_util/props-util';
2019-03-04 13:00:08 +00:00
import { cloneElement } from '../_util/vnode';
2019-01-12 03:33:27 +00:00
import Trigger from '../vc-trigger';
import Panel from './Panel';
import placements from './placements';
2018-03-19 02:16:27 +00:00
2019-01-12 03:33:27 +00:00
function noop() {}
2018-03-07 14:21:55 +00:00
2018-03-08 15:02:04 +00:00
export default {
name: 'VcTimePicker',
2019-02-01 09:23:00 +00:00
mixins: [BaseMixin],
2019-01-12 03:33:27 +00:00
props: initDefaultProps(
{
prefixCls: PropTypes.string,
clearText: PropTypes.string,
value: PropTypes.any,
defaultOpenValue: {
type: Object,
default: () => {
return moment();
},
2018-03-08 15:02:04 +00:00
},
2019-01-12 03:33:27 +00:00
inputReadOnly: PropTypes.bool,
disabled: PropTypes.bool,
allowEmpty: PropTypes.bool,
defaultValue: PropTypes.any,
open: PropTypes.bool,
defaultOpen: PropTypes.bool,
align: PropTypes.object,
placement: PropTypes.any,
transitionName: PropTypes.string,
getPopupContainer: PropTypes.func,
placeholder: PropTypes.string,
format: PropTypes.string,
showHour: PropTypes.bool,
showMinute: PropTypes.bool,
showSecond: PropTypes.bool,
popupClassName: PropTypes.string,
2019-03-04 13:00:08 +00:00
popupStyle: PropTypes.object,
2019-01-12 03:33:27 +00:00
disabledHours: PropTypes.func,
disabledMinutes: PropTypes.func,
disabledSeconds: PropTypes.func,
hideDisabledOptions: PropTypes.bool,
// onChange: PropTypes.func,
2019-03-04 13:00:08 +00:00
// onAmPmChange: PropTypes.func,
2019-01-12 03:33:27 +00:00
// onOpen: PropTypes.func,
// onClose: PropTypes.func,
// onFocus: PropTypes.func,
// onBlur: PropTypes.func,
name: PropTypes.string,
autoComplete: PropTypes.string,
use12Hours: PropTypes.bool,
hourStep: PropTypes.number,
minuteStep: PropTypes.number,
secondStep: PropTypes.number,
focusOnOpen: PropTypes.bool,
// onKeyDown: PropTypes.func,
autoFocus: PropTypes.bool,
id: PropTypes.string,
inputIcon: PropTypes.any,
clearIcon: PropTypes.any,
addon: PropTypes.func,
},
{
clearText: 'clear',
prefixCls: 'rc-time-picker',
defaultOpen: false,
inputReadOnly: false,
popupClassName: '',
2019-03-04 13:00:08 +00:00
popupStyle: {},
2019-01-12 03:33:27 +00:00
align: {},
allowEmpty: true,
showHour: true,
showMinute: true,
showSecond: true,
disabledHours: noop,
disabledMinutes: noop,
disabledSeconds: noop,
hideDisabledOptions: false,
placement: 'bottomLeft',
use12Hours: false,
focusOnOpen: false,
2018-03-08 15:02:04 +00:00
},
2019-01-12 03:33:27 +00:00
),
data() {
const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = this;
2018-03-08 15:02:04 +00:00
return {
sOpen: open,
sValue: value,
2019-01-12 03:33:27 +00:00
};
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2018-03-08 15:02:04 +00:00
watch: {
2019-01-12 03:33:27 +00:00
value(val) {
2018-03-07 14:21:55 +00:00
this.setState({
2018-03-08 15:02:04 +00:00
sValue: val,
2019-01-12 03:33:27 +00:00
});
2018-03-08 15:02:04 +00:00
},
2019-01-12 03:33:27 +00:00
open(val) {
2018-03-08 15:02:04 +00:00
if (val !== undefined) {
this.setState({
sOpen: val,
2019-01-12 03:33:27 +00:00
});
2018-03-08 15:02:04 +00:00
}
},
},
2019-02-01 09:23:00 +00:00
mounted() {
this.$nextTick(() => {
if (this.autoFocus) {
this.focus();
}
});
},
2018-03-08 15:02:04 +00:00
methods: {
2019-01-12 03:33:27 +00:00
onPanelChange(value) {
this.setValue(value);
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-03-04 13:00:08 +00:00
onAmPmChange(ampm) {
this.__emit('amPmChange', ampm);
},
onClear(event) {
event.stopPropagation();
2019-01-12 03:33:27 +00:00
this.setValue(null);
this.setOpen(false);
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
onVisibleChange(open) {
this.setOpen(open);
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
onEsc() {
this.setOpen(false);
this.focus();
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
onKeyDown(e) {
2018-03-08 15:02:04 +00:00
if (e.keyCode === 40) {
2019-01-12 03:33:27 +00:00
this.setOpen(true);
2018-03-08 15:02:04 +00:00
}
},
2019-01-12 03:33:27 +00:00
onKeyDown2(e) {
this.__emit('keydown', e);
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
setValue(value) {
2018-03-08 15:02:04 +00:00
if (!hasProp(this, 'value')) {
this.setState({
sValue: value,
2019-01-12 03:33:27 +00:00
});
2018-03-08 15:02:04 +00:00
}
2019-01-12 03:33:27 +00:00
this.__emit('change', value);
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
getFormat() {
const { format, showHour, showMinute, showSecond, use12Hours } = this;
2018-03-08 15:02:04 +00:00
if (format) {
2019-01-12 03:33:27 +00:00
return format;
2018-03-08 15:02:04 +00:00
}
2018-03-07 14:21:55 +00:00
2018-03-08 15:02:04 +00:00
if (use12Hours) {
2019-01-12 03:33:27 +00:00
const fmtString = [showHour ? 'h' : '', showMinute ? 'mm' : '', showSecond ? 'ss' : '']
.filter(item => !!item)
.join(':');
2018-03-08 15:02:04 +00:00
2019-01-12 03:33:27 +00:00
return fmtString.concat(' a');
2018-03-08 15:02:04 +00:00
}
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
return [showHour ? 'HH' : '', showMinute ? 'mm' : '', showSecond ? 'ss' : '']
.filter(item => !!item)
.join(':');
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
getPanelElement() {
2018-03-08 15:02:04 +00:00
const {
2019-01-12 03:33:27 +00:00
prefixCls,
placeholder,
disabledHours,
addon,
disabledMinutes,
disabledSeconds,
hideDisabledOptions,
inputReadOnly,
allowEmpty,
showHour,
showMinute,
showSecond,
defaultOpenValue,
clearText,
use12Hours,
focusOnOpen,
onKeyDown2,
hourStep,
minuteStep,
secondStep,
2018-03-08 15:02:04 +00:00
sValue,
2019-01-12 03:33:27 +00:00
} = this;
const clearIcon = getComponentFromProp(this, 'clearIcon');
2018-03-08 15:02:04 +00:00
return (
<Panel
clearText={clearText}
prefixCls={`${prefixCls}-panel`}
2019-01-12 03:33:27 +00:00
ref="panel"
2018-03-08 15:02:04 +00:00
value={sValue}
inputReadOnly={inputReadOnly}
onChange={this.onPanelChange}
2019-03-04 13:00:08 +00:00
onAmPmChange={this.onAmPmChange}
2018-03-08 15:02:04 +00:00
defaultOpenValue={defaultOpenValue}
showHour={showHour}
showMinute={showMinute}
showSecond={showSecond}
onEsc={this.onEsc}
allowEmpty={allowEmpty}
format={this.getFormat()}
placeholder={placeholder}
disabledHours={disabledHours}
disabledMinutes={disabledMinutes}
disabledSeconds={disabledSeconds}
hideDisabledOptions={hideDisabledOptions}
use12Hours={use12Hours}
hourStep={hourStep}
minuteStep={minuteStep}
secondStep={secondStep}
focusOnOpen={focusOnOpen}
onKeydown={onKeyDown2}
clearIcon={clearIcon}
addon={addon}
/>
2019-01-12 03:33:27 +00:00
);
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
getPopupClassName() {
const { showHour, showMinute, showSecond, use12Hours, prefixCls } = this;
let popupClassName = this.popupClassName;
2018-03-08 15:02:04 +00:00
// Keep it for old compatibility
if ((!showHour || !showMinute || !showSecond) && !use12Hours) {
2019-01-12 03:33:27 +00:00
popupClassName += ` ${prefixCls}-panel-narrow`;
2018-03-07 14:21:55 +00:00
}
2019-01-12 03:33:27 +00:00
let selectColumnCount = 0;
2018-03-08 15:02:04 +00:00
if (showHour) {
2019-01-12 03:33:27 +00:00
selectColumnCount += 1;
2018-03-07 14:21:55 +00:00
}
2018-03-08 15:02:04 +00:00
if (showMinute) {
2019-01-12 03:33:27 +00:00
selectColumnCount += 1;
2018-03-08 15:02:04 +00:00
}
if (showSecond) {
2019-01-12 03:33:27 +00:00
selectColumnCount += 1;
2018-03-08 15:02:04 +00:00
}
if (use12Hours) {
2019-01-12 03:33:27 +00:00
selectColumnCount += 1;
2018-03-08 15:02:04 +00:00
}
2019-01-12 03:33:27 +00:00
popupClassName += ` ${prefixCls}-panel-column-${selectColumnCount}`;
return popupClassName;
2018-03-08 15:02:04 +00:00
},
2019-01-12 03:33:27 +00:00
setOpen(open) {
2018-03-08 15:02:04 +00:00
if (this.sOpen !== open) {
if (!hasProp(this, 'open')) {
2019-01-12 03:33:27 +00:00
this.setState({ sOpen: open });
2018-03-08 15:02:04 +00:00
}
if (open) {
2019-01-12 03:33:27 +00:00
this.__emit('open', { open });
2018-03-08 15:02:04 +00:00
} else {
2019-01-12 03:33:27 +00:00
this.__emit('close', { open });
2018-03-08 15:02:04 +00:00
}
}
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
focus() {
this.$refs.picker.focus();
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
blur() {
this.$refs.picker.blur();
2018-03-08 15:02:04 +00:00
},
2019-01-12 03:33:27 +00:00
onFocus(e) {
this.__emit('focus', e);
2018-03-08 15:02:04 +00:00
},
2019-01-12 03:33:27 +00:00
onBlur(e) {
this.__emit('blur', e);
2018-03-08 15:02:04 +00:00
},
2019-03-04 13:00:08 +00:00
renderClearButton() {
const { sValue } = this;
const { prefixCls, allowEmpty, clearText } = this.$props;
if (!allowEmpty || !sValue) {
return null;
}
const clearIcon = getComponentFromProp(this, 'clearIcon');
if (isValidElement(clearIcon)) {
const { click } = getEvents(clearIcon) || {};
return cloneElement(clearIcon, {
on: {
click: (...args) => {
if (click) click(...args);
this.onClear(...args);
},
},
});
}
return (
<a
role="button"
class={`${prefixCls}-clear`}
title={clearText}
onClick={this.onClear}
tabIndex={0}
>
{clearIcon || <i class={`${prefixCls}-clear-icon`} />}
</a>
);
},
2018-03-08 15:02:04 +00:00
},
2018-03-07 14:21:55 +00:00
2019-01-12 03:33:27 +00:00
render() {
2018-03-07 14:21:55 +00:00
const {
2019-01-12 03:33:27 +00:00
prefixCls,
placeholder,
placement,
align,
id,
disabled,
transitionName,
getPopupContainer,
name,
autoComplete,
autoFocus,
inputReadOnly,
sOpen,
sValue,
onFocus,
onBlur,
2019-03-04 13:00:08 +00:00
popupStyle,
2019-01-12 03:33:27 +00:00
} = this;
const popupClassName = this.getPopupClassName();
const inputIcon = getComponentFromProp(this, 'inputIcon');
2018-03-07 14:21:55 +00:00
return (
<Trigger
prefixCls={`${prefixCls}-panel`}
popupClassName={popupClassName}
2019-03-04 13:00:08 +00:00
popupStyle={popupStyle}
2018-03-07 14:21:55 +00:00
popupAlign={align}
builtinPlacements={placements}
popupPlacement={placement}
action={disabled ? [] : ['click']}
destroyPopupOnHide
getPopupContainer={getPopupContainer}
popupTransitionName={transitionName}
2018-03-08 15:02:04 +00:00
popupVisible={sOpen}
2018-03-07 14:21:55 +00:00
onPopupVisibleChange={this.onVisibleChange}
>
2019-01-12 03:33:27 +00:00
<template slot="popup">{this.getPanelElement()}</template>
2018-03-08 15:02:04 +00:00
<span class={`${prefixCls}`}>
2018-03-07 14:21:55 +00:00
<input
2018-03-08 15:02:04 +00:00
class={`${prefixCls}-input`}
2019-01-12 03:33:27 +00:00
ref="picker"
type="text"
2018-03-07 14:21:55 +00:00
placeholder={placeholder}
name={name}
2018-03-08 15:02:04 +00:00
onKeydown={this.onKeyDown}
2018-03-07 14:21:55 +00:00
disabled={disabled}
2019-01-12 03:33:27 +00:00
value={(sValue && sValue.format(this.getFormat())) || ''}
2018-03-07 14:21:55 +00:00
autoComplete={autoComplete}
onFocus={onFocus}
onBlur={onBlur}
autoFocus={autoFocus}
readOnly={!!inputReadOnly}
2018-03-13 02:19:00 +00:00
id={id}
2018-03-07 14:21:55 +00:00
/>
2019-01-12 03:33:27 +00:00
{inputIcon || <span class={`${prefixCls}-icon`} />}
2019-03-04 13:00:08 +00:00
{this.renderClearButton()}
2018-03-07 14:21:55 +00:00
</span>
</Trigger>
2019-01-12 03:33:27 +00:00
);
2018-03-08 15:02:04 +00:00
},
2019-01-12 03:33:27 +00:00
};