Files
twenty/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerDropdown.tsx

110 lines
3.9 KiB
TypeScript

import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRecoilValue } from 'recoil';
import { IconChevronDown, IconList, useIcons } from 'twenty-ui';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/StyledDropdownButtonContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { MOBILE_VIEWPORT } from '@/ui/theme/constants/MobileViewport';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope';
import { ViewPickerCreateOrEditContent } from '@/views/view-picker/components/ViewPickerCreateOrEditContent';
import { ViewPickerCreateOrEditContentEffect } from '@/views/view-picker/components/ViewPickerCreateOrEditContentEffect';
import { ViewPickerListContent } from '@/views/view-picker/components/ViewPickerListContent';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { useViewPickerPersistView } from '@/views/view-picker/hooks/useViewPickerPersistView';
import { useViewStates } from '../../hooks/internal/useViewStates';
const StyledDropdownLabelAdornments = styled.span`
align-items: center;
color: ${({ theme }) => theme.grayScale.gray35};
display: inline-flex;
gap: ${({ theme }) => theme.spacing(1)};
margin-left: ${({ theme }) => theme.spacing(1)};
`;
const StyledViewName = styled.span`
margin-left: ${({ theme }) => theme.spacing(1)};
display: inline-block;
max-width: 130px;
@media (max-width: 375px) {
max-width: 90px;
}
@media (min-width: 376px) and (max-width: ${MOBILE_VIEWPORT}px) {
max-width: 110px;
}
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
`;
export const ViewPickerDropdown = () => {
const theme = useTheme();
const { entityCountInCurrentViewState } = useViewStates();
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
const { handleUpdate } = useViewPickerPersistView();
const entityCountInCurrentView = useRecoilValue(
entityCountInCurrentViewState,
);
const { isDropdownOpen: isViewsListDropdownOpen } = useDropdown(
VIEW_PICKER_DROPDOWN_ID,
);
const { viewPickerMode, setViewPickerMode } = useViewPickerMode();
const { getIcon } = useIcons();
const CurrentViewIcon = getIcon(currentViewWithCombinedFiltersAndSorts?.icon);
const handleClickOutside = async () => {
if (isViewsListDropdownOpen && viewPickerMode === 'edit') {
await handleUpdate();
}
setViewPickerMode('list');
};
return (
<Dropdown
dropdownId={VIEW_PICKER_DROPDOWN_ID}
dropdownHotkeyScope={{ scope: ViewsHotkeyScope.ListDropdown }}
dropdownOffset={{ x: 0, y: 8 }}
dropdownMenuWidth={200}
onClickOutside={handleClickOutside}
clickableComponent={
<StyledDropdownButtonContainer isUnfolded={isViewsListDropdownOpen}>
{currentViewWithCombinedFiltersAndSorts && CurrentViewIcon ? (
<CurrentViewIcon size={theme.icon.size.md} />
) : (
<IconList size={theme.icon.size.md} />
)}
<StyledViewName>
{currentViewWithCombinedFiltersAndSorts?.name ?? 'All'}
</StyledViewName>
<StyledDropdownLabelAdornments>
· {entityCountInCurrentView}{' '}
<IconChevronDown size={theme.icon.size.sm} />
</StyledDropdownLabelAdornments>
</StyledDropdownButtonContainer>
}
dropdownComponents={
viewPickerMode === 'list' ? (
<ViewPickerListContent />
) : (
<>
<ViewPickerCreateOrEditContent />
<ViewPickerCreateOrEditContentEffect />
</>
)
}
/>
);
};