Skip to content

Commit

Permalink
feat(DatePicker): add needConfirm api (#3011)
Browse files Browse the repository at this point in the history
* feat(datepicker): add needConfirm api

* fix(date-picker): fix missing attribute
  • Loading branch information
HaixingOoO authored Jul 29, 2024
1 parent 7c004d2 commit d5da695
Show file tree
Hide file tree
Showing 11 changed files with 74 additions and 17 deletions.
27 changes: 27 additions & 0 deletions src/date-picker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { parseToDayjs, getDefaultFormat, formatTime, formatDate } from '../_comm
import { subtractMonth, addMonth, extractTimeObj, covertToDate } from '../_common/js/date-picker/utils';
import { datePickerDefaultProps } from './defaultProps';
import useDefaultProps from '../hooks/useDefaultProps';
import useLatest from '../hooks/useLatest';
import useUpdateEffect from '../hooks/useUpdateEffect';

export interface DatePickerProps extends TdDatePickerProps, StyledProps {}

Expand All @@ -32,6 +34,7 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
defaultTime,
timePickerProps,
presetsPlacement,
needConfirm,
onPick,
} = props;

Expand Down Expand Up @@ -63,6 +66,29 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
enableTimePicker,
});

const onTriggerNeedConfirm = useLatest(() => {
if (!needConfirm && enableTimePicker && !popupVisible) {
const nextValue = formatDate(inputValue, { format });
if (nextValue) {
onChange(formatDate(inputValue, { format, targetFormat: valueType }), {
dayjsValue: parseToDayjs(inputValue, format),
trigger: 'confirm',
});
} else {
setInputValue(
formatDate(value, {
format,
}),
);
}
}
});

useUpdateEffect(() => {
// 日期时间选择器不需要点击确认按钮完成的操作
onTriggerNeedConfirm.current();
}, [popupVisible]);

