add time-picker demo

pull/165/head
tjz 2018-03-08 23:02:04 +08:00
parent 116d2457bb
commit 18f4a62129
57 changed files with 1347 additions and 960 deletions

View File

@ -89,6 +89,7 @@ export { default as Cascader } from './cascader'
export { default as BackTop } from './back-top' export { default as BackTop } from './back-top'
export { default as Modal } from './modal' export { default as Modal } from './modal'
export { default as Alert } from './alert' export { default as Alert } from './alert'
export { default as TimePicker } from './time-picker'
const api = { const api = {
notification, notification,

View File

@ -29,3 +29,4 @@ import './cascader/style'
import './back-top/style' import './back-top/style'
import './modal/style' import './modal/style'
import './alert/style' import './alert/style'
import './time-picker/style'

View File

@ -0,0 +1,28 @@
<cn>
#### 12 小时制
12 小时制的时间选择器,默认的 format 为 `h:mm:ss a`
</cn>
<us>
#### 12 hours
TimePicker of 12 hours format, with default format `h:mm:ss a`.
</us>
```html
<template>
<div>
<a-time-picker use12Hours @change="onChange" />
<a-time-picker use12Hours format="h:mm:ss A" @change="onChange" />
<a-time-picker use12Hours format="h:mm a" @change="onChange" />
</div>
</template>
<script>
export default {
methods: {
onChange(time, timeString){
console.log(time, timeString);
}
},
}
</script>
```

View File

@ -0,0 +1,43 @@
<cn>
#### 附加内容
在 TimePicker 选择框底部显示自定义的内容。
</cn>
<us>
#### Addon
Render addon contents to timepicker panel's bottom.
</us>
```html
<template>
<div>
<a-time-picker @openChange="handleOpenChange" :open="open">
<a-button slot="addon" size="small" type="primary" @click="handleClose">Ok</a-button>
</a-time-picker>
<a-time-picker :open.sync="open2">
<a-button slot="addon" size="small" type="primary" @click="handleClose">Ok</a-button>
</a-time-picker>
</div>
</template>
<script>
import moment from 'moment';
export default {
data() {
return {
open: false,
open2: false,
}
},
methods: {
handleOpenChange(open){
console.log('open', open);
this.open = open
},
handleClose(){
this.open = false
this.open2 = false
}
},
}
</script>
```

View File

@ -0,0 +1,26 @@
<cn>
#### 基本
点击 TimePicker然后可以在浮层中选择或者输入某一时间。
</cn>
<us>
#### Basic
Click `TimePicker`, and then we could select or input a time in panel.
</us>
```html
<template>
<a-time-picker @change="onChange" :defaultOpenValue="moment('00:00:00', 'HH:mm:ss')" />
</template>
<script>
import moment from 'moment';
export default {
methods: {
moment,
onChange(time, timeString){
console.log(time, timeString);
}
},
}
</script>
```

View File

@ -0,0 +1,23 @@
<cn>
#### 禁用
禁用时间选择。
</cn>
<us>
#### disabled
A disabled state of the `TimePicker`.
</us>
```html
<template>
<a-time-picker :defaultValue="moment('12:08:23', 'HH:mm:ss')" disabled />
</template>
<script>
import moment from 'moment';
export default {
methods: {
moment,
}
}
</script>
```

View File

@ -0,0 +1,23 @@
<cn>
#### 选择时分
TimePicker 浮层中的列会随着 `format` 变化,当略去 `format` 中的某部分时,浮层中对应的列也会消失。
</cn>
<us>
#### Hour and minute
While part of `format` is omitted, the corresponding column in panel will disappear, too.
</us>
```html
<template>
<a-time-picker :defaultValue="moment('12:08', 'HH:mm')" format="HH:mm" />
</template>
<script>
import moment from 'moment';
export default {
methods: {
moment,
},
}
</script>
```

View File

@ -0,0 +1,15 @@
<cn>
#### 步长选项
可以使用 `hourStep` `minuteStep` `secondStep` 按步长展示可选的时分秒。
</cn>
<us>
#### interval option
Show stepped options by `hourStep` `minuteStep` `secondStep`.
</us>
```html
<template>
<a-time-picker :minuteStep="15" :secondStep="10" />
</template>
```

View File

@ -0,0 +1,27 @@
<cn>
#### 三种大小
三种大小的输入框,大的用在表单中,中的为默认。
</cn>
<us>
#### Three Sizes
The input box comes in three sizes. large is used in the form, while the medium size is the default.
</us>
```html
<template>
<div>
<a-time-picker :defaultValue="moment('12:08:23', 'HH:mm:ss')" size="large" />
<a-time-picker :defaultValue="moment('12:08:23', 'HH:mm:ss')" />
<a-time-picker :defaultValue="moment('12:08:23', 'HH:mm:ss')" size="small" />
</div>
</template>
<script>
import moment from 'moment';
export default {
methods: {
moment,
},
}
</script>
```

View File

@ -0,0 +1,43 @@
<cn>
#### 受控组件
value 和 onChange 需要配合使用。也可以直接使用v-model。
</cn>
<us>
#### Under Control
`value` and `@change` should be used together or use v-model.
</us>
```html
<template>
<div>
<p>use value and @change</p>
<a-time-picker @change="onChange" :value="value" />
<br/>
<br/>
<p>v-model</p>
<a-time-picker v-model="value" />
<br/>
<br/>
<p>Do not change</p>
<a-time-picker :value="value2" />
</div>
</template>
<script>
import moment from 'moment';
export default {
data(){
return {
value: null,
value2: moment(),
}
},
methods: {
onChange(time,){
console.log(time);
this.value = time;
}
},
}
</script>
```

View File

@ -1,11 +1,13 @@
<script> <script>
import * as moment from 'moment'; import * as moment from 'moment'
import RcTimePicker from 'rc-time-picker/lib/TimePicker'; import VcTimePicker from '../vc-time-picker'
import classNames from 'classnames'; import LocaleReceiver from '../locale-provider/LocaleReceiver'
import LocaleReceiver from '../locale-provider/LocaleReceiver'; import defaultLocale from './locale/en_US'
import defaultLocale from './locale/en_US'; import BaseMixin from '../_util/BaseMixin'
import PropTypes from '../_util/vue-types'
import { initDefaultProps, hasProp, getOptionProps, getComponentFromProp } from '../_util/props-util'
export function generateShowHourMinuteSecond(format: string) { export function generateShowHourMinuteSecond (format) {
// Ref: http://momentjs.com/docs/#/parsing/string-format/ // Ref: http://momentjs.com/docs/#/parsing/string-format/
return { return {
showHour: ( showHour: (
@ -15,45 +17,40 @@ export function generateShowHourMinuteSecond(format: string) {
), ),
showMinute: format.indexOf('m') > -1, showMinute: format.indexOf('m') > -1,
showSecond: format.indexOf('s') > -1, showSecond: format.indexOf('s') > -1,
}; }
} }
export interface TimePickerProps { export const TimePickerProps = {
className?: string; size: PropTypes.oneOf(['large', 'default', 'small']),
size?: 'large' | 'default' | 'small'; value: PropTypes.object,
value?: moment.Moment; defaultValue: PropTypes.object,
defaultValue?: moment.Moment | moment.Moment[]; open: PropTypes.bool,
open?: boolean; format: PropTypes.string,
format?: string; disabled: PropTypes.bool,
onChange?: (time: moment.Moment, timeString: string) => void; placeholder: PropTypes.string,
onOpenChange?: (open: boolean) => void; prefixCls: PropTypes.string,
disabled?: boolean; hideDisabledOptions: PropTypes.bool,
placeholder?: string; disabledHours: PropTypes.func,
prefixCls?: string; disabledMinutes: PropTypes.func,
hideDisabledOptions?: boolean; disabledSeconds: PropTypes.func,
disabledHours?: () => number[]; getPopupContainer: PropTypes.func,
disabledMinutes?: (selectedHour: number) => number[]; use12Hours: PropTypes.bool,
disabledSeconds?: (selectedHour: number, selectedMinute: number) => number[]; focusOnOpen: PropTypes.bool,
style?: React.CSSProperties; hourStep: PropTypes.number,
getPopupContainer?: (triggerNode: Element) => HTMLElement; minuteStep: PropTypes.number,
addon?: Function; secondStep: PropTypes.number,
use12Hours?: boolean; allowEmpty: PropTypes.bool,
focusOnOpen?: boolean; clearText: PropTypes.string,
hourStep?: number; defaultOpenValue: PropTypes.object,
minuteStep?: number; popupClassName: PropTypes.string,
secondStep?: number; align: PropTypes.object,
allowEmpty?: boolean; placement: PropTypes.any,
clearText?: string; transitionName: PropTypes.string,
defaultOpenValue?: moment.Moment;
popupClassName?: string;
} }
export interface TimePickerLocale { export default {
placeholder: string; mixins: [BaseMixin],
} props: initDefaultProps(TimePickerProps, {
export default class TimePicker extends React.Component<TimePickerProps, any> {
static defaultProps = {
prefixCls: 'ant-time-picker', prefixCls: 'ant-time-picker',
align: { align: {
offset: [0, -2], offset: [0, -2],
@ -66,114 +63,104 @@ export default class TimePicker extends React.Component<TimePickerProps, any> {
placement: 'bottomLeft', placement: 'bottomLeft',
transitionName: 'slide-up', transitionName: 'slide-up',
focusOnOpen: true, focusOnOpen: true,
}; }),
model: {
private timePickerRef: typeof RcTimePicker; prop: 'value',
event: 'change',
constructor(props: TimePickerProps) { },
super(props); data () {
const value = props.value || props.defaultValue; const value = this.value || this.defaultValue
if (value && !moment.isMoment(value)) { if (value && !moment.isMoment(value)) {
throw new Error( throw new Error(
'The value/defaultValue of TimePicker must be a moment object after `antd@2.0`, ' + 'The value/defaultValue of TimePicker must be a moment object, ',
'see: https://u.ant.design/time-picker-value', )
);
} }
this.state = { return {
value, sValue: value,
};
}
componentWillReceiveProps(nextProps: TimePickerProps) {
if ('value' in nextProps) {
this.setState({ value: nextProps.value });
} }
} },
watch: {
value (val) {
this.setState({ sValue: val })
},
},
methods: {
handleChange (value) {
if (!hasProp(this, 'value')) {
this.setState({ sValue: value })
}
const { format = 'HH:mm:ss' } = this
this.$emit('change', value, (value && value.format(format)) || '')
},
handleChange = (value: moment.Moment) => { handleOpenClose ({ open }) {
if (!('value' in this.props)) { this.$emit('openChange', open)
this.setState({ value }); this.$emit('update:open', open)
} },
const { onChange, format = 'HH:mm:ss' } = this.props;
if (onChange) {
onChange(value, (value && value.format(format)) || '');
}
}
handleOpenClose = ({ open }: { open: boolean }) => { focus () {
const { onOpenChange } = this.props; this.$refs.timePicker.focus()
if (onOpenChange) { },
onOpenChange(open);
}
}
saveTimePicker = (timePickerRef: typeof RcTimePicker) => { blur () {
this.timePickerRef = timePickerRef; this.$refs.timePicker.blur()
} },
focus() { getDefaultFormat () {
this.timePickerRef.focus(); const { format, use12Hours } = this
} if (format) {
return format
} else if (use12Hours) {
return 'h:mm:ss a'
}
return 'HH:mm:ss'
},
blur() { renderTimePicker (locale) {
this.timePickerRef.blur(); const props = getOptionProps(this)
} delete props.defaultValue
getDefaultFormat() { const format = this.getDefaultFormat()
const { format, use12Hours } = this.props; const className = {
if (format) { [`${props.prefixCls}-${props.size}`]: !!props.size,
return format; }
} else if (use12Hours) { const tempAddon = getComponentFromProp(this, 'addon')
return 'h:mm:ss a'; const timeProps = {
} props: {
return 'HH:mm:ss'; ...generateShowHourMinuteSecond(format),
} ...props,
format,
value: this.sValue,
placeholder: props.placeholder === undefined ? locale.placeholder : props.placeholder,
},
class: className,
ref: 'timePicker',
on: {
change: this.handleChange,
open: this.handleOpenClose,
close: this.handleOpenClose,
},
}
return (
<VcTimePicker {...timeProps}>
{tempAddon ? <template slot='addon'>
<div class={`${props.prefixCls}-panel-addon`}>
{tempAddon}
</div>
</template> : null}
</VcTimePicker>
)
},
},
renderTimePicker = (locale: TimePickerLocale) => { render () {
const props = {
...this.props,
};
delete props.defaultValue;
const format = this.getDefaultFormat();
const className = classNames(props.className, {
[`${props.prefixCls}-${props.size}`]: !!props.size,
});
const addon = (panel: React.ReactElement<any>) => (
props.addon ? (
<div className={`${props.prefixCls}-panel-addon`}>
{props.addon(panel)}
</div>
) : null
);
return (
<RcTimePicker
{...generateShowHourMinuteSecond(format)}
{...props}
ref={this.saveTimePicker}
format={format}
className={className}
value={this.state.value}
placeholder={props.placeholder === undefined ? locale.placeholder : props.placeholder}
onChange={this.handleChange}
onOpen={this.handleOpenClose}
onClose={this.handleOpenClose}
addon={addon}
/>
);
}
render() {
return ( return (
<LocaleReceiver <LocaleReceiver
componentName="TimePicker" componentName='TimePicker'
defaultLocale={defaultLocale} defaultLocale={defaultLocale}
> children={this.renderTimePicker}
{this.renderTimePicker} />
</LocaleReceiver> )
); },
}
} }
</script> </script>

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Избор на час', placeholder: 'Избор на час',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Seleccionar hora', placeholder: 'Seleccionar hora',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Vybrat čas', placeholder: 'Vybrat čas',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Zeit auswählen', placeholder: 'Zeit auswählen',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Επιλέξτε ώρα', placeholder: 'Επιλέξτε ώρα',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Select time', placeholder: 'Select time',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Select time', placeholder: 'Select time',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Seleccionar hora', placeholder: 'Seleccionar hora',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Vali aeg', placeholder: 'Vali aeg',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'انتخاب زمان', placeholder: 'انتخاب زمان',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Valitse aika', placeholder: 'Valitse aika',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Sélectionner l\'heure', placeholder: 'Sélectionner l\'heure',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Sélectionner l\'heure', placeholder: 'Sélectionner l\'heure',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Velja tíma', placeholder: 'Velja tíma',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Selezionare il tempo', placeholder: 'Selezionare il tempo',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: '時刻を選択', placeholder: '時刻を選択',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: '날짜 선택', placeholder: '날짜 선택',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Demê hilbijêre', placeholder: 'Demê hilbijêre',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Velg tid', placeholder: 'Velg tid',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Selecteer tijd', placeholder: 'Selecteer tijd',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Selecteer tijd', placeholder: 'Selecteer tijd',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Wybierz godzinę', placeholder: 'Wybierz godzinę',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Hora', placeholder: 'Hora',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Hora', placeholder: 'Hora',
}; }
export default locale; export default locale

View File

@ -3,6 +3,6 @@
*/ */
const locale = { const locale = {
placeholder: 'Выберите время', placeholder: 'Выберите время',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Vybrať čas', placeholder: 'Vybrať čas',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Izaberite vreme', placeholder: 'Izaberite vreme',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Välj tid', placeholder: 'Välj tid',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'เลือกเวลา', placeholder: 'เลือกเวลา',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Zaman Seç', placeholder: 'Zaman Seç',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Оберіть час', placeholder: 'Оберіть час',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: 'Chọn thời gian', placeholder: 'Chọn thời gian',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: '请选择时间', placeholder: '请选择时间',
}; }
export default locale; export default locale

View File

@ -1,5 +1,5 @@
const locale = { const locale = {
placeholder: '請選擇時間', placeholder: '請選擇時間',
}; }
export default locale; export default locale

View File

@ -0,0 +1,5 @@
import '../../style/index.less'
import './index.less'
// style dependencies
import '../../input/style'

View File

@ -1,5 +0,0 @@
import '../../style/index.less';
import './index.less';
// style dependencies
import '../../input/style';

View File

@ -1,6 +1,7 @@
<script> <script>
import PropTypes from 'prop-types' import PropTypes from '../_util/vue-types'
import Select from './Select' import Select from './Select'
import BaseMixin from '../_util/BaseMixin'
const formatOption = (option, disabledOptions) => { const formatOption = (option, disabledOptions) => {
let value = `${option}` let value = `${option}`
@ -19,13 +20,15 @@ const formatOption = (option, disabledOptions) => {
} }
} }
class Combobox extends Component { const Combobox = {
static propTypes = { mixins: [BaseMixin],
name: 'Combobox',
props: {
format: PropTypes.string, format: PropTypes.string,
defaultOpenValue: PropTypes.object, defaultOpenValue: PropTypes.object,
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
value: PropTypes.object, value: PropTypes.object,
onChange: PropTypes.func, // onChange: PropTypes.func,
showHour: PropTypes.bool, showHour: PropTypes.bool,
showMinute: PropTypes.bool, showMinute: PropTypes.bool,
showSecond: PropTypes.bool, showSecond: PropTypes.bool,
@ -35,156 +38,157 @@ class Combobox extends Component {
disabledHours: PropTypes.func, disabledHours: PropTypes.func,
disabledMinutes: PropTypes.func, disabledMinutes: PropTypes.func,
disabledSeconds: PropTypes.func, disabledSeconds: PropTypes.func,
onCurrentSelectPanelChange: PropTypes.func, // onCurrentSelectPanelChange: PropTypes.func,
use12Hours: PropTypes.bool, use12Hours: PropTypes.bool,
isAM: PropTypes.bool, isAM: PropTypes.bool,
}; },
methods: {
onItemChange (type, itemValue) {
const { defaultOpenValue, use12Hours, isAM } = this
const value = (this.value || defaultOpenValue).clone()
onItemChange = (type, itemValue) => { if (type === 'hour') {
const { onChange, defaultOpenValue, use12Hours } = this.props if (use12Hours) {
const value = (this.props.value || defaultOpenValue).clone() if (isAM) {
value.hour(+itemValue % 12)
if (type === 'hour') { } else {
if (use12Hours) { value.hour((+itemValue % 12) + 12)
if (this.props.isAM) { }
value.hour(+itemValue % 12)
} else { } else {
value.hour((+itemValue % 12) + 12) value.hour(+itemValue)
}
} else {
value.hour(+itemValue)
}
} else if (type === 'minute') {
value.minute(+itemValue)
} else if (type === 'ampm') {
const ampm = itemValue.toUpperCase()
if (use12Hours) {
if (ampm === 'PM' && value.hour() < 12) {
value.hour((value.hour() % 12) + 12)
} }
} else if (type === 'minute') {
value.minute(+itemValue)
} else if (type === 'ampm') {
const ampm = itemValue.toUpperCase()
if (use12Hours) {
if (ampm === 'PM' && value.hour() < 12) {
value.hour((value.hour() % 12) + 12)
}
if (ampm === 'AM') { if (ampm === 'AM') {
if (value.hour() >= 12) { if (value.hour() >= 12) {
value.hour(value.hour() - 12) value.hour(value.hour() - 12)
}
} }
} }
} else {
value.second(+itemValue)
} }
} else { this.__emit('change', value)
value.second(+itemValue) },
}
onChange(value)
}
onEnterSelectPanel = (range) => { onEnterSelectPanel (range) {
this.props.onCurrentSelectPanelChange(range) this.__emit('currentSelectPanelChange', range)
} },
getHourSelect (hour) { getHourSelect (hour) {
const { prefixCls, hourOptions, disabledHours, showHour, use12Hours } = this.props const { prefixCls, hourOptions, disabledHours, showHour, use12Hours } = this
if (!showHour) { if (!showHour) {
return null return null
} }
const disabledOptions = disabledHours() const disabledOptions = disabledHours()
let hourOptionsAdj let hourOptionsAdj
let hourAdj let hourAdj
if (use12Hours) { if (use12Hours) {
hourOptionsAdj = [12].concat(hourOptions.filter(h => h < 12 && h > 0)) hourOptionsAdj = [12].concat(hourOptions.filter(h => h < 12 && h > 0))
hourAdj = (hour % 12) || 12 hourAdj = (hour % 12) || 12
} else { } else {
hourOptionsAdj = hourOptions hourOptionsAdj = hourOptions
hourAdj = hour hourAdj = hour
} }
return ( return (
<Select <Select
prefixCls={prefixCls} prefixCls={prefixCls}
options={hourOptionsAdj.map(option => formatOption(option, disabledOptions))} options={hourOptionsAdj.map(option => formatOption(option, disabledOptions))}
selectedIndex={hourOptionsAdj.indexOf(hourAdj)} selectedIndex={hourOptionsAdj.indexOf(hourAdj)}
type='hour' type='hour'
onSelect={this.onItemChange} onSelect={this.onItemChange}
onMouseEnter={this.onEnterSelectPanel.bind(this, 'hour')} onMouseenter={this.onEnterSelectPanel.bind(this, 'hour')}
/> />
) )
} },
getMinuteSelect (minute) { getMinuteSelect (minute) {
const { prefixCls, minuteOptions, disabledMinutes, defaultOpenValue, showMinute } = this.props const { prefixCls, minuteOptions, disabledMinutes, defaultOpenValue, showMinute } = this
if (!showMinute) { if (!showMinute) {
return null return null
} }
const value = this.props.value || defaultOpenValue const value = this.value || defaultOpenValue
const disabledOptions = disabledMinutes(value.hour()) const disabledOptions = disabledMinutes(value.hour())
return ( return (
<Select <Select
prefixCls={prefixCls} prefixCls={prefixCls}
options={minuteOptions.map(option => formatOption(option, disabledOptions))} options={minuteOptions.map(option => formatOption(option, disabledOptions))}
selectedIndex={minuteOptions.indexOf(minute)} selectedIndex={minuteOptions.indexOf(minute)}
type='minute' type='minute'
onSelect={this.onItemChange} onSelect={this.onItemChange}
onMouseEnter={this.onEnterSelectPanel.bind(this, 'minute')} onMouseenter={this.onEnterSelectPanel.bind(this, 'minute')}
/> />
) )
} },
getSecondSelect (second) { getSecondSelect (second) {
const { prefixCls, secondOptions, disabledSeconds, showSecond, defaultOpenValue } = this.props const { prefixCls, secondOptions, disabledSeconds, showSecond, defaultOpenValue } = this
if (!showSecond) { if (!showSecond) {
return null return null
} }
const value = this.props.value || defaultOpenValue const value = this.value || defaultOpenValue
const disabledOptions = disabledSeconds(value.hour(), value.minute()) const disabledOptions = disabledSeconds(value.hour(), value.minute())
return ( return (
<Select <Select
prefixCls={prefixCls} prefixCls={prefixCls}
options={secondOptions.map(option => formatOption(option, disabledOptions))} options={secondOptions.map(option => formatOption(option, disabledOptions))}
selectedIndex={secondOptions.indexOf(second)} selectedIndex={secondOptions.indexOf(second)}
type='second' type='second'
onSelect={this.onItemChange} onSelect={this.onItemChange}
onMouseEnter={this.onEnterSelectPanel.bind(this, 'second')} onMouseenter={this.onEnterSelectPanel.bind(this, 'second')}
/> />
) )
} },
getAMPMSelect () { getAMPMSelect () {
const { prefixCls, use12Hours, format } = this.props const { prefixCls, use12Hours, format, isAM } = this
if (!use12Hours) { if (!use12Hours) {
return null return null
} }
const AMPMOptions = ['am', 'pm'] // If format has A char, then we should uppercase AM/PM const AMPMOptions = ['am', 'pm'] // If format has A char, then we should uppercase AM/PM
.map(c => format.match(/\sA/) ? c.toUpperCase() : c) .map(c => format.match(/\sA/) ? c.toUpperCase() : c)
.map(c => ({ value: c })) .map(c => ({ value: c }))
const selected = this.props.isAM ? 0 : 1 const selected = isAM ? 0 : 1
return ( return (
<Select <Select
prefixCls={prefixCls} prefixCls={prefixCls}
options={AMPMOptions} options={AMPMOptions}
selectedIndex={selected} selectedIndex={selected}
type='ampm' type='ampm'
onSelect={this.onItemChange} onSelect={this.onItemChange}
onMouseEnter={this.onEnterSelectPanel.bind(this, 'ampm')} onMouseenter={this.onEnterSelectPanel.bind(this, 'ampm')}
/> />
) )
} },
},
render () { render () {
const { prefixCls, defaultOpenValue } = this.props const { prefixCls, defaultOpenValue } = this
const value = this.props.value || defaultOpenValue const value = this.value || defaultOpenValue
return ( return (
<div className={`${prefixCls}-combobox`}> <div class={`${prefixCls}-combobox`}>
{this.getHourSelect(value.hour())} {this.getHourSelect(value.hour())}
{this.getMinuteSelect(value.minute())} {this.getMinuteSelect(value.minute())}
{this.getSecondSelect(value.second())} {this.getSecondSelect(value.second())}
{this.getAMPMSelect(value.hour())} {this.getAMPMSelect(value.hour())}
</div> </div>
) )
} },
} }
export default Combobox export default Combobox
</script> </script>

View File

@ -1,202 +1,203 @@
<script> <script>
import PropTypes from 'prop-types' import PropTypes from '../_util/vue-types'
import BaseMixin from '../_util/BaseMixin'
import moment from 'moment' import moment from 'moment'
class Header extends Component { const Header = {
static propTypes = { mixins: [BaseMixin],
props: {
format: PropTypes.string, format: PropTypes.string,
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
disabledDate: PropTypes.func, disabledDate: PropTypes.func,
placeholder: PropTypes.string, placeholder: PropTypes.string,
clearText: PropTypes.string, clearText: PropTypes.string,
value: PropTypes.object, value: PropTypes.object,
inputReadOnly: PropTypes.bool, inputReadOnly: PropTypes.bool.def(false),
hourOptions: PropTypes.array, hourOptions: PropTypes.array,
minuteOptions: PropTypes.array, minuteOptions: PropTypes.array,
secondOptions: PropTypes.array, secondOptions: PropTypes.array,
disabledHours: PropTypes.func, disabledHours: PropTypes.func,
disabledMinutes: PropTypes.func, disabledMinutes: PropTypes.func,
disabledSeconds: PropTypes.func, disabledSeconds: PropTypes.func,
onChange: PropTypes.func, // onChange: PropTypes.func,
onClear: PropTypes.func, // onClear: PropTypes.func,
onEsc: PropTypes.func, // onEsc: PropTypes.func,
allowEmpty: PropTypes.bool, allowEmpty: PropTypes.bool,
defaultOpenValue: PropTypes.object, defaultOpenValue: PropTypes.object,
currentSelectPanel: PropTypes.string, currentSelectPanel: PropTypes.string,
focusOnOpen: PropTypes.bool, focusOnOpen: PropTypes.bool,
onKeyDown: PropTypes.func, // onKeyDown: PropTypes.func,
}; showStr: PropTypes.bool.def(true),
},
static defaultProps = { data () {
inputReadOnly: false, const { value, format } = this
} return {
constructor (props) {
super(props)
const { value, format } = props
this.state = {
str: value && value.format(format) || '', str: value && value.format(format) || '',
invalid: false, invalid: false,
} }
} },
componentDidMount () { mounted () {
if (this.props.focusOnOpen) { if (this.focusOnOpen) {
// 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.$refs.input.focus()
this.refs.input.select() this.$refs.input.select()
}) })
} }
} },
watch: {
componentWillReceiveProps (nextProps) { '$props': {
const { value, format } = nextProps handler: function (nextProps) {
this.setState({ const { value, format } = nextProps
str: value && value.format(format) || '',
invalid: false,
})
}
onInputChange = (event) => {
const str = event.target.value
this.setState({
str,
})
const {
format, hourOptions, minuteOptions, secondOptions,
disabledHours, disabledMinutes,
disabledSeconds, onChange, allowEmpty,
} = this.props
if (str) {
const originalValue = this.props.value
const value = this.getProtoValue().clone()
const parsed = moment(str, format, true)
if (!parsed.isValid()) {
this.setState({ this.setState({
invalid: true, str: value && value.format(format) || '',
invalid: false,
}) })
return },
} deep: true,
value.hour(parsed.hour()).minute(parsed.minute()).second(parsed.second()) },
},
// if time value not allowed, response warning. methods: {
if ( onInputChange (event) {
hourOptions.indexOf(value.hour()) < 0 || const str = event.target.value
this.showStr = true
this.setState({
str,
})
const {
format, hourOptions, minuteOptions, secondOptions,
disabledHours, disabledMinutes,
disabledSeconds, allowEmpty,
value: originalValue,
} = this
if (str) {
const value = this.getProtoValue().clone()
const parsed = moment(str, format, true)
if (!parsed.isValid()) {
this.setState({
invalid: true,
})
return
}
value.hour(parsed.hour()).minute(parsed.minute()).second(parsed.second())
// if time value not allowed, response warning.
if (
hourOptions.indexOf(value.hour()) < 0 ||
minuteOptions.indexOf(value.minute()) < 0 || minuteOptions.indexOf(value.minute()) < 0 ||
secondOptions.indexOf(value.second()) < 0 secondOptions.indexOf(value.second()) < 0
) { ) {
this.setState({ this.setState({
invalid: true, invalid: true,
}) })
return return
} }
// if time value is disabled, response warning. // if time value is disabled, response warning.
const disabledHourOptions = disabledHours() const disabledHourOptions = disabledHours()
const disabledMinuteOptions = disabledMinutes(value.hour()) const disabledMinuteOptions = disabledMinutes(value.hour())
const disabledSecondOptions = disabledSeconds(value.hour(), value.minute()) const disabledSecondOptions = disabledSeconds(value.hour(), value.minute())
if ( if (
(disabledHourOptions && disabledHourOptions.indexOf(value.hour()) >= 0) || (disabledHourOptions && disabledHourOptions.indexOf(value.hour()) >= 0) ||
(disabledMinuteOptions && disabledMinuteOptions.indexOf(value.minute()) >= 0) || (disabledMinuteOptions && disabledMinuteOptions.indexOf(value.minute()) >= 0) ||
(disabledSecondOptions && disabledSecondOptions.indexOf(value.second()) >= 0) (disabledSecondOptions && disabledSecondOptions.indexOf(value.second()) >= 0)
) { ) {
this.setState({
invalid: true,
})
return
}
if (originalValue) {
if (
originalValue.hour() !== value.hour() ||
originalValue.minute() !== value.minute() ||
originalValue.second() !== value.second()
) {
// keep other fields for rc-calendar
const changedValue = originalValue.clone()
changedValue.hour(value.hour())
changedValue.minute(value.minute())
changedValue.second(value.second())
this.__emit('change', changedValue)
}
} else if (originalValue !== value) {
this.__emit('change', value)
}
} else if (allowEmpty) {
this.__emit('change', null)
} else {
this.setState({ this.setState({
invalid: true, invalid: true,
}) })
return return
} }
if (originalValue) {
if (
originalValue.hour() !== value.hour() ||
originalValue.minute() !== value.minute() ||
originalValue.second() !== value.second()
) {
// keep other fields for rc-calendar
const changedValue = originalValue.clone()
changedValue.hour(value.hour())
changedValue.minute(value.minute())
changedValue.second(value.second())
onChange(changedValue)
}
} else if (originalValue !== value) {
onChange(value)
}
} else if (allowEmpty) {
onChange(null)
} else {
this.setState({ this.setState({
invalid: true, invalid: false,
}) })
return },
}
this.setState({ onKeyDown (e) {
invalid: false, if (e.keyCode === 27) {
}) this.__emit('esc')
} }
this.__emit('keydown', e)
},
onKeyDown = (e) => { onClear () {
const { onEsc, onKeyDown } = this.props this.__emit('clear')
if (e.keyCode === 27) { this.setState({ str: '' })
onEsc() },
}
onKeyDown(e) getClearButton () {
} const { prefixCls, allowEmpty, clearText } = this
if (!allowEmpty) {
return null
}
return (<a
class={`${prefixCls}-clear-btn`}
role='button'
title={clearText}
onMousedown={this.onClear}
/>)
},
onClear = () => { getProtoValue () {
this.setState({ str: '' }) return this.value || this.defaultOpenValue
this.props.onClear() },
}
getClearButton () { getInput () {
const { prefixCls, allowEmpty } = this.props const { prefixCls, placeholder, inputReadOnly, invalid, str, showStr } = this
if (!allowEmpty) { const invalidClass = invalid ? `${prefixCls}-input-invalid` : ''
return null return (
} <input
return (<a class={`${prefixCls}-input ${invalidClass}`}
className={`${prefixCls}-clear-btn`} ref='input'
role='button' onKeydown={this.onKeyDown}
title={this.props.clearText} value={showStr ? str : ''}
onMouseDown={this.onClear} placeholder={placeholder}
/>) onInput={this.onInputChange}
} readOnly={!!inputReadOnly}
/>
getProtoValue () { )
return this.props.value || this.props.defaultOpenValue },
} },
getInput () {
const { prefixCls, placeholder, inputReadOnly } = this.props
const { invalid, str } = this.state
const invalidClass = invalid ? `${prefixCls}-input-invalid` : ''
return (
<input
className={`${prefixCls}-input ${invalidClass}`}
ref='input'
onKeyDown={this.onKeyDown}
value={str}
placeholder={placeholder}
onChange={this.onInputChange}
readOnly={!!inputReadOnly}
/>
)
}
render () { render () {
const { prefixCls } = this.props const { prefixCls } = this
return ( return (
<div className={`${prefixCls}-input-wrap`}> <div class={`${prefixCls}-input-wrap`}>
{this.getInput()} {this.getInput()}
{this.getClearButton()} {this.getClearButton()}
</div> </div>
) )
} },
} }
export default Header export default Header
</script> </script>

