Skip to content

Commit 555604e

Browse files
committed
refactor(RangePicker): track focus containers by ref
1 parent d33c1c6 commit 555604e

3 files changed

Lines changed: 27 additions & 12 deletions

File tree

src/PickerInput/Popup/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ export type PopupShowTimeConfig<DateType extends object = any> = Omit<
2020
Pick<SharedTimeProps<DateType>, 'disabledTime'>;
2121

2222
export interface PopupProps<DateType extends object = any, PresetValue = DateType>
23-
extends Pick<React.InputHTMLAttributes<HTMLDivElement>, 'onFocus' | 'onBlur'>,
23+
extends
24+
Pick<React.InputHTMLAttributes<HTMLDivElement>, 'onFocus' | 'onBlur'>,
2425
FooterProps<DateType>,
2526
PopupPanelProps<DateType> {
27+
containerRef?: React.Ref<HTMLDivElement>;
2628
panelRender?: SharedPickerProps['panelRender'];
2729

2830
// Presets
@@ -52,6 +54,7 @@ export interface PopupProps<DateType extends object = any, PresetValue = DateTyp
5254

5355
export default function Popup<DateType extends object = any>(props: PopupProps<DateType>) {
5456
const {
57+
containerRef,
5558
panelRender,
5659
internalMode,
5760
picker,
@@ -216,6 +219,7 @@ export default function Popup<DateType extends object = any>(props: PopupProps<D
216219
// Container
217220
let renderNode = (
218221
<div
222+
ref={containerRef}
219223
onMouseDown={onPanelMouseDown}
220224
tabIndex={-1}
221225
className={clsx(

src/PickerInput/RangePicker.tsx

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import PickerContext from './context';
2929
import useCellRender from './hooks/useCellRender';
3030
import useFieldsInvalidate from './hooks/useFieldsInvalidate';
3131
import useFilledProps from './hooks/useFilledProps';
32-
import useFocusControl from './hooks/useFocusControl';
32+
import useFocusControl, { isPickerElement } from './hooks/useFocusControl';
3333
import useOpen from './hooks/useOpen';
3434
import usePickerRef from './hooks/usePickerRef';
3535
import usePresets from './hooks/usePresets';
@@ -236,6 +236,7 @@ function RangePicker<DateType extends object = any>(
236236

237237
// ========================= Refs =========================
238238
const selectorRef = usePickerRef(ref);
239+
const popupRef = React.useRef<HTMLDivElement>(null);
239240

240241
// ======================= Semantic =======================
241242
const [mergedClassNames, mergedStyles] = useSemantic(propClassNames, propStyles);
@@ -346,15 +347,9 @@ function RangePicker<DateType extends object = any>(
346347
resetValue,
347348
);
348349

349-
const isPickerElement = useEvent((element: EventTarget | null) => {
350-
const target = element as HTMLElement;
351-
352-
return (
353-
!!target &&
354-
(selectorRef.current.nativeElement.contains(target) ||
355-
!!target.closest?.(`.${prefixCls}-panel-container`))
356-
);
357-
});
350+
const isInternalPickerElement = useEvent((element: EventTarget | null) =>
351+
isPickerElement(element, selectorRef.current.nativeElement, popupRef.current),
352+
);
358353

359354
const triggerFocusChange = useEvent((index: number, type: 'focus' | 'blur') => {
360355
const nextFocused = type === 'focus';
@@ -367,7 +362,7 @@ function RangePicker<DateType extends object = any>(
367362
});
368363

369364
const [onFieldFocus, onFieldBlur] = useFocusControl(
370-
isPickerElement,
365+
isInternalPickerElement,
371366
triggerFocusChange,
372367
(index, event) => {
373368
onFocus?.(event, {
@@ -620,6 +615,7 @@ function RangePicker<DateType extends object = any>(
620615
// >>> Render
621616
const panel = (
622617
<Popup<any>
618+
containerRef={popupRef}
623619
// MISC
624620
{...panelProps}
625621
showNow={mergedShowNow}

src/PickerInput/hooks/useFocusControl.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,21 @@ export type UseFocusControlReturn = [
3939
onFieldBlur: FieldBlurHandler,
4040
];
4141

42+
// ============================= Utils =============================
43+
/** Check whether the target is the container itself or inside it. / 判断目标是否为容器自身或其子元素。 */
44+
function containsElement(container: HTMLElement | null, target: EventTarget | null) {
45+
return !!container && (container === target || container.contains(target as Node));
46+
}
47+
48+
/** Check whether the target belongs to the selector or popup. / 判断目标是否属于输入区域或弹出区域。 */
49+
export function isPickerElement(
50+
target: EventTarget | null,
51+
selectorElement: HTMLElement | null,
52+
popupElement: HTMLElement | null,
53+
) {
54+
return containsElement(selectorElement, target) || containsElement(popupElement, target);
55+
}
56+
4257
/**
4358
* Control field focus and blur events.
4459
* 控制 field 的聚焦与失焦事件。

0 commit comments

Comments
 (0)