useEffect(() => {
// 面板展开重置数据
// Date valueType、week mode 、quarter mode nad empty string don't need to be parsed
Expand Down Expand Up @@ -212,6 +238,7 @@ const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>((originalProps, r
enableTimePicker,
presetsPlacement,
popupVisible,
needConfirm,
onCellClick,
onCellMouseEnter,
onCellMouseLeave,
Expand Down
8 changes: 7 additions & 1 deletion src/date-picker/DatePickerPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import useDefaultProps from '../hooks/useDefaultProps';
export interface DatePickerPanelProps extends TdDatePickerPanelProps, StyledProps {}

const DatePickerPanel = forwardRef<HTMLDivElement, DatePickerPanelProps>((originalProps, ref) => {
const props = useDefaultProps<DatePickerPanelProps>(originalProps, { mode: 'date', defaultValue: '' });
const props = useDefaultProps<DatePickerPanelProps>(originalProps, {
mode: 'date',
defaultValue: '',
needConfirm: true,
});
const { value, onChange, time, setTime, month, setMonth, year, setYear, cacheValue, setCacheValue } =
useSingleValue(props);

Expand All @@ -31,6 +35,7 @@ const DatePickerPanel = forwardRef<HTMLDivElement, DatePickerPanelProps>((origin
presets,
timePickerProps,
presetsPlacement,
needConfirm,
onPanelClick,
} = props;

Expand Down Expand Up @@ -174,6 +179,7 @@ const DatePickerPanel = forwardRef<HTMLDivElement, DatePickerPanelProps>((origin
timePickerProps,
enableTimePicker,
presetsPlacement,
needConfirm,
onCellClick,
onJumperClick,
onConfirmClick,
Expand Down
6 changes: 4 additions & 2 deletions src/date-picker/base/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import Button from '../../button';
import useConfig from '../../hooks/useConfig';
import { TdDatePickerProps, TdDateRangePickerProps, DateValue } from '../type';

interface DatePickerFooterProps extends Pick<TdDatePickerProps, 'enableTimePicker' | 'presetsPlacement'> {
interface DatePickerFooterProps
extends Pick<TdDatePickerProps, 'enableTimePicker' | 'presetsPlacement' | 'needConfirm'> {
presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets'];
onPresetClick?: Function;
onConfirmClick?: Function;
Expand All @@ -25,6 +26,7 @@ const DatePickerFooter = (props: DatePickerFooterProps) => {
presets,
onPresetClick,
selectedValue,
needConfirm,
} = props;

const footerClass = classNames(
Expand All @@ -49,7 +51,7 @@ const DatePickerFooter = (props: DatePickerFooterProps) => {
))}
</div>
}
{enableTimePicker && (
{enableTimePicker && needConfirm && (
<Button disabled={!selectedValue} size="small" theme="primary" onClick={(e) => onConfirmClick({ e })}>
{confirmText}
</Button>
Expand Down
1 change: 1 addition & 0 deletions src/date-picker/date-picker.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ firstDayOfWeek | Number | 7 | options: 1/2/3/4/5/6/7 | N
format | String | 'YYYY-MM-DD' | \- | N
inputProps | Object | - | Typescript:`InputProps`[Input API Documents](./input?tab=api)[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N
mode | String | date | options: year/quarter/month/week/date | N
needConfirm | Boolean | true | whether a confirmation button needs to be clicked to complete the action in the date-time picker scenario, default is true | N
placeholder | String / Array | undefined | Typescript:`string` | N
popupProps | Object | - | Typescript:`PopupProps`[Popup API Documents](./popup?tab=api)[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N
prefixIcon | TElement | - | Typescript:`TNode`[see more ts definition](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N
Expand Down
2 changes: 2 additions & 0 deletions src/date-picker/date-picker.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
:: BASE_DOC ::

## API

### DatePicker Props

名称 | 类型 | 默认值 | 说明 | 必传
Expand All @@ -18,6 +19,7 @@ firstDayOfWeek | Number | 7 | 第一天从星期几开始。可选项:1/2/3/4/
format | String | 'YYYY-MM-DD' | 仅用于格式化日期显示的格式,不影响日期值。注意和 `valueType` 的区别,`valueType`会直接决定日期值 `value` 的格式。全局配置默认为:'YYYY-MM-DD',[详细文档](https://day.js.org/docs/en/display/format) | N
inputProps | Object | - | 透传给输入框(Input)组件的参数。TS 类型:`InputProps`[Input API Documents](./input?tab=api)[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N
mode | String | date | 选择器模式。可选项:year/quarter/month/week/date | N
needConfirm | Boolean | true | 决定在日期时间选择器的场景下是否需要点击确认按钮才完成选择动作,默认为`true` | N
placeholder | String / Array | undefined | 占位符。TS 类型:`string` | N
popupProps | Object | - | 透传给 popup 组件的参数。TS 类型:`PopupProps`[Popup API Documents](./popup?tab=api)[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/date-picker/type.ts) | N
prefixIcon | TElement | - | 用于自定义组件前置图标。TS 类型:`TNode`[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N
Expand Down
1 change: 1 addition & 0 deletions src/date-picker/defaultProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const datePickerDefaultProps: TdDatePickerProps = {
enableTimePicker: false,
format: undefined,
mode: 'date',
needConfirm: true,
placeholder: undefined,
presetsPlacement: 'bottom',
size: 'medium',
Expand Down
11 changes: 8 additions & 3 deletions src/date-picker/panel/ExtraContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ import type { SinglePanelProps } from './SinglePanel';
import type { TdDatePickerProps, TdDateRangePickerProps, DateValue } from '../type';

export interface ExtraContentProps
extends Pick<SinglePanelProps, 'enableTimePicker' | 'presetsPlacement' | 'onPresetClick' | 'onConfirmClick'> {
extends Pick<
SinglePanelProps,
'enableTimePicker' | 'presetsPlacement' | 'onPresetClick' | 'onConfirmClick' | 'needConfirm'
> {
selectedValue?: DateValue;
presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets'];
}

export default function ExtraContent(props: ExtraContentProps) {
const { presets, enableTimePicker, presetsPlacement, onPresetClick, onConfirmClick, selectedValue } = props;
const { presets, enableTimePicker, presetsPlacement, onPresetClick, onConfirmClick, selectedValue, needConfirm } =
props;

const showPanelFooter = enableTimePicker || presets;
const showPanelFooter = (enableTimePicker && needConfirm) || presets;

return showPanelFooter ? (
<DateFooter
Expand All @@ -22,6 +26,7 @@ export default function ExtraContent(props: ExtraContentProps) {
onConfirmClick={onConfirmClick}
presetsPlacement={presetsPlacement}
selectedValue={selectedValue}
needConfirm={needConfirm}
/>
) : null;
}
5 changes: 4 additions & 1 deletion src/date-picker/panel/RangePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const RangePanel = forwardRef<HTMLDivElement, RangePanelProps>((originalProps, r
panelPreselection: true,
enableTimePicker: false,
presetsPlacement: 'bottom',
needConfirm: true,
});
const {
value = [],
Expand All @@ -52,7 +53,7 @@ const RangePanel = forwardRef<HTMLDivElement, RangePanelProps>((originalProps, r
disableDate: disableDateFromProps,
firstDayOfWeek = globalDatePickerConfig.firstDayOfWeek,
isFirstValueSelected,

needConfirm,
style,
className,
activeIndex,
Expand Down Expand Up @@ -153,6 +154,7 @@ const RangePanel = forwardRef<HTMLDivElement, RangePanelProps>((originalProps, r
onPresetClick={onPresetClick}
onConfirmClick={onConfirmClick}
presetsPlacement={presetsPlacement}
needConfirm={needConfirm}
/>
) : null}
<div className={`${panelName}-content-wrapper`}>
Expand Down Expand Up @@ -200,6 +202,7 @@ const RangePanel = forwardRef<HTMLDivElement, RangePanelProps>((originalProps, r
onPresetClick={onPresetClick}
onConfirmClick={onConfirmClick}
presetsPlacement={presetsPlacement}
needConfirm={needConfirm}
/>
) : null}
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/date-picker/panel/SinglePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const SinglePanel = forwardRef<HTMLDivElement, SinglePanelProps>((originalProps,
mode,
presetsPlacement,
firstDayOfWeek = globalDatePickerConfig.firstDayOfWeek,

needConfirm,
style,
className,
year,
Expand Down Expand Up @@ -95,6 +95,7 @@ const SinglePanel = forwardRef<HTMLDivElement, SinglePanelProps>((originalProps,
onPresetClick: props.onPresetClick,
onConfirmClick: props.onConfirmClick,
selectedValue: props.value,
needConfirm,
};

return (
Expand Down
11 changes: 11 additions & 0 deletions src/date-picker/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ export interface TdDatePickerProps {
* @default date
*/
mode?: 'year' | 'quarter' | 'month' | 'week' | 'date';
/**
* 决定在日期时间选择器的场景下是否需要点击确认按钮才完成选择动作,默认为`true`
* @default true
*/
needConfirm?: boolean;
/**
* 占位符
*/
Expand Down Expand Up @@ -195,6 +200,11 @@ export interface TdDateRangePickerProps {
* @default date
*/
mode?: 'year' | 'quarter' | 'month' | 'week' | 'date';
/**
* 决定在日期时间区间选择器的场景下是否需要点击确认按钮才完成选择动作,默认为 `true`
* @default true
*/
needConfirm?: boolean;
/**
* 在开始日期选中之前,面板是否显示预选状态,即是否高亮预选日期
* @default true
Expand Down Expand Up @@ -327,6 +337,7 @@ export interface TdDatePickerPanelProps
| 'presets'
| 'presetsPlacement'
| 'timePickerProps'
| 'needConfirm'
> {
/**
* 时间选择器默认值,当 value/defaultValue 未设置值时有效
Expand Down
16 changes: 7 additions & 9 deletions src/hooks/useUpdateEffect.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { useRef, DependencyList } from 'react';
import useLayoutEffect from './useLayoutEffect';
import { useEffect } from 'react';
import type { DependencyList, EffectCallback } from 'react';
import useIsFirstRender from './useIsFirstRender';

const useUpdateEffect = (callback: () => void, dependency: DependencyList) => {
const ref = useRef(false);
const useUpdateEffect = (callback: EffectCallback, dependency: DependencyList) => {
const isFirstRender = useIsFirstRender();

useLayoutEffect(() => {
if (!ref.current) {
ref.current = true;
return undefined;
}
useEffect(() => {
if (isFirstRender) return;

return callback();
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down

0 comments on commit d5da695

Please sign in to comment.