Fixed date input fields (#9442)
- Fixed date input fields : proper hotkey management, like other fields - Removed DropdownUnmountEffect which was causing many bugs.
This commit is contained in:
@ -1,6 +1,10 @@
|
|||||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated This hook uses useEffect
|
||||||
|
* Use event handlers and imperative code to manage hotkey scope changes.
|
||||||
|
*/
|
||||||
export const useHotkeyScopeOnMount = (hotkeyScope: string) => {
|
export const useHotkeyScopeOnMount = (hotkeyScope: string) => {
|
||||||
const {
|
const {
|
||||||
goBackToPreviousHotkeyScope,
|
goBackToPreviousHotkeyScope,
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export const DateFieldInput = ({
|
|||||||
onClear,
|
onClear,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
}: DateFieldInputProps) => {
|
}: DateFieldInputProps) => {
|
||||||
const { fieldValue, setDraftValue } = useDateField();
|
const { fieldValue, setDraftValue, hotkeyScope } = useDateField();
|
||||||
|
|
||||||
const persistField = usePersistField();
|
const persistField = usePersistField();
|
||||||
|
|
||||||
@ -77,6 +77,7 @@ export const DateFieldInput = ({
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onClear={handleClear}
|
onClear={handleClear}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
hotkeyScope={hotkeyScope}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export const DateTimeFieldInput = ({
|
|||||||
onClear,
|
onClear,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
}: DateTimeFieldInputProps) => {
|
}: DateTimeFieldInputProps) => {
|
||||||
const { fieldValue, setDraftValue } = useDateTimeField();
|
const { fieldValue, setDraftValue, hotkeyScope } = useDateTimeField();
|
||||||
|
|
||||||
const persistField = usePersistField();
|
const persistField = usePersistField();
|
||||||
|
|
||||||
@ -80,6 +80,7 @@ export const DateTimeFieldInput = ({
|
|||||||
isDateTimeInput
|
isDateTimeInput
|
||||||
onClear={handleClear}
|
onClear={handleClear}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
|
hotkeyScope={hotkeyScope}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { Nullable } from 'twenty-ui';
|
import { Nullable } from 'twenty-ui';
|
||||||
|
|
||||||
|
import { useRegisterInputEvents } from '@/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents';
|
||||||
import {
|
import {
|
||||||
InternalDatePicker,
|
InternalDatePicker,
|
||||||
MONTH_AND_YEAR_DROPDOWN_ID,
|
MONTH_AND_YEAR_DROPDOWN_ID,
|
||||||
@ -8,7 +9,6 @@ import {
|
|||||||
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
|
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
|
||||||
} from '@/ui/input/components/internal/date/components/InternalDatePicker';
|
} from '@/ui/input/components/internal/date/components/InternalDatePicker';
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
|
||||||
|
|
||||||
export type DateInputProps = {
|
export type DateInputProps = {
|
||||||
value: Nullable<Date>;
|
value: Nullable<Date>;
|
||||||
@ -24,6 +24,7 @@ export type DateInputProps = {
|
|||||||
onClear?: () => void;
|
onClear?: () => void;
|
||||||
onSubmit?: (newDate: Nullable<Date>) => void;
|
onSubmit?: (newDate: Nullable<Date>) => void;
|
||||||
hideHeaderInput?: boolean;
|
hideHeaderInput?: boolean;
|
||||||
|
hotkeyScope: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DateInput = ({
|
export const DateInput = ({
|
||||||
@ -37,6 +38,7 @@ export const DateInput = ({
|
|||||||
onClear,
|
onClear,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
hideHeaderInput,
|
hideHeaderInput,
|
||||||
|
hotkeyScope,
|
||||||
}: DateInputProps) => {
|
}: DateInputProps) => {
|
||||||
const [internalValue, setInternalValue] = useState(value);
|
const [internalValue, setInternalValue] = useState(value);
|
||||||
|
|
||||||
@ -65,17 +67,39 @@ export const DateInput = ({
|
|||||||
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
|
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
|
||||||
);
|
);
|
||||||
|
|
||||||
useListenClickOutside({
|
const handleEnter = () => {
|
||||||
refs: [wrapperRef],
|
closeDropdownYearSelect();
|
||||||
listenerId: 'DateInput',
|
closeDropdownMonthSelect();
|
||||||
callback: (event) => {
|
closeDropdown();
|
||||||
event.stopImmediatePropagation();
|
|
||||||
|
|
||||||
closeDropdownYearSelect();
|
onEnter?.(internalValue);
|
||||||
closeDropdownMonthSelect();
|
};
|
||||||
closeDropdown();
|
|
||||||
onClickOutside(event, internalValue);
|
const handleEscape = () => {
|
||||||
},
|
closeDropdownYearSelect();
|
||||||
|
closeDropdownMonthSelect();
|
||||||
|
closeDropdown();
|
||||||
|
|
||||||
|
onEscape?.(internalValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClickOutside = (event: MouseEvent | TouchEvent) => {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
|
||||||
|
closeDropdownYearSelect();
|
||||||
|
closeDropdownMonthSelect();
|
||||||
|
closeDropdown();
|
||||||
|
|
||||||
|
onClickOutside(event, internalValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
useRegisterInputEvents({
|
||||||
|
inputRef: wrapperRef,
|
||||||
|
inputValue: internalValue,
|
||||||
|
onEnter: handleEnter,
|
||||||
|
onEscape: handleEscape,
|
||||||
|
onClickOutside: handleClickOutside,
|
||||||
|
hotkeyScope: hotkeyScope,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import ReactDatePicker from 'react-datepicker';
|
import ReactDatePicker from 'react-datepicker';
|
||||||
import { Key } from 'ts-key-enum';
|
|
||||||
import {
|
import {
|
||||||
IconCalendarX,
|
IconCalendarX,
|
||||||
MenuItemLeftContent,
|
MenuItemLeftContent,
|
||||||
@ -305,11 +304,8 @@ export const InternalDatePicker = ({
|
|||||||
date,
|
date,
|
||||||
onChange,
|
onChange,
|
||||||
onMouseSelect,
|
onMouseSelect,
|
||||||
onEnter,
|
|
||||||
onEscape,
|
|
||||||
clearable = true,
|
clearable = true,
|
||||||
isDateTimeInput,
|
isDateTimeInput,
|
||||||
keyboardEventsDisabled,
|
|
||||||
onClear,
|
onClear,
|
||||||
isRelative,
|
isRelative,
|
||||||
relativeDate,
|
relativeDate,
|
||||||
@ -345,31 +341,6 @@ export const InternalDatePicker = ({
|
|||||||
onMouseSelect?.(newDate);
|
onMouseSelect?.(newDate);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
||||||
if (isDefined(keyboardEventsDisabled) && keyboardEventsDisabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event.key) {
|
|
||||||
case Key.Enter: {
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
closeDropdowns();
|
|
||||||
onEnter?.(internalDate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Key.Escape: {
|
|
||||||
event.stopPropagation();
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
closeDropdowns();
|
|
||||||
onEscape?.(internalDate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleChangeMonth = (month: number) => {
|
const handleChangeMonth = (month: number) => {
|
||||||
const newDate = new Date(internalDate);
|
const newDate = new Date(internalDate);
|
||||||
newDate.setMonth(month);
|
newDate.setMonth(month);
|
||||||
@ -469,7 +440,7 @@ export const InternalDatePicker = ({
|
|||||||
const selectedDates = isRelative ? highlightedDates : [dateToUse];
|
const selectedDates = isRelative ? highlightedDates : [dateToUse];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer onKeyDown={handleKeyDown} calendarDisabled={isRelative}>
|
<StyledContainer calendarDisabled={isRelative}>
|
||||||
<div className={clearable ? 'clearable ' : ''}>
|
<div className={clearable ? 'clearable ' : ''}>
|
||||||
<ReactDatePicker
|
<ReactDatePicker
|
||||||
open={true}
|
open={true}
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import { Keys } from 'react-hotkeys-hook';
|
|||||||
import { useDropdown } from '../hooks/useDropdown';
|
import { useDropdown } from '../hooks/useDropdown';
|
||||||
|
|
||||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||||
import { DropdownUnmountEffect } from '@/ui/layout/dropdown/components/DropdownUnmountEffect';
|
|
||||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponeInstanceContext';
|
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponeInstanceContext';
|
||||||
import { dropdownHotkeyComponentState } from '@/ui/layout/dropdown/states/dropdownHotkeyComponentState';
|
import { dropdownHotkeyComponentState } from '@/ui/layout/dropdown/states/dropdownHotkeyComponentState';
|
||||||
import { dropdownMaxHeightComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownMaxHeightComponentStateV2';
|
import { dropdownMaxHeightComponentStateV2 } from '@/ui/layout/dropdown/states/dropdownMaxHeightComponentStateV2';
|
||||||
@ -165,7 +164,6 @@ export const Dropdown = ({
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
</DropdownScope>
|
</DropdownScope>
|
||||||
<DropdownUnmountEffect dropdownId={dropdownId} />
|
|
||||||
</DropdownComponentInstanceContext.Provider>
|
</DropdownComponentInstanceContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
export const DropdownUnmountEffect = ({
|
|
||||||
dropdownId,
|
|
||||||
}: {
|
|
||||||
dropdownId: string;
|
|
||||||
}) => {
|
|
||||||
const { closeDropdown } = useDropdownV2();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
closeDropdown(dropdownId);
|
|
||||||
};
|
|
||||||
}, [closeDropdown, dropdownId]);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user