eba997be98
# Replace hotkey scopes by focus stack (Part 6 - Remove Hotkey scopes) This PR is the last part of a refactoring aiming to deprecate the hotkey scopes api in favor of the new focus stack api which is more robust. Part 1: https://github.com/twentyhq/twenty/pull/12673 Part 2: https://github.com/twentyhq/twenty/pull/12798 Part 3: https://github.com/twentyhq/twenty/pull/12910 Part 4: https://github.com/twentyhq/twenty/pull/12933 Part 5: https://github.com/twentyhq/twenty/pull/13106 In this part, we completely remove the hotkey scopes.
127 lines
3.4 KiB
TypeScript
127 lines
3.4 KiB
TypeScript
import { useRef, useState } from 'react';
|
|
|
|
import { useRegisterInputEvents } from '@/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents';
|
|
import {
|
|
DateTimePicker,
|
|
MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID,
|
|
MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID,
|
|
} from '@/ui/input/components/internal/date/components/InternalDatePicker';
|
|
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
|
import { currentFocusIdSelector } from '@/ui/utilities/focus/states/currentFocusIdSelector';
|
|
import { useRecoilCallback } from 'recoil';
|
|
import { Nullable } from 'twenty-ui/utilities';
|
|
|
|
export type DateInputProps = {
|
|
instanceId: string;
|
|
value: Nullable<Date>;
|
|
onEnter: (newDate: Nullable<Date>) => void;
|
|
onEscape: (newDate: Nullable<Date>) => void;
|
|
onClickOutside: (
|
|
event: MouseEvent | TouchEvent,
|
|
newDate: Nullable<Date>,
|
|
) => void;
|
|
clearable?: boolean;
|
|
onChange?: (newDate: Nullable<Date>) => void;
|
|
isDateTimeInput?: boolean;
|
|
onClear?: () => void;
|
|
onSubmit?: (newDate: Nullable<Date>) => void;
|
|
hideHeaderInput?: boolean;
|
|
};
|
|
|
|
export const DateInput = ({
|
|
instanceId,
|
|
value,
|
|
onEnter,
|
|
onEscape,
|
|
onClickOutside,
|
|
clearable,
|
|
onChange,
|
|
isDateTimeInput,
|
|
onClear,
|
|
onSubmit,
|
|
hideHeaderInput,
|
|
}: DateInputProps) => {
|
|
const [internalValue, setInternalValue] = useState(value);
|
|
|
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
|
|
const handleChange = (newDate: Date | null) => {
|
|
setInternalValue(newDate);
|
|
onChange?.(newDate);
|
|
};
|
|
|
|
const handleClear = () => {
|
|
setInternalValue(null);
|
|
onClear?.();
|
|
};
|
|
|
|
const handleClose = (newDate: Date | null) => {
|
|
setInternalValue(newDate);
|
|
onSubmit?.(newDate);
|
|
};
|
|
|
|
const { closeDropdown: closeDropdownMonthSelect } = useCloseDropdown();
|
|
const { closeDropdown: closeDropdownYearSelect } = useCloseDropdown();
|
|
|
|
const handleEnter = () => {
|
|
closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
|
|
closeDropdownMonthSelect(MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID);
|
|
|
|
onEnter(internalValue);
|
|
};
|
|
|
|
const handleEscape = () => {
|
|
closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
|
|
closeDropdownMonthSelect(MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID);
|
|
|
|
onEscape(internalValue);
|
|
};
|
|
|
|
const handleClickOutside = useRecoilCallback(
|
|
({ snapshot }) =>
|
|
(event: MouseEvent | TouchEvent) => {
|
|
const currentFocusId = snapshot
|
|
.getLoadable(currentFocusIdSelector)
|
|
.getValue();
|
|
|
|
if (currentFocusId === instanceId) {
|
|
closeDropdownYearSelect(MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID);
|
|
closeDropdownMonthSelect(MONTH_AND_YEAR_DROPDOWN_MONTH_SELECT_ID);
|
|
onClickOutside(event, internalValue);
|
|
}
|
|
},
|
|
[
|
|
instanceId,
|
|
closeDropdownYearSelect,
|
|
closeDropdownMonthSelect,
|
|
onClickOutside,
|
|
internalValue,
|
|
],
|
|
);
|
|
|
|
useRegisterInputEvents({
|
|
focusId: instanceId,
|
|
inputRef: wrapperRef,
|
|
inputValue: internalValue,
|
|
onEnter: handleEnter,
|
|
onEscape: handleEscape,
|
|
onClickOutside: handleClickOutside,
|
|
});
|
|
|
|
return (
|
|
<div ref={wrapperRef}>
|
|
<DateTimePicker
|
|
date={internalValue ?? null}
|
|
onChange={handleChange}
|
|
onClose={handleClose}
|
|
clearable={clearable ?? false}
|
|
onEnter={onEnter}
|
|
onEscape={onEscape}
|
|
onClear={handleClear}
|
|
hideHeaderInput={hideHeaderInput}
|
|
isDateTimeInput={isDateTimeInput}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|