Skip to content

Commit

Permalink
fix: correctly control popup open state in pickers
Browse files Browse the repository at this point in the history
  • Loading branch information
ValeraS committed Nov 14, 2023
1 parent f109e42 commit 24b89d7
Show file tree
Hide file tree
Showing 10 changed files with 250 additions and 220 deletions.
8 changes: 5 additions & 3 deletions src/components/DateField/hooks/useDateFieldProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,15 @@ export function useDateFieldProps(
if (state.selectedSectionIndexes !== null) {
return;
}
const input = inputRef.current;
const input = e.target;
const isAutofocus = !inputRef.current;
setTimeout(() => {
if (!input || input !== inputRef.current) {
return;
}

if (
if (isAutofocus) {
state.focusSectionInPosition(0);
} else if (
// avoid selecting all sections when focusing empty field without value
input.value.length &&
Number(input.selectionEnd) - Number(input.selectionStart) ===
Expand Down
4 changes: 1 addition & 3 deletions src/components/DateField/hooks/useDateFieldState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,7 @@ export function useDateFieldState(props: DateFieldStateOptions): DateFieldState
: placeholderDate;
const sectionsState = useSectionsState(sections, displayValue, validSegments);

const [selectedSections, setSelectedSections] = React.useState<number | 'all'>(() => {
return sectionsState.editableSections[0]?.previousEditableSection ?? -1;
});
const [selectedSections, setSelectedSections] = React.useState<number | 'all'>(-1);

const selectedSectionIndexes = React.useMemo<{
startIndex: number;
Expand Down
8 changes: 8 additions & 0 deletions src/components/DatePicker/DatePicker.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ $block: '.#{variables.$ns}date-picker';

display: inline-block;

outline: none;

&__field {
width: 100%;

Expand All @@ -15,6 +17,12 @@ $block: '.#{variables.$ns}date-picker';
}
}

&__popup-anchor {
position: absolute;
z-index: -1;
inset: 0;
}

&__popup-content {
outline: none;
}
Expand Down
96 changes: 31 additions & 65 deletions src/components/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';

import {TextInput, useFocusWithin, useMobile} from '@gravity-ui/uikit';
import {Calendar as CalendarIcon} from '@gravity-ui/icons';
import {Button, Icon, Popup, TextInput, useMobile} from '@gravity-ui/uikit';

import type {CalendarProps} from '../Calendar';
import {useDateFieldProps, useDateFieldState} from '../DateField';
import {Calendar, type CalendarProps} from '../Calendar';
import {DateField} from '../DateField';
import type {
AccessibilityProps,
DateFieldBase,
Expand All @@ -14,8 +15,8 @@ import type {
TextInputProps,
} from '../types';

import {DesktopCalendar, DesktopCalendarButton} from './DesktopCalendar';
import {MobileCalendar, MobileCalendarIcon} from './MobileCalendar';
import {useDatePickerProps} from './hooks/useDatePickerProps';
import {useDatePickerState} from './hooks/useDatePickerState';
import {b} from './utils';

Expand All @@ -32,16 +33,7 @@ export interface DatePickerProps
children?: (props: CalendarProps) => React.ReactNode;
}

export function DatePicker({
value,
defaultValue,
onUpdate,
className,
onFocus,
onBlur,
children,
...props
}: DatePickerProps) {
export function DatePicker({value, defaultValue, onUpdate, className, ...props}: DatePickerProps) {
const anchorRef = React.useRef<HTMLDivElement>(null);

const state = useDatePickerState({
Expand All @@ -51,70 +43,44 @@ export function DatePicker({
onUpdate,
});

const [isMobile] = useMobile();

const [isActive, setActive] = React.useState(false);
const {focusWithinProps} = useFocusWithin({
onFocusWithin: onFocus,
onBlurWithin: onBlur,
onFocusWithinChange(isFocusWithin) {
setActive(isFocusWithin);
},
});
const {groupProps, fieldProps, calendarButtonProps, popupProps, calendarProps, timeInputProps} =
useDatePickerProps(state, props);

const fieldState = useDateFieldState({
value: state.value,
onUpdate: state.setValue,
disabled: state.disabled,
readOnly: state.readOnly,
validationState: props.validationState,
minValue: props.minValue,
maxValue: props.maxValue,
isDateUnavailable: props.isDateUnavailable,
format: state.format,
placeholderValue: props.placeholderValue,
timeZone: props.timeZone,
});

const {inputProps} = useDateFieldProps(fieldState, props);
const [isMobile] = useMobile();

return (
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
<div
ref={anchorRef}
className={b(null, className)}
style={props.style}
{...focusWithinProps}
role="group"
aria-disabled={state.disabled || undefined}
onKeyDown={(e) => {
if (e.altKey && (e.key === 'ArrowDown' || e.key === 'ArrowUp')) {
e.preventDefault();
e.stopPropagation();
state.setOpen(true);
}
}}
>
<div className={b(null, className)} {...groupProps}>
{isMobile ? (
<MobileCalendar props={props} state={state} />
) : (
<DesktopCalendar
anchorRef={anchorRef}
props={props}
state={state}
renderCalendar={children}
/>
<div ref={anchorRef} className={b('popup-anchor')}>
<Popup anchorRef={anchorRef} {...popupProps}>
<div className={b('popup-content')}>
{typeof props.children === 'function' ? (
props.children(calendarProps)
) : (
<Calendar {...calendarProps} />
)}
{state.hasTime && (
<div className={b('time-field-wrapper')}>
<DateField {...timeInputProps} />
</div>
)}
</div>
</Popup>
</div>
)}
<TextInput
{...inputProps}
value={fieldState.isEmpty && !isActive && props.placeholder ? '' : inputProps.value}
{...fieldProps}
className={b('field', {mobile: isMobile})}
hasClear={!isMobile && inputProps.hasClear}
hasClear={!isMobile && fieldProps.hasClear}
rightContent={
isMobile ? (
<MobileCalendarIcon props={props} state={state} />
) : (
<DesktopCalendarButton props={props} state={state} />
<Button {...calendarButtonProps}>
<Icon data={CalendarIcon} />
</Button>
)
}
/>
Expand Down
118 changes: 0 additions & 118 deletions src/components/DatePicker/DesktopCalendar.tsx

This file was deleted.

Loading

0 comments on commit 24b89d7

Please sign in to comment.