View File

@ -1,9 +1,9 @@
<script> <script>
import PropTypes from 'prop-types' import PropTypes from '../_util/vue-types'
import BaseMixin from '../_util/BaseMixin'
import Header from './Header' import Header from './Header'
import Combobox from './Combobox' import Combobox from './Combobox'
import moment from 'moment' import moment from 'moment'
import classNames from 'classnames'
function noop () { function noop () {
} }
@ -17,114 +17,110 @@ function generateOptions (length, disabledOptions, hideDisabledOptions, step = 1
} }
return arr return arr
} }
const Panel = {
class Panel extends Component { mixins: [BaseMixin],
static propTypes = { props: {
clearText: PropTypes.string, clearText: PropTypes.string,
prefixCls: PropTypes.string, prefixCls: PropTypes.string.def('rc-time-picker-panel'),
className: PropTypes.string, defaultOpenValue: {
defaultOpenValue: PropTypes.object, type: Object,
default: () => {
return moment()
},
},
value: PropTypes.object, value: PropTypes.object,
placeholder: PropTypes.string, placeholder: PropTypes.string,
format: PropTypes.string, format: PropTypes.string,
inputReadOnly: PropTypes.bool, inputReadOnly: PropTypes.bool.def(false),
disabledHours: PropTypes.func, disabledHours: PropTypes.func.def(noop),
disabledMinutes: PropTypes.func, disabledMinutes: PropTypes.func.def(noop),
disabledSeconds: PropTypes.func, disabledSeconds: PropTypes.func.def(noop),
hideDisabledOptions: PropTypes.bool, hideDisabledOptions: PropTypes.bool,
onChange: PropTypes.func, // onChange: PropTypes.func,
onEsc: PropTypes.func, // onEsc: PropTypes.func,
allowEmpty: PropTypes.bool, allowEmpty: PropTypes.bool,
showHour: PropTypes.bool, showHour: PropTypes.bool,
showMinute: PropTypes.bool, showMinute: PropTypes.bool,
showSecond: PropTypes.bool, showSecond: PropTypes.bool,
onClear: PropTypes.func, // onClear: PropTypes.func,
use12Hours: PropTypes.bool, use12Hours: PropTypes.bool.def(false),
hourStep: PropTypes.number, hourStep: PropTypes.number,
minuteStep: PropTypes.number, minuteStep: PropTypes.number,
secondStep: PropTypes.number, secondStep: PropTypes.number,
addon: PropTypes.func,
focusOnOpen: PropTypes.bool, focusOnOpen: PropTypes.bool,
onKeyDown: PropTypes.func, // onKeydown: PropTypes.func,
}; },
data () {
static defaultProps = { return {
prefixCls: 'rc-time-picker-panel', sValue: this.value,
onChange: noop,
onClear: noop,
disabledHours: noop,
disabledMinutes: noop,
disabledSeconds: noop,
defaultOpenValue: moment(),
use12Hours: false,
addon: noop,
onKeyDown: noop,
inputReadOnly: false,
};
constructor (props) {
super(props)
this.state = {
value: props.value,
selectionRange: [], selectionRange: [],
currentSelectPanel: '',
showStr: true,
} }
} },
watch: {
componentWillReceiveProps (nextProps) { value (val) {
const value = nextProps.value if (val) {
if (value) { this.setState({
this.setState({ sValue: val,
value, showStr: true,
}) })
}
}
onChange = (newValue) => {
this.setState({ value: newValue })
this.props.onChange(newValue)
}
onCurrentSelectPanelChange = (currentSelectPanel) => {
this.setState({ currentSelectPanel })
}
// https://github.com/ant-design/ant-design/issues/5829
close () {
this.props.onEsc()
}
disabledHours = () => {
const { use12Hours, disabledHours } = this.props
let disabledOptions = disabledHours()
if (use12Hours && Array.isArray(disabledOptions)) {
if (this.isAM()) {
disabledOptions = disabledOptions.filter(h => h < 12).map(h => (h === 0 ? 12 : h))
} else { } else {
disabledOptions = disabledOptions.map(h => (h === 12 ? 12 : h - 12)) this.setState({
showStr: false,
})
} }
} },
return disabledOptions },
}
isAM () { methods: {
const value = (this.state.value || this.props.defaultOpenValue) onChange (newValue) {
return value.hour() >= 0 && value.hour() < 12 this.setState({ sValue: newValue })
} this.__emit('change', newValue)
},
onCurrentSelectPanelChange (currentSelectPanel) {
this.setState({ currentSelectPanel })
},
// https://github.com/ant-design/ant-design/issues/5829
close () {
this.__emit('esc')
},
disabledHours2 () {
const { use12Hours, disabledHours } = this
let disabledOptions = disabledHours()
if (use12Hours && Array.isArray(disabledOptions)) {
if (this.isAM()) {
disabledOptions = disabledOptions.filter(h => h < 12).map(h => (h === 0 ? 12 : h))
} else {
disabledOptions = disabledOptions.map(h => (h === 12 ? 12 : h - 12))
}
}
return disabledOptions
},
isAM () {
const value = this.sValue || this.defaultOpenValue
return value.hour() >= 0 && value.hour() < 12
},
},
render () { render () {
const { const {
prefixCls, className, placeholder, disabledMinutes, prefixCls, placeholder, disabledMinutes,
disabledSeconds, hideDisabledOptions, allowEmpty, showHour, showMinute, showSecond, disabledSeconds, hideDisabledOptions, allowEmpty, showHour, showMinute, showSecond,
format, defaultOpenValue, clearText, onEsc, addon, use12Hours, onClear, format, defaultOpenValue, clearText, use12Hours,
focusOnOpen, onKeyDown, hourStep, minuteStep, secondStep, inputReadOnly, focusOnOpen, hourStep, minuteStep, secondStep, inputReadOnly,
} = this.props sValue, currentSelectPanel, showStr, $listeners = {},
const { } = this
value, currentSelectPanel, const { esc = noop, clear = noop, keydown = noop } = $listeners
} = this.state
const disabledHourOptions = this.disabledHours() const disabledHourOptions = this.disabledHours2()
const disabledMinuteOptions = disabledMinutes(value ? value.hour() : null) const disabledMinuteOptions = disabledMinutes(sValue ? sValue.hour() : null)
const disabledSecondOptions = disabledSeconds(value ? value.hour() : null, const disabledSecondOptions = disabledSeconds(sValue ? sValue.hour() : null,
value ? value.minute() : null) sValue ? sValue.minute() : null)
const hourOptions = generateOptions( const hourOptions = generateOptions(
24, disabledHourOptions, hideDisabledOptions, hourStep 24, disabledHourOptions, hideDisabledOptions, hourStep
) )
@ -136,32 +132,33 @@ class Panel extends Component {
) )
return ( return (
<div className={classNames({ [`${prefixCls}-inner`]: true, [className]: !!className })}> <div class={`${prefixCls}-inner`}>
<Header <Header
clearText={clearText} clearText={clearText}
prefixCls={prefixCls} prefixCls={prefixCls}
defaultOpenValue={defaultOpenValue} defaultOpenValue={defaultOpenValue}
value={value} value={sValue}
currentSelectPanel={currentSelectPanel} currentSelectPanel={currentSelectPanel}
onEsc={onEsc} onEsc={esc}
format={format} format={format}
placeholder={placeholder} placeholder={placeholder}
hourOptions={hourOptions} hourOptions={hourOptions}
minuteOptions={minuteOptions} minuteOptions={minuteOptions}
secondOptions={secondOptions} secondOptions={secondOptions}
disabledHours={this.disabledHours} disabledHours={this.disabledHours2}
disabledMinutes={disabledMinutes} disabledMinutes={disabledMinutes}
disabledSeconds={disabledSeconds} disabledSeconds={disabledSeconds}
onChange={this.onChange} onChange={this.onChange}
onClear={onClear} onClear={clear}
allowEmpty={allowEmpty} allowEmpty={allowEmpty}
focusOnOpen={focusOnOpen} focusOnOpen={focusOnOpen}
onKeyDown={onKeyDown} onKeydown={keydown}
inputReadOnly={inputReadOnly} inputReadOnly={inputReadOnly}
showStr={showStr}
/> />
<Combobox <Combobox
prefixCls={prefixCls} prefixCls={prefixCls}
value={value} value={sValue}
defaultOpenValue={defaultOpenValue} defaultOpenValue={defaultOpenValue}
format={format} format={format}
onChange={this.onChange} onChange={this.onChange}
@ -171,17 +168,17 @@ class Panel extends Component {
hourOptions={hourOptions} hourOptions={hourOptions}
minuteOptions={minuteOptions} minuteOptions={minuteOptions}
secondOptions={secondOptions} secondOptions={secondOptions}
disabledHours={this.disabledHours} disabledHours={this.disabledHours2}
disabledMinutes={disabledMinutes} disabledMinutes={disabledMinutes}
disabledSeconds={disabledSeconds} disabledSeconds={disabledSeconds}
onCurrentSelectPanelChange={this.onCurrentSelectPanelChange} onCurrentSelectPanelChange={this.onCurrentSelectPanelChange}
use12Hours={use12Hours} use12Hours={use12Hours}
isAM={this.isAM()} isAM={this.isAM()}
/> />
{addon(this)} {this.$slots.default}
</div> </div>
) )
} },
} }
export default Panel export default Panel

