add date-picker
parent
fa0829e256
commit
4b2f56a7a9
|
@ -0,0 +1,366 @@
|
|||
/* tslint:disable jsx-no-multiline-js */
|
||||
import * as React from 'react';
|
||||
import * as moment from 'moment';
|
||||
import RangeCalendar from 'rc-calendar/lib/RangeCalendar';
|
||||
import RcDatePicker from 'rc-calendar/lib/Picker';
|
||||
import classNames from 'classnames';
|
||||
import Icon from '../icon';
|
||||
import warning from '../_util/warning';
|
||||
import callMoment from '../_util/callMoment';
|
||||
import { RangePickerValue, RangePickerPresetRange } from './interface';
|
||||
|
||||
export interface RangePickerState {
|
||||
value?: RangePickerValue;
|
||||
showDate?: RangePickerValue;
|
||||
open?: boolean;
|
||||
hoverValue?: RangePickerValue;
|
||||
}
|
||||
|
||||
function getShowDateFromValue(value: RangePickerValue) {
|
||||
const [start, end] = value;
|
||||
// value could be an empty array, then we should not reset showDate
|
||||
if (!start && !end) {
|
||||
return;
|
||||
}
|
||||
const newEnd = end && end.isSame(start, 'month') ? end.clone().add(1, 'month') : end;
|
||||
return [start, newEnd] as RangePickerValue;
|
||||
}
|
||||
|
||||
function formatValue(value: moment.Moment | undefined, format: string): string {
|
||||
return (value && value.format(format)) || '';
|
||||
}
|
||||
|
||||
function pickerValueAdapter(value?: moment.Moment | RangePickerValue): RangePickerValue | undefined {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(value)) {
|
||||
return value;
|
||||
}
|
||||
return [value, value.clone().add(1, 'month')];
|
||||
}
|
||||
|
||||
function isEmptyArray(arr: any) {
|
||||
if (Array.isArray(arr)) {
|
||||
return arr.length === 0 || arr.every(i => !i);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function fixLocale(value: RangePickerValue | undefined, localeCode: string) {
|
||||
if (!localeCode) {
|
||||
return;
|
||||
}
|
||||
if (!value || value.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (value[0]) {
|
||||
value[0]!.locale(localeCode);
|
||||
}
|
||||
if (value[1]) {
|
||||
value[1]!.locale(localeCode);
|
||||
}
|
||||
}
|
||||
|
||||
export default class RangePicker extends React.Component<any, RangePickerState> {
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-calendar',
|
||||
allowClear: true,
|
||||
showToday: false,
|
||||
};
|
||||
|
||||
private picker: HTMLSpanElement;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
const value = props.value || props.defaultValue || [];
|
||||
if (
|
||||
value[0] && !moment.isMoment(value[0]) ||
|
||||
value[1] && !moment.isMoment(value[1])
|
||||
) {
|
||||
throw new Error(
|
||||
'The value/defaultValue of RangePicker must be a moment object array after `antd@2.0`, ' +
|
||||
'see: https://u.ant.design/date-picker-value',
|
||||
);
|
||||
}
|
||||
const pickerValue = !value || isEmptyArray(value) ? props.defaultPickerValue : value;
|
||||
this.state = {
|
||||
value,
|
||||
showDate: pickerValueAdapter(pickerValue || callMoment(moment)),
|
||||
open: props.open,
|
||||
hoverValue: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: any) {
|
||||
if ('value' in nextProps) {
|
||||
const state = this.state;
|
||||
const value = nextProps.value || [];
|
||||
this.setState({
|
||||
value,
|
||||
showDate: getShowDateFromValue(value) || state.showDate,
|
||||
});
|
||||
}
|
||||
if ('open' in nextProps) {
|
||||
this.setState({
|
||||
open: nextProps.open,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
clearSelection = (e: React.MouseEvent<HTMLElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.setState({ value: [] });
|
||||
this.handleChange([]);
|
||||
}
|
||||
|
||||
clearHoverValue = () => this.setState({ hoverValue: [] });
|
||||
|
||||
handleChange = (value: RangePickerValue) => {
|
||||
const props = this.props;
|
||||
if (!('value' in props)) {
|
||||
this.setState(({ showDate }) => ({
|
||||
value,
|
||||
showDate: getShowDateFromValue(value) || showDate,
|
||||
}));
|
||||
}
|
||||
props.onChange(value, [
|
||||
formatValue(value[0], props.format),
|
||||
formatValue(value[1], props.format),
|
||||
]);
|
||||
}
|
||||
|
||||
handleOpenChange = (open: boolean) => {
|
||||
if (!('open' in this.props)) {
|
||||
this.setState({ open });
|
||||
}
|
||||
|
||||
if (open === false) {
|
||||
this.clearHoverValue();
|
||||
}
|
||||
|
||||
const { onOpenChange } = this.props;
|
||||
if (onOpenChange) {
|
||||
onOpenChange(open);
|
||||
}
|
||||
}
|
||||
|
||||
handleShowDateChange = (showDate: RangePickerValue) => this.setState({ showDate });
|
||||
|
||||
handleHoverChange = (hoverValue: any) => this.setState({ hoverValue });
|
||||
|
||||
handleRangeMouseLeave = () => {
|
||||
if (this.state.open) {
|
||||
this.clearHoverValue();
|
||||
}
|
||||
}
|
||||
|
||||
handleCalendarInputSelect = (value: RangePickerValue) => {
|
||||
if (!value[0]) {
|
||||
return;
|
||||
}
|
||||
this.setState(({ showDate }) => ({
|
||||
value,
|
||||
showDate: getShowDateFromValue(value) || showDate,
|
||||
}));
|
||||
}
|
||||
|
||||
handleRangeClick = (value: RangePickerPresetRange) => {
|
||||
if (typeof value === 'function') {
|
||||
value = value();
|
||||
}
|
||||
|
||||
this.setValue(value, true);
|
||||
|
||||
const { onOk } = this.props;
|
||||
if (onOk) {
|
||||
onOk(value);
|
||||
}
|
||||
}
|
||||
|
||||
setValue(value: RangePickerValue, hidePanel?: boolean) {
|
||||
this.handleChange(value);
|
||||
if ((hidePanel || !this.props.showTime) && !('open' in this.props)) {
|
||||
this.setState({ open: false });
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.picker.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.picker.blur();
|
||||
}
|
||||
|
||||
savePicker = (node: HTMLSpanElement) => {
|
||||
this.picker = node;
|
||||
}
|
||||
|
||||
renderFooter = (...args: any[]) => {
|
||||
const { prefixCls, ranges, renderExtraFooter } = this.props;
|
||||
if (!ranges && !renderExtraFooter) {
|
||||
return null;
|
||||
}
|
||||
const customFooter = renderExtraFooter ? (
|
||||
<div className={`${prefixCls}-footer-extra`} key="extra">
|
||||
{renderExtraFooter(...args)}
|
||||
</div>
|
||||
) : null;
|
||||
const operations = Object.keys(ranges || {}).map((range) => {
|
||||
const value = ranges[range];
|
||||
return (
|
||||
<a
|
||||
key={range}
|
||||
onClick={() => this.handleRangeClick(value)}
|
||||
onMouseEnter={() => this.setState({ hoverValue: value })}
|
||||
onMouseLeave={this.handleRangeMouseLeave}
|
||||
>
|
||||
{range}
|
||||
</a>
|
||||
);
|
||||
});
|
||||
const rangeNode = (
|
||||
<div className={`${prefixCls}-footer-extra ${prefixCls}-range-quick-selector`} key="range">
|
||||
{operations}
|
||||
</div>
|
||||
);
|
||||
return [rangeNode, customFooter];
|
||||
}
|
||||
|
||||
render() {
|
||||
const { state, props } = this;
|
||||
const { value, showDate, hoverValue, open } = state;
|
||||
const {
|
||||
prefixCls, popupStyle, style,
|
||||
disabledDate, disabledTime,
|
||||
showTime, showToday,
|
||||
ranges, onOk, locale, localeCode, format,
|
||||
dateRender, onCalendarChange,
|
||||
} = props;
|
||||
|
||||
fixLocale(value, localeCode);
|
||||
fixLocale(showDate, localeCode);
|
||||
|
||||
warning(!('onOK' in props), 'It should be `RangePicker[onOk]`, instead of `onOK`!');
|
||||
|
||||
const calendarClassName = classNames({
|
||||
[`${prefixCls}-time`]: showTime,
|
||||
[`${prefixCls}-range-with-ranges`]: ranges,
|
||||
});
|
||||
|
||||
// 需要选择时间时,点击 ok 时才触发 onChange
|
||||
let pickerChangeHandler = {
|
||||
onChange: this.handleChange,
|
||||
};
|
||||
let calendarProps: any = {
|
||||
onOk: this.handleChange,
|
||||
};
|
||||
if (props.timePicker) {
|
||||
pickerChangeHandler.onChange = changedValue => this.handleChange(changedValue);
|
||||
} else {
|
||||
calendarProps = {};
|
||||
}
|
||||
if ('mode' in props) {
|
||||
calendarProps.mode = props.mode;
|
||||
}
|
||||
|
||||
const startPlaceholder = ('placeholder' in props)
|
||||
? props.placeholder[0] : locale.lang.rangePlaceholder[0];
|
||||
const endPlaceholder = ('placeholder' in props)
|
||||
? props.placeholder[1] : locale.lang.rangePlaceholder[1];
|
||||
|
||||
const calendar = (
|
||||
<RangeCalendar
|
||||
{...calendarProps}
|
||||
onChange={onCalendarChange}
|
||||
format={format}
|
||||
prefixCls={prefixCls}
|
||||
className={calendarClassName}
|
||||
renderFooter={this.renderFooter}
|
||||
timePicker={props.timePicker}
|
||||
disabledDate={disabledDate}
|
||||
disabledTime={disabledTime}
|
||||
dateInputPlaceholder={[startPlaceholder, endPlaceholder]}
|
||||
locale={locale.lang}
|
||||
onOk={onOk}
|
||||
dateRender={dateRender}
|
||||
value={showDate}
|
||||
onValueChange={this.handleShowDateChange}
|
||||
hoverValue={hoverValue}
|
||||
onHoverChange={this.handleHoverChange}
|
||||
onPanelChange={props.onPanelChange}
|
||||
showToday={showToday}
|
||||
onInputSelect={this.handleCalendarInputSelect}
|
||||
/>
|
||||
);
|
||||
|
||||
// default width for showTime
|
||||
const pickerStyle = {} as any;
|
||||
if (props.showTime) {
|
||||
pickerStyle.width = (style && style.width) || 350;
|
||||
}
|
||||
|
||||
const clearIcon = (!props.disabled && props.allowClear && value && (value[0] || value[1])) ? (
|
||||
<Icon
|
||||
type="cross-circle"
|
||||
className={`${prefixCls}-picker-clear`}
|
||||
onClick={this.clearSelection}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
const input = ({ value: inputValue }: { value: any }) => {
|
||||
const start = inputValue[0];
|
||||
const end = inputValue[1];
|
||||
return (
|
||||
<span className={props.pickerInputClass}>
|
||||
<input
|
||||
disabled={props.disabled}
|
||||
readOnly
|
||||
value={(start && start.format(props.format)) || ''}
|
||||
placeholder={startPlaceholder}
|
||||
className={`${prefixCls}-range-picker-input`}
|
||||
tabIndex={-1}
|
||||
/>
|
||||
<span className={`${prefixCls}-range-picker-separator`}> ~ </span>
|
||||
<input
|
||||
disabled={props.disabled}
|
||||
readOnly
|
||||
value={(end && end.format(props.format)) || ''}
|
||||
placeholder={endPlaceholder}
|
||||
className={`${prefixCls}-range-picker-input`}
|
||||
tabIndex={-1}
|
||||
/>
|
||||
{clearIcon}
|
||||
<span className={`${prefixCls}-picker-icon`} />
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<span
|
||||
ref={this.savePicker}
|
||||
id={props.id}
|
||||
className={classNames(props.className, props.pickerClass)}
|
||||
style={{ ...style, ...pickerStyle }}
|
||||
tabIndex={props.disabled ? -1 : 0}
|
||||
onFocus={props.onFocus}
|
||||
onBlur={props.onBlur}
|
||||
>
|
||||
<RcDatePicker
|
||||
{...props}
|
||||
{...pickerChangeHandler}
|
||||
calendar={calendar}
|
||||
value={value}
|
||||
open={open}
|
||||
onOpenChange={this.handleOpenChange}
|
||||
prefixCls={`${prefixCls}-picker-container`}
|
||||
style={popupStyle}
|
||||
>
|
||||
{input}
|
||||
</RcDatePicker>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
<script>
|
||||
import * as moment from 'moment'
|
||||
import Calendar from '../vc-calendar'
|
||||
import VcDatePicker from '../vc-calendar/src/Picker'
|
||||
import Icon from '../icon'
|
||||
import { hasProp, getOptionProps } from '../_util/props-util'
|
||||
import BaseMixin from '../_util/BaseMixin'
|
||||
|
||||
function formatValue (value, format) {
|
||||
return (value && value.format(format)) || ''
|
||||
}
|
||||
function noop () {}
|
||||
|
||||
export default {
|
||||
// static defaultProps = {
|
||||
// format: 'YYYY-wo',
|
||||
// allowClear: true,
|
||||
// };
|
||||
|
||||
// private input: any;
|
||||
mixins: [BaseMixin],
|
||||
data () {
|
||||
const value = this.value || this.defaultValue
|
||||
if (value && !moment.isMoment(value)) {
|
||||
throw new Error(
|
||||
'The value/defaultValue of DatePicker or MonthPicker must be ' +
|
||||
'a moment object',
|
||||
)
|
||||
}
|
||||
return {
|
||||
sValue: value,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
this.setState({ sValue: val })
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
weekDateRender (current) {
|
||||
const selectedValue = this.sValue
|
||||
const { prefixCls } = this
|
||||
if (selectedValue &&
|
||||
current.year() === selectedValue.year() &&
|
||||
current.week() === selectedValue.week()) {
|
||||
return (
|
||||
<div class={`${prefixCls}-selected-day`}>
|
||||
<div class={`${prefixCls}-date`}>
|
||||
{current.date()}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div class={`${prefixCls}-calendar-date`}>
|
||||
{current.date()}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
handleChange (value) {
|
||||
if (!hasProp(this, 'value')) {
|
||||
this.setState({ sValue: value })
|
||||
}
|
||||
this.$emit('change', value, formatValue(value, this.format))
|
||||
},
|
||||
clearSelection (e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
this.handleChange(null)
|
||||
},
|
||||
|
||||
focus () {
|
||||
this.$refs.input.focus()
|
||||
},
|
||||
|
||||
blur () {
|
||||
this.$refs.input.blur()
|
||||
},
|
||||
},
|
||||
|
||||
render () {
|
||||
const props = getOptionProps(this)
|
||||
const {
|
||||
prefixCls, disabled, pickerClass, popupStyle,
|
||||
pickerInputClass, format, allowClear, locale, localeCode, disabledDate,
|
||||
sValue: pickerValue, $listeners,
|
||||
} = this
|
||||
const { focus = noop, blur = noop } = $listeners
|
||||
|
||||
if (pickerValue && localeCode) {
|
||||
pickerValue.locale(localeCode)
|
||||
}
|
||||
|
||||
const placeholder = hasProp(this, 'placeholder') ? this.placeholder : locale.lang.placeholder
|
||||
|
||||
const calendar = (
|
||||
<Calendar
|
||||
showWeekNumber
|
||||
dateRender={this.weekDateRender}
|
||||
prefixCls={prefixCls}
|
||||
format={format}
|
||||
locale={locale.lang}
|
||||
showDateInput={false}
|
||||
showToday={false}
|
||||
disabledDate={disabledDate}
|
||||
/>
|
||||
)
|
||||
const clearIcon = (!disabled && allowClear && this.sValue) ? (
|
||||
<Icon
|
||||
type='cross-circle'
|
||||
class={`${prefixCls}-picker-clear`}
|
||||
onClick={this.clearSelection}
|
||||
/>
|
||||
) : null
|
||||
const input = ({ value }) => {
|
||||
return (
|
||||
<span>
|
||||
<input
|
||||
ref='input'
|
||||
disabled={disabled}
|
||||
readOnly
|
||||
value={(value && value.format(format)) || ''}
|
||||
placeholder={placeholder}
|
||||
class={pickerInputClass}
|
||||
onFocus={focus}
|
||||
onBlur={blur}
|
||||
/>
|
||||
{clearIcon}
|
||||
<span class={`${prefixCls}-picker-icon`} />
|
||||
</span>
|
||||
)
|
||||
}
|
||||
const vcDatePickerProps = {
|
||||
props: {
|
||||
...props,
|
||||
calendar,
|
||||
prefixCls: `${prefixCls}-picker-container`,
|
||||
value: pickerValue,
|
||||
},
|
||||
on: {
|
||||
...$listeners,
|
||||
change: this.handleChange,
|
||||
},
|
||||
style: popupStyle,
|
||||
}
|
||||
return (
|
||||
<span class={pickerClass}>
|
||||
<VcDatePicker
|
||||
{...vcDatePickerProps}
|
||||
>
|
||||
{input}
|
||||
</VcDatePicker>
|
||||
</span>
|
||||
)
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,196 @@
|
|||
import * as React from 'react';
|
||||
import * as moment from 'moment';
|
||||
import MonthCalendar from 'rc-calendar/lib/MonthCalendar';
|
||||
import RcDatePicker from 'rc-calendar/lib/Picker';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Icon from '../icon';
|
||||
import warning from '../_util/warning';
|
||||
import callMoment from '../_util/callMoment';
|
||||
|
||||
export interface PickerProps {
|
||||
value?: moment.Moment;
|
||||
prefixCls: string;
|
||||
}
|
||||
|
||||
export default function createPicker(TheCalendar: React.ComponentClass): any {
|
||||
return class CalenderWrapper extends React.Component<any, any> {
|
||||
static defaultProps = {
|
||||
prefixCls: 'ant-calendar',
|
||||
allowClear: true,
|
||||
showToday: true,
|
||||
};
|
||||
|
||||
private input: any;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
const value = props.value || props.defaultValue;
|
||||
if (value && !moment.isMoment(value)) {
|
||||
throw new Error(
|
||||
'The value/defaultValue of DatePicker or MonthPicker must be ' +
|
||||
'a moment object after `antd@2.0`, see: https://u.ant.design/date-picker-value',
|
||||
);
|
||||
}
|
||||
this.state = {
|
||||
value,
|
||||
showDate: value,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: PickerProps) {
|
||||
if ('value' in nextProps) {
|
||||
this.setState({
|
||||
value: nextProps.value,
|
||||
showDate: nextProps.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderFooter = (...args: any[]) => {
|
||||
const { prefixCls, renderExtraFooter } = this.props;
|
||||
return renderExtraFooter ? (
|
||||
<div className={`${prefixCls}-footer-extra`}>
|
||||
{renderExtraFooter(...args)}
|
||||
</div>
|
||||
) : null;
|
||||
}
|
||||
|
||||
clearSelection = (e: React.MouseEvent<HTMLElement>) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.handleChange(null);
|
||||
}
|
||||
|
||||
handleChange = (value: moment.Moment | null) => {
|
||||
const props = this.props;
|
||||
if (!('value' in props)) {
|
||||
this.setState({
|
||||
value,
|
||||
showDate: value,
|
||||
});
|
||||
}
|
||||
props.onChange(value, (value && value.format(props.format)) || '');
|
||||
}
|
||||
|
||||
handleCalendarChange = (value: moment.Moment) => {
|
||||
this.setState({ showDate: value });
|
||||
}
|
||||
|
||||
focus() {
|
||||
this.input.focus();
|
||||
}
|
||||
|
||||
blur() {
|
||||
this.input.blur();
|
||||
}
|
||||
|
||||
saveInput = (node: any) => {
|
||||
this.input = node;
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value, showDate } = this.state;
|
||||
const props = omit(this.props, ['onChange']);
|
||||
const { prefixCls, locale, localeCode } = props;
|
||||
|
||||
const placeholder = ('placeholder' in props)
|
||||
? props.placeholder : locale.lang.placeholder;
|
||||
|
||||
const disabledTime = props.showTime ? props.disabledTime : null;
|
||||
|
||||
const calendarClassName = classNames({
|
||||
[`${prefixCls}-time`]: props.showTime,
|
||||
[`${prefixCls}-month`]: MonthCalendar === TheCalendar,
|
||||
});
|
||||
|
||||
if (value && localeCode) {
|
||||
value.locale(localeCode);
|
||||
}
|
||||
|
||||
let pickerProps: Object = {};
|
||||
let calendarProps: any = {};
|
||||
if (props.showTime) {
|
||||
calendarProps = {
|
||||
// fix https://github.com/ant-design/ant-design/issues/1902
|
||||
onSelect: this.handleChange,
|
||||
};
|
||||
} else {
|
||||
pickerProps = {
|
||||
onChange: this.handleChange,
|
||||
};
|
||||
}
|
||||
if ('mode' in props) {
|
||||
calendarProps.mode = props.mode;
|
||||
}
|
||||
|
||||
warning(!('onOK' in props), 'It should be `DatePicker[onOk]` or `MonthPicker[onOk]`, instead of `onOK`!');
|
||||
const calendar = (
|
||||
<TheCalendar
|
||||
{...calendarProps}
|
||||
disabledDate={props.disabledDate}
|
||||
disabledTime={disabledTime}
|
||||
locale={locale.lang}
|
||||
timePicker={props.timePicker}
|
||||
defaultValue={props.defaultPickerValue || callMoment(moment)}
|
||||
dateInputPlaceholder={placeholder}
|
||||
prefixCls={prefixCls}
|
||||
className={calendarClassName}
|
||||
onOk={props.onOk}
|
||||
dateRender={props.dateRender}
|
||||
format={props.format}
|
||||
showToday={props.showToday}
|
||||
monthCellContentRender={props.monthCellContentRender}
|
||||
renderFooter={this.renderFooter}
|
||||
onPanelChange={props.onPanelChange}
|
||||
onChange={this.handleCalendarChange}
|
||||
value={showDate}
|
||||
/>
|
||||
);
|
||||
|
||||
const clearIcon = (!props.disabled && props.allowClear && value) ? (
|
||||
<Icon
|
||||
type="cross-circle"
|
||||
className={`${prefixCls}-picker-clear`}
|
||||
onClick={this.clearSelection}
|
||||
/>
|
||||
) : null;
|
||||
|
||||
const input = ({ value: inputValue }: { value: moment.Moment | null }) => (
|
||||
<div>
|
||||
<input
|
||||
ref={this.saveInput}
|
||||
disabled={props.disabled}
|
||||
readOnly
|
||||
value={(inputValue && inputValue.format(props.format)) || ''}
|
||||
placeholder={placeholder}
|
||||
className={props.pickerInputClass}
|
||||
/>
|
||||
{clearIcon}
|
||||
<span className={`${prefixCls}-picker-icon`} />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<span
|
||||
id={props.id}
|
||||
className={classNames(props.className, props.pickerClass)}
|
||||
style={props.style}
|
||||
onFocus={props.onFocus}
|
||||
onBlur={props.onBlur}
|
||||
>
|
||||
<RcDatePicker
|
||||
{...props}
|
||||
{...pickerProps}
|
||||
calendar={calendar}
|
||||
value={value}
|
||||
prefixCls={`${prefixCls}-picker-container`}
|
||||
style={props.popupStyle}
|
||||
>
|
||||
{input}
|
||||
</RcDatePicker>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
order: 0
|
||||
title:
|
||||
zh-CN: 基本
|
||||
en-US: Basic
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
最简单的用法,在浮层中可以选择或者输入日期。
|
||||
|
||||
## en-US
|
||||
|
||||
Basic use case. Users can select or input a date in panel.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
|
||||
|
||||
function onChange(date, dateString) {
|
||||
console.log(date, dateString);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker onChange={onChange} />
|
||||
<br />
|
||||
<MonthPicker onChange={onChange} placeholder="Select month" />
|
||||
<br />
|
||||
<RangePicker onChange={onChange} />
|
||||
<br />
|
||||
<WeekPicker onChange={onChange} placeholder="Select week" />
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
|
@ -0,0 +1,52 @@
|
|||
---
|
||||
order: 12
|
||||
title:
|
||||
zh-CN: 定制日期单元格
|
||||
en-US: Customized Date Rendering
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `dateRender` 可以自定义日期单元格的内容和样式。
|
||||
|
||||
## en-US
|
||||
|
||||
We can customize the rendering of date cells in the calendar by providing a `dateRender` function to `DatePicker`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker
|
||||
dateRender={(current) => {
|
||||
const style = {};
|
||||
if (current.date() === 1) {
|
||||
style.border = '1px solid #1890ff';
|
||||
style.borderRadius = '50%';
|
||||
}
|
||||
return (
|
||||
<div className="ant-calendar-date" style={style}>
|
||||
{current.date()}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<RangePicker
|
||||
dateRender={(current) => {
|
||||
const style = {};
|
||||
if (current.date() === 1) {
|
||||
style.border = '1px solid #1890ff';
|
||||
style.borderRadius = '50%';
|
||||
}
|
||||
return (
|
||||
<div className="ant-calendar-date" style={style}>
|
||||
{current.date()}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
|
@ -0,0 +1,80 @@
|
|||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 不可选择日期和时间
|
||||
en-US: Disabled Date & Time
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可用 `disabledDate` 和 `disabledTime` 分别禁止选择部分日期和时间,其中 `disabledTime` 需要和 `showTime` 一起使用。
|
||||
|
||||
## en-US
|
||||
|
||||
Disabled part of dates and time by `disabledDate` and `disabledTime` respectively, and `disabledTime` only works with `showTime`.
|
||||
|
||||
````jsx
|
||||
import moment from 'moment';
|
||||
import { DatePicker } from 'antd';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
function range(start, end) {
|
||||
const result = [];
|
||||
for (let i = start; i < end; i++) {
|
||||
result.push(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function disabledDate(current) {
|
||||
// Can not select days before today and today
|
||||
return current && current < moment().endOf('day');
|
||||
}
|
||||
|
||||
function disabledDateTime() {
|
||||
return {
|
||||
disabledHours: () => range(0, 24).splice(4, 20),
|
||||
disabledMinutes: () => range(30, 60),
|
||||
disabledSeconds: () => [55, 56],
|
||||
};
|
||||
}
|
||||
|
||||
function disabledRangeTime(_, type) {
|
||||
if (type === 'start') {
|
||||
return {
|
||||
disabledHours: () => range(0, 60).splice(4, 20),
|
||||
disabledMinutes: () => range(30, 60),
|
||||
disabledSeconds: () => [55, 56],
|
||||
};
|
||||
}
|
||||
return {
|
||||
disabledHours: () => range(0, 60).splice(20, 4),
|
||||
disabledMinutes: () => range(0, 31),
|
||||
disabledSeconds: () => [55, 56],
|
||||
};
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
disabledDate={disabledDate}
|
||||
disabledTime={disabledDateTime}
|
||||
showTime={{ defaultValue: moment('00:00:00', 'HH:mm:ss') }}
|
||||
/>
|
||||
<br />
|
||||
<MonthPicker disabledDate={disabledDate} placeholder="Select month" />
|
||||
<br />
|
||||
<RangePicker
|
||||
disabledDate={disabledDate}
|
||||
disabledTime={disabledRangeTime}
|
||||
showTime={{
|
||||
hideDisabledOptions: true,
|
||||
defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('11:59:59', 'HH:mm:ss')],
|
||||
}}
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 禁用
|
||||
en-US: Disabled
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
选择框的不可用状态。
|
||||
|
||||
## en-US
|
||||
|
||||
A disabled state of the `DatePicker`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
const dateFormat = 'YYYY-MM-DD';
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker defaultValue={moment('2015-06-06', dateFormat)} disabled />
|
||||
<br />
|
||||
<MonthPicker defaultValue={moment('2015-06', 'YYYY-MM')} disabled />
|
||||
<br />
|
||||
<RangePicker
|
||||
defaultValue={[moment('2015-06-06', dateFormat), moment('2015-06-06', dateFormat)]}
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
order: 10
|
||||
title:
|
||||
zh-CN: 额外的页脚
|
||||
en-US: Extra Footer
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
在浮层中加入额外的页脚,以满足某些定制信息的需求。
|
||||
|
||||
## en-US
|
||||
|
||||
Render extra footer in panel for customized requirements.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { RangePicker, MonthPicker } = DatePicker;
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker renderExtraFooter={() => 'extra footer'} />
|
||||
<DatePicker renderExtraFooter={() => 'extra footer'} showTime />
|
||||
<RangePicker renderExtraFooter={() => 'extra footer'} />
|
||||
<RangePicker renderExtraFooter={() => 'extra footer'} showTime />
|
||||
<MonthPicker renderExtraFooter={() => 'extra footer'} placeholder="Select month" />
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 日期格式
|
||||
en-US: Date Format
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `format` 属性,可以自定义日期显示格式。
|
||||
|
||||
## en-US
|
||||
|
||||
We can set the date format by `format`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
const { MonthPicker, RangePicker } = DatePicker;
|
||||
|
||||
const dateFormat = 'YYYY/MM/DD';
|
||||
const monthFormat = 'YYYY/MM';
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker defaultValue={moment('2015/01/01', dateFormat)} format={dateFormat} />
|
||||
<br />
|
||||
<MonthPicker defaultValue={moment('2015/01', monthFormat)} format={monthFormat} />
|
||||
<br />
|
||||
<RangePicker
|
||||
defaultValue={[moment('2015/01/01', dateFormat), moment('2015/01/01', dateFormat)]}
|
||||
format={dateFormat}
|
||||
/>
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
|
@ -0,0 +1,82 @@
|
|||
---
|
||||
order: 11
|
||||
title:
|
||||
zh-CN: 受控面板
|
||||
en-US: Controlled Panels
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过组合 `mode` 与 `onPanelChange` 控制要展示的面板。
|
||||
|
||||
## en-US
|
||||
|
||||
Determing which panel to show with `mode` and `onPanelChange`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
class ControlledDatePicker extends React.Component {
|
||||
state = { mode: 'time' };
|
||||
|
||||
handleOpenChange = (open) => {
|
||||
if (open) {
|
||||
this.setState({ mode: 'time' });
|
||||
}
|
||||
}
|
||||
|
||||
handlePanelChange = (value, mode) => {
|
||||
this.setState({ mode });
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<DatePicker
|
||||
mode={this.state.mode}
|
||||
showTime
|
||||
onOpenChange={this.handleOpenChange}
|
||||
onPanelChange={this.handlePanelChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ControlledRangePicker extends React.Component {
|
||||
state = {
|
||||
mode: ['month', 'month'],
|
||||
value: [],
|
||||
};
|
||||
|
||||
handlePanelChange = (value, mode) => {
|
||||
this.setState({
|
||||
value,
|
||||
mode: [
|
||||
mode[0] === 'date' ? 'month' : mode[0],
|
||||
mode[1] === 'date' ? 'month' : mode[1],
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value, mode } = this.state;
|
||||
return (
|
||||
<RangePicker
|
||||
placeholder={['Start month', 'End month']}
|
||||
format="YYYY-MM"
|
||||
value={value}
|
||||
mode={mode}
|
||||
onPanelChange={this.handlePanelChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<ControlledDatePicker />
|
||||
<br />
|
||||
<ControlledRangePicker />
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 预设范围
|
||||
en-US: Presetted Ranges
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
RangePicker 可以设置常用的 预设范围 提高用户体验。
|
||||
|
||||
## en-US
|
||||
|
||||
We can set presetted ranges to RangePicker to improve user experience.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
import moment from 'moment';
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
function onChange(dates, dateStrings) {
|
||||
console.log('From: ', dates[0], ', to: ', dates[1]);
|
||||
console.log('From: ', dateStrings[0], ', to: ', dateStrings[1]);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<RangePicker
|
||||
ranges={{ Today: [moment(), moment()], 'This Month': [moment(), moment().endOf('month')] }}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<br />
|
||||
<RangePicker
|
||||
ranges={{ Today: [moment(), moment()], 'This Month': [moment(), moment().endOf('month')] }}
|
||||
showTime
|
||||
format="YYYY/MM/DD HH:mm:ss"
|
||||
onChange={onChange}
|
||||
/>
|
||||
</div>,
|
||||
mountNode
|
||||
);
|
||||
````
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 三种大小
|
||||
en-US: Three Sizes
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
三种大小的输入框,若不设置,则为 `default`。
|
||||
|
||||
## en-US
|
||||
|
||||
The input box comes in three sizes. `default` will be used if `size` is omitted.
|
||||
|
||||
|
||||
````jsx
|
||||
import { DatePicker, Radio } from 'antd';
|
||||
const { MonthPicker, RangePicker, WeekPicker } = DatePicker;
|
||||
|
||||
class PickerSizesDemo extends React.Component {
|
||||
state = {
|
||||
size: 'default',
|
||||
};
|
||||
|
||||
handleSizeChange = (e) => {
|
||||
this.setState({ size: e.target.value });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { size } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<Radio.Group value={size} onChange={this.handleSizeChange}>
|
||||
<Radio.Button value="large">Large</Radio.Button>
|
||||
<Radio.Button value="default">Default</Radio.Button>
|
||||
<Radio.Button value="small">Small</Radio.Button>
|
||||
</Radio.Group>
|
||||
<br /><br />
|
||||
<DatePicker size={size} />
|
||||
<br />
|
||||
<MonthPicker size={size} placeholder="Select Month" />
|
||||
<br />
|
||||
<RangePicker size={size} />
|
||||
<br />
|
||||
<WeekPicker size={size} placeholder="Select Week" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<PickerSizesDemo />, mountNode);
|
||||
````
|
|
@ -0,0 +1,99 @@
|
|||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 自定义日期范围选择
|
||||
en-US: Customized Range Picker
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
当 `RangePicker` 无法满足业务需求时,可以使用两个 `DatePicker` 实现类似的功能。
|
||||
> * 通过设置 `disabledDate` 方法,来约束开始和结束日期。
|
||||
> * 通过 `open` `onOpenChange` 来优化交互。
|
||||
|
||||
## en-US
|
||||
|
||||
When `RangePicker` does not satisfied your requirements, try to implement similar functionality with two `DatePicker`.
|
||||
> * Use the `disabledDate` property to limit the start and end dates.
|
||||
> * Improve user experience with `open` and `onOpenChange`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
|
||||
class DateRange extends React.Component {
|
||||
state = {
|
||||
startValue: null,
|
||||
endValue: null,
|
||||
endOpen: false,
|
||||
};
|
||||
|
||||
disabledStartDate = (startValue) => {
|
||||
const endValue = this.state.endValue;
|
||||
if (!startValue || !endValue) {
|
||||
return false;
|
||||
}
|
||||
return startValue.valueOf() > endValue.valueOf();
|
||||
}
|
||||
|
||||
disabledEndDate = (endValue) => {
|
||||
const startValue = this.state.startValue;
|
||||
if (!endValue || !startValue) {
|
||||
return false;
|
||||
}
|
||||
return endValue.valueOf() <= startValue.valueOf();
|
||||
}
|
||||
|
||||
onChange = (field, value) => {
|
||||
this.setState({
|
||||
[field]: value,
|
||||
});
|
||||
}
|
||||
|
||||
onStartChange = (value) => {
|
||||
this.onChange('startValue', value);
|
||||
}
|
||||
|
||||
onEndChange = (value) => {
|
||||
this.onChange('endValue', value);
|
||||
}
|
||||
|
||||
handleStartOpenChange = (open) => {
|
||||
if (!open) {
|
||||
this.setState({ endOpen: true });
|
||||
}
|
||||
}
|
||||
|
||||
handleEndOpenChange = (open) => {
|
||||
this.setState({ endOpen: open });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { startValue, endValue, endOpen } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<DatePicker
|
||||
disabledDate={this.disabledStartDate}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value={startValue}
|
||||
placeholder="Start"
|
||||
onChange={this.onStartChange}
|
||||
onOpenChange={this.handleStartOpenChange}
|
||||
/>
|
||||
<DatePicker
|
||||
disabledDate={this.disabledEndDate}
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value={endValue}
|
||||
placeholder="End"
|
||||
onChange={this.onEndChange}
|
||||
open={endOpen}
|
||||
onOpenChange={this.handleEndOpenChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<DateRange />, mountNode);
|
||||
````
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
order: 3
|
||||
title:
|
||||
zh-CN: 日期时间选择
|
||||
en-US: Choose Time
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
增加选择时间功能,当 `showTime` 为一个对象时,其属性会传递给内建的 `TimePicker`。
|
||||
|
||||
## en-US
|
||||
|
||||
This property provide an additional time selection. When `showTime` is an Object, its properties will be passed on to built-in `TimePicker`.
|
||||
|
||||
````jsx
|
||||
import { DatePicker } from 'antd';
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
function onChange(value, dateString) {
|
||||
console.log('Selected Time: ', value);
|
||||
console.log('Formatted Selected Time: ', dateString);
|
||||
}
|
||||
|
||||
function onOk(value) {
|
||||
console.log('onOk: ', value);
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<DatePicker
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="Select Time"
|
||||
onChange={onChange}
|
||||
onOk={onOk}
|
||||
/>
|
||||
<br />
|
||||
<RangePicker
|
||||
showTime={{ format: 'HH:mm' }}
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
placeholder={['Start Time', 'End Time']}
|
||||
onChange={onChange}
|
||||
onOk={onOk}
|
||||
/>
|
||||
</div>
|
||||
, mountNode);
|
||||
````
|
|
@ -0,0 +1,116 @@
|
|||
---
|
||||
category: Components
|
||||
type: Data Entry
|
||||
title: DatePicker
|
||||
---
|
||||
|
||||
To select or input a date.
|
||||
|
||||
## When To Use
|
||||
|
||||
By clicking the input box, you can select a date from a popup calendar.
|
||||
|
||||
## API
|
||||
|
||||
There are four kinds of picker:
|
||||
|
||||
- DatePicker
|
||||
- MonthPicker
|
||||
- RangePicker
|
||||
- WeekPicker
|
||||
|
||||
**Note:** Part of locale of DatePicker, MonthPicker, RangePicker, WeekPicker is read from value. So, please set the locale of moment correctly.
|
||||
|
||||
```jsx
|
||||
// The default locale is en-US, if you want to use other locale, just set locale in entry file globaly.
|
||||
// import moment from 'moment';
|
||||
// import 'moment/locale/zh-cn';
|
||||
// moment.locale('zh-cn');
|
||||
|
||||
<DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
|
||||
```
|
||||
|
||||
### Common API
|
||||
|
||||
The following APIs are shared by DatePicker, MonthPicker, RangePicker, WeekPicker.
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| allowClear | Whether to show clear button | boolean | true |
|
||||
| autoFocus | get focus when component mounted | boolean | false |
|
||||
| className | picker className | string | '' |
|
||||
| dateRender | custom rendering function for date cells | function(currentDate: moment, today: moment) => React.ReactNode | - |
|
||||
| disabled | determine whether the DatePicker is disabled | boolean | false |
|
||||
| disabledDate | specify the date that cannot be selected | (currentDate: moment) => boolean | - |
|
||||
| getCalendarContainer | to set the container of the floating layer, while the default is to create a `div` element in `body` | function(trigger) | - |
|
||||
| locale | localization configuration | object | [default](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) |
|
||||
| open | open state of picker | boolean | - |
|
||||
| placeholder | placeholder of date input | string\|RangePicker\[] | - |
|
||||
| popupStyle | to customize the style of the popup calendar | object | {} |
|
||||
| size | determine the size of the input box, the height of `large` and `small`, are 40px and 24px respectively, while default size is 32px | string | - |
|
||||
| style | to customize the style of the input box | object | {} |
|
||||
| onOpenChange | a callback function, can be executed whether the popup calendar is popped up or closed | function(status) | - |
|
||||
|
||||
### Common Methods
|
||||
|
||||
| Name | Description |
|
||||
| ---- | ----------- |
|
||||
| blur() | remove focus |
|
||||
| focus() | get focus |
|
||||
|
||||
### DatePicker
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| defaultValue | to set default date | [moment](http://momentjs.com/) | - |
|
||||
| disabledTime | to specify the time that cannot be selected | function(date) | - |
|
||||
| format | to set the date format, refer to [moment.js](http://momentjs.com/) | string | "YYYY-MM-DD" |
|
||||
| renderExtraFooter | render extra footer in panel | () => React.ReactNode | - |
|
||||
| showTime | to provide an additional time selection | object\|boolean | [TimePicker Options](/components/time-picker/#API) |
|
||||
| showTime.defaultValue | to set default time of selected date, [demo](https://ant.design/components/date-picker/#components-date-picker-demo-disabled-date) | [moment](http://momentjs.com/) | moment() |
|
||||
| showToday | whether to show "Today" button | boolean | true |
|
||||
| value | to set date | [moment](http://momentjs.com/) | - |
|
||||
| onCalendarChange | a callback function, can be executed when the start time or the end time of the range is changing | function(dates: [moment, moment], dateStrings: [string, string]) | 无 |
|
||||
| onChange | a callback function, can be executed when the selected time is changing | function(date: moment, dateString: string) | - |
|
||||
| onOk | callback when click ok button | function() | - |
|
||||
|
||||
### MonthPicker
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| defaultValue | to set default date | [moment](http://momentjs.com/) | - |
|
||||
| format | to set the date format, refer to [moment.js](http://momentjs.com/) | string | "YYYY-MM" |
|
||||
| monthCellContentRender | Custom month cell content render method | function(date, locale): ReactNode | - |
|
||||
| renderExtraFooter | render extra footer in panel | () => React.ReactNode | - |
|
||||
| value | to set date | [moment](http://momentjs.com/) | - |
|
||||
| onChange | a callback function, can be executed when the selected time is changing | function(date: moment, dateString: string) | - |
|
||||
|
||||
### WeekPicker
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| defaultValue | to set default date | [moment](http://momentjs.com/) | - |
|
||||
| format | to set the date format, refer to [moment.js](http://momentjs.com/) | string | "YYYY-wo" |
|
||||
| value | to set date | [moment](http://momentjs.com/) | - |
|
||||
| onChange | a callback function, can be executed when the selected time is changing | function(date: moment, dateString: string) | - |
|
||||
|
||||
### RangePicker
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| defaultValue | to set default date | \[[moment](http://momentjs.com/), [moment](http://momentjs.com/)] | - |
|
||||
| disabledTime | to specify the time that cannot be selected | function(dates: [moment, moment], partial: `'start'|'end'`) | - |
|
||||
| format | to set the date format | string | "YYYY-MM-DD HH:mm:ss" |
|
||||
| ranges | preseted ranges for quick selection | { \[range: string\]: [moment](http://momentjs.com/)\[] } \| () => { \[range: string\]: [moment](http://momentjs.com/)\[] } | - |
|
||||
| renderExtraFooter | render extra footer in panel | () => React.ReactNode | - |
|
||||
| showTime | to provide an additional time selection | object\|boolean | [TimePicker Options](/components/time-picker/#API) |
|
||||
| showTime.defaultValue | to set default time of selected date, [demo](https://ant.design/components/date-picker/#components-date-picker-demo-disabled-date) | [moment](http://momentjs.com/)\[] | [moment(), moment()] |
|
||||
| value | to set date | \[[moment](http://momentjs.com/), [moment](http://momentjs.com/)] | - |
|
||||
| onChange | a callback function, can be executed when the selected time is changing | function(dates: [moment, moment], dateStrings: [string, string]) | - |
|
||||
| onOk | callback when click ok button | function() | - |
|
||||
|
||||
<style>
|
||||
.code-box-demo .ant-calendar-picker {
|
||||
margin: 0 8px 12px 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,18 @@
|
|||
import VcCalendar from '../vc-calendar'
|
||||
import MonthCalendar from '../vc-calendar/src/MonthCalendar'
|
||||
import createPicker from './createPicker'
|
||||
import wrapPicker from './wrapPicker'
|
||||
import RangePicker from './RangePicker'
|
||||
import WeekPicker from './WeekPicker'
|
||||
|
||||
const DatePicker = wrapPicker(createPicker(VcCalendar))
|
||||
|
||||
const MonthPicker = wrapPicker(createPicker(MonthCalendar), 'YYYY-MM')
|
||||
|
||||
Object.assign(DatePicker, {
|
||||
RangePicker: wrapPicker(RangePicker),
|
||||
MonthPicker,
|
||||
WeekPicker: wrapPicker(WeekPicker, 'YYYY-wo'),
|
||||
})
|
||||
|
||||
export default DatePicker
|
|
@ -0,0 +1,117 @@
|
|||
---
|
||||
category: Components
|
||||
type: Data Entry
|
||||
title: DatePicker
|
||||
subtitle: 日期选择框
|
||||
---
|
||||
|
||||
输入或选择日期的控件。
|
||||
|
||||
## 何时使用
|
||||
|
||||
当用户需要输入一个日期,可以点击标准输入框,弹出日期面板进行选择。
|
||||
|
||||
## API
|
||||
|
||||
日期类组件包括以下四种形式。
|
||||
|
||||
- DatePicker
|
||||
- MonthPicker
|
||||
- RangePicker
|
||||
- WeekPicker
|
||||
|
||||
**注意:**DatePicker、MonthPicker、RangePicker、WeekPicker 部分 locale 是从 value 中读取,所以请先正确设置 moment 的 locale。
|
||||
|
||||
```jsx
|
||||
// 默认语言为 en-US,如果你需要设置其他语言,推荐在入口文件全局设置 locale
|
||||
// import moment from 'moment';
|
||||
// import 'moment/locale/zh-cn';
|
||||
// moment.locale('zh-cn');
|
||||
|
||||
<DatePicker defaultValue={moment('2015-01-01', 'YYYY-MM-DD')} />
|
||||
```
|
||||
|
||||
### 共同的 API
|
||||
|
||||
以下 API 为 DatePicker、MonthPicker、RangePicker, WeekPicker 共享的 API。
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| allowClear | 是否显示清除按钮 | boolean | true |
|
||||
| autoFocus | 自动获取焦点 | boolean | false |
|
||||
| className | 选择器 className | string | '' |
|
||||
| dateRender | 自定义日期单元格的内容 | function(currentDate: moment, today: moment) => React.ReactNode | - |
|
||||
| disabled | 禁用 | boolean | false |
|
||||
| disabledDate | 不可选择的日期 | (currentDate: moment) => boolean | 无 |
|
||||
| getCalendarContainer | 定义浮层的容器,默认为 body 上新建 div | function(trigger) | 无 |
|
||||
| locale | 国际化配置 | object | [默认配置](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) |
|
||||
| open | 控制弹层是否展开 | boolean | - |
|
||||
| placeholder | 输入框提示文字 | string\|RangePicker\[] | - |
|
||||
| popupStyle | 格外的弹出日历样式 | object | {} |
|
||||
| size | 输入框大小,`large` 高度为 40px,`small` 为 24px,默认是 32px | string | 无 |
|
||||
| style | 自定义输入框样式 | object | {} |
|
||||
| onOpenChange | 弹出日历和关闭日历的回调 | function(status) | 无 |
|
||||
|
||||
### 共同的方法
|
||||
|
||||
| 名称 | 描述 |
|
||||
| --- | --- |
|
||||
| blur() | 移除焦点 |
|
||||
| focus() | 获取焦点 |
|
||||
|
||||
### DatePicker
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| defaultValue | 默认日期 | [moment](http://momentjs.com/) | 无 |
|
||||
| disabledTime | 不可选择的时间 | function(date) | 无 |
|
||||
| format | 展示的日期格式,配置参考 [moment.js](http://momentjs.com/) | string | "YYYY-MM-DD" |
|
||||
| renderExtraFooter | 在面板中添加额外的页脚 | () => React.ReactNode | - |
|
||||
| showTime | 增加时间选择功能 | Object\|boolean | [TimePicker Options](/components/time-picker/#API) |
|
||||
| showTime.defaultValue | 设置用户选择日期时默认的时分秒,[例子](https://ant.design/components/date-picker/#components-date-picker-demo-disabled-date) | [moment](http://momentjs.com/) | moment() |
|
||||
| showToday | 是否展示“今天”按钮 | boolean | true |
|
||||
| value | 日期 | [moment](http://momentjs.com/) | 无 |
|
||||
| onChange | 时间发生变化的回调 | function(date: moment, dateString: string) | 无 |
|
||||
| onOk | 点击确定按钮的回调 | function() | - |
|
||||
|
||||
### MonthPicker
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| defaultValue | 默认日期 | [moment](http://momentjs.com/) | 无 |
|
||||
| format | 展示的日期格式,配置参考 [moment.js](http://momentjs.com/) | string | "YYYY-MM" |
|
||||
| monthCellContentRender | 自定义的月份内容渲染方法 | function(date, locale): ReactNode | - |
|
||||
| renderExtraFooter | 在面板中添加额外的页脚 | () => React.ReactNode | - |
|
||||
| value | 日期 | [moment](http://momentjs.com/) | 无 |
|
||||
| onChange | 时间发生变化的回调,发生在用户选择时间时 | function(date: moment, dateString: string) | - |
|
||||
|
||||
### WeekPicker
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| defaultValue | 默认日期 | [moment](http://momentjs.com/) | - |
|
||||
| format | 展示的日期格式,配置参考 [moment.js](http://momentjs.com/) | string | "YYYY-wo" |
|
||||
| value | 日期 | [moment](http://momentjs.com/) | - |
|
||||
| onChange | 时间发生变化的回调,发生在用户选择时间时 | function(date: moment, dateString: string) | - |
|
||||
|
||||
### RangePicker
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| defaultValue | 默认日期 | [moment](http://momentjs.com/)\[] | 无 |
|
||||
| disabledTime | 不可选择的时间 | function(dates: [moment, moment], partial: `'start'|'end'`) | 无 |
|
||||
| format | 展示的日期格式 | string | "YYYY-MM-DD HH:mm:ss" |
|
||||
| ranges | 预设时间范围快捷选择 | { \[range: string\]: [moment](http://momentjs.com/)\[] } \| () => { \[range: string\]: [moment](http://momentjs.com/)\[] } | 无 |
|
||||
| renderExtraFooter | 在面板中添加额外的页脚 | () => React.ReactNode | - |
|
||||
| showTime | 增加时间选择功能 | Object\|boolean | [TimePicker Options](/components/time-picker/#API) |
|
||||
| showTime.defaultValue | 设置用户选择日期时默认的时分秒,[例子](https://ant.design/components/date-picker/#components-date-picker-demo-disabled-date) | [moment](http://momentjs.com/)\[] | [moment(), moment()] |
|
||||
| value | 日期 | [moment](http://momentjs.com/)\[] | 无 |
|
||||
| onCalendarChange | 待选日期发生变化的回调 | function(dates: [moment, moment], dateStrings: [string, string]) | 无 |
|
||||
| onChange | 日期范围发生变化的回调 | function(dates: [moment, moment], dateStrings: [string, string]) | 无 |
|
||||
| onOk | 点击确定按钮的回调 | function() | - |
|
||||
|
||||
<style>
|
||||
.code-box-demo .ant-calendar-picker {
|
||||
margin: 0 8px 12px 0;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,90 @@
|
|||
import * as React from 'react';
|
||||
import * as moment from 'moment';
|
||||
import { TimePickerProps } from '../time-picker';
|
||||
|
||||
export interface PickerProps {
|
||||
id?: number | string;
|
||||
prefixCls?: string;
|
||||
inputPrefixCls?: string;
|
||||
format?: string;
|
||||
disabled?: boolean;
|
||||
allowClear?: boolean;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
popupStyle?: React.CSSProperties;
|
||||
locale?: any;
|
||||
size?: 'large' | 'small' | 'default';
|
||||
getCalendarContainer?: (triggerNode: Element) => HTMLElement;
|
||||
open?: boolean;
|
||||
onOpenChange?: (status: boolean) => void;
|
||||
disabledDate?: (current: moment.Moment) => boolean;
|
||||
renderExtraFooter?: () => React.ReactNode;
|
||||
dateRender?: (current: moment.Moment, today: moment.Moment) => React.ReactNode;
|
||||
}
|
||||
|
||||
export interface SinglePickerProps {
|
||||
value?: moment.Moment;
|
||||
defaultValue?: moment.Moment;
|
||||
defaultPickerValue?: moment.Moment;
|
||||
onChange?: (date: moment.Moment, dateString: string) => void;
|
||||
}
|
||||
|
||||
export interface DatePickerProps extends PickerProps, SinglePickerProps {
|
||||
className?: string;
|
||||
showTime?: TimePickerProps | boolean;
|
||||
showToday?: boolean;
|
||||
open?: boolean;
|
||||
disabledTime?: (current: moment.Moment) => {
|
||||
disabledHours?: () => number[],
|
||||
disabledMinutes?: () => number[],
|
||||
disabledSeconds?: () => number[],
|
||||
};
|
||||
onOpenChange?: (status: boolean) => void;
|
||||
onOk?: (selectedTime: moment.Moment) => void;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export interface MonthPickerProps extends PickerProps, SinglePickerProps {
|
||||
className?: string;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export type RangePickerValue =
|
||||
undefined[] |
|
||||
[moment.Moment] |
|
||||
[undefined, moment.Moment] |
|
||||
[moment.Moment, moment.Moment];
|
||||
export type RangePickerPresetRange = RangePickerValue | (() => RangePickerValue);
|
||||
|
||||
export interface RangePickerProps extends PickerProps {
|
||||
className?: string;
|
||||
value?: RangePickerValue;
|
||||
defaultValue?: RangePickerValue;
|
||||
defaultPickerValue?: RangePickerValue;
|
||||
onChange?: (dates: RangePickerValue, dateStrings: [string, string]) => void;
|
||||
onCalendarChange?: (dates: RangePickerValue, dateStrings: [string, string]) => void;
|
||||
onOk?: (selectedTime: moment.Moment) => void;
|
||||
showTime?: TimePickerProps | boolean;
|
||||
ranges?: {
|
||||
[range: string]: RangePickerPresetRange,
|
||||
};
|
||||
placeholder?: [string, string];
|
||||
mode?: string | string[];
|
||||
disabledTime?: (current: moment.Moment, type: string) => {
|
||||
disabledHours?: () => number[],
|
||||
disabledMinutes?: () => number[],
|
||||
disabledSeconds?: () => number[],
|
||||
};
|
||||
onPanelChange?: (value?: RangePickerValue, mode?: string | string[]) => void;
|
||||
}
|
||||
|
||||
export interface WeexPickerProps extends PickerProps, SinglePickerProps {
|
||||
className?: string;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export interface DatePickerDecorator extends React.ClassicComponentClass<DatePickerProps> {
|
||||
RangePicker: React.ClassicComponentClass<RangePickerProps>;
|
||||
MonthPicker: React.ClassicComponentClass<MonthPickerProps>;
|
||||
WeekPicker: React.ClassicComponentClass<WeexPickerProps>;
|
||||
}
|
|
@ -0,0 +1,336 @@
|
|||
.calendarPanelHeader(@calendar-prefix-cls) {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
user-select: none;
|
||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
|
||||
a:hover {
|
||||
color: @link-hover-color;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-century-select,
|
||||
.@{calendar-prefix-cls}-decade-select,
|
||||
.@{calendar-prefix-cls}-year-select,
|
||||
.@{calendar-prefix-cls}-month-select {
|
||||
padding: 0 2px;
|
||||
font-weight: 500;
|
||||
display: inline-block;
|
||||
color: @heading-color;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-century-select-arrow,
|
||||
.@{calendar-prefix-cls}-decade-select-arrow,
|
||||
.@{calendar-prefix-cls}-year-select-arrow,
|
||||
.@{calendar-prefix-cls}-month-select-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-prev-century-btn,
|
||||
.@{calendar-prefix-cls}-next-century-btn,
|
||||
.@{calendar-prefix-cls}-prev-decade-btn,
|
||||
.@{calendar-prefix-cls}-next-decade-btn,
|
||||
.@{calendar-prefix-cls}-prev-month-btn,
|
||||
.@{calendar-prefix-cls}-next-month-btn,
|
||||
.@{calendar-prefix-cls}-prev-year-btn,
|
||||
.@{calendar-prefix-cls}-next-year-btn {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
color: @text-color-secondary;
|
||||
font-family: Arial, "Hiragino Sans GB", "Microsoft Yahei", "Microsoft Sans Serif", sans-serif;
|
||||
padding: 0 5px;
|
||||
font-size: 16px;
|
||||
display: inline-block;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-prev-century-btn,
|
||||
.@{calendar-prefix-cls}-prev-decade-btn,
|
||||
.@{calendar-prefix-cls}-prev-year-btn {
|
||||
left: 7px;
|
||||
|
||||
&:after {
|
||||
content: '«';
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-next-century-btn,
|
||||
.@{calendar-prefix-cls}-next-decade-btn,
|
||||
.@{calendar-prefix-cls}-next-year-btn {
|
||||
right: 7px;
|
||||
|
||||
&:after {
|
||||
content: '»';
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-prev-month-btn {
|
||||
left: 29px;
|
||||
|
||||
&:after {
|
||||
content: '‹';
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-next-month-btn {
|
||||
right: 29px;
|
||||
|
||||
&:after {
|
||||
content: '›';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls} {
|
||||
position: relative;
|
||||
outline: none;
|
||||
width: 280px;
|
||||
border: @border-width-base @border-style-base #fff;
|
||||
list-style: none;
|
||||
font-size: @font-size-base;
|
||||
text-align: left;
|
||||
background-color: @component-background;
|
||||
border-radius: @border-radius-base;
|
||||
box-shadow: @box-shadow-base;
|
||||
background-clip: padding-box;
|
||||
line-height: @line-height-base;
|
||||
|
||||
&-input-wrap {
|
||||
height: 34px;
|
||||
padding: 6px @control-padding-horizontal - 2px;
|
||||
border-bottom: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
|
||||
&-input {
|
||||
border: 0;
|
||||
width: 100%;
|
||||
cursor: auto;
|
||||
outline: 0;
|
||||
height: 22px;
|
||||
color: @input-color;
|
||||
background: @input-bg;
|
||||
.placeholder;
|
||||
}
|
||||
|
||||
&-week-number {
|
||||
width: 286px;
|
||||
|
||||
&-cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
&-header {
|
||||
.calendarPanelHeader(@calendar-prefix-cls);
|
||||
}
|
||||
|
||||
&-body {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
max-width: 100%;
|
||||
background-color: transparent;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
border: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&-calendar-table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&-column-header {
|
||||
line-height: 18px;
|
||||
width: 33px;
|
||||
padding: 6px 0;
|
||||
text-align: center;
|
||||
.@{calendar-prefix-cls}-column-header-inner {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
&-week-number-header {
|
||||
.@{calendar-prefix-cls}-column-header-inner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-cell {
|
||||
padding: 3px 0;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
&-date {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
color: @text-color;
|
||||
border-radius: @border-radius-sm;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 22px;
|
||||
border: @border-width-base @border-style-base transparent;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&-panel {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: @item-hover-bg;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: #fff;
|
||||
background: @primary-5;
|
||||
}
|
||||
}
|
||||
|
||||
&-today &-date {
|
||||
border-color: @primary-color;
|
||||
font-weight: bold;
|
||||
color: @primary-color;
|
||||
}
|
||||
|
||||
&-last-month-cell &-date,
|
||||
&-next-month-btn-day &-date {
|
||||
color: @disabled-color;
|
||||
}
|
||||
|
||||
&-selected-day &-date {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
border: @border-width-base @border-style-base transparent;
|
||||
|
||||
&:hover {
|
||||
background: @primary-color;
|
||||
}
|
||||
}
|
||||
|
||||
&-disabled-cell &-date {
|
||||
cursor: not-allowed;
|
||||
color: #bcbcbc;
|
||||
background: @disabled-bg;
|
||||
border-radius: 0;
|
||||
width: auto;
|
||||
border: @border-width-base @border-style-base transparent;
|
||||
|
||||
&:hover {
|
||||
background: @disabled-bg;
|
||||
}
|
||||
}
|
||||
&-disabled-cell&-today &-date {
|
||||
position: relative;
|
||||
margin-right: 5px;
|
||||
padding-left: 5px;
|
||||
&:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: 5px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: @border-width-base @border-style-base #bcbcbc;
|
||||
border-radius: @border-radius-sm;
|
||||
}
|
||||
}
|
||||
|
||||
&-disabled-cell-first-of-row &-date {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
&-disabled-cell-last-of-row &-date {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
&-footer {
|
||||
border-top: @border-width-base @border-style-base @border-color-split;
|
||||
line-height: 38px;
|
||||
padding: 0 12px;
|
||||
&:empty {
|
||||
border-top: 0;
|
||||
}
|
||||
&-btn {
|
||||
text-align: center;
|
||||
display: block;
|
||||
}
|
||||
&-extra + &-btn {
|
||||
border-top: @border-width-base @border-style-base @border-color-split;
|
||||
margin: 0 -12px;
|
||||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-today-btn,
|
||||
.@{calendar-prefix-cls}-clear-btn {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
margin: 0 0 0 8px;
|
||||
&-disabled {
|
||||
color: @disabled-color;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&:only-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-clear-btn {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
text-indent: -76px;
|
||||
overflow: hidden;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
top: 7px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-clear-btn:after {
|
||||
.iconfont-font("\e62e");
|
||||
font-size: @font-size-base;
|
||||
color: @disabled-color;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
width: 20px;
|
||||
text-indent: 43px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-clear-btn:hover:after {
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-ok-btn {
|
||||
.btn;
|
||||
.btn-primary;
|
||||
.button-size(@btn-height-sm; @btn-padding-sm; @font-size-base; @border-radius-base);
|
||||
line-height: @btn-height-sm - 2px;
|
||||
|
||||
&-disabled {
|
||||
.button-color(@btn-disable-color; @btn-disable-bg; @btn-disable-border);
|
||||
cursor: not-allowed;
|
||||
&:hover {
|
||||
.button-color(@btn-disable-color; @btn-disable-bg; @btn-disable-border);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
.@{calendar-prefix-cls}-decade-panel {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
background: @component-background;
|
||||
border-radius: @border-radius-base;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-decade-panel-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-decade-panel-header {
|
||||
.calendarPanelHeader(~"@{calendar-prefix-cls}-decade-panel");
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-decade-panel-body {
|
||||
height: ~"calc(100% - 40px)";
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-decade-panel-table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-decade-panel-cell {
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-decade-panel-decade {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
padding: 0 6px;
|
||||
border-radius: @border-radius-sm;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: @item-hover-bg;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-decade-panel-selected-cell .@{calendar-prefix-cls}-decade-panel-decade {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-decade-panel-last-century-cell,
|
||||
.@{calendar-prefix-cls}-decade-panel-next-century-cell {
|
||||
.@{calendar-prefix-cls}-decade-panel-decade {
|
||||
user-select: none;
|
||||
color: @disabled-color;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
.@{calendar-prefix-cls}-month-panel {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
border-radius: @border-radius-base;
|
||||
background: @component-background;
|
||||
outline: none;
|
||||
|
||||
> div { // TODO: this is a useless wrapper, and we need to remove it in rc-calendar
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-month-panel-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-month-panel-header {
|
||||
.calendarPanelHeader(~"@{calendar-prefix-cls}-month-panel");
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-month-panel-body {
|
||||
height: ~"calc(100% - 40px)";
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-month-panel-table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-month-panel-selected-cell .@{calendar-prefix-cls}-month-panel-month {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-month-panel-cell {
|
||||
text-align: center;
|
||||
|
||||
&-disabled .@{calendar-prefix-cls}-month-panel-month {
|
||||
&,
|
||||
&:hover {
|
||||
cursor: not-allowed;
|
||||
color: #bcbcbc;
|
||||
background: @disabled-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-month-panel-month {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
padding: 0 8px;
|
||||
border-radius: @border-radius-sm;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: @item-hover-bg;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
.@{calendar-prefix-cls}-month {
|
||||
.@{calendar-prefix-cls}-month-header-wrap {
|
||||
position: relative;
|
||||
height: 288px;
|
||||
}
|
||||
.@{calendar-prefix-cls}-month-panel,
|
||||
.@{calendar-prefix-cls}-year-panel {
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
@import "../../button/style/mixin";
|
||||
|
||||
.@{calendar-prefix-cls}-picker-container {
|
||||
.reset-component;
|
||||
position: absolute;
|
||||
z-index: @zindex-picker;
|
||||
|
||||
&.slide-up-enter.slide-up-enter-active&-placement-topLeft,
|
||||
&.slide-up-enter.slide-up-enter-active&-placement-topRight,
|
||||
&.slide-up-appear.slide-up-appear-active&-placement-topLeft,
|
||||
&.slide-up-appear.slide-up-appear-active&-placement-topRight {
|
||||
animation-name: antSlideDownIn;
|
||||
}
|
||||
|
||||
&.slide-up-enter.slide-up-enter-active&-placement-bottomLeft,
|
||||
&.slide-up-enter.slide-up-enter-active&-placement-bottomRight,
|
||||
&.slide-up-appear.slide-up-appear-active&-placement-bottomLeft,
|
||||
&.slide-up-appear.slide-up-appear-active&-placement-bottomRight {
|
||||
animation-name: antSlideUpIn;
|
||||
}
|
||||
|
||||
&.slide-up-leave.slide-up-leave-active&-placement-topLeft,
|
||||
&.slide-up-leave.slide-up-leave-active&-placement-topRight {
|
||||
animation-name: antSlideDownOut;
|
||||
}
|
||||
|
||||
&.slide-up-leave.slide-up-leave-active&-placement-bottomLeft,
|
||||
&.slide-up-leave.slide-up-leave-active&-placement-bottomRight {
|
||||
animation-name: antSlideUpOut;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-picker {
|
||||
.reset-component;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
outline: none;
|
||||
transition: opacity 0.3s;
|
||||
|
||||
&-input {
|
||||
outline: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:hover &-input:not(.@{ant-prefix}-input-disabled) {
|
||||
border-color: @primary-color;
|
||||
}
|
||||
|
||||
&:focus &-input:not(.@{ant-prefix}-input-disabled) {
|
||||
.active();
|
||||
}
|
||||
|
||||
&-clear,
|
||||
&-icon {
|
||||
position: absolute;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
right: @control-padding-horizontal;
|
||||
top: 50%;
|
||||
margin-top: -7px;
|
||||
line-height: 14px;
|
||||
font-size: @font-size-sm;
|
||||
transition: all .3s;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
&-clear {
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
color: @disabled-color;
|
||||
background: @input-bg;
|
||||
pointer-events: none;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover &-clear {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
color: @disabled-color;
|
||||
&:after {
|
||||
content: "\e6bb";
|
||||
font-family: "anticon";
|
||||
font-size: @font-size-base;
|
||||
color: @disabled-color;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&-small &-clear,
|
||||
&-small &-icon {
|
||||
right: @control-padding-horizontal-sm;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
@input-box-height: 34px;
|
||||
|
||||
.@{calendar-prefix-cls}-range-picker-input {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
height: 99%;
|
||||
outline: 0;
|
||||
width: 44%;
|
||||
text-align: center;
|
||||
.placeholder();
|
||||
|
||||
&[disabled] {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range-picker-separator {
|
||||
color: @text-color-secondary;
|
||||
width: 10px;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range {
|
||||
width: 552px;
|
||||
overflow: hidden;
|
||||
|
||||
.@{calendar-prefix-cls}-date-panel {
|
||||
&::after {
|
||||
content: ".";
|
||||
display: block;
|
||||
height: 0;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
&-part {
|
||||
width: 50%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-left {
|
||||
float: left;
|
||||
.@{calendar-prefix-cls} {
|
||||
&-time-picker-inner {
|
||||
border-right: 1.5px solid @border-color-split;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-right {
|
||||
float: right;
|
||||
.@{calendar-prefix-cls} {
|
||||
&-time-picker-inner {
|
||||
border-left: 1.5px solid @border-color-split;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-middle {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
width: 20px;
|
||||
margin-left: -132px;
|
||||
text-align: center;
|
||||
height: @input-box-height;
|
||||
line-height: @input-box-height;
|
||||
color: @text-color-secondary;
|
||||
}
|
||||
|
||||
&-right .@{calendar-prefix-cls}-date-input-wrap {
|
||||
margin-left: -118px;
|
||||
}
|
||||
|
||||
&.@{calendar-prefix-cls}-time &-middle {
|
||||
margin-left: -12px;
|
||||
}
|
||||
|
||||
&.@{calendar-prefix-cls}-time &-right .@{calendar-prefix-cls}-date-input-wrap {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-input-wrap {
|
||||
position: relative;
|
||||
height: @input-box-height;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-input,
|
||||
.@{calendar-timepicker-prefix-cls}-input {
|
||||
.input;
|
||||
height: @input-height-sm;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-timepicker-prefix-cls}-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.@{calendar-prefix-cls}-week-number {
|
||||
width: 574px;
|
||||
|
||||
.@{calendar-prefix-cls}-range-part {
|
||||
width: 286px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel,
|
||||
.@{calendar-prefix-cls}-month-panel,
|
||||
.@{calendar-prefix-cls}-decade-panel {
|
||||
top: @input-box-height;
|
||||
}
|
||||
.@{calendar-prefix-cls}-month-panel .@{calendar-prefix-cls}-year-panel {
|
||||
top: 0;
|
||||
}
|
||||
.@{calendar-prefix-cls}-decade-panel-table,
|
||||
.@{calendar-prefix-cls}-year-panel-table,
|
||||
.@{calendar-prefix-cls}-month-panel-table {
|
||||
height: 208px;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-in-range-cell {
|
||||
border-radius: 0;
|
||||
position: relative;
|
||||
> div {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
&:before {
|
||||
content: '';
|
||||
display: block;
|
||||
background: @item-active-bg;
|
||||
border-radius: 0;
|
||||
border: 0;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
bottom: 4px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// `div` for selector specificity
|
||||
div&-quick-selector {
|
||||
text-align: left;
|
||||
|
||||
> a {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls},
|
||||
.@{calendar-prefix-cls}-month-panel,
|
||||
.@{calendar-prefix-cls}-year-panel {
|
||||
&-header {
|
||||
border-bottom: 0;
|
||||
}
|
||||
&-body {
|
||||
border-top: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
}
|
||||
|
||||
&.@{calendar-prefix-cls}-time {
|
||||
.@{calendar-timepicker-prefix-cls} {
|
||||
height: 207px;
|
||||
width: 100%;
|
||||
top: 68px;
|
||||
z-index: 2; // cover .ant-calendar-range .ant-calendar-in-range-cell > div (z-index: 1)
|
||||
&-panel {
|
||||
height: 267px;
|
||||
margin-top: -34px;
|
||||
}
|
||||
|
||||
&-inner {
|
||||
padding-top: 40px;
|
||||
height: 100%;
|
||||
background: none;
|
||||
}
|
||||
|
||||
&-combobox {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
background-color: @component-background;
|
||||
border-top: @border-width-base @border-style-base @border-color-split;
|
||||
}
|
||||
&-select {
|
||||
height: 100%;
|
||||
ul {
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.@{calendar-prefix-cls}-footer .@{calendar-prefix-cls}-time-picker-btn {
|
||||
margin-right: 8px;
|
||||
}
|
||||
.@{calendar-prefix-cls}-today-btn {
|
||||
margin: 8px 12px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
&-with-ranges.@{calendar-prefix-cls}-time .@{calendar-timepicker-prefix-cls} {
|
||||
height: 247px;
|
||||
&-panel {
|
||||
height: 281px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-range.@{calendar-prefix-cls}-show-time-picker {
|
||||
.@{calendar-prefix-cls}-body {
|
||||
border-top-color: transparent;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
.@{calendar-timepicker-prefix-cls} {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 40px;
|
||||
background-color: @component-background;
|
||||
|
||||
&-panel {
|
||||
z-index: @zindex-picker;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-inner {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
outline: none;
|
||||
list-style: none;
|
||||
font-size: @font-size-base;
|
||||
text-align: left;
|
||||
background-color: @component-background;
|
||||
background-clip: padding-box;
|
||||
line-height: 1.5;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
&-combobox {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-column-1,
|
||||
&-column-1 &-select {
|
||||
width: 100%;
|
||||
}
|
||||
&-column-2 &-select {
|
||||
width: 50%;
|
||||
}
|
||||
&-column-3 &-select {
|
||||
width: 33.33%;
|
||||
}
|
||||
&-column-4 &-select {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
&-input-wrap {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&-select {
|
||||
float: left;
|
||||
font-size: @font-size-base;
|
||||
border-right: @border-width-base @border-style-base @border-color-split;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
position: relative; // Fix chrome weird render bug
|
||||
height: 226px;
|
||||
|
||||
&:hover {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
max-height: 206px;
|
||||
}
|
||||
|
||||
li {
|
||||
text-align: center;
|
||||
list-style: none;
|
||||
box-sizing: content-box;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
li:last-child:after {
|
||||
content: '';
|
||||
height: 202px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
li:hover {
|
||||
background: @item-hover-bg;
|
||||
}
|
||||
|
||||
li&-option-selected {
|
||||
background: @time-picker-selected-bg;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
li&-option-disabled {
|
||||
color: @btn-disable-color;
|
||||
&:hover {
|
||||
background: transparent;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-time {
|
||||
.@{calendar-prefix-cls}-day-select {
|
||||
padding: 0 2px;
|
||||
font-weight: 500;
|
||||
display: inline-block;
|
||||
color: @heading-color;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-footer {
|
||||
position: relative;
|
||||
height: auto;
|
||||
|
||||
&-btn {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-today-btn {
|
||||
float: left;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-time-picker-btn {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
|
||||
&-disabled {
|
||||
color: @disabled-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
.@{calendar-prefix-cls}-week-number {
|
||||
&-cell {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.@{calendar-prefix-cls}-body tr {
|
||||
transition: all .3s;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: @primary-1;
|
||||
}
|
||||
&.@{calendar-prefix-cls}-active-week {
|
||||
background: @primary-2;
|
||||
font-weight: bold;
|
||||
}
|
||||
.@{calendar-prefix-cls}-selected-day .@{calendar-prefix-cls}-date,
|
||||
.@{calendar-prefix-cls}-selected-day:hover .@{calendar-prefix-cls}-date {
|
||||
background: transparent;
|
||||
color: @text-color;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
.@{calendar-prefix-cls}-year-panel {
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
border-radius: @border-radius-base;
|
||||
background: @component-background;
|
||||
outline: none;
|
||||
|
||||
> div { // TODO: this is a useless wrapper, and we need to remove it in rc-calendar
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel-header {
|
||||
.calendarPanelHeader(~"@{calendar-prefix-cls}-year-panel");
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel-body {
|
||||
height: ~"calc(100% - 40px)";
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel-table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel-cell {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel-year {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color: @text-color;
|
||||
background: transparent;
|
||||
text-align: center;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
padding: 0 8px;
|
||||
border-radius: @border-radius-sm;
|
||||
transition: background 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: @item-hover-bg;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel-selected-cell .@{calendar-prefix-cls}-year-panel-year {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
|
||||
&:hover {
|
||||
background: @primary-color;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.@{calendar-prefix-cls}-year-panel-last-decade-cell,
|
||||
.@{calendar-prefix-cls}-year-panel-next-decade-cell {
|
||||
.@{calendar-prefix-cls}-year-panel-year {
|
||||
user-select: none;
|
||||
color: @disabled-color;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import '../../style/index.less'
|
||||
import './index.less'
|
||||
|
||||
// style dependencies
|
||||
import '../../input/style'
|
||||
import '../../time-picker/style'
|
|
@ -0,0 +1,17 @@
|
|||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
@import "../../input/style/mixin";
|
||||
@import "../../button/style/mixin";
|
||||
|
||||
@calendar-prefix-cls: ~"@{ant-prefix}-calendar";
|
||||
@calendar-timepicker-prefix-cls: ~"@{ant-prefix}-calendar-time-picker";
|
||||
|
||||
@import "Picker";
|
||||
@import "Calendar";
|
||||
@import "RangePicker";
|
||||
@import "TimePicker";
|
||||
@import "MonthPanel";
|
||||
@import "YearPanel";
|
||||
@import "DecadePanel";
|
||||
@import "MonthPicker";
|
||||
@import "WeekPicker";
|
|
@ -0,0 +1,161 @@
|
|||
<script>
|
||||
import TimePickerPanel from '../vc-time-picker/src/Panel'
|
||||
import classNames from 'classnames'
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver'
|
||||
import { generateShowHourMinuteSecond } from '../time-picker'
|
||||
import enUS from './locale/en_US'
|
||||
import { getOptionProps } from '../_util/props-util'
|
||||
|
||||
function getColumns ({ showHour, showMinute, showSecond, use12Hours }) {
|
||||
let column = 0
|
||||
if (showHour) {
|
||||
column += 1
|
||||
}
|
||||
if (showMinute) {
|
||||
column += 1
|
||||
}
|
||||
if (showSecond) {
|
||||
column += 1
|
||||
}
|
||||
if (use12Hours) {
|
||||
column += 1
|
||||
}
|
||||
return column
|
||||
}
|
||||
|
||||
export default function wrapPicker (Picker, defaultFormat) {
|
||||
return {
|
||||
props: {
|
||||
|
||||
},
|
||||
// static defaultProps = {
|
||||
// format: defaultFormat || 'YYYY-MM-DD',
|
||||
// transitionName: 'slide-up',
|
||||
// popupStyle: {},
|
||||
// onChange() {
|
||||
// },
|
||||
// onOk() {
|
||||
// },
|
||||
// onOpenChange() {
|
||||
// },
|
||||
// locale: {},
|
||||
// prefixCls: 'ant-calendar',
|
||||
// inputPrefixCls: 'ant-input',
|
||||
// };
|
||||
|
||||
mounted () {
|
||||
const { autoFocus, disabled } = this
|
||||
if (autoFocus && !disabled) {
|
||||
this.$nextTick(() => {
|
||||
this.focus()
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleOpenChange (open) {
|
||||
this.$emit('openChange', open)
|
||||
},
|
||||
|
||||
handleFocus (e) {
|
||||
this.$emit('focus', e)
|
||||
},
|
||||
|
||||
handleBlur (e) {
|
||||
this.$emit('blur', e)
|
||||
},
|
||||
|
||||
focus () {
|
||||
this.$refs.picker.focus()
|
||||
},
|
||||
|
||||
blur () {
|
||||
this.$refs.picker.blur()
|
||||
},
|
||||
|
||||
getDefaultLocale () {
|
||||
const result = {
|
||||
...enUS,
|
||||
...this.locale,
|
||||
}
|
||||
result.lang = {
|
||||
...result.lang,
|
||||
...(this.locale || {}).lang,
|
||||
}
|
||||
return result
|
||||
},
|
||||
|
||||
renderPicker (locale, localeCode) {
|
||||
const props = getOptionProps(this)
|
||||
const { prefixCls, inputPrefixCls, size, showTime, disabled } = props
|
||||
const pickerClass = classNames(`${prefixCls}-picker`, {
|
||||
[`${prefixCls}-picker-${size}`]: !!size,
|
||||
})
|
||||
const pickerInputClass = classNames(`${prefixCls}-picker-input`, inputPrefixCls, {
|
||||
[`${inputPrefixCls}-lg`]: size === 'large',
|
||||
[`${inputPrefixCls}-sm`]: size === 'small',
|
||||
[`${inputPrefixCls}-disabled`]: disabled,
|
||||
})
|
||||
|
||||
const timeFormat = (showTime && showTime.format) || 'HH:mm:ss'
|
||||
const vcTimePickerProps = {
|
||||
...generateShowHourMinuteSecond(timeFormat),
|
||||
format: timeFormat,
|
||||
use12Hours: (showTime && showTime.use12Hours),
|
||||
}
|
||||
const columns = getColumns(vcTimePickerProps)
|
||||
const timePickerCls = `${prefixCls}-time-picker-column-${columns}`
|
||||
const timePickerPanelProps = {
|
||||
props: {
|
||||
...vcTimePickerProps,
|
||||
...showTime,
|
||||
prefixCls: `${prefixCls}-time-picker`,
|
||||
placeholder: locale.timePickerLocale.placeholder,
|
||||
transitionName: 'slide-up',
|
||||
},
|
||||
class: timePickerCls,
|
||||
}
|
||||
const timePicker = showTime ? (
|
||||
<TimePickerPanel
|
||||
{...timePickerPanelProps}
|
||||
/>
|
||||
) : null
|
||||
const pickerProps = {
|
||||
props: {
|
||||
...props,
|
||||
pickerClass,
|
||||
pickerInputClass,
|
||||
locale,
|
||||
localeCode,
|
||||
timePicker,
|
||||
},
|
||||
on: {
|
||||
...this.$listeners,
|
||||
openChange: this.handleOpenChange,
|
||||
focus: this.handleFocus,
|
||||
blur: this.handleBlur,
|
||||
},
|
||||
ref: 'picker',
|
||||
|
||||
}
|
||||
return (
|
||||
<Picker
|
||||
{...pickerProps}
|
||||
/>
|
||||
)
|
||||
},
|
||||
},
|
||||
|
||||
render () {
|
||||
return (
|
||||
<LocaleReceiver
|
||||
componentName='DatePicker'
|
||||
defaultLocale={this.getDefaultLocale}
|
||||
scopedSlots={
|
||||
{ default: this.renderPicker }
|
||||
}
|
||||
/>
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -36,7 +36,9 @@ export default {
|
|||
},
|
||||
|
||||
render () {
|
||||
return this.children(this.getLocale(), this.getLocaleCode())
|
||||
const { $scopedSlots } = this
|
||||
const children = this.children || $scopedSlots.default
|
||||
return children(this.getLocale(), this.getLocaleCode())
|
||||
},
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue