Fixed (#11482)
This PR fixes many small bugs around the recent hotkey scope refactor. - Removed unused ActionBar files - Created components CommandMenuOpenContainer and KeyboardShortcutMenuOpenContent to avoid mounting listeners when not needed - Added DEFAULT_CELL_SCOPE where missing in some field inputs - Called setHotkeyScopeAndMemorizePreviousScope instead of setHotkeyScope in new useOpenFieldInputEditMode hook - Broke down RecordTableBodyUnselectEffect into multiple simpler effect components that are mounted only when needed to avoid listening for keyboard and clickoutside event - Re-implemented recently deleted table cell soft focus component logic into RecordTableCellDisplayMode - Created component selector isAtLeastOneTableRowSelectedSelector - Drill down hotkey scope when opening a dropdown - Improved debug logs
This commit is contained in:
@ -1,12 +1,8 @@
|
||||
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
|
||||
import { COMMAND_MENU_ANIMATION_VARIANTS } from '@/command-menu/constants/CommandMenuAnimationVariants';
|
||||
import { CommandMenuOpenContainer } from '@/command-menu/components/CommandMenuOpenContainer';
|
||||
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
|
||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { useCommandMenuCloseAnimationCompleteCleanup } from '@/command-menu/hooks/useCommandMenuCloseAnimationCompleteCleanup';
|
||||
import { useCommandMenuHotKeys } from '@/command-menu/hooks/useCommandMenuHotKeys';
|
||||
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
|
||||
import { CommandMenuAnimationVariant } from '@/command-menu/types/CommandMenuAnimationVariant';
|
||||
import { CommandMenuHotkeyScope } from '@/command-menu/types/CommandMenuHotkeyScope';
|
||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
||||
@ -15,78 +11,20 @@ import { RecordFilterGroupsComponentInstanceContext } from '@/object-record/reco
|
||||
import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
|
||||
import { RecordSortsComponentInstanceContext } from '@/object-record/record-sort/states/context/RecordSortsComponentInstanceContext';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
import { RootStackingContextZIndices } from '@/ui/layout/constants/RootStackingContextZIndices';
|
||||
import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { useRef } from 'react';
|
||||
import { useRecoilCallback, useRecoilValue } from 'recoil';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
const StyledCommandMenu = styled(motion.div)`
|
||||
background: ${({ theme }) => theme.background.primary};
|
||||
border-left: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
box-shadow: ${({ theme }) => theme.boxShadow.strong};
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
right: 0%;
|
||||
top: 0%;
|
||||
z-index: ${RootStackingContextZIndices.CommandMenu};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
export const CommandMenuContainer = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) => {
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
|
||||
const { commandMenuCloseAnimationCompleteCleanup } =
|
||||
useCommandMenuCloseAnimationCompleteCleanup();
|
||||
|
||||
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
|
||||
|
||||
const commandMenuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useCommandMenuHotKeys();
|
||||
|
||||
const handleClickOutside = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
() => {
|
||||
const hotkeyScope = snapshot
|
||||
.getLoadable(currentHotkeyScopeState)
|
||||
.getValue();
|
||||
|
||||
if (hotkeyScope?.scope === CommandMenuHotkeyScope.CommandMenuFocused) {
|
||||
closeCommandMenu();
|
||||
}
|
||||
},
|
||||
[closeCommandMenu],
|
||||
);
|
||||
|
||||
useListenClickOutside({
|
||||
refs: [commandMenuRef],
|
||||
callback: handleClickOutside,
|
||||
listenerId: 'COMMAND_MENU_LISTENER_ID',
|
||||
excludeClassNames: ['page-header-command-menu-button'],
|
||||
});
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const targetVariantForAnimation: CommandMenuAnimationVariant = isMobile
|
||||
? 'fullScreen'
|
||||
: 'normal';
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const objectMetadataItemId = useRecoilComponentValueV2(
|
||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
||||
COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
@ -129,18 +67,9 @@ export const CommandMenuContainer = ({
|
||||
onExitComplete={commandMenuCloseAnimationCompleteCleanup}
|
||||
>
|
||||
{isCommandMenuOpened && (
|
||||
<StyledCommandMenu
|
||||
data-testid="command-menu"
|
||||
ref={commandMenuRef}
|
||||
className="command-menu"
|
||||
animate={targetVariantForAnimation}
|
||||
initial="closed"
|
||||
exit="closed"
|
||||
variants={COMMAND_MENU_ANIMATION_VARIANTS}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
>
|
||||
<CommandMenuOpenContainer>
|
||||
{children}
|
||||
</StyledCommandMenu>
|
||||
</CommandMenuOpenContainer>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</ActionMenuComponentInstanceContext.Provider>
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
import { COMMAND_MENU_ANIMATION_VARIANTS } from '@/command-menu/constants/CommandMenuAnimationVariants';
|
||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { useCommandMenuHotKeys } from '@/command-menu/hooks/useCommandMenuHotKeys';
|
||||
import { CommandMenuAnimationVariant } from '@/command-menu/types/CommandMenuAnimationVariant';
|
||||
import { CommandMenuHotkeyScope } from '@/command-menu/types/CommandMenuHotkeyScope';
|
||||
import { RootStackingContextZIndices } from '@/ui/layout/constants/RootStackingContextZIndices';
|
||||
import { currentHotkeyScopeState } from '@/ui/utilities/hotkey/states/internal/currentHotkeyScopeState';
|
||||
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
|
||||
import { useTheme } from '@emotion/react';
|
||||
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useRef } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { useIsMobile } from 'twenty-ui/utilities';
|
||||
|
||||
const StyledCommandMenu = styled(motion.div)`
|
||||
background: ${({ theme }) => theme.background.primary};
|
||||
border-left: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
box-shadow: ${({ theme }) => theme.boxShadow.strong};
|
||||
font-family: ${({ theme }) => theme.font.family};
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
right: 0%;
|
||||
top: 0%;
|
||||
z-index: ${RootStackingContextZIndices.CommandMenu};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
export const CommandMenuOpenContainer = ({
|
||||
children,
|
||||
}: React.PropsWithChildren) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const targetVariantForAnimation: CommandMenuAnimationVariant = isMobile
|
||||
? 'fullScreen'
|
||||
: 'normal';
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
|
||||
const commandMenuRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useCommandMenuHotKeys();
|
||||
|
||||
const handleClickOutside = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
() => {
|
||||
const hotkeyScope = snapshot
|
||||
.getLoadable(currentHotkeyScopeState)
|
||||
.getValue();
|
||||
|
||||
if (hotkeyScope?.scope === CommandMenuHotkeyScope.CommandMenuFocused) {
|
||||
closeCommandMenu();
|
||||
}
|
||||
},
|
||||
[closeCommandMenu],
|
||||
);
|
||||
|
||||
useListenClickOutside({
|
||||
refs: [commandMenuRef],
|
||||
callback: handleClickOutside,
|
||||
listenerId: 'COMMAND_MENU_LISTENER_ID',
|
||||
excludeClassNames: ['page-header-command-menu-button'],
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledCommandMenu
|
||||
data-testid="command-menu"
|
||||
ref={commandMenuRef}
|
||||
className="command-menu"
|
||||
animate={targetVariantForAnimation}
|
||||
initial="closed"
|
||||
exit="closed"
|
||||
variants={COMMAND_MENU_ANIMATION_VARIANTS}
|
||||
transition={{ duration: theme.animation.duration.normal }}
|
||||
>
|
||||
{children}
|
||||
</StyledCommandMenu>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user