View File

@ -1,7 +1,8 @@
<script> <script>
import PropTypes from 'prop-types' import PropTypes from '../_util/vue-types'
import BaseMixin from '../_util/BaseMixin'
import classnames from 'classnames' import classnames from 'classnames'
function noop () {}
const scrollTo = (element, to, duration) => { const scrollTo = (element, to, duration) => {
const requestAnimationFrame = window.requestAnimationFrame || const requestAnimationFrame = window.requestAnimationFrame ||
function requestAnimationFrameTimeout () { function requestAnimationFrameTimeout () {
@ -22,109 +23,111 @@ const scrollTo = (element, to, duration) => {
}) })
} }
class Select extends Component { const Select = {
static propTypes = { mixins: [BaseMixin],
props: {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
options: PropTypes.array, options: PropTypes.array,
selectedIndex: PropTypes.number, selectedIndex: PropTypes.number,
type: PropTypes.string, type: PropTypes.string,
onSelect: PropTypes.func, // onSelect: PropTypes.func,
onMouseEnter: PropTypes.func, // onMouseEnter: PropTypes.func,
}; },
data () {
state = { return {
active: false, active: false,
};
componentDidMount () {
// jump to selected option
this.scrollToSelected(0)
}
componentDidUpdate (prevProps) {
// smooth scroll to selected option
if (prevProps.selectedIndex !== this.props.selectedIndex) {
this.scrollToSelected(120)
} }
} },
onSelect = (value) => { mounted () {
const { onSelect, type } = this.props this.$nextTick(() => {
onSelect(type, value) // jump to selected option
} this.scrollToSelected(0)
getOptions () {
const { options, selectedIndex, prefixCls } = this.props
return options.map((item, index) => {
const cls = classnames({
[`${prefixCls}-select-option-selected`]: selectedIndex === index,
[`${prefixCls}-select-option-disabled`]: item.disabled,
})
let onclick = null
if (!item.disabled) {
onclick = this.onSelect.bind(this, item.value)
}
return (<li
className={cls}
key={index}
onClick={onclick}
disabled={item.disabled}
>
{item.value}
</li>)
}) })
} },
watch: {
selectedIndex (val) {
this.$nextTick(() => {
// smooth scroll to selected option
this.scrollToSelected(120)
})
},
},
methods: {
onSelect (value) {
const { type } = this
this.__emit('select', type, value)
},
scrollToSelected (duration) { getOptions () {
const { options, selectedIndex, prefixCls } = this
return options.map((item, index) => {
const cls = classnames({
[`${prefixCls}-select-option-selected`]: selectedIndex === index,
[`${prefixCls}-select-option-disabled`]: item.disabled,
})
let onClick = noop
if (!item.disabled) {
onClick = this.onSelect.bind(this, item.value)
}
return (<li
class={cls}
key={index}
onClick={onClick}
disabled={item.disabled}
>
{item.value}
</li>)
})
},
scrollToSelected (duration) {
// move to selected item // move to selected item
const select = ReactDom.findDOMNode(this) const select = this.$el
const list = ReactDom.findDOMNode(this.list) const list = this.$refs.list
if (!list) { if (!list) {
return return
} }
let index = this.props.selectedIndex let index = this.selectedIndex
if (index < 0) { if (index < 0) {
index = 0 index = 0
} }
const topOption = list.children[index] const topOption = list.children[index]
const to = topOption.offsetTop const to = topOption.offsetTop
scrollTo(select, to, duration) scrollTo(select, to, duration)
} },
handleMouseEnter = (e) => { handleMouseEnter (e) {
this.setState({ active: true }) this.setState({ active: true })
this.props.onMouseEnter(e) this.__emit('mouseenter', e)
} },
handleMouseLeave = () => { handleMouseLeave () {
this.setState({ active: false }) this.setState({ active: false })
} },
},
saveList = (node) => {
this.list = node
}
render () { render () {
if (this.props.options.length === 0) { if (this.options.length === 0) {
return null return null
} }
const { prefixCls } = this.props const { prefixCls } = this
const cls = classnames({ const cls = {
[`${prefixCls}-select`]: 1, [`${prefixCls}-select`]: 1,
[`${prefixCls}-select-active`]: this.state.active, [`${prefixCls}-select-active`]: this.active,
}) }
return ( return (
<div <div
className={cls} class={cls}
onMouseEnter={this.handleMouseEnter} onMouseenter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave} onMouseleave={this.handleMouseLeave}
> >
<ul ref={this.saveList}>{this.getOptions()}</ul> <ul ref='list'>{this.getOptions()}</ul>
</div> </div>
) )
} },
} }
export default Select export default Select

