You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

170 lines
6.8 KiB

import * as React from 'react';
import { forwardRef, useContext } from 'react';
import classNames from 'classnames';
import CalendarOutlined from '@ant-design/icons/CalendarOutlined';
import ClockCircleOutlined from '@ant-design/icons/ClockCircleOutlined';
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import SwapRightOutlined from '@ant-design/icons/SwapRightOutlined';
import { RangePicker as RCRangePicker } from 'rc-picker';
import type { GenerateConfig } from 'rc-picker/lib/generate/index';
import enUS from '../locale/en_US';
import type { ConfigConsumerProps } from '../../config-provider';
import { ConfigContext } from '../../config-provider';
import SizeContext from '../../config-provider/SizeContext';
import DisabledContext from '../../config-provider/DisabledContext';
import LocaleReceiver from '../../locale-provider/LocaleReceiver';
import { getRangePlaceholder, transPlacement2DropdownAlign } from '../util';
import type { PickerLocale, RangePickerProps } from '.';
import { Components, getTimeProps } from '.';
import { FormItemInputContext } from '../../form/context';
import { getMergedStatus, getStatusClassNames } from '../../_util/statusUtils';
import useStyle from '../style';
import type { PickerComponentClass } from './interface';
export default function generateRangePicker<DateType>(
generateConfig: GenerateConfig<DateType>,
): PickerComponentClass<RangePickerProps<DateType>> {
type InternalRangePickerProps = RangePickerProps<DateType> & {
hashId?: string;
};
class RangePicker extends React.Component<InternalRangePickerProps> {
static contextType = ConfigContext;
context: ConfigConsumerProps;
pickerRef = React.createRef<RCRangePicker<DateType>>();
focus = () => {
if (this.pickerRef.current) {
this.pickerRef.current.focus();
}
};
blur = () => {
if (this.pickerRef.current) {
this.pickerRef.current.blur();
}
};
renderPicker = (contextLocale: PickerLocale) => {
const locale = { ...contextLocale, ...this.props.locale };
const { getPrefixCls, direction, getPopupContainer } = this.context;
const {
prefixCls,
getPopupContainer: customGetPopupContainer,
className,
placement,
size: customizeSize,
disabled: customDisabled,
bordered = true,
placeholder,
status: customStatus,
dropdownClassName,
hashId,
...restProps
} = this.props;
const { format, showTime, picker } = this.props as any;
let additionalOverrideProps: any = {};
additionalOverrideProps = {
...additionalOverrideProps,
...(showTime ? getTimeProps({ format, picker, ...showTime }) : {}),
...(picker === 'time' ? getTimeProps({ format, ...this.props, picker }) : {}),
};
const rootPrefixCls = getPrefixCls();
return (
<DisabledContext.Consumer>
{disabled => {
const mergedDisabled = customDisabled || disabled;
return (
<SizeContext.Consumer>
{size => {
const mergedSize = customizeSize || size;
return (
<FormItemInputContext.Consumer>
{({ hasFeedback, status: contextStatus, feedbackIcon }) => {
const suffixNode = (
<>
{picker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />}
{hasFeedback && feedbackIcon}
</>
);
return (
<RCRangePicker<DateType>
separator={
<span aria-label="to" className={`${prefixCls}-separator`}>
<SwapRightOutlined />
</span>
}
disabled={mergedDisabled}
ref={this.pickerRef}
dropdownAlign={transPlacement2DropdownAlign(direction, placement)}
placeholder={getRangePlaceholder(picker, locale, placeholder)}
suffixIcon={suffixNode}
clearIcon={<CloseCircleFilled />}
prevIcon={<span className={`${prefixCls}-prev-icon`} />}
nextIcon={<span className={`${prefixCls}-next-icon`} />}
superPrevIcon={<span className={`${prefixCls}-super-prev-icon`} />}
superNextIcon={<span className={`${prefixCls}-super-next-icon`} />}
allowClear
transitionName={`${rootPrefixCls}-slide-up`}
{...restProps}
{...additionalOverrideProps}
className={classNames(
{
[`${prefixCls}-${mergedSize}`]: mergedSize,
[`${prefixCls}-borderless`]: !bordered,
},
getStatusClassNames(
prefixCls as string,
getMergedStatus(contextStatus, customStatus),
hasFeedback,
),
hashId,
className,
)}
locale={locale!.lang}
prefixCls={prefixCls}
getPopupContainer={customGetPopupContainer || getPopupContainer}
generateConfig={generateConfig}
components={Components}
direction={direction}
dropdownClassName={classNames(hashId, dropdownClassName)}
/>
);
}}
</FormItemInputContext.Consumer>
);
}}
</SizeContext.Consumer>
);
}}
</DisabledContext.Consumer>
);
};
render() {
return (
<LocaleReceiver componentName="DatePicker" defaultLocale={enUS}>
{this.renderPicker}
</LocaleReceiver>
);
}
}
return forwardRef<RangePicker, RangePickerProps<DateType>>((props, ref) => {
const { prefixCls: customizePrefixCls } = props;
const { getPrefixCls } = useContext(ConfigContext);
const prefixCls = getPrefixCls('picker', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls);
return wrapSSR(<RangePicker {...props} prefixCls={prefixCls} ref={ref} hashId={hashId} />);
}) as unknown as PickerComponentClass<RangePickerProps<DateType>>;
}