Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 42 additions & 5 deletions docs/examples/debug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,56 @@ export default () => {
return (
<div>
<input defaultValue="2000-01-01" />
<RangePicker
{/* <RangePicker
{...sharedLocale}
style={{ width: 400 }}
onChange={(val) => console.error('>>>>>>>', val)}
/> */}
<RangePicker
{...sharedLocale}
style={{ width: 400 }}
showTime
// disabledDate={(_, info) => {
// console.log('Date:', info);
// return false;
// }}
disabledTime={(date, range, info) => {
// console.log(`Time-${range}`, range, info);
const { from } = info;

if (from) {
console.log(
`Time-${range}`,
from.format('YYYY-MM-DD HH:mm:ss'),
date.format('YYYY-MM-DD HH:mm:ss'),
);
}

if (from && from.isSame(date, 'day')) {
return {
disabledHours: () => [from.hour()],
disabledMinutes: () => [0, 1, 2, 3],
disabledSeconds: () => [0, 1, 2, 3],
};
}
return {};
}}
/>
{/* <RangePicker {...sharedLocale} style={{ width: 400 }} showTime showMinute={false} /> */}
{/* <SinglePicker {...dateFnsSharedLocale} style={{ width: 400 }} multiple placeholder="good" /> */}
<SinglePicker
{/* <SinglePicker
{...dateFnsSharedLocale}
style={{ width: 400 }}
showTime
disabledTime={(...args) => {
console.log('Time Single:', ...args);
return {};
}}
/> */}
{/* <SinglePicker
{...sharedLocale}
style={{ width: 400 }}
minDate={dayjs()}
onChange={(val) => console.error('>>>>>>>', val)}
/>
/> */}
</div>
);
};
11 changes: 3 additions & 8 deletions src/PickerInput/Popup/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,9 @@ import classNames from 'classnames';
import * as React from 'react';
import type { GenerateConfig } from '../../generate';
import useTimeInfo from '../../hooks/useTimeInfo';
import type {
DisabledDate,
InternalMode,
PanelMode,
RangeTimeProps,
SharedPickerProps,
} from '../../interface';
import type { DisabledDate, InternalMode, PanelMode, SharedPickerProps } from '../../interface';
import PickerContext from '../context';
import type { PopupShowTimeConfig } from '.';

