Fix hover on table cells when the command menu is opened (#10446)
This PR allows the table cell hover to be accessible even when the command menu is opened. I extracted the hotkeys logic from `RecordTableCellSoftFocusMode` into `RecordTableCellSoftFocusModeHotkeysSetterEffect`. This component is mounted conditionally if the hotkey scope is `TableSoftFocus`. By doing so, the table cell hotkey scopes are not available when the command menu is opened. Before https://github.com/user-attachments/assets/f0925565-f00a-4962-b18d-3c1617f77dd0 After https://github.com/user-attachments/assets/49ec9195-3110-46d7-abb6-12854a8bb991 --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -34,10 +34,6 @@ export const RightDrawerRecord = () => {
|
|||||||
throw new Error(`Object name is not defined`);
|
throw new Error(`Object name is not defined`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!viewableRecordId && !isNewViewableRecordLoading) {
|
|
||||||
throw new Error(`Record id is not defined`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { objectNameSingular, objectRecordId } = useRecordShowPage(
|
const { objectNameSingular, objectRecordId } = useRecordShowPage(
|
||||||
viewableRecordNameSingular ?? '',
|
viewableRecordNameSingular ?? '',
|
||||||
viewableRecordId ?? '',
|
viewableRecordId ?? '',
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useHandleContainerMouseEnter } from '@/object-record/record-table/hooks
|
|||||||
import { useUpsertTableRecordNoGroup } from '@/object-record/record-table/hooks/internal/useUpsertTableRecordNoGroup';
|
import { useUpsertTableRecordNoGroup } from '@/object-record/record-table/hooks/internal/useUpsertTableRecordNoGroup';
|
||||||
import { useRecordTableMoveFocus } from '@/object-record/record-table/hooks/useRecordTableMoveFocus';
|
import { useRecordTableMoveFocus } from '@/object-record/record-table/hooks/useRecordTableMoveFocus';
|
||||||
import { useCloseRecordTableCellNoGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup';
|
import { useCloseRecordTableCellNoGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellNoGroup';
|
||||||
import { useMoveSoftFocusToCellOnHoverV2 } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCellOnHoverV2';
|
import { useMoveSoftFocusToCurrentCellOnHover } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover';
|
||||||
import {
|
import {
|
||||||
OpenTableCellArgs,
|
OpenTableCellArgs,
|
||||||
useOpenRecordTableCellV2,
|
useOpenRecordTableCellV2,
|
||||||
@ -55,11 +55,13 @@ export const RecordTableNoRecordGroupBodyContextProvider = ({
|
|||||||
closeTableCellNoGroup();
|
closeTableCellNoGroup();
|
||||||
};
|
};
|
||||||
|
|
||||||
const { moveSoftFocusToCell } =
|
const { moveSoftFocusToCurrentCell } =
|
||||||
useMoveSoftFocusToCellOnHoverV2(recordTableId);
|
useMoveSoftFocusToCurrentCellOnHover(recordTableId);
|
||||||
|
|
||||||
const handleMoveSoftFocusToCell = (cellPosition: TableCellPosition) => {
|
const handleMoveSoftFocusToCurrentCell = (
|
||||||
moveSoftFocusToCell(cellPosition);
|
cellPosition: TableCellPosition,
|
||||||
|
) => {
|
||||||
|
moveSoftFocusToCurrentCell(cellPosition);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { triggerActionMenuDropdown } = useTriggerActionMenuDropdown({
|
const { triggerActionMenuDropdown } = useTriggerActionMenuDropdown({
|
||||||
@ -84,7 +86,7 @@ export const RecordTableNoRecordGroupBodyContextProvider = ({
|
|||||||
onOpenTableCell: handleOpenTableCell,
|
onOpenTableCell: handleOpenTableCell,
|
||||||
onMoveFocus: handleMoveFocus,
|
onMoveFocus: handleMoveFocus,
|
||||||
onCloseTableCell: handleCloseTableCell,
|
onCloseTableCell: handleCloseTableCell,
|
||||||
onMoveSoftFocusToCell: handleMoveSoftFocusToCell,
|
onMoveSoftFocusToCurrentCell: handleMoveSoftFocusToCurrentCell,
|
||||||
onActionMenuDropdownOpened: handleActionMenuDropdown,
|
onActionMenuDropdownOpened: handleActionMenuDropdown,
|
||||||
onCellMouseEnter: handleContainerMouseEnter,
|
onCellMouseEnter: handleContainerMouseEnter,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useHandleContainerMouseEnter } from '@/object-record/record-table/hooks
|
|||||||
import { useUpsertTableRecordInGroup } from '@/object-record/record-table/hooks/internal/useUpsertTableRecordInGroup';
|
import { useUpsertTableRecordInGroup } from '@/object-record/record-table/hooks/internal/useUpsertTableRecordInGroup';
|
||||||
import { useRecordTableMoveFocus } from '@/object-record/record-table/hooks/useRecordTableMoveFocus';
|
import { useRecordTableMoveFocus } from '@/object-record/record-table/hooks/useRecordTableMoveFocus';
|
||||||
import { useCloseRecordTableCellInGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup';
|
import { useCloseRecordTableCellInGroup } from '@/object-record/record-table/record-table-cell/hooks/internal/useCloseRecordTableCellInGroup';
|
||||||
import { useMoveSoftFocusToCellOnHoverV2 } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCellOnHoverV2';
|
import { useMoveSoftFocusToCurrentCellOnHover } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover';
|
||||||
import {
|
import {
|
||||||
OpenTableCellArgs,
|
OpenTableCellArgs,
|
||||||
useOpenRecordTableCellV2,
|
useOpenRecordTableCellV2,
|
||||||
@ -59,11 +59,13 @@ export const RecordTableRecordGroupBodyContextProvider = ({
|
|||||||
closeTableCellInGroup();
|
closeTableCellInGroup();
|
||||||
};
|
};
|
||||||
|
|
||||||
const { moveSoftFocusToCell } =
|
const { moveSoftFocusToCurrentCell } =
|
||||||
useMoveSoftFocusToCellOnHoverV2(recordTableId);
|
useMoveSoftFocusToCurrentCellOnHover(recordTableId);
|
||||||
|
|
||||||
const handleMoveSoftFocusToCell = (cellPosition: TableCellPosition) => {
|
const handleMoveSoftFocusToCurrentCell = (
|
||||||
moveSoftFocusToCell(cellPosition);
|
cellPosition: TableCellPosition,
|
||||||
|
) => {
|
||||||
|
moveSoftFocusToCurrentCell(cellPosition);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { triggerActionMenuDropdown } = useTriggerActionMenuDropdown({
|
const { triggerActionMenuDropdown } = useTriggerActionMenuDropdown({
|
||||||
@ -88,7 +90,7 @@ export const RecordTableRecordGroupBodyContextProvider = ({
|
|||||||
onOpenTableCell: handleOpenTableCell,
|
onOpenTableCell: handleOpenTableCell,
|
||||||
onMoveFocus: handleMoveFocus,
|
onMoveFocus: handleMoveFocus,
|
||||||
onCloseTableCell: handlecloseTableCellInGroup,
|
onCloseTableCell: handlecloseTableCellInGroup,
|
||||||
onMoveSoftFocusToCell: handleMoveSoftFocusToCell,
|
onMoveSoftFocusToCurrentCell: handleMoveSoftFocusToCurrentCell,
|
||||||
onActionMenuDropdownOpened: handleActionMenuDropdown,
|
onActionMenuDropdownOpened: handleActionMenuDropdown,
|
||||||
onCellMouseEnter: handleContainerMouseEnter,
|
onCellMouseEnter: handleContainerMouseEnter,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -94,7 +94,7 @@ const meta: Meta = {
|
|||||||
onOpenTableCell: () => {},
|
onOpenTableCell: () => {},
|
||||||
onMoveFocus: () => {},
|
onMoveFocus: () => {},
|
||||||
onCloseTableCell: () => {},
|
onCloseTableCell: () => {},
|
||||||
onMoveSoftFocusToCell: () => {},
|
onMoveSoftFocusToCurrentCell: () => {},
|
||||||
onActionMenuDropdownOpened: () => {},
|
onActionMenuDropdownOpened: () => {},
|
||||||
onCellMouseEnter: () => {},
|
onCellMouseEnter: () => {},
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export type RecordTableBodyContextProps = {
|
|||||||
onOpenTableCell: (args: OpenTableCellArgs) => void;
|
onOpenTableCell: (args: OpenTableCellArgs) => void;
|
||||||
onMoveFocus: (direction: MoveFocusDirection) => void;
|
onMoveFocus: (direction: MoveFocusDirection) => void;
|
||||||
onCloseTableCell: () => void;
|
onCloseTableCell: () => void;
|
||||||
onMoveSoftFocusToCell: (cellPosition: TableCellPosition) => void;
|
onMoveSoftFocusToCurrentCell: (cellPosition: TableCellPosition) => void;
|
||||||
onActionMenuDropdownOpened: (
|
onActionMenuDropdownOpened: (
|
||||||
event: React.MouseEvent,
|
event: React.MouseEvent,
|
||||||
recordId: string,
|
recordId: string,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
import { useMoveSoftFocusToCellOnHoverV2 } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCellOnHoverV2';
|
import { useMoveSoftFocusToCurrentCellOnHover } from '@/object-record/record-table/record-table-cell/hooks/useMoveSoftFocusToCurrentCellOnHover';
|
||||||
import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
|
import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
|
||||||
import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState';
|
import { isSoftFocusOnTableCellComponentFamilyState } from '@/object-record/record-table/states/isSoftFocusOnTableCellComponentFamilyState';
|
||||||
import { isSoftFocusUsingMouseState } from '@/object-record/record-table/states/isSoftFocusUsingMouseState';
|
import { isSoftFocusUsingMouseState } from '@/object-record/record-table/states/isSoftFocusUsingMouseState';
|
||||||
@ -18,8 +18,8 @@ export const useHandleContainerMouseEnter = ({
|
|||||||
}: {
|
}: {
|
||||||
recordTableId: string;
|
recordTableId: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { moveSoftFocusToCell } =
|
const { moveSoftFocusToCurrentCell } =
|
||||||
useMoveSoftFocusToCellOnHoverV2(recordTableId);
|
useMoveSoftFocusToCurrentCellOnHover(recordTableId);
|
||||||
|
|
||||||
const currentTableCellInEditModePositionState =
|
const currentTableCellInEditModePositionState =
|
||||||
useRecoilComponentCallbackStateV2(
|
useRecoilComponentCallbackStateV2(
|
||||||
@ -56,7 +56,7 @@ export const useHandleContainerMouseEnter = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!isSomeCellInEditMode && !isSoftFocusOnTableCell) {
|
if (!isSomeCellInEditMode && !isSoftFocusOnTableCell) {
|
||||||
moveSoftFocusToCell(cellPosition);
|
moveSoftFocusToCurrentCell(cellPosition);
|
||||||
set(isSoftFocusUsingMouseState, true);
|
set(isSoftFocusUsingMouseState, true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -64,7 +64,7 @@ export const useHandleContainerMouseEnter = ({
|
|||||||
isSoftFocusOnTableCellFamilyState,
|
isSoftFocusOnTableCellFamilyState,
|
||||||
currentTableCellInEditModePositionState,
|
currentTableCellInEditModePositionState,
|
||||||
isTableCellInEditModeFamilyState,
|
isTableCellInEditModeFamilyState,
|
||||||
moveSoftFocusToCell,
|
moveSoftFocusToCurrentCell,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export const RecordTableCellBaseContainer = ({
|
|||||||
const isReadOnly = useIsFieldValueReadOnly();
|
const isReadOnly = useIsFieldValueReadOnly();
|
||||||
const { hasSoftFocus, cellPosition } = useContext(RecordTableCellContext);
|
const { hasSoftFocus, cellPosition } = useContext(RecordTableCellContext);
|
||||||
|
|
||||||
const { onMoveSoftFocusToCell, onCellMouseEnter } =
|
const { onMoveSoftFocusToCurrentCell, onCellMouseEnter } =
|
||||||
useRecordTableBodyContextOrThrow();
|
useRecordTableBodyContextOrThrow();
|
||||||
|
|
||||||
const handleContainerMouseMove = () => {
|
const handleContainerMouseMove = () => {
|
||||||
@ -77,7 +77,7 @@ export const RecordTableCellBaseContainer = ({
|
|||||||
|
|
||||||
const handleContainerClick = () => {
|
const handleContainerClick = () => {
|
||||||
if (!hasSoftFocus) {
|
if (!hasSoftFocus) {
|
||||||
onMoveSoftFocusToCell(cellPosition);
|
onMoveSoftFocusToCurrentCell(cellPosition);
|
||||||
openTableCell();
|
openTableCell();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,6 +4,10 @@ import { RecordTableCellContext } from '@/object-record/record-table/contexts/Re
|
|||||||
import { RecordTableCellBaseContainer } from '@/object-record/record-table/record-table-cell/components/RecordTableCellBaseContainer';
|
import { RecordTableCellBaseContainer } from '@/object-record/record-table/record-table-cell/components/RecordTableCellBaseContainer';
|
||||||
import { RecordTableCellSoftFocusMode } from '@/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode';
|
import { RecordTableCellSoftFocusMode } from '@/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode';
|
||||||
|
|
||||||
|
import { RecordTableCellSoftFocusModeHotkeysSetterEffect } from '@/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusModeHotkeysSetterEffect';
|
||||||
|
import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
|
||||||
|
import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
import { RecordTableCellDisplayMode } from './RecordTableCellDisplayMode';
|
import { RecordTableCellDisplayMode } from './RecordTableCellDisplayMode';
|
||||||
import { RecordTableCellEditMode } from './RecordTableCellEditMode';
|
import { RecordTableCellEditMode } from './RecordTableCellEditMode';
|
||||||
|
|
||||||
@ -22,15 +26,22 @@ export const RecordTableCellContainer = ({
|
|||||||
}: RecordTableCellContainerProps) => {
|
}: RecordTableCellContainerProps) => {
|
||||||
const { hasSoftFocus, isInEditMode } = useContext(RecordTableCellContext);
|
const { hasSoftFocus, isInEditMode } = useContext(RecordTableCellContext);
|
||||||
|
|
||||||
|
const currentHotkeyScope = useRecoilValue(currentHotkeyScopeState);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RecordTableCellBaseContainer>
|
<RecordTableCellBaseContainer>
|
||||||
{isInEditMode ? (
|
{isInEditMode ? (
|
||||||
<RecordTableCellEditMode>{editModeContent}</RecordTableCellEditMode>
|
<RecordTableCellEditMode>{editModeContent}</RecordTableCellEditMode>
|
||||||
) : hasSoftFocus ? (
|
) : hasSoftFocus ? (
|
||||||
<RecordTableCellSoftFocusMode
|
<>
|
||||||
editModeContent={editModeContent}
|
{currentHotkeyScope.scope === TableHotkeyScope.TableSoftFocus && (
|
||||||
nonEditModeContent={nonEditModeContent}
|
<RecordTableCellSoftFocusModeHotkeysSetterEffect />
|
||||||
/>
|
)}
|
||||||
|
<RecordTableCellSoftFocusMode
|
||||||
|
editModeContent={editModeContent}
|
||||||
|
nonEditModeContent={nonEditModeContent}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<RecordTableCellDisplayMode>
|
<RecordTableCellDisplayMode>
|
||||||
{nonEditModeContent}
|
{nonEditModeContent}
|
||||||
|
|||||||
@ -1,24 +1,16 @@
|
|||||||
import { ReactElement, useContext, useEffect, useRef } from 'react';
|
import { ReactElement, useContext, useEffect, useRef } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
|
||||||
import { IconArrowUpRight } from 'twenty-ui';
|
import { IconArrowUpRight } from 'twenty-ui';
|
||||||
|
|
||||||
import { useClearField } from '@/object-record/record-field/hooks/useClearField';
|
|
||||||
import { useGetButtonIcon } from '@/object-record/record-field/hooks/useGetButtonIcon';
|
import { useGetButtonIcon } from '@/object-record/record-field/hooks/useGetButtonIcon';
|
||||||
import { useIsFieldClearable } from '@/object-record/record-field/hooks/useIsFieldClearable';
|
|
||||||
import { useIsFieldEmpty } from '@/object-record/record-field/hooks/useIsFieldEmpty';
|
import { useIsFieldEmpty } from '@/object-record/record-field/hooks/useIsFieldEmpty';
|
||||||
import { useIsFieldInputOnly } from '@/object-record/record-field/hooks/useIsFieldInputOnly';
|
import { useIsFieldInputOnly } from '@/object-record/record-field/hooks/useIsFieldInputOnly';
|
||||||
import { useToggleEditOnlyInput } from '@/object-record/record-field/hooks/useToggleEditOnlyInput';
|
|
||||||
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
|
import { RecordTableCellContext } from '@/object-record/record-table/contexts/RecordTableCellContext';
|
||||||
import { RecordTableCellButton } from '@/object-record/record-table/record-table-cell/components/RecordTableCellButton';
|
import { RecordTableCellButton } from '@/object-record/record-table/record-table-cell/components/RecordTableCellButton';
|
||||||
import { useOpenRecordTableCellFromCell } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell';
|
import { useOpenRecordTableCellFromCell } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell';
|
||||||
import { isSoftFocusUsingMouseState } from '@/object-record/record-table/states/isSoftFocusUsingMouseState';
|
import { isSoftFocusUsingMouseState } from '@/object-record/record-table/states/isSoftFocusUsingMouseState';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
|
||||||
import { isNonTextWritingKey } from '@/ui/utilities/hotkey/utils/isNonTextWritingKey';
|
|
||||||
import { isDefined } from 'twenty-shared';
|
import { isDefined } from 'twenty-shared';
|
||||||
|
|
||||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
|
||||||
|
|
||||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||||
import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
|
import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
|
||||||
import { useRecordTableBodyContextOrThrow } from '@/object-record/record-table/contexts/RecordTableBodyContext';
|
import { useRecordTableBodyContextOrThrow } from '@/object-record/record-table/contexts/RecordTableBodyContext';
|
||||||
@ -48,13 +40,9 @@ export const RecordTableCellSoftFocusMode = ({
|
|||||||
|
|
||||||
const isEmpty = useIsFieldEmpty();
|
const isEmpty = useIsFieldEmpty();
|
||||||
|
|
||||||
const isFieldClearable = useIsFieldClearable();
|
|
||||||
|
|
||||||
const toggleEditOnlyInput = useToggleEditOnlyInput();
|
|
||||||
const scrollRef = useRef<HTMLDivElement>(null);
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const isSoftFocusUsingMouse = useRecoilValue(isSoftFocusUsingMouseState);
|
const isSoftFocusUsingMouse = useRecoilValue(isSoftFocusUsingMouseState);
|
||||||
const clearField = useClearField();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isSoftFocusUsingMouse) {
|
if (!isSoftFocusUsingMouse) {
|
||||||
@ -62,65 +50,6 @@ export const RecordTableCellSoftFocusMode = ({
|
|||||||
}
|
}
|
||||||
}, [isSoftFocusUsingMouse]);
|
}, [isSoftFocusUsingMouse]);
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
[Key.Backspace, Key.Delete],
|
|
||||||
() => {
|
|
||||||
if (!isFieldInputOnly && isFieldClearable) {
|
|
||||||
clearField();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
TableHotkeyScope.TableSoftFocus,
|
|
||||||
[clearField, isFieldClearable, isFieldInputOnly],
|
|
||||||
);
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
Key.Enter,
|
|
||||||
() => {
|
|
||||||
if (isFieldReadOnly) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isFieldInputOnly) {
|
|
||||||
openTableCell();
|
|
||||||
} else {
|
|
||||||
toggleEditOnlyInput();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
TableHotkeyScope.TableSoftFocus,
|
|
||||||
[openTableCell],
|
|
||||||
);
|
|
||||||
|
|
||||||
useScopedHotkeys(
|
|
||||||
'*',
|
|
||||||
(keyboardEvent) => {
|
|
||||||
if (isFieldReadOnly) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isFieldInputOnly) {
|
|
||||||
const isWritingText =
|
|
||||||
!isNonTextWritingKey(keyboardEvent.key) &&
|
|
||||||
!keyboardEvent.ctrlKey &&
|
|
||||||
!keyboardEvent.metaKey;
|
|
||||||
|
|
||||||
if (!isWritingText) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
keyboardEvent.preventDefault();
|
|
||||||
keyboardEvent.stopPropagation();
|
|
||||||
keyboardEvent.stopImmediatePropagation();
|
|
||||||
|
|
||||||
openTableCell(keyboardEvent.key);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
TableHotkeyScope.TableSoftFocus,
|
|
||||||
[openTableCell],
|
|
||||||
{
|
|
||||||
preventDefault: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (!isFieldInputOnly && !isFieldReadOnly) {
|
if (!isFieldInputOnly && !isFieldReadOnly) {
|
||||||
openTableCell();
|
openTableCell();
|
||||||
|
|||||||
@ -0,0 +1,99 @@
|
|||||||
|
import { useEffect, useRef } from 'react';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
|
import { useClearField } from '@/object-record/record-field/hooks/useClearField';
|
||||||
|
import { useIsFieldClearable } from '@/object-record/record-field/hooks/useIsFieldClearable';
|
||||||
|
import { useIsFieldInputOnly } from '@/object-record/record-field/hooks/useIsFieldInputOnly';
|
||||||
|
import { useToggleEditOnlyInput } from '@/object-record/record-field/hooks/useToggleEditOnlyInput';
|
||||||
|
import { useOpenRecordTableCellFromCell } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell';
|
||||||
|
import { isSoftFocusUsingMouseState } from '@/object-record/record-table/states/isSoftFocusUsingMouseState';
|
||||||
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
|
import { isNonTextWritingKey } from '@/ui/utilities/hotkey/utils/isNonTextWritingKey';
|
||||||
|
|
||||||
|
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||||
|
|
||||||
|
import { useIsFieldValueReadOnly } from '@/object-record/record-field/hooks/useIsFieldValueReadOnly';
|
||||||
|
|
||||||
|
export const RecordTableCellSoftFocusModeHotkeysSetterEffect = () => {
|
||||||
|
const isFieldReadOnly = useIsFieldValueReadOnly();
|
||||||
|
|
||||||
|
const { openTableCell } = useOpenRecordTableCellFromCell();
|
||||||
|
|
||||||
|
const isFieldInputOnly = useIsFieldInputOnly();
|
||||||
|
|
||||||
|
const isFieldClearable = useIsFieldClearable();
|
||||||
|
|
||||||
|
const toggleEditOnlyInput = useToggleEditOnlyInput();
|
||||||
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const isSoftFocusUsingMouse = useRecoilValue(isSoftFocusUsingMouseState);
|
||||||
|
const clearField = useClearField();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isSoftFocusUsingMouse) {
|
||||||
|
scrollRef.current?.scrollIntoView({ block: 'nearest' });
|
||||||
|
}
|
||||||
|
}, [isSoftFocusUsingMouse]);
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
[Key.Backspace, Key.Delete],
|
||||||
|
() => {
|
||||||
|
if (!isFieldInputOnly && isFieldClearable) {
|
||||||
|
clearField();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TableHotkeyScope.TableSoftFocus,
|
||||||
|
[clearField, isFieldClearable, isFieldInputOnly],
|
||||||
|
);
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
Key.Enter,
|
||||||
|
() => {
|
||||||
|
if (isFieldReadOnly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFieldInputOnly) {
|
||||||
|
openTableCell();
|
||||||
|
} else {
|
||||||
|
toggleEditOnlyInput();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TableHotkeyScope.TableSoftFocus,
|
||||||
|
[openTableCell],
|
||||||
|
);
|
||||||
|
|
||||||
|
useScopedHotkeys(
|
||||||
|
'*',
|
||||||
|
(keyboardEvent) => {
|
||||||
|
if (isFieldReadOnly) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFieldInputOnly) {
|
||||||
|
const isWritingText =
|
||||||
|
!isNonTextWritingKey(keyboardEvent.key) &&
|
||||||
|
!keyboardEvent.ctrlKey &&
|
||||||
|
!keyboardEvent.metaKey;
|
||||||
|
|
||||||
|
if (!isWritingText) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboardEvent.preventDefault();
|
||||||
|
keyboardEvent.stopPropagation();
|
||||||
|
keyboardEvent.stopImmediatePropagation();
|
||||||
|
|
||||||
|
openTableCell(keyboardEvent.key);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TableHotkeyScope.TableSoftFocus,
|
||||||
|
[openTableCell],
|
||||||
|
{
|
||||||
|
preventDefault: false,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
};
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { act, renderHook } from '@testing-library/react';
|
import { renderHook } from '@testing-library/react';
|
||||||
|
import { act } from 'react';
|
||||||
import { CallbackInterface, RecoilRoot } from 'recoil';
|
import { CallbackInterface, RecoilRoot } from 'recoil';
|
||||||
|
|
||||||
import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
|
import { RecordTableComponentInstance } from '@/object-record/record-table/components/RecordTableComponentInstance';
|
||||||
@ -98,17 +99,15 @@ const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
|||||||
describe('useMoveSoftFocusToCurrentCellOnHover', () => {
|
describe('useMoveSoftFocusToCurrentCellOnHover', () => {
|
||||||
it('should work as expected', () => {
|
it('should work as expected', () => {
|
||||||
const { result } = renderHook(
|
const { result } = renderHook(
|
||||||
() => {
|
() => useMoveSoftFocusToCurrentCellOnHover('scopeId'),
|
||||||
return {
|
|
||||||
moveSoftFocusToCurrentCellOnHover:
|
|
||||||
useMoveSoftFocusToCurrentCellOnHover(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
{ wrapper: Wrapper },
|
{ wrapper: Wrapper },
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
result.current.moveSoftFocusToCurrentCellOnHover();
|
result.current.moveSoftFocusToCurrentCell({
|
||||||
|
column: 3,
|
||||||
|
row: 2,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(mockCallbackInterface.set).toHaveBeenNthCalledWith(
|
expect(mockCallbackInterface.set).toHaveBeenNthCalledWith(
|
||||||
|
|||||||
@ -1,66 +0,0 @@
|
|||||||
import { useRecoilCallback } from 'recoil';
|
|
||||||
|
|
||||||
import { useSetSoftFocus } from '@/object-record/record-table/record-table-cell/hooks/useSetSoftFocus';
|
|
||||||
import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
|
|
||||||
import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
|
|
||||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
|
||||||
|
|
||||||
import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
|
|
||||||
import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
|
|
||||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
|
||||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
|
||||||
|
|
||||||
export const useMoveSoftFocusToCellOnHoverV2 = (recordTableId: string) => {
|
|
||||||
const setSoftFocus = useSetSoftFocus(recordTableId);
|
|
||||||
|
|
||||||
const currentTableCellInEditModePositionState =
|
|
||||||
useRecoilComponentCallbackStateV2(
|
|
||||||
currentTableCellInEditModePositionComponentState,
|
|
||||||
recordTableId,
|
|
||||||
);
|
|
||||||
const isTableCellInEditModeFamilyState = useRecoilComponentCallbackStateV2(
|
|
||||||
isTableCellInEditModeComponentFamilyState,
|
|
||||||
recordTableId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const moveSoftFocusToCell = useRecoilCallback(
|
|
||||||
({ snapshot }) =>
|
|
||||||
(cellPosition: TableCellPosition) => {
|
|
||||||
const currentTableCellInEditModePosition = getSnapshotValue(
|
|
||||||
snapshot,
|
|
||||||
currentTableCellInEditModePositionState,
|
|
||||||
);
|
|
||||||
|
|
||||||
const isSomeCellInEditMode = snapshot
|
|
||||||
.getLoadable(
|
|
||||||
isTableCellInEditModeFamilyState(
|
|
||||||
currentTableCellInEditModePosition,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
const currentHotkeyScope = snapshot
|
|
||||||
.getLoadable(currentHotkeyScopeState)
|
|
||||||
.getValue();
|
|
||||||
|
|
||||||
if (
|
|
||||||
currentHotkeyScope.scope !== TableHotkeyScope.TableSoftFocus &&
|
|
||||||
currentHotkeyScope.scope !== TableHotkeyScope.CellEditMode &&
|
|
||||||
currentHotkeyScope.scope !== TableHotkeyScope.Table
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isSomeCellInEditMode) {
|
|
||||||
setSoftFocus(cellPosition);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[
|
|
||||||
currentTableCellInEditModePositionState,
|
|
||||||
isTableCellInEditModeFamilyState,
|
|
||||||
setSoftFocus,
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
return { moveSoftFocusToCell };
|
|
||||||
};
|
|
||||||
@ -1,29 +1,32 @@
|
|||||||
import { useRecoilCallback } from 'recoil';
|
import { useRecoilCallback } from 'recoil';
|
||||||
|
|
||||||
|
import { useSetSoftFocus } from '@/object-record/record-table/record-table-cell/hooks/useSetSoftFocus';
|
||||||
|
import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
|
||||||
import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
|
import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
|
||||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||||
|
|
||||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
|
||||||
|
|
||||||
import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
|
import { currentTableCellInEditModePositionComponentState } from '@/object-record/record-table/states/currentTableCellInEditModePositionComponentState';
|
||||||
import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
|
import { isTableCellInEditModeComponentFamilyState } from '@/object-record/record-table/states/isTableCellInEditModeComponentFamilyState';
|
||||||
|
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
||||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||||
import { useSetSoftFocusOnCurrentTableCell } from './useSetSoftFocusOnCurrentTableCell';
|
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||||
|
|
||||||
export const useMoveSoftFocusToCurrentCellOnHover = () => {
|
export const useMoveSoftFocusToCurrentCellOnHover = (recordTableId: string) => {
|
||||||
const setSoftFocusOnCurrentTableCell = useSetSoftFocusOnCurrentTableCell();
|
const setSoftFocus = useSetSoftFocus(recordTableId);
|
||||||
|
|
||||||
const currentTableCellInEditModePositionState =
|
const currentTableCellInEditModePositionState =
|
||||||
useRecoilComponentCallbackStateV2(
|
useRecoilComponentCallbackStateV2(
|
||||||
currentTableCellInEditModePositionComponentState,
|
currentTableCellInEditModePositionComponentState,
|
||||||
|
recordTableId,
|
||||||
);
|
);
|
||||||
const isTableCellInEditModeFamilyState = useRecoilComponentCallbackStateV2(
|
const isTableCellInEditModeFamilyState = useRecoilComponentCallbackStateV2(
|
||||||
isTableCellInEditModeComponentFamilyState,
|
isTableCellInEditModeComponentFamilyState,
|
||||||
|
recordTableId,
|
||||||
);
|
);
|
||||||
|
|
||||||
return useRecoilCallback(
|
const moveSoftFocusToCurrentCell = useRecoilCallback(
|
||||||
({ snapshot }) =>
|
({ snapshot }) =>
|
||||||
() => {
|
(cellPosition: TableCellPosition) => {
|
||||||
const currentTableCellInEditModePosition = getSnapshotValue(
|
const currentTableCellInEditModePosition = getSnapshotValue(
|
||||||
snapshot,
|
snapshot,
|
||||||
currentTableCellInEditModePositionState,
|
currentTableCellInEditModePositionState,
|
||||||
@ -44,19 +47,22 @@ export const useMoveSoftFocusToCurrentCellOnHover = () => {
|
|||||||
if (
|
if (
|
||||||
currentHotkeyScope.scope !== TableHotkeyScope.TableSoftFocus &&
|
currentHotkeyScope.scope !== TableHotkeyScope.TableSoftFocus &&
|
||||||
currentHotkeyScope.scope !== TableHotkeyScope.CellEditMode &&
|
currentHotkeyScope.scope !== TableHotkeyScope.CellEditMode &&
|
||||||
currentHotkeyScope.scope !== TableHotkeyScope.Table
|
currentHotkeyScope.scope !== TableHotkeyScope.Table &&
|
||||||
|
currentHotkeyScope.scope !== AppHotkeyScope.CommandMenuOpen
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isSomeCellInEditMode) {
|
if (!isSomeCellInEditMode) {
|
||||||
setSoftFocusOnCurrentTableCell();
|
setSoftFocus(cellPosition);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
currentTableCellInEditModePositionState,
|
currentTableCellInEditModePositionState,
|
||||||
isTableCellInEditModeFamilyState,
|
isTableCellInEditModeFamilyState,
|
||||||
setSoftFocusOnCurrentTableCell,
|
setSoftFocus,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return { moveSoftFocusToCurrentCell };
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import { TableCellPosition } from '@/object-record/record-table/types/TableCellP
|
|||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
|
|
||||||
import { isSoftFocusActiveComponentState } from '@/object-record/record-table/states/isSoftFocusActiveComponentState';
|
import { isSoftFocusActiveComponentState } from '@/object-record/record-table/states/isSoftFocusActiveComponentState';
|
||||||
|
import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
|
||||||
|
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
||||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||||
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
import { TableHotkeyScope } from '../../types/TableHotkeyScope';
|
||||||
|
|
||||||
@ -19,13 +21,18 @@ export const useSetSoftFocus = (recordTableId?: string) => {
|
|||||||
const setHotkeyScope = useSetHotkeyScope();
|
const setHotkeyScope = useSetHotkeyScope();
|
||||||
|
|
||||||
return useRecoilCallback(
|
return useRecoilCallback(
|
||||||
({ set }) =>
|
({ snapshot, set }) =>
|
||||||
(newPosition: TableCellPosition) => {
|
(newPosition: TableCellPosition) => {
|
||||||
setSoftFocusPosition(newPosition);
|
setSoftFocusPosition(newPosition);
|
||||||
|
|
||||||
set(isSoftFocusActiveState, true);
|
set(isSoftFocusActiveState, true);
|
||||||
|
|
||||||
setHotkeyScope(TableHotkeyScope.TableSoftFocus);
|
if (
|
||||||
|
snapshot.getLoadable(currentHotkeyScopeState).getValue().scope !==
|
||||||
|
AppHotkeyScope.CommandMenuOpen
|
||||||
|
) {
|
||||||
|
setHotkeyScope(TableHotkeyScope.TableSoftFocus);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
[setSoftFocusPosition, isSoftFocusActiveState, setHotkeyScope],
|
[setSoftFocusPosition, isSoftFocusActiveState, setHotkeyScope],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export const RecordTableDecorator: Decorator = (Story) => {
|
|||||||
onOpenTableCell: () => {},
|
onOpenTableCell: () => {},
|
||||||
onActionMenuDropdownOpened: () => {},
|
onActionMenuDropdownOpened: () => {},
|
||||||
onMoveFocus: () => {},
|
onMoveFocus: () => {},
|
||||||
onMoveSoftFocusToCell: () => {},
|
onMoveSoftFocusToCurrentCell: () => {},
|
||||||
onUpsertRecord: () => {},
|
onUpsertRecord: () => {},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user