ant-design/components/date-picker/generatePicker/generateSinglePicker.tsx
二货爱吃白萝卜 18e85a7b81
feat: New Picker (#46982)
* chore: init

* chore: link picker

* chore: move files

* chore: update style

* chore: update types

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: fix test case

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: update snapshot

* chore: clesn up useless types

* chore: update types

* chore: fix types

* chore: fix types

* chore: fix types

* chore: fix types

* chore: fix types

* chore: fix types

* chore: fix types

* chore: fix types

* chore: fix types

* chore: update style

* chore: clean up

* chore: update types

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: update snapshot

* fix: format

* chore: update deps

* chore: feature merge master (#46794)

* fix: Fix typo s/Notificaiton/Notification/ (#46775)

* docs: supplement form preserve field description (#46788)

close https://github.com/ant-design/ant-design/issues/46773

* docs: tweak changelog drawer width in small screen (#46791)

* docs: Update compatible-style.zh-CN.md (#46790)

Signed-off-by: afc163 <afc163@gmail.com>

---------

Signed-off-by: afc163 <afc163@gmail.com>
Co-authored-by: hugo-syn <61210734+hugo-syn@users.noreply.github.com>
Co-authored-by: Shunze Chen <qianlonwork@outlook.com>
Co-authored-by: afc163 <afc163@gmail.com>

* chore: update locale size

* chore: lock dumi

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: update snapshot

* chore: bump version

* test: update snapshot

* test: update snapshot

* chore: bump version

* chore: update limit

* test: update snapshot

* docs: update 7 days sample

* chore: rm useless style

* chore: clean up style

* docs: add buddihist era demo

* refactor: interface

* chore: add multiple types

* docs: add demo

* chore: init style

* chore: init style

* chore: fill style

* chore: fill style

* chore: style

* chore: size of it

* chore: size style

* docs: add align demo

* docs: needConfirm

* chore: fix showWeek style

* test: update snapshot

* chore: fix ts

* chore: fix ts

* chore: fix ts

* chore: fix ts

* fix: week style

* docs: update dayjs note

* fix: style missing

* chore: fix footer extra style missing

* test: update snapshot

* test: update snapshot

* test: update snapshot

* test: update snapshot

* chore: demo update

* docs: update demo

* docs: min & max date

* test: update snapshot

* docs: add order

* chore: update deps

* test: update snapshot

* test: update snapshot

* chore: adjust style

* chore: clean up style

* test: update snapshot

* chore: fix comment

* chore: update align

* chore: bump rc-picker

* test: update snapshot

* test: update snapshot

* test: update snapshot

---------

Signed-off-by: afc163 <afc163@gmail.com>
Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: hugo-syn <61210734+hugo-syn@users.noreply.github.com>
Co-authored-by: Shunze Chen <qianlonwork@outlook.com>
Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: lijianan <574980606@qq.com>
2024-01-29 15:34:48 +08:00

211 lines
8.0 KiB
TypeScript

import * as React from 'react';
import { forwardRef, useContext, useImperativeHandle } from 'react';
import CalendarOutlined from '@ant-design/icons/CalendarOutlined';
import ClockCircleOutlined from '@ant-design/icons/ClockCircleOutlined';
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled';
import classNames from 'classnames';
import RCPicker, { type PickerRef } from 'rc-picker';
import type { GenerateConfig } from 'rc-picker/lib/generate/index';
import type { PickerMode } from 'rc-picker/lib/interface';
import { useZIndex } from '../../_util/hooks/useZIndex';
import { getMergedStatus, getStatusClassNames } from '../../_util/statusUtils';
import type { AnyObject } from '../../_util/type';
import { devUseWarning } from '../../_util/warning';
import { ConfigContext } from '../../config-provider';
import DisabledContext from '../../config-provider/DisabledContext';
import useCSSVarCls from '../../config-provider/hooks/useCSSVarCls';
import useSize from '../../config-provider/hooks/useSize';
import { FormItemInputContext } from '../../form/context';
import useVariant from '../../form/hooks/useVariants';
import { useLocale } from '../../locale';
import { NoCompactStyle, useCompactItemContext } from '../../space/Compact';
import enUS from '../locale/en_US';
import useStyle from '../style';
import { getPlaceholder, mergeAllowClear, transPlacement2DropdownAlign } from '../util';
import type { PickerProps, PickerPropsWithMultiple } from './interface';
import useComponents from './useComponents';
export default function generatePicker<DateType extends AnyObject>(
generateConfig: GenerateConfig<DateType>,
) {
type DatePickerProps = PickerProps<DateType>;
type TimePickerProps = Omit<PickerProps<DateType>, 'picker' | 'showTime'>;
function getPicker<InnerPickerProps extends DatePickerProps>(
picker?: PickerMode,
displayName?: string,
) {
const consumerName = displayName === 'TimePicker' ? 'timePicker' : 'datePicker';
const Picker = forwardRef<PickerRef, InnerPickerProps>((props, ref) => {
const {
prefixCls: customizePrefixCls,
getPopupContainer: customizeGetPopupContainer,
components,
style,
className,
rootClassName,
size: customizeSize,
bordered,
placement,
placeholder,
popupClassName,
dropdownClassName,
disabled: customDisabled,
status: customStatus,
clearIcon,
allowClear,
variant: customVariant,
...restProps
} = props;
const {
getPrefixCls,
direction,
getPopupContainer,
// Consume different styles according to different names
[consumerName]: consumerStyle,
} = useContext(ConfigContext);
const prefixCls = getPrefixCls('picker', customizePrefixCls);
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
const innerRef = React.useRef<PickerRef>(null);
const [variant, enableVariantCls] = useVariant(customVariant, bordered);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
useImperativeHandle(ref, () => innerRef.current!);
const additionalProps = {
showToday: true,
};
const mergedPicker = picker || props.picker;
const rootPrefixCls = getPrefixCls();
// =================== Warning =====================
if (process.env.NODE_ENV !== 'production') {
const warning = devUseWarning(displayName! || 'DatePicker');
warning(
picker !== 'quarter',
'deprecated',
`DatePicker.${displayName} is legacy usage. Please use DatePicker[picker='${picker}'] directly.`,
);
warning.deprecated(!dropdownClassName, 'dropdownClassName', 'popupClassName');
warning.deprecated(!('bordered' in props), 'bordered', 'variant');
}
// ================== components ==================
const mergedComponents = useComponents(components);
// ===================== Size =====================
const mergedSize = useSize((ctx) => customizeSize ?? compactSize ?? ctx);
// ===================== Disabled =====================
const disabled = React.useContext(DisabledContext);
const mergedDisabled = customDisabled ?? disabled;
// ===================== FormItemInput =====================
const formItemContext = useContext(FormItemInputContext);
const { hasFeedback, status: contextStatus, feedbackIcon } = formItemContext;
const suffixNode = (
<>
{mergedPicker === 'time' ? <ClockCircleOutlined /> : <CalendarOutlined />}
{hasFeedback && feedbackIcon}
</>
);
const [contextLocale] = useLocale('DatePicker', enUS);
const locale = { ...contextLocale, ...props.locale! };
// ============================ zIndex ============================
const [zIndex] = useZIndex('DatePicker', props.popupStyle?.zIndex as number);
return wrapCSSVar(
<NoCompactStyle>
<RCPicker<DateType>
ref={innerRef}
placeholder={getPlaceholder(locale, mergedPicker, placeholder)}
suffixIcon={suffixNode}
dropdownAlign={transPlacement2DropdownAlign(direction, placement)}
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`} />}
transitionName={`${rootPrefixCls}-slide-up`}
picker={picker}
{...additionalProps}
{...restProps}
locale={locale!.lang}
className={classNames(
{
[`${prefixCls}-${mergedSize}`]: mergedSize,
[`${prefixCls}-${variant}`]: enableVariantCls,
},
getStatusClassNames(
prefixCls,
getMergedStatus(contextStatus, customStatus),
hasFeedback,
),
hashId,
compactItemClassnames,
consumerStyle?.className,
className,
cssVarCls,
rootCls,
rootClassName,
)}
style={{ ...consumerStyle?.style, ...style }}
prefixCls={prefixCls}
getPopupContainer={customizeGetPopupContainer || getPopupContainer}
generateConfig={generateConfig}
components={mergedComponents}
direction={direction}
disabled={mergedDisabled}
classNames={{
popup: classNames(
hashId,
cssVarCls,
rootCls,
rootClassName,
popupClassName || dropdownClassName,
),
}}
styles={{
popup: {
...props.popupStyle,
zIndex,
},
}}
allowClear={mergeAllowClear(allowClear, clearIcon, <CloseCircleFilled />)}
/>
</NoCompactStyle>,
);
});
if (process.env.NODE_ENV !== 'production' && displayName) {
Picker.displayName = displayName;
}
return Picker as unknown as (<ValueType = DateType>(
props: PickerPropsWithMultiple<DateType, InnerPickerProps, ValueType>,
) => React.ReactElement) & { displayName?: string };
}
const DatePicker = getPicker<DatePickerProps>();
const WeekPicker = getPicker<Omit<DatePickerProps, 'picker'>>('week', 'WeekPicker');
const MonthPicker = getPicker<Omit<DatePickerProps, 'picker'>>('month', 'MonthPicker');
const YearPicker = getPicker<Omit<DatePickerProps, 'picker'>>('year', 'YearPicker');
const TimePicker = getPicker<Omit<TimePickerProps, 'picker'>>('time', 'TimePicker');
const QuarterPicker = getPicker<Omit<TimePickerProps, 'picker'>>('quarter', 'QuarterPicker');
return { DatePicker, WeekPicker, MonthPicker, YearPicker, TimePicker, QuarterPicker };
}