export interface FooterProps<DateType extends object = any> {
mode: PanelMode;
Expand All @@ -18,7 +13,7 @@ export interface FooterProps<DateType extends object = any> {
showNow: boolean;
generateConfig: GenerateConfig<DateType>;
disabledDate: DisabledDate<DateType>;
showTime?: Omit<RangeTimeProps<DateType>, 'defaultValue' | 'defaultOpenValue'>;
showTime?: PopupShowTimeConfig<DateType>;

// Invalid
/** From Footer component used only. Check if can OK button click */
Expand Down
13 changes: 12 additions & 1 deletion src/PickerInput/Popup/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import classNames from 'classnames';
import ResizeObserver, { type ResizeObserverProps } from 'rc-resize-observer';
import * as React from 'react';
import type { SharedPickerProps, ValueDate } from '../../interface';
import type {
RangeTimeProps,
SharedPickerProps,
SharedTimeProps,
ValueDate,
} from '../../interface';
import { toArray } from '../../utils/miscUtil';
import PickerContext from '../context';
import Footer, { type FooterProps } from './Footer';
import PopupPanel, { type PopupPanelProps } from './PopupPanel';
import PresetPanel from './PresetPanel';

export type PopupShowTimeConfig<DateType extends object = any> = Omit<
RangeTimeProps<DateType>,
'defaultValue' | 'defaultOpenValue' | 'disabledTime'
> &
Pick<SharedTimeProps<DateType>, 'disabledTime'>;

export interface PopupProps<DateType extends object = any, PresetValue = DateType>
extends Pick<React.InputHTMLAttributes<HTMLDivElement>, 'onFocus' | 'onBlur'>,
FooterProps<DateType>,
Expand Down
17 changes: 12 additions & 5 deletions src/PickerInput/RangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import type {
import type { PickerPanelProps } from '../PickerPanel';
import PickerTrigger from '../PickerTrigger';
import { pickTriggerProps } from '../PickerTrigger/util';
import { fillIndex, toArray } from '../utils/miscUtil';
import { fillIndex, getFromDate, toArray } from '../utils/miscUtil';
import PickerContext from './context';
import useCellRender from './hooks/useCellRender';
import useFieldsInvalidate from './hooks/useFieldsInvalidate';
Expand All @@ -33,7 +33,7 @@ import useRangeDisabledDate from './hooks/useRangeDisabledDate';
import useRangePickerValue from './hooks/useRangePickerValue';
import useRangeValue, { useInnerValue } from './hooks/useRangeValue';
import useShowNow from './hooks/useShowNow';
import Popup from './Popup';
import Popup, { PopupShowTimeConfig } from './Popup';
import RangeSelector, { type SelectorIdType } from './Selector/RangeSelector';

function separateConfig<T>(config: T | [T, T] | null | undefined, defaultConfig: T): [T, T] {
Expand Down Expand Up @@ -278,7 +278,10 @@ function RangePicker<DateType extends object = any>(
};

// ======================= ShowTime =======================
const mergedShowTime = React.useMemo(() => {
/** Used for Popup panel */
const mergedShowTime = React.useMemo<
PopupShowTimeConfig<DateType> & Pick<RangeTimeProps<DateType>, 'defaultOpenValue'>
>(() => {
if (!showTime) {
return null;
}
Expand All @@ -288,12 +291,15 @@ function RangePicker<DateType extends object = any>(
const proxyDisabledTime = disabledTime
? (date: DateType) => {
const range = getActiveRange(activeIndex);
return disabledTime(date, range);
const fromDate = getFromDate(calendarValue, activeIndexList, activeIndex);
return disabledTime(date, range, {
from: fromDate,
});
}
: undefined;

return { ...showTime, disabledTime: proxyDisabledTime };
}, [showTime, activeIndex]);
}, [showTime, activeIndex, calendarValue, activeIndexList]);

// ========================= Mode =========================
const [modes, setModes] = useMergedState<[PanelMode, PanelMode]>([picker, picker], {
Expand Down Expand Up @@ -542,6 +548,7 @@ function RangePicker<DateType extends object = any>(
'style',
'className',
'onPanelChange',
'disabledTime',
]);
return restProps;
}, [filledProps]);
Expand Down
5 changes: 4 additions & 1 deletion src/PickerInput/hooks/useInvalidate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ export default function useInvalidate<DateType extends object = any>(
}

if ((picker === 'date' || picker === 'time') && showTime) {
const range = info && info.activeIndex === 1 ? 'end' : 'start';
const { disabledHours, disabledMinutes, disabledSeconds, disabledMilliseconds } =
showTime.disabledTime?.(date, info && info.activeIndex === 1 ? 'end' : 'start') || {};
showTime.disabledTime?.(date, range, {
from: outsideInfo.from,
}) || {};

const {
disabledHours: legacyDisabledHours,
Expand Down
4 changes: 2 additions & 2 deletions src/PickerInput/hooks/useRangeDisabledDate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { GenerateConfig } from '../../generate';
import { isSame } from '../../utils/dateUtil';
import type { DisabledDate, Locale } from '../../interface';
import type { RangeValueType } from '../RangePicker';
import { getFromDate } from '../../utils/miscUtil';

/**
* RangePicker need additional logic to handle the `disabled` case. e.g.
Expand All @@ -16,14 +17,13 @@ export default function useRangeDisabledDate<DateType extends object = any>(
disabledDate?: DisabledDate<DateType>,
) {
const activeIndex = activeIndexList[activeIndexList.length - 1];
const firstValuedIndex = activeIndexList.find((index) => values[index]);

const rangeDisabledDate: DisabledDate<DateType> = (date, info) => {
const [start, end] = values;

const mergedInfo = {
...info,
from: activeIndex !== firstValuedIndex ? values[firstValuedIndex] : undefined,
from: getFromDate(values, activeIndexList),
};

// ============================ Disabled ============================
Expand Down
2 changes: 1 addition & 1 deletion src/PickerTrigger/util.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { SharedPickerProps } from '../interface';
import { pickProps } from '../utils/miscUtil';

export function pickTriggerProps(props: SharedPickerProps) {
export function pickTriggerProps(props: Omit<SharedPickerProps, 'showTime'>) {
return pickProps(props, [
'placement',
'builtinPlacements',
Expand Down
10 changes: 8 additions & 2 deletions src/interface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,19 +176,25 @@ export interface SharedTimeProps<DateType extends object = any> {
disabledSeconds?: DisabledTimes['disabledSeconds'];

/** Only work in picker is `time` */
disabledTime?: (date: DateType, range?: 'start' | 'end') => DisabledTimes;
disabledTime?: (date: DateType) => DisabledTimes;

/** Only work in picker is `time` */
changeOnScroll?: boolean;
}

export type RangeTimeProps<DateType extends object = any> = Omit<
SharedTimeProps<DateType>,
'defaultValue' | 'defaultOpenValue'
'defaultValue' | 'defaultOpenValue' | 'disabledTime'
> & {
/** @deprecated Use `defaultOpenValue` instead. */
defaultValue?: DateType[];
defaultOpenValue?: DateType[];

disabledTime?: (
date: DateType,
range: 'start' | 'end',
info: { from?: DateType },
) => DisabledTimes;
};

// ======================= Components =======================
Expand Down
12 changes: 12 additions & 0 deletions src/utils/miscUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,15 @@ export function getRowFormat(
return locale.fieldDateFormat;
}
}

export function getFromDate<DateType>(
calendarValues: DateType[],
activeIndexList: number[],
activeIndex?: number,
) {
const mergedActiveIndex =
activeIndex !== undefined ? activeIndex : activeIndexList[activeIndexList.length - 1];
const firstValuedIndex = activeIndexList.find((index) => calendarValues[index]);

return mergedActiveIndex !== firstValuedIndex ? calendarValues[firstValuedIndex] : undefined;
}
32 changes: 32 additions & 0 deletions tests/new-range.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1294,4 +1294,36 @@ describe('NewPicker.Range', () => {
'1990-09-24 02:00:00',
]);
});

it('disabledTime support `from` info', () => {
const disabledTime = jest.fn(() => ({}));

const { container } = render(
<DayRangePicker
showTime={{
disabledTime,
}}
/>,
);

openPicker(container);
expect(disabledTime).toHaveBeenCalledWith(expect.anything(), 'start', {});
disabledTime.mockReset();

// Select
selectCell(5);
fireEvent.doubleClick(findCell(5));

let existed = false;
for (let i = 0; i < disabledTime.mock.calls.length; i += 1) {
const args: any[] = disabledTime.mock.calls[i];
if (
args[1] === 'end' &&
args[2]?.from?.format('YYYY-MM-DD HH:mm:ss') === '1990-09-05 00:00:00'
) {
existed = true;
}
}
expect(existed).toBeTruthy();
});
});