Skip to content

Commit

Permalink
fix(date-picker): fix date-picker month/year panel cannt back to date…
Browse files Browse the repository at this point in the history
…panel error (#1993)
  • Loading branch information
gavin-hao committed Apr 26, 2022
1 parent 9f09f5f commit 59638ee
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 61 deletions.
51 changes: 27 additions & 24 deletions src/date-range-picker/demos/DateRangePicker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { Meta, Story } from '@storybook/react/types-6-0';
import { action } from '@storybook/addon-actions';
import { DownOutlined, FoldOutlined } from '@gio-design/icons';
import { format,isBefore, startOfToday, subMonths } from 'date-fns';
import { format, isEqual, startOfDay, startOfToday, startOfWeek, subMonths } from 'date-fns';
import Docs from './DateRangePickerPage';
import DateRangePicker, { DateRangePickerProps, StaticDateRangePickerProps } from '../index';
import '../style';
Expand All @@ -26,7 +26,7 @@ export default {
} as Meta;

const Template: Story<DateRangePickerProps> = (args) => (
<DateRangePicker {...args} />
<DateRangePicker {...args} />
);

const ControlledTemplate: Story<DateRangePickerProps> = (args) => {
Expand All @@ -36,14 +36,14 @@ const ControlledTemplate: Story<DateRangePickerProps> = (args) => {
};
return (
<div style={{ width: 280 }}>
<DateRangePicker value={TimeRange} onSelect={onSelect} trigger={
<DateRangePicker value={TimeRange} onSelect={onSelect} trigger={
<Button type='secondary'>
{TimeRange[0] && format(TimeRange[0],'yyyy/MM/dd')}
{TimeRange[0] && format(TimeRange[0], 'yyyy/MM/dd')}
-
{TimeRange[1] && format(TimeRange[1],'yyyy/MM/dd')}
{TimeRange[1] && format(TimeRange[1], 'yyyy/MM/dd')}
</Button>
}
{...args}
{...args}
/>
</div>
);
Expand All @@ -53,17 +53,17 @@ export const CustomTrigger = ControlledTemplate.bind({});

export const Default = ControlledTemplate.bind({});
Default.args = {
placeholder:'选择日期范围',
trigger:null,
format:"yyyy/MM/dd",
disabled:false,
size:'normal',
placeholder: '选择日期范围',
trigger: null,
format: "yyyy/MM/dd",
disabled: false,
size: 'normal',
};

export const Format = Template.bind({})
Format.args={
Format.args = {
defaultValue: [new Date(), new Date()],
format:'yyyy--MM--dd'
format: 'yyyy--MM--dd'
}

export const PrefixAndSuffix = Template.bind({});
Expand All @@ -75,31 +75,31 @@ PrefixAndSuffix.args = {

export const OnSelectAndOnClose = Template.bind({});
OnSelectAndOnClose.args = {
allowClear:'true',
onSelect:action('onSelect'),
onChange:action('onChange'),
allowClear: 'true',
onSelect: action('onSelect'),
onChange: action('onChange'),
onClear: action('onClear'),
};

export const AllowClear = Template.bind({});
AllowClear.args = {
allowClear:true,
allowClear: true,
onClear: () => {
action('onClear')
},
};

export const Size = Template.bind({});
Size.args = {
defaultValue:[new Date(), new Date()],
size:'small'
defaultValue: [new Date(), new Date()],
size: 'small'
};

export const Disabled = Template.bind({});
Disabled.args = {
placeholder:'选择器Disabled',
placeholder: '选择器Disabled',
onSelect: action('selected:'),
disabled:true,
disabled: true,
disabledDate: (current: Date) => current.getTime() > new Date().getTime(),
};

Expand All @@ -110,11 +110,14 @@ const StaticTemplate: Story<StaticDateRangePickerProps> = (args) => (
export const StaticBasic = StaticTemplate.bind({});
StaticBasic.args = {};

export const StaticDisabledDate = StaticTemplate.bind({});
StaticDisabledDate.args = {
disabledDate: (date: Date) => isBefore(date, startOfToday()),
export const StaticDisabledDate: Story<StaticDateRangePickerProps> = () => {
const disabledDate = (date: Date) => isEqual(startOfWeek(date), startOfDay(date))
return <DateRangePicker.Static
disabledDate={disabledDate}
/>
};


export const StaticViewDates = StaticTemplate.bind({});
StaticViewDates.args = {
defaultViewDates: [subMonths(startOfToday(), 1), startOfToday()],
Expand Down
15 changes: 8 additions & 7 deletions src/past-time-picker/demos/PastTimePicker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ Quick.args = {
value: 'day:8,1',
};
export const QuickOptionsFilter = Template.bind({});
QuickOptionsFilter.args={
quickOptionsFilter:(s: { value: string; }) =>
QuickOptionsFilter.args = {
quickOptionsFilter: (s: { value: string; }) =>
['day:2,1', 'day:8,1', 'day:15,1', 'day:31,1'].includes(
s.value,
)
Expand All @@ -50,7 +50,7 @@ Relative.args = {
export const Absolute = Template.bind({});
Absolute.args = {
value: `abs:${getTime(subMonths(startOfToday(), 1))},${getTime(startOfToday())}`,
onRangeSelect:(date:any,index:number) => console.log(date,index)
onRangeSelect: (date: any, index: number) => console.log(date, index)
};

export const Experiment = Template.bind({});
Expand Down Expand Up @@ -87,10 +87,11 @@ Modes.args = {
modes: ['since', 'relative'],
};

export const DisabledDate = Template.bind({});
DisabledDate.args = {
disabledDate: (current: Date) => differenceInDays(startOfToday(), current) > 31,
};
export const DisabledDate = () => {
const disabledDate = (current: Date) => differenceInDays(startOfToday(), current) > 31
return <PastTimePicker onSelect={action('selected value:')} placeholder="时间范围" disabledDate={disabledDate} />;
}


const StaticTemplate: Story<PastTimePickerProps> = (args) => (
<PastTimePicker.Static onSelect={action('selected value:')} placeholder="时间范围" {...args} />
Expand Down
52 changes: 25 additions & 27 deletions src/static-date-picker/StaticDatePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useLayoutEffect, useRef, useState } from 'react';
import { useControlledState, useLocale, usePrefixCls } from '@gio-design/utils';
import { LeftDoubleOutlined, LeftOutlined, RightOutlined, RightDoubleOutlined } from '@gio-design/icons';
import PickerPanel from 'rc-picker/lib/PickerPanel';
import generateDateFns from 'rc-picker/lib/generate/dateFns';
import { Locale, PickerMode } from 'rc-picker/lib/interface';
import { isEqual } from 'date-fns';
import defaultLocale from './locales/zh-CN';
import { StaticDatePickerProps } from './interfaces';

Expand All @@ -15,7 +14,7 @@ const Cell: React.FC<{ visible: boolean; prefixCls: string; currentDate: Date }>
}) => {
const divRef = useRef<HTMLDivElement>(null);

useEffect(() => {
useLayoutEffect(() => {
const parent = divRef.current?.parentElement;

if (parent && !visible) {
Expand All @@ -25,9 +24,10 @@ const Cell: React.FC<{ visible: boolean; prefixCls: string; currentDate: Date }>
}
});


return (
<div ref={divRef} className={`${prefixCls}-cell-inner`}>
{visible && currentDate.getDate()}
<div ref={divRef} style={{ visibility: visible ? "visible" : "hidden" }} className={`${prefixCls}-cell-inner`}>
{currentDate.getDate()}
</div>
);
};
Expand All @@ -38,32 +38,28 @@ const StaticDatePicker: React.FC<StaticDatePickerProps> = ({
value,
defaultValue,
onPanelChange,
onSelect,
...restProps
}) => {
const locale = useLocale<Locale>('DatePicker') || defaultLocale;
const [viewDate, setViewDate] = useControlledState(viewDateProp, value ?? defaultValue ?? new Date());

const [mode, setMode] = useState<PickerMode>('date');
const [viewDate, setViewDate] = useState(() => viewDateProp ?? value ?? defaultValue ?? new Date());
const [innerValue] = useControlledState(value, defaultValue);
const [mode] = useState<PickerMode>('date');
const currentPickerMode = useRef(mode);

const prefixCls = usePrefixCls('picker');

const isSameYearAndMonth = (currentDate: Date) =>
isEqual(
new Date(currentDate.getFullYear(), currentDate.getMonth()),
new Date(viewDate.getFullYear(), viewDate.getMonth())
);

const omitOtherDate = (currentDate: Date) => {
if (isSameYearAndMonth(currentDate)) {
return <Cell currentDate={currentDate} prefixCls={prefixCls} visible />;
}
return <Cell currentDate={currentDate} prefixCls={prefixCls} visible={false} />;
const isSameYearMonth = (one: Date, two: Date) => one.getFullYear() === two.getFullYear() && one.getMonth() === two.getMonth()
const isOmittedDate = (currentDate: Date, currentMode: PickerMode) => currentMode === 'date' && !isSameYearMonth(currentDate, viewDate)
const dateRender = (currentDate: Date) => {
const visible = !isOmittedDate(currentDate, 'date');
// 移除非当前月份的日期
return <Cell currentDate={currentDate} prefixCls={prefixCls} visible={visible} />;
};
const disabledDate = (currentDate: Date) => {
if (mode === 'date') {
if (!isSameYearAndMonth(currentDate)) {
return true;
}
// rc-picker/panel 日期点击事件是绑定在外层元素上,设置不展示的日期为disabled,来禁止点击事件
if (isOmittedDate(currentDate, currentPickerMode.current)) {
return true;
}
if (typeof disabledDateProp === 'function') {
return disabledDateProp(currentDate);
Expand All @@ -74,17 +70,19 @@ const StaticDatePicker: React.FC<StaticDatePickerProps> = ({
return (
<PickerPanel<Date>
data-testid="static-date-picker"
dateRender={omitOtherDate}
dateRender={dateRender}
disabledDate={disabledDate}
value={value}
value={innerValue}
defaultValue={defaultValue}
{...restProps}
pickerValue={viewDate}
onPickerValueChange={(date) => setViewDate(date)}
onSelect={(date) => { onSelect?.(date); }}
onChange={(date) => { setViewDate(date) }}
locale={locale}
prefixCls={prefixCls}
onPanelChange={(changedValue, changedMode: PickerMode) => {
setMode(changedMode);
currentPickerMode.current = changedMode;
setViewDate(changedValue);
onPanelChange?.(changedValue, changedMode);
}}
picker={mode}
Expand Down
5 changes: 4 additions & 1 deletion src/static-past-time-picker/RelativeRangeHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import defaultLocale from './locales/zh-CN';
const convertDateToDays = (date: Date | undefined, defaultValue: number) =>
date ? differenceInDays(startOfToday(), startOfDay(date)) : defaultValue;

function RelativeRangeHeader({ dateRange, onRangeChange, onModeChange }: RelativeRangeHeaderProps) {
function RelativeRangeHeader({ dateRange, onRangeChange, onModeChange, inputDisabled = false }: RelativeRangeHeaderProps) {
const [startDays, setStartDays] = React.useState<number>(convertDateToDays(dateRange[0], 2));
const [endDays, setEndDays] = React.useState<number>(convertDateToDays(dateRange[1], 1));
const [endDaysHidden, setEndDaysHidden] = React.useState(endDays === 1);
Expand All @@ -36,6 +36,7 @@ function RelativeRangeHeader({ dateRange, onRangeChange, onModeChange }: Relativ
<span className={`${basePrefixCls}__text`}>{lastText}</span>
<span className={`${basePrefixCls}__input-number`} data-testid="duration">
<Input.InputNumber
disabled={inputDisabled}
min={1}
max={9999}
value={duration}
Expand Down Expand Up @@ -69,6 +70,7 @@ function RelativeRangeHeader({ dateRange, onRangeChange, onModeChange }: Relativ
<span className={`${basePrefixCls}__text`}>{lastText}</span>
<span data-testid="end-days">
<Input.InputNumber
disabled={inputDisabled}
min={0}
className={`${basePrefixCls}__input-number`}
max={startDays - 1}
Expand All @@ -85,6 +87,7 @@ function RelativeRangeHeader({ dateRange, onRangeChange, onModeChange }: Relativ
<span className={`${basePrefixCls}__text`}>{ToText}</span>
<span data-testid="start-days">
<Input.InputNumber
disabled={inputDisabled}
min={endDays + 1}
max={10000}
className={`${basePrefixCls}__input-number`}
Expand Down
5 changes: 3 additions & 2 deletions src/static-past-time-picker/RelativeRangePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { differenceInDays, startOfToday, startOfDay, isValid, isYesterday, startOfYesterday, isAfter } from 'date-fns';
import { isNil } from 'lodash';
import RelativeRangeBody from './RelativeRangeBody';
import RelativeRangeHeader from './RelativeRangeHeader';
import InnerRangePanel from './InnerRangePanel';
Expand All @@ -10,7 +11,7 @@ function RelativeRangePicker({ disabledDate, timeRange, onSelect, onCancel, ...r
const defaultDates = parseStartAndEndDate(timeRange ?? 'day:2,1');
const [dates, setDates] = React.useState<[Date, Date]>(defaultDates as [Date, Date]);
const [endDateHidden, setEndDateHidden] = React.useState<boolean>(isYesterday(dates[1]));

const inputDisabled = !isNil(disabledDate);
const handleDisabledDate = (current: Date) =>
disabledDate?.(current) || isAfter(startOfDay(current), endDateHidden ? startOfYesterday() : startOfToday());
const handleOnOK = () => {
Expand All @@ -20,7 +21,7 @@ function RelativeRangePicker({ disabledDate, timeRange, onSelect, onCancel, ...r
<InnerRangePanel
data-testid="relative-range-picker"
disableOK={!isValid(dates[0]) || !isValid(dates[1])}
header={<RelativeRangeHeader dateRange={dates} onRangeChange={setDates} onModeChange={setEndDateHidden} />}
header={<RelativeRangeHeader inputDisabled={inputDisabled} dateRange={dates} onRangeChange={setDates} onModeChange={setEndDateHidden} />}
body={
<RelativeRangeBody
dateRange={dates}
Expand Down
1 change: 1 addition & 0 deletions src/static-past-time-picker/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export interface RelativeRangeHeaderProps extends ExperimentProps, RangePickerIn
* 结束日期固定模式改变时的回调
*/
onModeChange: (fixedMode: boolean) => void;
inputDisabled?: boolean;
}

export interface RelativeRangeBodyProps extends RangePickerInnerProps, Pick<StaticDatePickerProps, 'disabledDate'> {
Expand Down

1 comment on commit 59638ee

@vercel
Copy link

@vercel vercel bot commented on 59638ee Apr 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

gio-design – ./

gio-design-growingio.vercel.app
gio-design-git-master-growingio.vercel.app
gio-design.vercel.app

Please sign in to comment.