Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(DatePicker2): Fix the arrow direction issue when popupAlign is set to br tr or tr br #5015

Open
wants to merge 1 commit into
base: next
Choose a base branch
from
Open
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
105 changes: 105 additions & 0 deletions components/date-picker2/__tests__/index-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,94 @@ describe('Picker', () => {
});
});

describe('RangePicker arrow', () => {
it('align tl bl', () => {
return co(function* () {
wrapper = render(<RangePicker popupAlign="tl bl" />);
const inputBegin = wrapper.find('.next-input')[0];
ReactTestUtils.Simulate.click(inputBegin);
yield delay(300);
assert.equal(findArrowDom().offsetTop, 13);
assert.equal(findArrowDom().style.left, `${getArrowLeft()}px`);
wrapper.unmount();
});
});
it('align tr br', () => {
return co(function* () {
wrapper = render(
<div
style={{
display: 'flex',
flexDirection: 'row',
}}
>
<div style={{ flex: 1 }}></div>
<div style={{ width: 300 }}>
<RangePicker dev={true} popupAlign="tr br" />
</div>
</div>
);
const inputBegin = wrapper.find('.next-input')[0];
ReactTestUtils.Simulate.click(inputBegin);
yield delay(300);
assert.equal(findArrowDom().offsetTop, 13);
assert.equal(findArrowDom().style.left, `${getArrowLeft()}px`);
wrapper.unmount();
});
});

it('align br tr', () => {
return co(function* () {
wrapper = render(
<div
style={{
display: 'flex',
flexDirection: 'row',
height: 400,
alignItems: 'end',
}}
>
<div style={{ flex: 1 }}></div>
<div style={{ width: 300 }}>
<RangePicker popupAlign="br tr" />
</div>
</div>
);
const inputBegin = wrapper.find('.next-input')[0];
ReactTestUtils.Simulate.click(inputBegin);
yield delay(300);
const count = findOverlayDom().offsetHeight - findArrowDom().offsetTop;
assert.equal(count, 25);
assert.equal(findArrowDom().style.left, `${getArrowLeft()}px`);
wrapper.unmount();
});
});

it('align bl tl', () => {
return co(function* () {
wrapper = render(
<div
style={{
display: 'flex',
flexDirection: 'row',
height: 400,
alignItems: 'end',
}}
>
<RangePicker popupAlign="bl tl" />
</div>
);
const inputBegin = wrapper.find('.next-input')[0];
ReactTestUtils.Simulate.click(inputBegin);
yield delay(300);
const count = findOverlayDom().offsetHeight - findArrowDom().offsetTop;
assert.equal(count, 25);
assert.equal(findArrowDom().style.left, `${getArrowLeft()}px`);
wrapper.unmount();
});
});
});

describe('event', () => {
it('onChange', () => {
let changeCount = 0;
Expand Down Expand Up @@ -1360,3 +1448,20 @@ function hasClassNames(node, classNames) {
function showTimePanel() {
return !!wrapper.find('.next-time-picker2-panel').length;
}

function findArrowDom() {
return document.querySelector('.next-range-picker2-arrow');
}

function findOverlayDom() {
return document.querySelector('.next-date-picker2-overlay');
}

function getArrowLeft() {
const inputBegin = wrapper.find('.next-input')[0];
const { left: arrowLeft } = inputBegin.getBoundingClientRect();
const { left: panelLeft } = findOverlayDom().getBoundingClientRect();
const offset = Math.round(Math.abs(arrowLeft - panelLeft));
const inputOffsetLeft = inputBegin.offsetLeft;
return offset + inputOffsetLeft;
}
11 changes: 11 additions & 0 deletions components/date-picker2/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,17 @@
transform: translate(0, 50%) rotate(135deg);
}
}
#{$date-picker2-prefix}-tr-br {
#{$range-picker2-prefix}-arrow {
top: 12.5px;
}
}
#{$date-picker2-prefix}-br-tr {
#{$range-picker2-prefix}-arrow {
bottom: 13px;
transform: translate(0, 50%) rotate(135deg);
}
}

