Skip to content

Commit 2726430

Browse files
committed
fix: use Rect for logic
1 parent 8863871 commit 2726430

File tree

5 files changed

+69
-35
lines changed

5 files changed

+69
-35
lines changed

assets/index.less

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
&-invalid {
3838
box-shadow: 0 0 2px red;
3939
}
40+
41+
&-panels {
42+
display: flex;
43+
flex-wrap: nowrap;
44+
}
45+
4046
&-panel {
4147
display: inline-block;
4248
vertical-align: top;

src/PickerInput/Popup/index.tsx

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type {
88
ValueDate,
99
} from '../../interface';
1010
import { toArray } from '../../utils/miscUtil';
11-
import { getRealPlacement, getoffsetUnit } from '../../utils/uiUtil';
11+
import { getRealPlacement, getOffsetUnit } from '../../utils/uiUtil';
1212
import PickerContext from '../context';
1313
import Footer, { type FooterProps } from './Footer';
1414
import PopupPanel, { type PopupPanelProps } from './PopupPanel';
@@ -32,7 +32,7 @@ export interface PopupProps<DateType extends object = any, PresetValue = DateTyp
3232
onPresetSubmit: (presetValue: PresetValue) => void;
3333

3434
// Range
35-
activeOffset?: number;
35+
activeInfo?: [activeInputLeft: number, activeInputRight: number, selectorWidth: number];
3636
placement?: string;
3737
// Direction
3838
direction?: 'ltr' | 'rtl';
@@ -59,7 +59,7 @@ export default function Popup<DateType extends object = any>(props: PopupProps<D
5959
// Range
6060
range,
6161
multiple,
62-
activeOffset = 0,
62+
activeInfo = [0, 0, 0],
6363
placement,
6464

6565
// Presets
@@ -96,28 +96,46 @@ export default function Popup<DateType extends object = any>(props: PopupProps<D
9696
// ======================== Offset ========================
9797
const [containerWidth, setContainerWidth] = React.useState<number>(0);
9898
const [containerOffset, setContainerOffset] = React.useState<number>(0);
99+
const [arrowOffset, setArrowOffset] = React.useState<number>(0);
99100

100101
const onResize: ResizeObserverProps['onResize'] = (info) => {
101102
if (info.offsetWidth) {
102103
setContainerWidth(info.offsetWidth);
103104
}
104105
};
105106

107+
const [activeInputLeft, activeInputRight, selectorWidth] = activeInfo;
108+
106109
React.useEffect(() => {
107110
// `activeOffset` is always align with the active input element
108111
// So we need only check container contains the `activeOffset`
109-
if (range) {
112+
if (range && wrapperRef.current) {
110113
// Offset in case container has border radius
111114
const arrowWidth = arrowRef.current?.offsetWidth || 0;
112115

113-
const maxOffset = containerWidth - arrowWidth;
114-
if (activeOffset <= maxOffset) {
115-
setContainerOffset(0);
116+
// Arrow Offset
117+
const wrapperRect = wrapperRef.current.getBoundingClientRect();
118+
const nextArrowOffset = rtl
119+
? activeInputRight - arrowWidth
120+
: activeInputLeft - wrapperRect.left;
121+
setArrowOffset(nextArrowOffset);
122+
123+
// Container Offset
124+
if (containerWidth < selectorWidth) {
125+
if (rtl) {
126+
const offset = wrapperRect.right - (activeInputRight - arrowWidth + containerWidth);
127+
const safeOffset = Math.max(0, offset);
128+
setContainerOffset(safeOffset);
129+
} else {
130+
const offset = activeInputLeft + arrowWidth - wrapperRect.left - containerWidth;
131+
const safeOffset = Math.max(0, offset);
132+
setContainerOffset(safeOffset);
133+
}
116134
} else {
117-
setContainerOffset(activeOffset + arrowWidth - containerWidth);
135+
setContainerOffset(0);
118136
}
119137
}
120-
}, [containerWidth, activeOffset, range]);
138+
}, [rtl, containerWidth, activeInputLeft, activeInputRight, selectorWidth, range]);
121139

122140
// ======================== Custom ========================
123141
function filterEmpty<T>(list: T[]) {
@@ -213,19 +231,13 @@ export default function Popup<DateType extends object = any>(props: PopupProps<D
213231
);
214232

215233
if (range) {
216-
const realPlacement = getRealPlacement(placement, rtl);
217-
const offsetUnit = getoffsetUnit(realPlacement, rtl);
218234
renderNode = (
219235
<div
220236
onMouseDown={onPanelMouseDown}
221237
ref={wrapperRef}
222238
className={classNames(`${prefixCls}-range-wrapper`, `${prefixCls}-${picker}-range-wrapper`)}
223239
>
224-
<div
225-
ref={arrowRef}
226-
className={`${prefixCls}-range-arrow`}
227-
style={{ [offsetUnit]: activeOffset }}
228-
/>
240+
<div ref={arrowRef} className={`${prefixCls}-range-arrow`} style={{ left: arrowOffset }} />
229241

230242
{/* Watch for container size */}
231243
<ResizeObserver onResize={onResize}>{renderNode}</ResizeObserver>

src/PickerInput/RangePicker.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,10 @@ function RangePicker<DateType extends object = any>(
473473
// == Panels ==
474474
// ========================================================
475475
// Save the offset with active bar position
476-
const [activeOffset, setActiveOffset] = React.useState(0);
476+
// const [activeOffset, setActiveOffset] = React.useState(0);
477+
const [activeInfo, setActiveInfo] = React.useState<
478+
[activeInputLeft: number, activeInputRight: number, selectorWidth: number]
479+
>([0, 0, 0]);
477480

478481
// ======================= Presets ========================
479482
const presetList = usePresets(presets, ranges);
@@ -574,7 +577,7 @@ function RangePicker<DateType extends object = any>(
574577
// Range
575578
range
576579
multiplePanel={multiplePanel}
577-
activeOffset={activeOffset}
580+
activeInfo={activeInfo}
578581
placement={placement}
579582
// Disabled
580583
disabledDate={mergedDisabledDate}
@@ -796,7 +799,7 @@ function RangePicker<DateType extends object = any>(
796799
invalid={submitInvalidates}
797800
onInvalid={onSelectorInvalid}
798801
// Offset
799-
onActiveOffset={setActiveOffset}
802+
onActiveInfo={setActiveInfo}
800803
/>
801804
</PickerTrigger>
802805
</PickerContext.Provider>

src/PickerInput/Selector/RangeSelector.tsx

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import useInputProps from './hooks/useInputProps';
88
import useRootProps from './hooks/useRootProps';
99
import Icon, { ClearIcon } from './Icon';
1010
import Input, { type InputRef } from './Input';
11-
import { getoffsetUnit, getRealPlacement } from '../../utils/uiUtil';
11+
// import { getOffsetUnit, getRealPlacement } from '../../utils/uiUtil';
1212

1313
export type SelectorIdType =
1414
| string
@@ -42,7 +42,9 @@ export interface RangeSelectorProps<DateType = any> extends SelectorProps<DateTy
4242
* Trigger when the active bar offset position changed.
4343
* This is used for popup panel offset.
4444
*/
45-
onActiveOffset: (offset: number) => void;
45+
onActiveInfo: (
46+
info: [activeInputLeft: number, activeInputRight: number, selectorWidth: number],
47+
) => void;
4648
}
4749

4850
function RangeSelector<DateType extends object = any>(
@@ -102,7 +104,7 @@ function RangeSelector<DateType extends object = any>(
102104
onOpenChange,
103105

104106
// Offset
105-
onActiveOffset,
107+
onActiveInfo,
106108
placement,
107109

108110
// Native
@@ -173,9 +175,9 @@ function RangeSelector<DateType extends object = any>(
173175
});
174176

175177
// ====================== ActiveBar =======================
176-
const realPlacement = getRealPlacement(placement, rtl);
177-
const offsetUnit = getoffsetUnit(realPlacement, rtl);
178-
const placementRight = realPlacement?.toLowerCase().endsWith('right');
178+
// const realPlacement = getRealPlacement(placement, rtl);
179+
// const offsetUnit = getOffsetUnit(realPlacement, rtl);
180+
// const placementRight = realPlacement?.toLowerCase().endsWith('right');
179181
const [activeBarStyle, setActiveBarStyle] = React.useState<React.CSSProperties>({
180182
position: 'absolute',
181183
width: 0,
@@ -184,15 +186,26 @@ function RangeSelector<DateType extends object = any>(
184186
const syncActiveOffset = useEvent(() => {
185187
const input = getInput(activeIndex);
186188
if (input) {
187-
const { offsetWidth, offsetLeft, offsetParent } = input.nativeElement;
188-
const parentWidth = (offsetParent as HTMLElement)?.offsetWidth || 0;
189-
const activeOffset = placementRight ? (parentWidth - offsetWidth - offsetLeft) : offsetLeft;
190-
setActiveBarStyle(({ insetInlineStart, insetInlineEnd, ...rest }) => ({
191-
...rest,
189+
const { offsetWidth, offsetParent } = input.nativeElement;
190+
// const parentWidth = (offsetParent as HTMLElement)?.offsetWidth || 0;
191+
// const activeOffset = placementRight ? parentWidth - offsetWidth - offsetLeft : offsetLeft;
192+
// setActiveBarStyle(({ insetInlineStart, insetInlineEnd, ...rest }) => ({
193+
// ...rest,
194+
// width: offsetWidth,
195+
// [offsetUnit]: activeOffset
196+
// }));
197+
// onActiveOffset(activeOffset);
198+
199+
const inputRect = input.nativeElement.getBoundingClientRect();
200+
const parentRect = rootRef.current.getBoundingClientRect();
201+
202+
const rectOffset = inputRect.left - parentRect.left;
203+
setActiveBarStyle((ori) => ({
204+
...ori,
192205
width: offsetWidth,
193-
[offsetUnit]: activeOffset
206+
left: rectOffset,
194207
}));
195-
onActiveOffset(activeOffset);
208+
onActiveInfo([inputRect.left, inputRect.right, parentRect.width]);
196209
}
197210
});
198211

src/utils/uiUtil.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,12 @@ export function getRealPlacement(placement: string, rtl: boolean) {
195195
return rtl ? 'bottomRight' : 'bottomLeft';
196196
}
197197

198-
export function getoffsetUnit(placement: string, rtl: boolean) {
198+
export function getOffsetUnit(placement: string, rtl: boolean) {
199199
const realPlacement = getRealPlacement(placement, rtl);
200200
const placementRight = realPlacement?.toLowerCase().endsWith('right');
201201
let offsetUnit = placementRight ? 'insetInlineEnd' : 'insetInlineStart';
202202
if (rtl) {
203-
offsetUnit = ['insetInlineStart', 'insetInlineEnd'].find(unit => unit !== offsetUnit);
203+
offsetUnit = ['insetInlineStart', 'insetInlineEnd'].find((unit) => unit !== offsetUnit);
204204
}
205205
return offsetUnit;
206-
}
206+
}

0 commit comments

Comments
 (0)