View File

@ -1,27 +1,31 @@
<script> <script>
import PropTypes from 'prop-types' import PropTypes from '../_util/vue-types'
import Trigger from 'rc-trigger' import BaseMixin from '../_util/BaseMixin'
import Trigger from '../trigger'
import Panel from './Panel' import Panel from './Panel'
import placements from './placements' import placements from './placements'
import moment from 'moment' import moment from 'moment'
import { initDefaultProps, hasProp } from '../_util/props-util'
function noop () { function noop () {
} }
function refFn (field, component) { export default {
this[field] = component mixins: [BaseMixin],
} props: initDefaultProps({
export default class Picker extends Component {
static propTypes = {
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
clearText: PropTypes.string, clearText: PropTypes.string,
value: PropTypes.object, value: PropTypes.any,
defaultOpenValue: PropTypes.object, defaultOpenValue: {
type: Object,
default: () => {
return moment()
},
},
inputReadOnly: PropTypes.bool, inputReadOnly: PropTypes.bool,
disabled: PropTypes.bool, disabled: PropTypes.bool,
allowEmpty: PropTypes.bool, allowEmpty: PropTypes.bool,
defaultValue: PropTypes.object, defaultValue: PropTypes.any,
open: PropTypes.bool, open: PropTypes.bool,
defaultOpen: PropTypes.bool, defaultOpen: PropTypes.bool,
align: PropTypes.object, align: PropTypes.object,
@ -33,19 +37,16 @@ export default class Picker extends Component {
showHour: PropTypes.bool, showHour: PropTypes.bool,
showMinute: PropTypes.bool, showMinute: PropTypes.bool,
showSecond: PropTypes.bool, showSecond: PropTypes.bool,
style: PropTypes.object,
className: PropTypes.string,
popupClassName: PropTypes.string, popupClassName: PropTypes.string,
disabledHours: PropTypes.func, disabledHours: PropTypes.func,
disabledMinutes: PropTypes.func, disabledMinutes: PropTypes.func,
disabledSeconds: PropTypes.func, disabledSeconds: PropTypes.func,
hideDisabledOptions: PropTypes.bool, hideDisabledOptions: PropTypes.bool,
onChange: PropTypes.func, // onChange: PropTypes.func,
onOpen: PropTypes.func, // onOpen: PropTypes.func,
onClose: PropTypes.func, // onClose: PropTypes.func,
onFocus: PropTypes.func, // onFocus: PropTypes.func,
onBlur: PropTypes.func, // onBlur: PropTypes.func,
addon: PropTypes.func,
name: PropTypes.string, name: PropTypes.string,
autoComplete: PropTypes.string, autoComplete: PropTypes.string,
use12Hours: PropTypes.bool, use12Hours: PropTypes.bool,
@ -53,20 +54,15 @@ export default class Picker extends Component {
minuteStep: PropTypes.number, minuteStep: PropTypes.number,
secondStep: PropTypes.number, secondStep: PropTypes.number,
focusOnOpen: PropTypes.bool, focusOnOpen: PropTypes.bool,
onKeyDown: PropTypes.func, // onKeyDown: PropTypes.func,
autoFocus: PropTypes.bool, autoFocus: PropTypes.bool,
}; }, {
static defaultProps = {
clearText: 'clear', clearText: 'clear',
prefixCls: 'rc-time-picker', prefixCls: 'rc-time-picker',
defaultOpen: false, defaultOpen: false,
inputReadOnly: false, inputReadOnly: false,
style: {},
className: '',
popupClassName: '', popupClassName: '',
align: {}, align: {},
defaultOpenValue: moment(),
allowEmpty: true, allowEmpty: true,
showHour: true, showHour: true,
showMinute: true, showMinute: true,
@ -76,194 +72,195 @@ export default class Picker extends Component {
disabledSeconds: noop, disabledSeconds: noop,
hideDisabledOptions: false, hideDisabledOptions: false,
placement: 'bottomLeft', placement: 'bottomLeft',
onChange: noop,
onOpen: noop,
onClose: noop,
onFocus: noop,
onBlur: noop,
addon: noop,
use12Hours: false, use12Hours: false,
focusOnOpen: false, focusOnOpen: false,
onKeyDown: noop, }),
}; data () {
const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = this
constructor (props) { return {
super(props) sOpen: open,
this.saveInputRef = refFn.bind(this, 'picker') sValue: value,
this.savePanelRef = refFn.bind(this, 'panelInstance')
const { defaultOpen, defaultValue, open = defaultOpen, value = defaultValue } = props
this.state = {
open,
value,
} }
} },
componentWillReceiveProps (nextProps) { watch: {
const { value, open } = nextProps value (val) {
if ('value' in nextProps) {
this.setState({ this.setState({
value, sValue: val,
}) })
} },
if (open !== undefined) { open (val) {
this.setState({ open }) if (val !== undefined) {
} this.setState({
} sOpen: val,
})
}
},
},
methods: {
onPanelChange (value) {
this.setValue(value)
},
onPanelChange = (value) => { onPanelClear () {
this.setValue(value) this.setValue(null)
} this.setOpen(false)
},
onPanelClear = () => { onVisibleChange (open) {
this.setValue(null) this.setOpen(open)
this.setOpen(false) },
}
onVisibleChange = (open) => { onEsc () {
this.setOpen(open) this.setOpen(false)
} this.focus()
},
onEsc = () => { onKeyDown (e) {
this.setOpen(false) if (e.keyCode === 40) {
this.focus() this.setOpen(true)
} }
},
onKeyDown2 (e) {
this.__emit('keydown', e)
},
onKeyDown = (e) => { setValue (value) {
if (e.keyCode === 40) { if (!hasProp(this, 'value')) {
this.setOpen(true) this.setState({
} sValue: value,
} })
}
this.__emit('change', value)
},
setValue (value) { getFormat () {
if (!('value' in this.props)) { const { format, showHour, showMinute, showSecond, use12Hours } = this
this.setState({ if (format) {
value, return format
}) }
}
this.props.onChange(value)
}
getFormat () { if (use12Hours) {
const { format, showHour, showMinute, showSecond, use12Hours } = this.props const fmtString = ([
if (format) { showHour ? 'h' : '',
return format showMinute ? 'mm' : '',
} showSecond ? 'ss' : '',
].filter(item => !!item).join(':'))
if (use12Hours) { return fmtString.concat(' a')
const fmtString = ([ }
showHour ? 'h' : '',
return [
showHour ? 'HH' : '',
showMinute ? 'mm' : '', showMinute ? 'mm' : '',
showSecond ? 'ss' : '', showSecond ? 'ss' : '',
].filter(item => !!item).join(':')) ].filter(item => !!item).join(':')
},
return fmtString.concat(' a') getPanelElement () {
} const {
prefixCls, placeholder, disabledHours,
disabledMinutes, disabledSeconds, hideDisabledOptions, inputReadOnly,
allowEmpty, showHour, showMinute, showSecond, defaultOpenValue, clearText,
use12Hours, focusOnOpen, onKeyDown2, hourStep, minuteStep, secondStep,
sValue,
} = this
return (
<Panel
clearText={clearText}
prefixCls={`${prefixCls}-panel`}
ref='panel'
value={sValue}
inputReadOnly={inputReadOnly}
onChange={this.onPanelChange}
onClear={this.onPanelClear}
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}
>
{this.$slots.addon}
</Panel>
)
},
return [ getPopupClassName () {
showHour ? 'HH' : '', const { showHour, showMinute, showSecond, use12Hours, prefixCls } = this
showMinute ? 'mm' : '', let popupClassName = this.popupClassName
showSecond ? 'ss' : '', // Keep it for old compatibility
].filter(item => !!item).join(':') if ((!showHour || !showMinute || !showSecond) && !use12Hours) {
} popupClassName += ` ${prefixCls}-panel-narrow`
getPanelElement () {
const {
prefixCls, placeholder, disabledHours,
disabledMinutes, disabledSeconds, hideDisabledOptions, inputReadOnly,
allowEmpty, showHour, showMinute, showSecond, defaultOpenValue, clearText,
addon, use12Hours, focusOnOpen, onKeyDown, hourStep, minuteStep, secondStep,
} = this.props
return (
<Panel
clearText={clearText}
prefixCls={`${prefixCls}-panel`}
ref={this.savePanelRef}
value={this.state.value}
inputReadOnly={inputReadOnly}
onChange={this.onPanelChange}
onClear={this.onPanelClear}
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}
addon={addon}
focusOnOpen={focusOnOpen}
onKeyDown={onKeyDown}
/>
)
}
getPopupClassName () {
const { showHour, showMinute, showSecond, use12Hours, prefixCls } = this.props
let popupClassName = this.props.popupClassName
// Keep it for old compatibility
if ((!showHour || !showMinute || !showSecond) && !use12Hours) {
popupClassName += ` ${prefixCls}-panel-narrow`
}
let selectColumnCount = 0
if (showHour) {
selectColumnCount += 1
}
if (showMinute) {
selectColumnCount += 1
}
if (showSecond) {
selectColumnCount += 1
}
if (use12Hours) {
selectColumnCount += 1
}
popupClassName += ` ${prefixCls}-panel-column-${selectColumnCount}`
return popupClassName
}
setOpen (open) {
const { onOpen, onClose } = this.props
if (this.state.open !== open) {
if (!('open' in this.props)) {
this.setState({ open })
} }
if (open) { let selectColumnCount = 0
onOpen({ open }) if (showHour) {
} else { selectColumnCount += 1
onClose({ open })
} }
} if (showMinute) {
} selectColumnCount += 1
}
if (showSecond) {
selectColumnCount += 1
}
if (use12Hours) {
selectColumnCount += 1
}
popupClassName += ` ${prefixCls}-panel-column-${selectColumnCount}`
return popupClassName
},
focus () { setOpen (open) {
this.picker.focus() if (this.sOpen !== open) {
} if (!hasProp(this, 'open')) {
this.setState({ sOpen: open })
}
if (open) {
this.__emit('open', { open })
} else {
this.__emit('close', { open })
}
}
},
blur () { focus () {
this.picker.blur() this.$refs.picker.focus()
} },
blur () {
this.$refs.picker.blur()
},
onFocus (e) {
this.__emit('focus', e)
},
onBlur (e) {
this.__emit('blur', e)
},
},
render () { render () {
const { const {
prefixCls, placeholder, placement, align, prefixCls, placeholder, placement, align,
disabled, transitionName, style, className, getPopupContainer, name, autoComplete, disabled, transitionName, getPopupContainer, name, autoComplete,
onFocus, onBlur, autoFocus, inputReadOnly, autoFocus, inputReadOnly, sOpen, sValue, onFocus, onBlur,
} = this.props } = this
const { open, value } = this.state
const popupClassName = this.getPopupClassName() const popupClassName = this.getPopupClassName()
return ( return (
<Trigger <Trigger
prefixCls={`${prefixCls}-panel`} prefixCls={`${prefixCls}-panel`}
popupClassName={popupClassName} popupClassName={popupClassName}
popup={this.getPanelElement()}
popupAlign={align} popupAlign={align}
builtinPlacements={placements} builtinPlacements={placements}
popupPlacement={placement} popupPlacement={placement}
@ -271,19 +268,22 @@ export default class Picker extends Component {
destroyPopupOnHide destroyPopupOnHide
getPopupContainer={getPopupContainer} getPopupContainer={getPopupContainer}
popupTransitionName={transitionName} popupTransitionName={transitionName}
popupVisible={open} popupVisible={sOpen}
onPopupVisibleChange={this.onVisibleChange} onPopupVisibleChange={this.onVisibleChange}
> >
<span className={`${prefixCls} ${className}`} style={style}> <template slot='popup'>
{this.getPanelElement()}
</template>
<span class={`${prefixCls}`}>
<input <input
className={`${prefixCls}-input`} class={`${prefixCls}-input`}
ref={this.saveInputRef} ref='picker'
type='text' type='text'
placeholder={placeholder} placeholder={placeholder}
name={name} name={name}
onKeyDown={this.onKeyDown} onKeydown={this.onKeyDown}
disabled={disabled} disabled={disabled}
value={value && value.format(this.getFormat()) || ''} value={sValue && sValue.format(this.getFormat()) || ''}
autoComplete={autoComplete} autoComplete={autoComplete}
onFocus={onFocus} onFocus={onFocus}
onBlur={onBlur} onBlur={onBlur}
@ -291,10 +291,10 @@ export default class Picker extends Component {
onChange={noop} onChange={noop}
readOnly={!!inputReadOnly} readOnly={!!inputReadOnly}
/> />
<span className={`${prefixCls}-icon`}/> <span class={`${prefixCls}-icon`}/>
</span> </span>
</Trigger> </Trigger>
) )
} },
} }
</script> </script>

View File

@ -0,0 +1,160 @@
<script>
import '../assets/index.less'
import moment from 'moment'
import TimePicker from '../index'
const format = 'h:mm a'
const now = moment().hour(0).minute(0)
function onChange (value) {
console.log(value && value.format(format))
}
const showSecond = true
const str = showSecond ? 'HH:mm:ss' : 'HH:mm'
const now1 = moment().hour(14).minute(30)
function generateOptions (length, excludedOptions) {
const arr = []
for (let value = 0; value < length; value++) {
if (excludedOptions.indexOf(value) < 0) {
arr.push(value)
}
}
return arr
}
function onChange1 (value) {
console.log(value && value.format(str))
}
function disabledHours () {
return [0, 1, 2, 3, 4, 5, 6, 7, 8, 22, 23]
}
function disabledMinutes (h) {
switch (h) {
case 9:
return generateOptions(60, [30])
case 21:
return generateOptions(60, [0])
default:
return generateOptions(60, [0, 30])
}
}
function disabledSeconds (h, m) {
return [h + m % 60]
}
export default{
data () {
return {
open: false,
value: moment(),
}
},
methods: {
setOpen ({ open }) {
this.open = open
},
toggleOpen () {
this.open = !this.open
},
handleValueChange (value) {
console.log(value && value.format('HH:mm:ss'))
this.value = value
},
clear () {
this.value = undefined
},
},
render () {
return (
<div>
<TimePicker
showSecond={false}
defaultValue={now}
class='xxx'
onChange={onChange}
format={format}
use12Hours
inputReadOnly
/>
<br/>
<br/>
<div>
<h3>Disabled picker</h3>
<TimePicker
defaultValue={now1}
disabled
onChange={onChange1}
/>
<h3>Disabled options</h3>
<TimePicker
showSecond={showSecond}
defaultValue={now1}
class='xxx'
onChange={onChange1}
disabledHours={disabledHours}
disabledMinutes={disabledMinutes}
disabledSeconds={disabledSeconds}
/>
</div>
<div>
<TimePicker defaultValue={moment()} showHour={false} />
<TimePicker defaultValue={moment()} showMinute={false} />
<TimePicker defaultValue={moment()} showSecond={false} />
<TimePicker defaultValue={moment()} showMinute={false} showSecond={false} />
<TimePicker defaultValue={moment()} showHour={false} showSecond={false}/>
<TimePicker defaultValue={moment()} showHour={false} showMinute={false} />
</div>
<TimePicker
format={str}
showSecond={showSecond}
// use to control utfOffset, locale, default open value
defaultOpenValue={moment()}
class='xxx'
onChange={onChange1}
disabledHours={() => [0, 1, 2, 3, 4, 5, 6, 7, 8, 22, 23]}
disabledMinutes={() => [0, 2, 4, 6, 8]}
hideDisabledOptions
/>
<div>
<button onClick={this.toggleOpen}>Toggle open</button>
<TimePicker
open={this.open}
onOpen={this.setOpen}
onClose={this.setOpen}
focusOnOpen
/>
</div>
<TimePicker
style={{ width: '100px' }}
showSecond={showSecond}
defaultValue={moment()}
class='xxx'
onChange={onChange}
/>
<TimePicker defaultValue={moment()} showSecond={false} minuteStep={15} />
<div>
<TimePicker
defaultValue={this.value}
onChange={this.handleValueChange}
/>
<TimePicker
value={this.value}
onChange={this.handleValueChange}
/>
<button onClick={this.clear}>clear</button>
</div>
</div>
)
},
}
</script>

View File

@ -3,7 +3,7 @@ const AsyncComp = () => {
const hashs = window.location.hash.split('/') const hashs = window.location.hash.split('/')
const d = hashs[hashs.length - 1] const d = hashs[hashs.length - 1]
return { return {
component: import(`../components/grid/demo/${d}`), component: import(`../components/time-picker/demo/${d}`),
} }
} }
export default [ export default [

5
package-lock.json generated
View File

@ -3265,6 +3265,11 @@
"tapable": "0.2.8" "tapable": "0.2.8"
} }
}, },
"enquire.js": {
"version": "2.1.6",
"resolved": "http://registry.npm.taobao.org/enquire.js/download/enquire.js-2.1.6.tgz",
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
},
"ent": { "ent": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "http://r.cnpmjs.org/ent/download/ent-2.2.0.tgz", "resolved": "http://r.cnpmjs.org/ent/download/ent-2.2.0.tgz",

View File

@ -1,112 +1,112 @@
{ {
"name": "vue-ant-design", "name": "vue-ant-design",
"version": "1.0.0", "version": "1.0.0",
"description": "vue component", "description": "vue component",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "NODE_ENV=development ./node_modules/.bin/webpack-dev-server --open --hot", "start": "NODE_ENV=development ./node_modules/.bin/webpack-dev-server --open --hot",
"test": "karma start test/karma.conf.js --single-run", "test": "karma start test/karma.conf.js --single-run",
"build": "sh build.sh", "build": "sh build.sh",
"lint": "eslint -c ./.eslintrc --fix --ext .js ./src/", "lint": "eslint -c ./.eslintrc --fix --ext .js ./components/time-picker/locale",
"lint:style": "stylelint \"./examples/**/*.less\" --fix --syntax less" "lint:style": "stylelint \"./examples/**/*.less\" --fix --syntax less"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/vueComponent/ant-design.git" "url": "git+https://github.com/vueComponent/ant-design.git"
}, },
"keywords": [ "keywords": [
"vue" "vue"
], ],
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/vueComponent/ant-design/issues" "url": "https://github.com/vueComponent/ant-design/issues"
}, },
"homepage": "https://github.com/vueComponent/ant-design#readme", "homepage": "https://github.com/vueComponent/ant-design#readme",
"pre-commit": [ "pre-commit": [
"lint", "lint",
"lint:style" "lint:style"
], ],
"devDependencies": { "devDependencies": {
"babel-cli": "^6.26.0", "babel-cli": "^6.26.0",
"babel-eslint": "^8.0.1", "babel-eslint": "^8.0.1",
"babel-helper-vue-jsx-merge-props": "^2.0.2", "babel-helper-vue-jsx-merge-props": "^2.0.2",
"babel-loader": "^7.1.2", "babel-loader": "^7.1.2",
"babel-plugin-istanbul": "^4.1.1", "babel-plugin-istanbul": "^4.1.1",
"babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-decorators": "^6.24.1", "babel-plugin-transform-decorators": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-object-rest-spread": "^6.26.0", "babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-vue-jsx": "^3.5.0", "babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.0", "babel-preset-env": "^1.6.0",
"chai": "^4.1.2", "chai": "^4.1.2",
"cheerio": "^1.0.0-rc.2", "cheerio": "^1.0.0-rc.2",
"css-loader": "^0.28.7", "css-loader": "^0.28.7",
"eslint": "^4.7.2", "eslint": "^4.7.2",
"eslint-plugin-html": "^3.2.2", "eslint-plugin-html": "^3.2.2",
"eslint-plugin-vue-libs": "^1.2.1", "eslint-plugin-vue-libs": "^1.2.1",
"extract-text-webpack-plugin": "^3.0.2", "extract-text-webpack-plugin": "^3.0.2",
"fetch-jsonp": "^1.1.3", "fetch-jsonp": "^1.1.3",
"highlight.js": "^9.12.0", "highlight.js": "^9.12.0",
"html-webpack-plugin": "^2.30.1", "html-webpack-plugin": "^2.30.1",
"istanbul-instrumenter-loader": "^3.0.0", "istanbul-instrumenter-loader": "^3.0.0",
"jsonp": "^0.2.1", "jsonp": "^0.2.1",
"karma": "^1.4.1", "karma": "^1.4.1",
"karma-coverage": "^1.1.1", "karma-coverage": "^1.1.1",
"karma-coverage-istanbul-reporter": "^1.3.0", "karma-coverage-istanbul-reporter": "^1.3.0",
"karma-mocha": "^1.3.0", "karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.2", "karma-phantomjs-launcher": "^1.0.2",
"karma-phantomjs-shim": "^1.4.0", "karma-phantomjs-shim": "^1.4.0",
"karma-sinon-chai": "^1.3.1", "karma-sinon-chai": "^1.3.1",
"karma-sourcemap-loader": "^0.3.7", "karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.31", "karma-spec-reporter": "0.0.31",
"karma-webpack": "^2.0.2", "karma-webpack": "^2.0.2",
"less": "^2.7.2", "less": "^2.7.2",
"less-loader": "^4.0.5", "less-loader": "^4.0.5",
"markdown-it": "^8.4.0", "markdown-it": "^8.4.0",
"marked": "^0.3.7", "marked": "^0.3.7",
"mocha": "^3.2.0", "mocha": "^3.2.0",
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"querystring": "^0.2.0", "querystring": "^0.2.0",
"selenium-server": "^3.0.1", "selenium-server": "^3.0.1",
"semver": "^5.3.0", "semver": "^5.3.0",
"sinon": "^4.0.2", "sinon": "^4.0.2",
"sinon-chai": "^2.8.0", "sinon-chai": "^2.8.0",
"style-loader": "^0.18.2", "style-loader": "^0.18.2",
"stylelint": "^8.1.1", "stylelint": "^8.1.1",
"stylelint-config-standard": "^17.0.0", "stylelint-config-standard": "^17.0.0",
"vue-antd-md-loader": "^1.0.2", "vue-antd-md-loader": "^1.0.2",
"vue-loader": "^13.0.5", "vue-loader": "^13.0.5",
"vue-router": "^3.0.1", "vue-router": "^3.0.1",
"vue-template-compiler": "^2.5.13", "vue-template-compiler": "^2.5.13",
"webpack": "^3.6.0", "webpack": "^3.6.0",
"webpack-chunk-hash": "^0.5.0", "webpack-chunk-hash": "^0.5.0",
"webpack-dev-server": "^2.8.2", "webpack-dev-server": "^2.8.2",
"webpack-merge": "^4.1.1" "webpack-merge": "^4.1.1"
}, },
"dependencies": { "dependencies": {
"add-dom-event-listener": "^1.0.2", "add-dom-event-listener": "^1.0.2",
"array-tree-filter": "^2.1.0", "array-tree-filter": "^2.1.0",
"classnames": "^2.2.5", "classnames": "^2.2.5",
"component-classes": "^1.2.6", "component-classes": "^1.2.6",
"css-animation": "^1.4.1", "css-animation": "^1.4.1",
"dom-align": "^1.6.7", "dom-align": "^1.6.7",
"dom-scroll-into-view": "^1.2.1", "dom-scroll-into-view": "^1.2.1",
"enquire.js": "^2.1.6", "enquire.js": "^2.1.6",
"eslint-plugin-vue": "^3.13.0", "eslint-plugin-vue": "^3.13.0",
"lodash.clonedeep": "^4.5.0", "lodash.clonedeep": "^4.5.0",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"lodash.isequal": "^4.5.0", "lodash.isequal": "^4.5.0",
"lodash.isplainobject": "^4.0.6", "lodash.isplainobject": "^4.0.6",
"moment": "^2.21.0", "moment": "^2.21.0",
"omit.js": "^1.0.0", "omit.js": "^1.0.0",
"shallow-equal": "^1.0.0", "shallow-equal": "^1.0.0",
"shallowequal": "^1.0.2", "shallowequal": "^1.0.2",
"vue": "^2.5.13", "vue": "^2.5.13",
"vue-clipboard2": "0.0.8", "vue-clipboard2": "0.0.8",
"vue-types": "^1.0.2", "vue-types": "^1.0.2",
"warning": "^3.0.0" "warning": "^3.0.0"
} }
} }