diff --git a/src/RangePicker.tsx b/src/RangePicker.tsx index f0c832abf..d4adfb95a 100644 --- a/src/RangePicker.tsx +++ b/src/RangePicker.tsx @@ -893,13 +893,17 @@ function InnerRangePicker(props: RangePickerProps) { // Arrow offset arrowLeft = startInputDivRef.current.offsetWidth + separatorRef.current.offsetWidth; + // If panelWidth - arrowWidth - arrowMarginLeft < arrowLeft, panel should move to right side. + // If offsetLeft > arrowLeft, arrow position is absolutely right, because arrowLeft is not calculated with arrow margin. if ( panelDivRef.current.offsetWidth && arrowRef.current.offsetWidth && arrowLeft > panelDivRef.current.offsetWidth - arrowRef.current.offsetWidth - - (direction === 'rtl' ? 0 : arrowRef.current.offsetLeft) + (direction === 'rtl' || arrowRef.current.offsetLeft > arrowLeft + ? 0 + : arrowRef.current.offsetLeft) ) { panelLeft = arrowLeft; } diff --git a/tests/range.spec.tsx b/tests/range.spec.tsx index 19cbe6903..310687cf9 100644 --- a/tests/range.spec.tsx +++ b/tests/range.spec.tsx @@ -1536,4 +1536,76 @@ describe('Picker.Range', () => { wrapper.simulate('mousedown'); expect(handleMouseDown).toHaveBeenCalled(); }); + + it('panel should be stable: left', () => { + const mock = spyElementPrototypes(HTMLElement, { + offsetWidth: { + get() { + if (this.className.includes('range-arrow')) { + return 14; + } else if (this.className.includes('panel-container')) { + return 312; + } else if (this.className.includes('input')) { + return 236; + } else if (this.className.includes('range-separator')) { + return 10; + } + }, + }, + offsetLeft: { + get() { + if (this.className.includes('range-arrow')) { + return 16; + } + }, + }, + }); + const wrapper = mount( + X} + suffixIcon={O} + />, + ); + wrapper.openPicker(1); + expect(wrapper.find('.rc-picker-panel-container').getDOMNode().style.marginLeft).toBe('0px'); + mock.mockRestore(); + }); + + it('panel should be stable: right', () => { + const mock = spyElementPrototypes(HTMLElement, { + offsetWidth: { + get() { + if (this.className.includes('range-arrow')) { + return 14; + } else if (this.className.includes('panel-container')) { + return 312; + } else if (this.className.includes('input')) { + return 236; + } else if (this.className.includes('range-separator')) { + return 10; + } + }, + }, + offsetLeft: { + get() { + if (this.className.includes('range-arrow')) { + return 262; + } + }, + }, + }); + const wrapper = mount( + X} + suffixIcon={O} + />, + ); + wrapper.openPicker(1); + expect(wrapper.find('.rc-picker-panel-container').getDOMNode().style.marginLeft).toBe('0px'); + mock.mockRestore(); + }); });