Fix/scope hotkeys (#581)
* WIP * asd * Fix * Fix lint * Removed console log * asd * Removed isDefined * Fix/debounce company card onchange (#580) * Add internal state and debounce for editable text card * Use debounce for date fields too * Update refetch * Nit * Removed comments * Ménage --------- Co-authored-by: Emilien Chauvet <emilien.chauvet.enpc@gmail.com>
This commit is contained in:
@ -1,11 +1,11 @@
|
||||
import { ReactElement } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { HotkeysScopeStackItem } from '@/hotkeys/types/internal/HotkeysScopeStackItems';
|
||||
import { HotkeysScope } from '@/hotkeys/types/internal/HotkeysScope';
|
||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||
|
||||
import { useEditableCell } from './hooks/useCloseEditableCell';
|
||||
import { useCurrentCellEditMode } from './hooks/useCurrentCellEditMode';
|
||||
import { useEditableCell } from './hooks/useEditableCell';
|
||||
import { useIsSoftFocusOnCurrentCell } from './hooks/useIsSoftFocusOnCurrentCell';
|
||||
import { useSetSoftFocusOnCurrentCell } from './hooks/useSetSoftFocusOnCurrentCell';
|
||||
import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
||||
@ -28,7 +28,7 @@ type OwnProps = {
|
||||
nonEditModeContent: ReactElement;
|
||||
editModeHorizontalAlign?: 'left' | 'right';
|
||||
editModeVerticalPosition?: 'over' | 'below';
|
||||
editHotkeysScope?: HotkeysScopeStackItem;
|
||||
editHotkeysScope?: HotkeysScope;
|
||||
};
|
||||
|
||||
export function EditableCell({
|
||||
@ -60,9 +60,9 @@ export function EditableCell({
|
||||
scope: InternalHotkeysScope.CellEditMode,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
setSoftFocusOnCurrentCell();
|
||||
}
|
||||
|
||||
setSoftFocusOnCurrentCell();
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -7,7 +7,7 @@ import { useListenClickOutsideArrayOfRef } from '@/ui/hooks/useListenClickOutsid
|
||||
import { useMoveSoftFocus } from '@/ui/tables/hooks/useMoveSoftFocus';
|
||||
import { overlayBackground } from '@/ui/themes/effects';
|
||||
|
||||
import { useEditableCell } from './hooks/useCloseEditableCell';
|
||||
import { useEditableCell } from './hooks/useEditableCell';
|
||||
|
||||
export const EditableCellEditModeContainer = styled.div<OwnProps>`
|
||||
align-items: center;
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import React from 'react';
|
||||
|
||||
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
||||
import { HotkeysScopeStackItem } from '@/hotkeys/types/internal/HotkeysScopeStackItems';
|
||||
import { HotkeysScope } from '@/hotkeys/types/internal/HotkeysScope';
|
||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||
import { isNonTextWritingKey } from '@/utils/hotkeys/isNonTextWritingKey';
|
||||
|
||||
import { useEditableCell } from './hooks/useCloseEditableCell';
|
||||
import { useEditableCell } from './hooks/useEditableCell';
|
||||
import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
||||
|
||||
export function EditableCellSoftFocusMode({
|
||||
children,
|
||||
editHotkeysScope,
|
||||
}: React.PropsWithChildren<{ editHotkeysScope?: HotkeysScopeStackItem }>) {
|
||||
}: React.PropsWithChildren<{ editHotkeysScope?: HotkeysScope }>) {
|
||||
const { closeEditableCell, openEditableCell } = useEditableCell();
|
||||
|
||||
useScopedHotkeys(
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useAddToHotkeysScopeStack } from '@/hotkeys/hooks/useAddToHotkeysScopeStack';
|
||||
import { useRemoveHighestHotkeysScopeStackItem } from '@/hotkeys/hooks/useRemoveHighestHotkeysScopeStackItem';
|
||||
import { HotkeysScopeStackItem } from '@/hotkeys/types/internal/HotkeysScopeStackItems';
|
||||
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
||||
import { HotkeysScope } from '@/hotkeys/types/internal/HotkeysScope';
|
||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||
import { useCloseCurrentCellInEditMode } from '@/ui/tables/hooks/useClearCellInEditMode';
|
||||
import { isSoftFocusActiveState } from '@/ui/tables/states/isSoftFocusActiveState';
|
||||
import { isSomeInputInEditModeState } from '@/ui/tables/states/isSomeInputInEditModeState';
|
||||
@ -12,21 +12,18 @@ import { useCurrentCellEditMode } from './useCurrentCellEditMode';
|
||||
export function useEditableCell() {
|
||||
const { setCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||
|
||||
const addToHotkeysScopeStack = useAddToHotkeysScopeStack();
|
||||
const setHotkeysScope = useSetHotkeysScope();
|
||||
|
||||
const closeCurrentCellInEditMode = useCloseCurrentCellInEditMode();
|
||||
|
||||
const removeHighestHotkeysScopedStackItem =
|
||||
useRemoveHighestHotkeysScopeStackItem();
|
||||
|
||||
function closeEditableCell() {
|
||||
closeCurrentCellInEditMode();
|
||||
removeHighestHotkeysScopedStackItem();
|
||||
setHotkeysScope(InternalHotkeysScope.TableSoftFocus);
|
||||
}
|
||||
|
||||
const openEditableCell = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
(hotkeysScopeStackItem: HotkeysScopeStackItem) => {
|
||||
(hotkeysScope: HotkeysScope) => {
|
||||
const isSomeInputInEditMode = snapshot
|
||||
.getLoadable(isSomeInputInEditModeState)
|
||||
.valueOrThrow();
|
||||
@ -37,10 +34,10 @@ export function useEditableCell() {
|
||||
|
||||
setCurrentCellInEditMode();
|
||||
|
||||
addToHotkeysScopeStack(hotkeysScopeStackItem);
|
||||
setHotkeysScope(hotkeysScope.scope);
|
||||
}
|
||||
},
|
||||
[setCurrentCellInEditMode, addToHotkeysScopeStack],
|
||||
[setCurrentCellInEditMode, setHotkeysScope],
|
||||
);
|
||||
|
||||
return {
|
||||
@ -1,7 +1,7 @@
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { useAddToHotkeysScopeStack } from '@/hotkeys/hooks/useAddToHotkeysScopeStack';
|
||||
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||
import { useSetSoftFocusPosition } from '@/ui/tables/hooks/useSetSoftFocusPosition';
|
||||
@ -34,16 +34,16 @@ export function useSetSoftFocusOnCurrentCell() {
|
||||
|
||||
const [, setIsSoftFocusActive] = useRecoilState(isSoftFocusActiveState);
|
||||
|
||||
const addToHotkeysScopeStack = useAddToHotkeysScopeStack();
|
||||
const setHotkeysScope = useSetHotkeysScope();
|
||||
|
||||
return useCallback(() => {
|
||||
setSoftFocusPosition(currentTablePosition);
|
||||
setIsSoftFocusActive(true);
|
||||
addToHotkeysScopeStack({ scope: InternalHotkeysScope.TableSoftFocus });
|
||||
setHotkeysScope(InternalHotkeysScope.TableSoftFocus);
|
||||
}, [
|
||||
setSoftFocusPosition,
|
||||
currentTablePosition,
|
||||
setIsSoftFocusActive,
|
||||
addToHotkeysScopeStack,
|
||||
setHotkeysScope,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { InplaceInputDateEditMode } from '@/ui/inplace-inputs/components/InplaceInputDateEditMode';
|
||||
|
||||
import { useEditableCell } from '../hooks/useCloseEditableCell';
|
||||
import { useEditableCell } from '../hooks/useEditableCell';
|
||||
|
||||
export type EditableDateProps = {
|
||||
value: Date;
|
||||
|
||||
@ -7,7 +7,7 @@ import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysSc
|
||||
import { InplaceInputTextEditMode } from '@/ui/inplace-inputs/components/InplaceInputTextEditMode';
|
||||
import { useMoveSoftFocus } from '@/ui/tables/hooks/useMoveSoftFocus';
|
||||
|
||||
import { useEditableCell } from '../hooks/useCloseEditableCell';
|
||||
import { useEditableCell } from '../hooks/useEditableCell';
|
||||
|
||||
type OwnProps = {
|
||||
firstValue: string;
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
import { ChangeEvent, useRef } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { usePreviousHotkeysScope } from '@/hotkeys/hooks/internal/usePreviousHotkeysScope';
|
||||
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||
|
||||
type OwnProps = Omit<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
@ -52,10 +57,37 @@ export function TextInput({
|
||||
fullWidth,
|
||||
...props
|
||||
}: OwnProps): JSX.Element {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const {
|
||||
goBackToPreviousHotkeysScope,
|
||||
setHotkeysScopeAndMemorizePreviousScope,
|
||||
} = usePreviousHotkeysScope();
|
||||
|
||||
function handleFocus() {
|
||||
setHotkeysScopeAndMemorizePreviousScope(InternalHotkeysScope.TextInput);
|
||||
}
|
||||
|
||||
function handleBlur() {
|
||||
goBackToPreviousHotkeysScope();
|
||||
}
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Enter, Key.Escape],
|
||||
() => {
|
||||
inputRef.current?.blur();
|
||||
},
|
||||
InternalHotkeysScope.TextInput,
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
{label && <StyledLabel>{label}</StyledLabel>}
|
||||
<StyledInput
|
||||
ref={inputRef}
|
||||
tabIndex={props.tabIndex ?? 0}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
fullWidth={fullWidth ?? false}
|
||||
value={value}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { activeTableFiltersScopedState } from '@/filters-and-sorts/states/activeTableFiltersScopedState';
|
||||
import { filterDropdownSearchInputScopedState } from '@/filters-and-sorts/states/filterDropdownSearchInputScopedState';
|
||||
import { isFilterDropdownOperandSelectUnfoldedScopedState } from '@/filters-and-sorts/states/isFilterDropdownOperandSelectUnfoldedScopedState';
|
||||
import { selectedOperandInDropdownScopedState } from '@/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
||||
import { tableFilterDefinitionUsedInDropdownScopedState } from '@/filters-and-sorts/states/tableFilterDefinitionUsedInDropdownScopedState';
|
||||
import { useHotkeysScopeOnBooleanState } from '@/hotkeys/hooks/useHotkeysScopeOnBooleanState';
|
||||
import { useScopedHotkeys } from '@/hotkeys/hooks/useScopedHotkeys';
|
||||
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
||||
@ -23,11 +25,6 @@ import { FilterDropdownTextSearchInput } from './FilterDropdownTextSearchInput';
|
||||
export function FilterDropdownButton() {
|
||||
const [isUnfolded, setIsUnfolded] = useState(false);
|
||||
|
||||
useHotkeysScopeOnBooleanState(
|
||||
{ scope: InternalHotkeysScope.TableHeaderDropdownButton },
|
||||
isUnfolded,
|
||||
);
|
||||
|
||||
const [
|
||||
isFilterDropdownOperandSelectUnfolded,
|
||||
setIsFilterDropdownOperandSelectUnfolded,
|
||||
@ -71,18 +68,27 @@ export function FilterDropdownButton() {
|
||||
|
||||
const isFilterSelected = (activeTableFilters?.length ?? 0) > 0;
|
||||
|
||||
const setHotkeysScope = useSetHotkeysScope();
|
||||
|
||||
function handleIsUnfoldedChange(newIsUnfolded: boolean) {
|
||||
if (newIsUnfolded) {
|
||||
setIsUnfolded(true);
|
||||
} else {
|
||||
if (tableFilterDefinitionUsedInDropdown?.type === 'entity') {
|
||||
setHotkeysScope(InternalHotkeysScope.Table);
|
||||
}
|
||||
setIsUnfolded(false);
|
||||
resetState();
|
||||
}
|
||||
}
|
||||
|
||||
useHotkeysScopeOnBooleanState(
|
||||
{ scope: InternalHotkeysScope.RelationPicker },
|
||||
tableFilterDefinitionUsedInDropdown?.type === 'entity',
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
() => {
|
||||
handleIsUnfoldedChange(false);
|
||||
},
|
||||
InternalHotkeysScope.RelationPicker,
|
||||
[handleIsUnfoldedChange],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@ -3,6 +3,8 @@ import { filterDropdownSearchInputScopedState } from '@/filters-and-sorts/states
|
||||
import { selectedOperandInDropdownScopedState } from '@/filters-and-sorts/states/selectedOperandInDropdownScopedState';
|
||||
import { tableFilterDefinitionUsedInDropdownScopedState } from '@/filters-and-sorts/states/tableFilterDefinitionUsedInDropdownScopedState';
|
||||
import { getOperandsForFilterType } from '@/filters-and-sorts/utils/getOperandsForFilterType';
|
||||
import { useSetHotkeysScope } from '@/hotkeys/hooks/useSetHotkeysScope';
|
||||
import { InternalHotkeysScope } from '@/hotkeys/types/internal/InternalHotkeysScope';
|
||||
import { useRecoilScopedState } from '@/recoil-scope/hooks/useRecoilScopedState';
|
||||
import { useRecoilScopedValue } from '@/recoil-scope/hooks/useRecoilScopedValue';
|
||||
import { TableContext } from '@/ui/tables/states/TableContext';
|
||||
@ -33,6 +35,8 @@ export function FilterDropdownFilterSelect() {
|
||||
TableContext,
|
||||
);
|
||||
|
||||
const setHotkeysScope = useSetHotkeysScope();
|
||||
|
||||
return (
|
||||
<DropdownMenuItemContainer style={{ maxHeight: '300px' }}>
|
||||
{availableTableFilters.map((availableTableFilter, index) => (
|
||||
@ -40,6 +44,11 @@ export function FilterDropdownFilterSelect() {
|
||||
key={`select-filter-${index}`}
|
||||
onClick={() => {
|
||||
setTableFilterDefinitionUsedInDropdown(availableTableFilter);
|
||||
|
||||
if (availableTableFilter.type === 'entity') {
|
||||
setHotkeysScope(InternalHotkeysScope.RelationPicker);
|
||||
}
|
||||
|
||||
setSelectedOperandInDropdown(
|
||||
getOperandsForFilterType(availableTableFilter.type)?.[0],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user