2025-04-09 16:34:31 +00:00
|
|
|
import { COMMAND_MENU_ANIMATION_VARIANTS } from '@/command-menu/constants/CommandMenuAnimationVariants';
|
2025-05-22 16:10:51 +00:00
|
|
|
import { COMMAND_MENU_CLICK_OUTSIDE_ID } from '@/command-menu/constants/CommandMenuClickOutsideId';
|
2025-04-09 16:34:31 +00:00
|
|
|
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
|
|
|
|
import { CommandMenuAnimationVariant } from '@/command-menu/types/CommandMenuAnimationVariant';
|
|
|
|
|
import { CommandMenuHotkeyScope } from '@/command-menu/types/CommandMenuHotkeyScope';
|
2025-06-05 18:32:46 +00:00
|
|
|
import { RECORD_CHIP_CLICK_OUTSIDE_ID } from '@/object-record/record-table/constants/RecordChipClickOutsideId';
|
2025-06-12 09:30:10 +00:00
|
|
|
import { SLASH_MENU_DROPDOWN_CLICK_OUTSIDE_ID } from '@/ui/input/constants/SlashMenuDropdownClickOutsideId';
|
2025-04-09 16:34:31 +00:00
|
|
|
import { RootStackingContextZIndices } from '@/ui/layout/constants/RootStackingContextZIndices';
|
2025-05-22 16:10:51 +00:00
|
|
|
import { PAGE_HEADER_COMMAND_MENU_BUTTON_CLICK_OUTSIDE_ID } from '@/ui/layout/page-header/constants/PageHeaderCommandMenuButtonClickOutsideId';
|
2025-04-09 16:34:31 +00:00
|
|
|
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';
|
2025-05-28 10:32:49 +00:00
|
|
|
import { LINK_CHIP_CLICK_OUTSIDE_ID } from 'twenty-ui/components';
|
2025-04-09 16:34:31 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
const handleClickOutside = useRecoilCallback(
|
|
|
|
|
({ snapshot }) =>
|
2025-06-16 08:33:57 +00:00
|
|
|
(event: MouseEvent | TouchEvent) => {
|
2025-04-09 16:34:31 +00:00
|
|
|
const hotkeyScope = snapshot
|
|
|
|
|
.getLoadable(currentHotkeyScopeState)
|
|
|
|
|
.getValue();
|
|
|
|
|
|
|
|
|
|
if (hotkeyScope?.scope === CommandMenuHotkeyScope.CommandMenuFocused) {
|
2025-06-16 08:33:57 +00:00
|
|
|
event.stopImmediatePropagation();
|
|
|
|
|
event.preventDefault();
|
2025-04-09 16:34:31 +00:00
|
|
|
closeCommandMenu();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
[closeCommandMenu],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
useListenClickOutside({
|
|
|
|
|
refs: [commandMenuRef],
|
|
|
|
|
callback: handleClickOutside,
|
|
|
|
|
listenerId: 'COMMAND_MENU_LISTENER_ID',
|
2025-05-28 10:32:49 +00:00
|
|
|
excludedClickOutsideIds: [
|
|
|
|
|
PAGE_HEADER_COMMAND_MENU_BUTTON_CLICK_OUTSIDE_ID,
|
|
|
|
|
LINK_CHIP_CLICK_OUTSIDE_ID,
|
2025-06-05 18:32:46 +00:00
|
|
|
RECORD_CHIP_CLICK_OUTSIDE_ID,
|
2025-06-12 09:30:10 +00:00
|
|
|
SLASH_MENU_DROPDOWN_CLICK_OUTSIDE_ID,
|
2025-05-28 10:32:49 +00:00
|
|
|
],
|
2025-04-09 16:34:31 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<StyledCommandMenu
|
|
|
|
|
data-testid="command-menu"
|
2025-05-22 16:10:51 +00:00
|
|
|
data-click-outside-id={COMMAND_MENU_CLICK_OUTSIDE_ID}
|
2025-04-09 16:34:31 +00:00
|
|
|
ref={commandMenuRef}
|
|
|
|
|
animate={targetVariantForAnimation}
|
|
|
|
|
initial="closed"
|
|
|
|
|
exit="closed"
|
|
|
|
|
variants={COMMAND_MENU_ANIMATION_VARIANTS}
|
|
|
|
|
transition={{ duration: theme.animation.duration.normal }}
|
|
|
|
|
>
|
|
|
|
|
{children}
|
|
|
|
|
</StyledCommandMenu>
|
|
|
|
|
);
|
|
|
|
|
};
|