.#{$css-prefix}date-time-picker-wrapper {
border-left: 1px solid $color-line1-1;
Expand Down
68 changes: 58 additions & 10 deletions components/date-picker2/picker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -425,11 +425,11 @@ class Picker extends React.Component {
if (isRange) {
const updatedInputValue = [...inputValue];
updatedInputValue[inputType] = updatedInputValue[inputType] + ' ';
this.setState({ inputValue: updatedInputValue })
this.setState({ inputValue: updatedInputValue });
} else {
this.setState({
inputValue: inputValue + ' '
})
inputValue: inputValue + ' ',
});
}
break;
}
Expand All @@ -441,7 +441,13 @@ class Picker extends React.Component {
handleChange = (v, eventType) => {
const { format } = this.props;
const { isRange, showOk, value, preValue } = this.state;
const forceEvents = ['KEYDOWN_ENTER', 'CLICK_PRESET', 'CLICK_OK', 'INPUT_CLEAR', 'VISIBLE_CHANGE'];
const forceEvents = [
'KEYDOWN_ENTER',
'CLICK_PRESET',
'CLICK_OK',
'INPUT_CLEAR',
'VISIBLE_CHANGE',
];
const isTemporary = showOk && !forceEvents.includes(eventType);

// 面板收起时候,将值设置为确认值
Expand Down Expand Up @@ -566,15 +572,37 @@ class Picker extends React.Component {
return left;
};

getRangeInputStartClientRect = () => {
const rect =
this.dateInput &&
this.dateInput.input &&
this.dateInput.input[DATE_INPUT_TYPE.BEGIN] &&
this.dateInput.input &&
this.dateInput.input[DATE_INPUT_TYPE.BEGIN].getInputNode().getBoundingClientRect();
return rect || {};
};

getPopupOffsetLeft = () => {
const inputOffsetLeft = this.getRangeInputOffsetLeft();
const popupElement = this.popupRef.current;
const popupElementWidth = popupElement ? popupElement.offsetWidth : 0;
// 计算弹层相对于输入框的偏移量
let { left: inputLeft = 0 } = this.getRangeInputStartClientRect();
const popupElementLeft = popupElement ? popupElement.getBoundingClientRect().left || 0 : 0;
const offset = popupElementWidth ? Math.round(Math.abs(popupElementLeft - inputLeft)) : 0;

// 没有的时候,默认不偏移,要不然会因为 css 中的 transform 属性导致会有偏移动画
if (!popupElementWidth || (!inputOffsetLeft && inputOffsetLeft !== 0)) {
return {
arrowLeft: 0,
panelLeft: 0,
};
}

// 弹层宽度大于输入元素长度,只偏移 arrow
if (popupElementWidth > 1.2 * inputOffsetLeft) {
return {
arrowLeft: inputOffsetLeft,
arrowLeft: inputOffsetLeft + offset,
panelLeft: 0,
};
} else {
Expand All @@ -587,7 +615,13 @@ class Picker extends React.Component {
};

renderArrow = left => {
return <div key="arrow" className={`${this.props.prefix}range-picker2-arrow`} style={{ left }} />;
return (
<div
key="arrow"
className={`${this.props.prefix}range-picker2-arrow`}
style={{ left }}
/>
);
};

render() {
Expand Down Expand Up @@ -641,7 +675,10 @@ class Picker extends React.Component {

return (
<div className={previewCls}>
{renderNode(renderPreview, isRange ? inputValue.join('-') : inputValue, [curValue, this.props])}
{renderNode(renderPreview, isRange ? inputValue.join('-') : inputValue, [
curValue,
this.props,
])}
</div>
);
}
Expand Down Expand Up @@ -698,13 +735,20 @@ class Picker extends React.Component {
};

const DateNode = isRange ? (
<RangePanel justBeginInput={justBeginInput} onCalendarChange={onCalendarChange} {...panelProps} />
<RangePanel
justBeginInput={justBeginInput}
onCalendarChange={onCalendarChange}
{...panelProps}
/>
) : (
<DatePanel {...panelProps} />
);

// 底部节点
const oKable = !!(!this.checkValueDisabled(inputValue) && (isRange ? inputValue && inputValue[inputType] : inputValue));
const oKable = !!(
!this.checkValueDisabled(inputValue) &&
(isRange ? inputValue && inputValue[inputType] : inputValue)
);
const shouldShowFooter = showOk || preset || extraFooterRender;

const footerNode = shouldShowFooter ? (
Expand Down Expand Up @@ -774,7 +818,11 @@ class Picker extends React.Component {
>
{/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
<div onMouseDown={handleMouseDown} style={{ marginLeft: panelLeft }}>
<div dir={rtl ? 'rtl' : undefined} className={`${prefixCls}-wrapper`} ref={this.popupRef}>
<div
dir={rtl ? 'rtl' : undefined}
className={`${prefixCls}-wrapper`}
ref={this.popupRef}
>
{isRange ? this.renderArrow(arrowLeft) : null}
{DateNode}
{this.state.panelMode !== this.props.mode ? null : footerNode}
Expand Down
Loading