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
6 changes: 6 additions & 0 deletions docs/examples/debug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ export default () => {
defaultOpenValue={dayjs()}
// open
picker="time"
format={{
format: 'HH:mm:ss.SSS A',
type: 'mask',
}}
// showTime={{
// defaultValue: dayjs(),
// }}
Expand All @@ -171,6 +175,8 @@ export default () => {
// }),
// }}
// showTime={{}}
// disabled
open
onChange={(...args) => {
console.log('🔥 Change:', ...args);
}}
Expand Down
28 changes: 10 additions & 18 deletions src/PickerInput/hooks/useDelayState.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import { useEvent, useMergedState } from 'rc-util';
import raf from 'rc-util/lib/raf';
import React from 'react';

// We need wait for outside state updated.
// Which means need 2 effect:
// 1. Outside sync state
// 2. Still may be old state
// 3. Safe to sync state
const DELAY_TIMES = 2;

/**
* Will be `true` immediately for next effect.
* But will be `false` for a delay of effect.
Expand All @@ -21,10 +15,14 @@ export default function useDelayState<T>(
value,
});

const [times, setTimes] = React.useState<number | false>(false);
const nextValueRef = React.useRef<T>(value);

// ============================= Update =============================
const rafRef = React.useRef<number>();
const cancelRaf = () => {
raf.cancel(rafRef.current);
};

const doUpdate = useEvent(() => {
setState(nextValueRef.current);

Expand All @@ -34,24 +32,18 @@ export default function useDelayState<T>(
});

const updateValue = useEvent((next: T, immediately?: boolean) => {
cancelRaf();

nextValueRef.current = next;

if (next || immediately) {
doUpdate();
setTimes(false);
} else {
setTimes(0);
rafRef.current = raf(doUpdate);
}
});

// ============================= Effect =============================
React.useEffect(() => {
if (times === DELAY_TIMES) {
doUpdate();
} else if (times !== false && times < DELAY_TIMES) {
setTimes(times + 1);
}
}, [times, doUpdate]);
React.useEffect(() => cancelRaf, []);

return [state, updateValue];
}
2 changes: 1 addition & 1 deletion src/PickerInput/hooks/useFieldFormat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function useFieldFormat<DateType = any>(

const firstFormat = formatList[0];
const maskFormat =
typeof firstFormat === 'object' && firstFormat.align ? firstFormat.format : null;
typeof firstFormat === 'object' && firstFormat.type === 'mask' ? firstFormat.format : null;

return [
// Format list
Expand Down
4 changes: 2 additions & 2 deletions src/interface.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ export interface SharedPickerProps<DateType extends object = any>
showWeek?: boolean;
/**
* Config the input field parse and format.
* When set `format.align`, it will force user input align with your input,
* When set `format.type`, it will force user input type with your input,
* it's only support basic format mask: YYYY, MM, DD, HH, mm, ss, SSS.
* Once use config mode, it must be fill with format your config.
*/
Expand All @@ -340,7 +340,7 @@ export interface SharedPickerProps<DateType extends object = any>
| FormatType<DateType>[]
| {
format: string;
align?: boolean;
type?: 'mask';
};

// Icons
Expand Down
5 changes: 5 additions & 0 deletions tests/keyboard.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ describe('Picker.Keyboard', () => {
fireEvent.keyDown(container.querySelector('input'), {
key: 'Escape',
});

act(() => {
jest.runAllTimers();
});

expect(isOpen()).toBeFalsy();
});

Expand Down
6 changes: 5 additions & 1 deletion tests/new-range.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,10 @@ describe('NewPicker.Range', () => {

// Close panel to auto focus next end field
fireEvent.click(document.body);
act(() => {
jest.runAllTimers();
});

expect(container.querySelectorAll('input')[1]).toHaveFocus();

expect(isOpen()).toBeTruthy();
Expand Down Expand Up @@ -846,7 +850,7 @@ describe('NewPicker.Range', () => {
<DayRangePicker
format={{
format: 'YYYYMMDD',
align: true,
type: 'mask',
}}
{...props}
/>
Expand Down
5 changes: 5 additions & 0 deletions tests/picker.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ describe('Picker.Basic', () => {
for (let i = 0; i < 10; i += 1) {
act(() => {
fireEvent.click(document.body);
jest.runAllTimers();
});
expect(onOpenChange).toHaveBeenCalledTimes(i + 1);
}
Expand Down Expand Up @@ -1064,6 +1065,10 @@ describe('Picker.Basic', () => {
expect(isOpen()).toBeTruthy();

keyDown(KeyCode.ESC);
act(() => {
jest.runAllTimers();
});

expect(onKeyDown).toHaveBeenCalled();
expect(isOpen()).toBeFalsy();
onKeyDown.mockClear();
Expand Down
1 change: 1 addition & 0 deletions tests/range.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1082,6 +1082,7 @@ describe('Picker.Range', () => {
defaultValue={[getDay(defaultValue[0]), getDay(defaultValue[1] || defaultValue[0])]}
/>,
);

openPicker(container, 1);
selectCell(targetCell);
closePicker(container, 1);
Expand Down
9 changes: 6 additions & 3 deletions tests/util/commonUtil.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,12 @@ export function closePicker(container: HTMLElement, index = 0) {
const input = container.querySelectorAll('input')[index];
fireEvent.blur(input);

act(() => {
jest.runAllTimers();
});
// Loop to pass all the timer (includes raf)
for (let i = 0; i < 5; i += 1) {
act(() => {
jest.runAllTimers();
});
}
}

export function isOpen() {
Expand Down