Refactor useDropdownV2 (#12875)
# What this PR does This PR introduces what’s needed to progressively refactor the useDropdown hooks we have. It removes useDropdownV2 and renames useDropdown used for multi-page dropdowns to useDropdownContextStateManagement ## The 3 useDropdown hooks There are currently 3 useDropdown hooks : One is used for managing states in some dropdowns that have multiple inner pages with contexts and without recoil. It is limited and would need a separate refactoring, thus I just renamed it. Then we have useDropdown and useDropdownV2, which followed our multiple versions of recoil state management wrappers. Now that the state management has been stabilized, we can merge everything on the last version. ## What this refactor will allow next This refactor will allow to refactor the legacy recoil state management, because useDropdown is depending on legacy recoil states with scopeId. Because there are only a dozen of those legacy states left, and the dropdown’s ones are the harder to refactor, because swapping them as-is causes a big QA, and if we have a big QA to do on all dropdowns, better refactor the whole dropdown management and have everything clean. After this refactor, we will be able to delete the legacy dropdown states, and proceed with the other legacy states, then removing all the legacy recoil state mangament. ## How do we allow progressive refactoring ? There are many places where useDropdown is used. To have an easier refactoring process, we want to merge multiple small pull requests so that it is easier to QA and review. For this we will maintain both legacy component state and component state V2 in parallel for isDropdownOpen, so that the new hooks `useOpenDropdown` , `useCloseDropdown` are doing the same thing than `useDropdown` and `useDropdownV2` . Thus for the moment, whether we use the legacy hooks or the new ones, the effects are the same. And we can have dropdowns operating on the old states and the new states living side by side in the app. ## QA Component | Status | Comments -- | -- | -- CommandMenuActionMenuDropdown | Ok | RecordIndexActionMenuDropdown | Ok | RecordShowRightDrawerOpenRecordButton | Ok | useCloseActionMenu | Ok | CommandMenuContextChipGroups | Ok | useCommandMenuCloseAnimationCompleteCleanup | Ok | ObjectOptionsDropdown | Ok | ObjectOptionsDropdownContent | Ok | ObjectOptionsDropdownFieldsContent | Ok | ObjectOptionsDropdownHiddenFieldsContent | Ok | ObjectOptionsDropdownHiddenRecordGroupsContent | Ok | ObjectOptionsDropdownLayoutContent | Ok | ObjectOptionsDropdownLayoutOpenInContent | Ok | ObjectOptionsDropdownMenuContent | Ok | ObjectOptionsDropdownRecordGroupFieldsContent | Ok | ObjectOptionsDropdownRecordGroupsContent | Ok | ObjectOptionsDropdownRecordGroupSortContent | Ok | RecordBoardColumnHeaderAggregateDropdown | Ok | AggregateDropdownContent | Ok | RecordBoardColumnHeaderAggregateDropdownFieldsContent | Ok | RecordBoardColumnHeaderAggregateDropdownMenuContent | Ok | RecordBoardColumnHeaderAggregateDropdownMenuContent | Ok | RecordBoardColumnHeaderAggregateDropdownOptionsContent | Ok | RecordBoard | Ok | Used closeAnyOpenDropdown instead for a better UX RecordBoardCard | Ok | useRecordBoardSelection | Ok | RecordTableColumnAggregateFooterDropdownContent | Ok | RecordTableColumnFooterWithDropdown | Ok | useOpenRecordFilterChipFromTableHeader | Ok | useCloseAnyOpenDropdown | Ok | useCloseDropdownFromOutside | Removed | Removed because unused useDropdownV2 | Removed | Removed because all calls have been removed useOpenDropdownFromOutside | Removed | Removed because unused useCloseAndResetViewPicker | Ok | WorkflowVariablesDropdown | Ok |
This commit is contained in:
@ -8,7 +8,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useToggleDropdown } from '@/ui/layout/dropdown/hooks/useToggleDropdown';
|
||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
@ -30,12 +30,14 @@ export const CommandMenuActionMenuDropdown = () => {
|
||||
|
||||
const dropdownId =
|
||||
getRightDrawerActionMenuDropdownIdFromActionMenuId(actionMenuId);
|
||||
const { toggleDropdown } = useDropdownV2();
|
||||
const { toggleDropdown } = useToggleDropdown();
|
||||
|
||||
const hotkeysConfig = {
|
||||
keys: ['ctrl+o', 'meta+o'],
|
||||
callback: () => {
|
||||
toggleDropdown(dropdownId);
|
||||
toggleDropdown({
|
||||
dropdownComponentInstanceIdFromProps: dropdownId,
|
||||
});
|
||||
},
|
||||
scope: AppHotkeyScope.CommandMenuOpen,
|
||||
dependencies: [toggleDropdown],
|
||||
|
||||
@ -11,7 +11,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownHotkeyScope } from '@/ui/layout/dropdown/constants/DropdownHotkeyScope';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||
@ -48,7 +48,7 @@ export const RecordIndexActionMenuDropdown = () => {
|
||||
);
|
||||
|
||||
const dropdownId = getActionMenuDropdownIdFromActionMenuId(actionMenuId);
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const actionMenuDropdownPosition = useRecoilValue(
|
||||
extractComponentState(
|
||||
|
||||
@ -9,7 +9,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getShowPageTabListComponentId';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
@ -74,7 +74,7 @@ export const RecordShowRightDrawerOpenRecordButton = ({
|
||||
ActionMenuComponentInstanceContext,
|
||||
);
|
||||
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const handleOpenRecord = useRecoilCallback(
|
||||
({ snapshot, reset }) =>
|
||||
|
||||
@ -3,7 +3,7 @@ import { ActionMenuComponentInstanceContext } from '@/action-menu/states/context
|
||||
import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
|
||||
import { getRightDrawerActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getRightDrawerActionMenuDropdownIdFromActionMenuId';
|
||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useContext } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@ -19,7 +19,7 @@ export const useCloseActionMenu = ({
|
||||
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const actionMenuId = useAvailableComponentInstanceIdOrThrow(
|
||||
ActionMenuComponentInstanceContext,
|
||||
|
||||
@ -2,7 +2,7 @@ import { COMMAND_MENU_CONTEXT_CHIP_GROUPS_DROPDOWN_ID } from '@/command-menu/con
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { MenuItem } from 'twenty-ui/navigation';
|
||||
import {
|
||||
@ -15,7 +15,7 @@ export const CommandMenuContextChipGroups = ({
|
||||
}: {
|
||||
contextChips: CommandMenuContextChipProps[];
|
||||
}) => {
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
if (contextChips.length === 0) {
|
||||
return null;
|
||||
|
||||
@ -25,8 +25,8 @@ const mockResetContextStoreStates = jest.fn();
|
||||
const mockResetSelectedItem = jest.fn();
|
||||
const mockEmitSidePanelCloseEvent = jest.fn();
|
||||
|
||||
jest.mock('@/ui/layout/dropdown/hooks/useDropdownV2', () => ({
|
||||
useDropdownV2: () => ({
|
||||
jest.mock('@/ui/layout/dropdown/hooks/useCloseDropdown', () => ({
|
||||
useCloseDropdown: () => ({
|
||||
closeDropdown: mockCloseDropdown,
|
||||
}),
|
||||
}));
|
||||
|
||||
@ -13,7 +13,7 @@ import { isCommandMenuClosingState } from '@/command-menu/states/isCommandMenuCl
|
||||
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { emitSidePanelCloseEvent } from '@/ui/layout/right-drawer/utils/emitSidePanelCloseEvent';
|
||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||
import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getShowPageTabListComponentId';
|
||||
@ -27,7 +27,7 @@ export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
||||
|
||||
const { resetContextStoreStates } = useResetContextStoreStates();
|
||||
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const commandMenuCloseAnimationCompleteCleanup = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
export const useCurrentContentId = <T>() => {
|
||||
export const useDropdownContextCurrentContentId = <T>() => {
|
||||
const [currentContentId, setCurrentContentId] = useState<T | null>(null);
|
||||
|
||||
const [previousContentId, setPreviousContentId] = useState<T | null>(null);
|
||||
@ -4,7 +4,13 @@ import { RecordTableColumnAggregateFooterDropdownContextValue } from '@/object-r
|
||||
import { useDropdown as useDropdownUi } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { Context, useCallback, useContext } from 'react';
|
||||
|
||||
export const useDropdown = <
|
||||
/**
|
||||
*
|
||||
* @deprecated This hook is deprecated because it uses context instead of recoil and synchronous hooks like we do in the application
|
||||
*
|
||||
* TODO: refactor this generic way to handle multiple pages in a dropdown with state management and specific code paths in a dedicated module, instead of using context with generic union types.
|
||||
*/
|
||||
export const useDropdownContextStateManagement = <
|
||||
T extends
|
||||
| RecordBoardColumnHeaderAggregateDropdownContextValue
|
||||
| RecordTableColumnAggregateFooterDropdownContextValue
|
||||
@ -18,7 +24,7 @@ export const useDropdown = <
|
||||
|
||||
if (!dropdownContext) {
|
||||
throw new Error(
|
||||
`useDropdown must be used within a context provider (${context.Provider.name})`,
|
||||
`useDropdownContextStateManagement must be used within a context provider (${context.Provider.name})`,
|
||||
);
|
||||
}
|
||||
const dropdownId = dropdownContext.dropdownId;
|
||||
@ -1,5 +1,4 @@
|
||||
import { DROPDOWN_OFFSET_Y } from '@/dropdown/constants/DropdownOffsetY';
|
||||
import { useCurrentContentId } from '@/dropdown/hooks/useCurrentContentId';
|
||||
import { useDropdownContextCurrentContentId } from '@/dropdown-context-state-management/hooks/useDropdownContextCurrentContentId';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { ObjectOptionsDropdownContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownContent';
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
@ -9,6 +8,7 @@ import { RecordGroupReorderConfirmationModal } from '@/object-record/record-grou
|
||||
import { useRecordGroupReorderConfirmationModal } from '@/object-record/record-group/hooks/useRecordGroupReorderConfirmationModal';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton';
|
||||
import { DROPDOWN_OFFSET_Y } from '@/ui/layout/dropdown/constants/DropdownOffsetY';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
@ -25,7 +25,7 @@ export const ObjectOptionsDropdown = ({
|
||||
viewType,
|
||||
}: ObjectOptionsDropdownProps) => {
|
||||
const { currentContentId, handleContentChange, handleResetContent } =
|
||||
useCurrentContentId<ObjectOptionsContentId>();
|
||||
useDropdownContextCurrentContentId<ObjectOptionsContentId>();
|
||||
|
||||
const { isDropdownOpen } = useDropdown(OBJECT_OPTIONS_DROPDOWN_ID);
|
||||
const {
|
||||
|
||||
@ -7,10 +7,10 @@ import { ObjectOptionsDropdownMenuContent } from '@/object-record/object-options
|
||||
import { ObjectOptionsDropdownRecordGroupFieldsContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent';
|
||||
import { ObjectOptionsDropdownRecordGroupsContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupsContent';
|
||||
import { ObjectOptionsDropdownRecordGroupSortContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupSortContent';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
|
||||
export const ObjectOptionsDropdownContent = () => {
|
||||
const { currentContentId } = useOptionsDropdown();
|
||||
const { currentContentId } = useObjectOptionsDropdown();
|
||||
|
||||
switch (currentContentId) {
|
||||
case 'layout':
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
|
||||
import { useObjectOptionsForTable } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForTable';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
||||
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
|
||||
@ -20,7 +20,7 @@ export const ObjectOptionsDropdownFieldsContent = () => {
|
||||
objectMetadataItem,
|
||||
onContentChange,
|
||||
resetContent,
|
||||
} = useOptionsDropdown();
|
||||
} = useObjectOptionsDropdown();
|
||||
|
||||
const {
|
||||
handleColumnVisibilityChange,
|
||||
|
||||
@ -3,9 +3,9 @@ import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObjectNamePluralFromSingular';
|
||||
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
|
||||
import { useObjectOptionsForTable } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForTable';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { SettingsPath } from '@/types/SettingsPath';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
||||
@ -28,7 +28,7 @@ export const ObjectOptionsDropdownHiddenFieldsContent = () => {
|
||||
objectMetadataItem,
|
||||
onContentChange,
|
||||
closeDropdown,
|
||||
} = useOptionsDropdown();
|
||||
} = useObjectOptionsDropdown();
|
||||
|
||||
const { objectNamePlural } = useObjectNamePluralFromSingular({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
|
||||
@ -2,7 +2,7 @@ import { useEffect } from 'react';
|
||||
|
||||
import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObjectNamePluralFromSingular';
|
||||
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { RecordGroupsVisibilityDropdownSection } from '@/object-record/record-group/components/RecordGroupsVisibilityDropdownSection';
|
||||
import { useRecordGroupVisibility } from '@/object-record/record-group/hooks/useRecordGroupVisibility';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
@ -30,7 +30,7 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
objectMetadataItem,
|
||||
onContentChange,
|
||||
closeDropdown,
|
||||
} = useOptionsDropdown();
|
||||
} = useObjectOptionsDropdown();
|
||||
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useSetViewTypeFromLayoutOptionsMenu } from '@/object-record/object-options-dropdown/hooks/useSetViewTypeFromLayoutOptionsMenu';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
|
||||
@ -43,7 +43,7 @@ export const ObjectOptionsDropdownLayoutContent = () => {
|
||||
resetContent,
|
||||
onContentChange,
|
||||
dropdownId,
|
||||
} = useOptionsDropdown();
|
||||
} = useObjectOptionsDropdown();
|
||||
|
||||
const { isCompactModeActive, setAndPersistIsCompactModeActive } =
|
||||
useObjectOptionsForBoard({
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { useUpdateObjectViewOptions } from '@/object-record/object-options-dropdown/hooks/useUpdateObjectViewOptions';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
|
||||
@ -25,7 +25,7 @@ import {
|
||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||
|
||||
export const ObjectOptionsDropdownLayoutOpenInContent = () => {
|
||||
const { onContentChange } = useOptionsDropdown();
|
||||
const { onContentChange } = useObjectOptionsDropdown();
|
||||
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
const { setAndPersistOpenRecordIn } = useUpdateObjectViewOptions();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { ObjectOptionsDropdownMenuViewName } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownMenuViewName';
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
@ -33,7 +33,7 @@ import { MenuItem } from 'twenty-ui/navigation';
|
||||
export const ObjectOptionsDropdownMenuContent = () => {
|
||||
const { t } = useLingui();
|
||||
const { recordIndexId, objectMetadataItem, onContentChange, closeDropdown } =
|
||||
useOptionsDropdown();
|
||||
useObjectOptionsDropdown();
|
||||
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { useEffect } from 'react';
|
||||
import { useObjectNamePluralFromSingular } from '@/object-metadata/hooks/useObjectNamePluralFromSingular';
|
||||
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { useSearchRecordGroupField } from '@/object-record/object-options-dropdown/hooks/useSearchRecordGroupField';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
|
||||
@ -42,7 +42,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
onContentChange,
|
||||
resetContent,
|
||||
closeDropdown,
|
||||
} = useOptionsDropdown();
|
||||
} = useObjectOptionsDropdown();
|
||||
|
||||
const { objectNamePlural } = useObjectNamePluralFromSingular({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
|
||||
import { RecordGroupSort } from '@/object-record/record-group/types/RecordGroupSort';
|
||||
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
|
||||
@ -24,7 +24,7 @@ import {
|
||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||
|
||||
export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
const { currentContentId, onContentChange } = useOptionsDropdown();
|
||||
const { currentContentId, onContentChange } = useObjectOptionsDropdown();
|
||||
|
||||
const hiddenRecordGroupIds = useRecoilComponentValueV2(
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { RecordGroupsVisibilityDropdownSection } from '@/object-record/record-group/components/RecordGroupsVisibilityDropdownSection';
|
||||
import { useRecordGroupVisibility } from '@/object-record/record-group/hooks/useRecordGroupVisibility';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
@ -43,7 +43,7 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
onContentChange,
|
||||
resetContent,
|
||||
handleRecordGroupOrderChangeWithModal,
|
||||
} = useOptionsDropdown();
|
||||
} = useObjectOptionsDropdown();
|
||||
|
||||
const { currentView } = useGetCurrentViewOnly();
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { act } from 'react';
|
||||
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
|
||||
import { ObjectOptionsDropdownContext } from '@/object-record/object-options-dropdown/states/contexts/ObjectOptionsDropdownContext';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
@ -61,7 +61,7 @@ describe('useOptionsDropdown', () => {
|
||||
{children}
|
||||
</ObjectOptionsDropdownContext.Provider>
|
||||
);
|
||||
return renderHook(() => useOptionsDropdown(), { wrapper });
|
||||
return renderHook(() => useObjectOptionsDropdown(), { wrapper });
|
||||
};
|
||||
|
||||
it('provides closeDropdown functionality from the context', () => {
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { useDropdown } from '@/dropdown/hooks/useDropdown';
|
||||
import { useDropdownContextStateManagement } from '@/dropdown-context-state-management/hooks/useDropdownContextStateManagement';
|
||||
import { ObjectOptionsDropdownContext } from '@/object-record/object-options-dropdown/states/contexts/ObjectOptionsDropdownContext';
|
||||
import { useContext } from 'react';
|
||||
|
||||
export const useOptionsDropdown = () => {
|
||||
export const useObjectOptionsDropdown = () => {
|
||||
const context = useContext(ObjectOptionsDropdownContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error('useOptionsDropdown must be used within a context');
|
||||
throw new Error('useObjectOptionsDropdown must be used within a context');
|
||||
}
|
||||
|
||||
const { closeDropdown } = useDropdown({
|
||||
const { closeDropdown } = useDropdownContextStateManagement({
|
||||
context: ObjectOptionsDropdownContext,
|
||||
});
|
||||
|
||||
@ -4,7 +4,6 @@ import { useContext, useRef } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID } from '@/action-menu/constants/ActionMenuDropdownClickOutsideId';
|
||||
import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
|
||||
import { COMMAND_MENU_CLICK_OUTSIDE_ID } from '@/command-menu/constants/CommandMenuClickOutsideId';
|
||||
import { RecordBoardHeader } from '@/object-record/record-board/components/RecordBoardHeader';
|
||||
import { RecordBoardScrollToFocusedCardEffect } from '@/object-record/record-board/components/RecordBoardScrollToFocusedCardEffect';
|
||||
@ -26,7 +25,7 @@ import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-ind
|
||||
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseAnyOpenDropdown } from '@/ui/layout/dropdown/hooks/useCloseAnyOpenDropdown';
|
||||
import { MODAL_BACKDROP_CLICK_OUTSIDE_ID } from '@/ui/layout/modal/constants/ModalBackdropClickOutsideId';
|
||||
import { useModal } from '@/ui/layout/modal/hooks/useModal';
|
||||
import { PAGE_ACTION_CONTAINER_CLICK_OUTSIDE_ID } from '@/ui/layout/page/constants/PageActionContainerClickOutsideId';
|
||||
@ -81,15 +80,13 @@ export const RecordBoard = () => {
|
||||
RECORD_BOARD_CLICK_OUTSIDE_LISTENER_ID,
|
||||
);
|
||||
|
||||
const actionMenuId = getActionMenuIdFromRecordIndexId(recordBoardId);
|
||||
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeAnyOpenDropdown } = useCloseAnyOpenDropdown();
|
||||
|
||||
const { deactivateBoardCard } = useActiveRecordBoardCard(recordBoardId);
|
||||
const { unfocusBoardCard } = useFocusedRecordBoardCard(recordBoardId);
|
||||
|
||||
const handleDragSelectionStart = () => {
|
||||
closeDropdown(actionMenuId);
|
||||
closeAnyOpenDropdown();
|
||||
|
||||
toggleClickOutside(false);
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@ import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionM
|
||||
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
|
||||
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
|
||||
import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardSelectedRecordIdsComponentSelector';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
|
||||
@ -28,7 +28,7 @@ export const useRecordBoardSelection = (recordBoardId?: string) => {
|
||||
recordBoardId,
|
||||
);
|
||||
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const dropdownId = getActionMenuDropdownIdFromActionMenuId(
|
||||
getActionMenuIdFromRecordIndexId(instanceIdFromProps),
|
||||
|
||||
@ -15,7 +15,7 @@ import { RecordBoardCardBody } from '@/object-record/record-board/record-board-c
|
||||
import { RecordBoardCardHeader } from '@/object-record/record-board/record-board-card/components/RecordBoardCardHeader';
|
||||
import { RECORD_BOARD_CARD_CLICK_OUTSIDE_ID } from '@/object-record/record-board/record-board-card/constants/RecordBoardCardClickOutsideId';
|
||||
import { useOpenRecordFromIndexView } from '@/object-record/record-index/hooks/useOpenRecordFromIndexView';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { useScrollWrapperElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperElement';
|
||||
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
|
||||
@ -140,22 +140,25 @@ export const RecordBoardCard = () => {
|
||||
),
|
||||
);
|
||||
|
||||
const { openDropdown } = useDropdownV2();
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
|
||||
const { openRecordFromIndexView } = useOpenRecordFromIndexView();
|
||||
const { activateBoardCard } = useActiveRecordBoardCard(recordBoardId);
|
||||
const { unfocusBoardCard } = useFocusedRecordBoardCard(recordBoardId);
|
||||
|
||||
const handleActionMenuDropdown = (event: React.MouseEvent) => {
|
||||
const handleContextMenuOpen = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
setIsCurrentCardSelected(true);
|
||||
setActionMenuDropdownPosition({
|
||||
x: event.clientX,
|
||||
y: event.clientY,
|
||||
});
|
||||
openDropdown(actionMenuDropdownId, {
|
||||
enableGlobalHotkeysWithModifiers: true,
|
||||
enableGlobalHotkeysConflictingWithKeyboard: false,
|
||||
openDropdown({
|
||||
dropdownComponentInstanceIdFromProps: actionMenuDropdownId,
|
||||
globalHotkeysConfig: {
|
||||
enableGlobalHotkeysWithModifiers: true,
|
||||
enableGlobalHotkeysConflictingWithKeyboard: false,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@ -185,7 +188,7 @@ export const RecordBoardCard = () => {
|
||||
return (
|
||||
<StyledBoardCardWrapper
|
||||
data-click-outside-id={RECORD_BOARD_CARD_CLICK_OUTSIDE_ID}
|
||||
onContextMenu={handleActionMenuDropdown}
|
||||
onContextMenu={handleContextMenuOpen}
|
||||
>
|
||||
<InView>
|
||||
<StyledBoardCard
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { DROPDOWN_OFFSET_Y } from '@/dropdown/constants/DropdownOffsetY';
|
||||
import { useCurrentContentId } from '@/dropdown/hooks/useCurrentContentId';
|
||||
import { useDropdownContextCurrentContentId } from '@/dropdown-context-state-management/hooks/useDropdownContextCurrentContentId';
|
||||
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownComponentInstanceContext } from '@/object-record/record-board/contexts/RecordBoardColumnHeaderAggregateDropdownComponentInstanceContext';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownButton } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownButton';
|
||||
@ -7,6 +6,7 @@ import { AggregateDropdownContent } from '@/object-record/record-board/record-bo
|
||||
import { RecordBoardColumnHeaderAggregateDropdownContext } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownContext';
|
||||
import { RecordBoardColumnHeaderAggregateContentId } from '@/object-record/record-board/types/RecordBoardColumnHeaderAggregateContentId';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DROPDOWN_OFFSET_Y } from '@/ui/layout/dropdown/constants/DropdownOffsetY';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
type RecordBoardColumnHeaderAggregateDropdownProps = {
|
||||
@ -31,7 +31,8 @@ export const RecordBoardColumnHeaderAggregateDropdown = ({
|
||||
handleContentChange,
|
||||
handleResetContent,
|
||||
previousContentId,
|
||||
} = useCurrentContentId<RecordBoardColumnHeaderAggregateContentId>();
|
||||
} =
|
||||
useDropdownContextCurrentContentId<RecordBoardColumnHeaderAggregateContentId>();
|
||||
|
||||
return (
|
||||
<RecordBoardColumnHeaderAggregateDropdownComponentInstanceContext.Provider
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useDropdown } from '@/dropdown/hooks/useDropdown';
|
||||
import { useDropdownContextStateManagement } from '@/dropdown-context-state-management/hooks/useDropdownContextStateManagement';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownContext } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownContext';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownFieldsContent } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownFieldsContent';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownMenuContent } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownMenuContent';
|
||||
@ -12,9 +12,10 @@ import { getAvailableFieldsIdsForAggregationFromObjectFields } from '@/object-re
|
||||
import { t } from '@lingui/core/macro';
|
||||
|
||||
export const AggregateDropdownContent = () => {
|
||||
const { currentContentId, objectMetadataItem } = useDropdown({
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
});
|
||||
const { currentContentId, objectMetadataItem } =
|
||||
useDropdownContextStateManagement({
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
});
|
||||
|
||||
switch (currentContentId) {
|
||||
case 'countAggregateOperationsOptions': {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useDropdown } from '@/dropdown/hooks/useDropdown';
|
||||
import { useDropdownContextStateManagement } from '@/dropdown-context-state-management/hooks/useDropdownContextStateManagement';
|
||||
import { RecordBoardColumnHeaderAggregateDropdownContext } from '@/object-record/record-board/record-board-column/components/RecordBoardColumnHeaderAggregateDropdownContext';
|
||||
import { aggregateOperationComponentState } from '@/object-record/record-board/record-board-column/states/aggregateOperationComponentState';
|
||||
import { availableFieldIdsForAggregateOperationComponentState } from '@/object-record/record-board/record-board-column/states/availableFieldIdsForAggregateOperationComponentState';
|
||||
@ -27,7 +27,7 @@ export const RecordBoardColumnHeaderAggregateDropdownFieldsContent = () => {
|
||||
onContentChange,
|
||||
resetContent,
|
||||
previousContentId,
|
||||
} = useDropdown({
|
||||
} = useDropdownContextStateManagement({
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
});
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Key } from 'ts-key-enum';
|
||||
|
||||
import { useDropdown } from '@/dropdown/hooks/useDropdown';
|
||||
import { useDropdownContextStateManagement } from '@/dropdown-context-state-management/hooks/useDropdownContextStateManagement';
|
||||
import {
|
||||
RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
RecordBoardColumnHeaderAggregateDropdownContextValue,
|
||||
@ -17,9 +17,11 @@ export const RecordBoardColumnHeaderAggregateDropdownMenuContent = () => {
|
||||
const { t } = useLingui();
|
||||
|
||||
const { onContentChange, closeDropdown } =
|
||||
useDropdown<RecordBoardColumnHeaderAggregateDropdownContextValue>({
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
});
|
||||
useDropdownContextStateManagement<RecordBoardColumnHeaderAggregateDropdownContextValue>(
|
||||
{
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
},
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useDropdown } from '@/dropdown/hooks/useDropdown';
|
||||
import { useDropdownContextStateManagement } from '@/dropdown-context-state-management/hooks/useDropdownContextStateManagement';
|
||||
import {
|
||||
RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
RecordBoardColumnHeaderAggregateDropdownContextValue,
|
||||
@ -32,9 +32,11 @@ export const RecordBoardColumnHeaderAggregateDropdownOptionsContent = ({
|
||||
title: string;
|
||||
}) => {
|
||||
const { onContentChange, closeDropdown, resetContent } =
|
||||
useDropdown<RecordBoardColumnHeaderAggregateDropdownContextValue>({
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
});
|
||||
useDropdownContextStateManagement<RecordBoardColumnHeaderAggregateDropdownContextValue>(
|
||||
{
|
||||
context: RecordBoardColumnHeaderAggregateDropdownContext,
|
||||
},
|
||||
);
|
||||
|
||||
useScopedHotkeys(
|
||||
[Key.Escape],
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useDropdown } from '@/dropdown/hooks/useDropdown';
|
||||
import { useDropdownContextStateManagement } from '@/dropdown-context-state-management/hooks/useDropdownContextStateManagement';
|
||||
import { AggregateOperations } from '@/object-record/record-table/constants/AggregateOperations';
|
||||
import { DateAggregateOperations } from '@/object-record/record-table/constants/DateAggregateOperations';
|
||||
import { RecordTableColumnAggregateFooterDropdownSubmenuContent } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateDropdownSubmenuContent';
|
||||
@ -14,9 +14,10 @@ import { useLingui } from '@lingui/react/macro';
|
||||
|
||||
export const RecordTableColumnAggregateFooterDropdownContent = () => {
|
||||
const { t } = useLingui();
|
||||
const { currentContentId, fieldMetadataType } = useDropdown({
|
||||
context: RecordTableColumnAggregateFooterDropdownContext,
|
||||
});
|
||||
const { currentContentId, fieldMetadataType } =
|
||||
useDropdownContextStateManagement({
|
||||
context: RecordTableColumnAggregateFooterDropdownContext,
|
||||
});
|
||||
|
||||
const availableAggregateOperations =
|
||||
getAvailableAggregateOperationsForFieldMetadataType({
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useCurrentContentId } from '@/dropdown/hooks/useCurrentContentId';
|
||||
import { useDropdownContextCurrentContentId } from '@/dropdown-context-state-management/hooks/useDropdownContextCurrentContentId';
|
||||
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
|
||||
import { RecordTableColumnAggregateFooterCellContext } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterCellContext';
|
||||
import { RecordTableColumnAggregateFooterDropdownContent } from '@/object-record/record-table/record-table-footer/components/RecordTableColumnAggregateFooterDropdownContent';
|
||||
@ -19,7 +19,7 @@ export const RecordTableColumnFooterWithDropdown = ({
|
||||
isFirstCell,
|
||||
}: RecordTableColumnFooterWithDropdownProps) => {
|
||||
const { currentContentId, handleContentChange, handleResetContent } =
|
||||
useCurrentContentId<RecordTableFooterAggregateContentId>();
|
||||
useDropdownContextCurrentContentId<RecordTableFooterAggregateContentId>();
|
||||
|
||||
const { fieldMetadataId } = useContext(
|
||||
RecordTableColumnAggregateFooterCellContext,
|
||||
|
||||
@ -2,7 +2,7 @@ import { useCreateEmptyRecordFilterFromFieldMetadataItem } from '@/object-record
|
||||
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
|
||||
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEditableFilterChipDropdownStates';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@ -20,7 +20,7 @@ export const useOpenRecordFilterChipFromTableHeader = () => {
|
||||
|
||||
const { upsertRecordFilter } = useUpsertRecordFilter();
|
||||
|
||||
const { openDropdown } = useDropdownV2();
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
|
||||
const { setEditableFilterChipDropdownStates } =
|
||||
useSetEditableFilterChipDropdownStates();
|
||||
@ -45,7 +45,10 @@ export const useOpenRecordFilterChipFromTableHeader = () => {
|
||||
|
||||
if (isDefined(existingNonAdvancedRecordFilter)) {
|
||||
setEditableFilterChipDropdownStates(existingNonAdvancedRecordFilter);
|
||||
openDropdown(existingNonAdvancedRecordFilter.id);
|
||||
openDropdown({
|
||||
dropdownComponentInstanceIdFromProps:
|
||||
existingNonAdvancedRecordFilter.id,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -56,7 +59,7 @@ export const useOpenRecordFilterChipFromTableHeader = () => {
|
||||
upsertRecordFilter(newRecordFilter);
|
||||
|
||||
setEditableFilterChipDropdownStates(newRecordFilter);
|
||||
openDropdown(newRecordFilter.id);
|
||||
openDropdown({ dropdownComponentInstanceIdFromProps: newRecordFilter.id });
|
||||
};
|
||||
|
||||
return { openRecordFilterChipFromTableHeader };
|
||||
|
||||
@ -2,7 +2,7 @@ import { DropdownOnToggleEffect } from '@/ui/layout/dropdown/components/Dropdown
|
||||
import { DropdownInternalContainer } from '@/ui/layout/dropdown/components/internal/DropdownInternalContainer';
|
||||
import { DROPDOWN_RESIZE_MIN_HEIGHT } from '@/ui/layout/dropdown/constants/DropdownResizeMinHeight';
|
||||
import { DROPDOWN_RESIZE_MIN_WIDTH } from '@/ui/layout/dropdown/constants/DropdownResizeMinWidth';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponeInstanceContext';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { dropdownMaxHeightComponentState } from '@/ui/layout/dropdown/states/internal/dropdownMaxHeightComponentState';
|
||||
import { dropdownMaxWidthComponentState } from '@/ui/layout/dropdown/states/internal/dropdownMaxWidthComponentState';
|
||||
|
||||
@ -3,20 +3,36 @@ import { renderHook } from '@testing-library/react';
|
||||
import { act } from 'react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useCloseAnyOpenDropdown } from '@/ui/layout/dropdown/hooks/useCloseAnyOpenDropdown';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
const dropdownId = 'test-dropdown-id';
|
||||
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
return <RecoilRoot>{children}</RecoilRoot>;
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<DropdownComponentInstanceContext.Provider
|
||||
value={{ instanceId: dropdownId }}
|
||||
>
|
||||
{children}
|
||||
</DropdownComponentInstanceContext.Provider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
describe('useCloseAnyOpenDropdown', () => {
|
||||
it('should open dropdown and then close it with closeAnyOpenDropdown', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const { openDropdown, isDropdownOpen } = useDropdown(dropdownId);
|
||||
const isDropdownOpen = useRecoilComponentValueV2(
|
||||
isDropdownOpenComponentStateV2,
|
||||
dropdownId,
|
||||
);
|
||||
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
|
||||
const { closeAnyOpenDropdown } = useCloseAnyOpenDropdown();
|
||||
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
import { expect } from '@storybook/test';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { act } from 'react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { useCloseDropdownFromOutside } from '@/ui/layout/dropdown/hooks/useCloseDropdownFromOutside';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
|
||||
const dropdownId = 'test-dropdown-id';
|
||||
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => {
|
||||
return <RecoilRoot>{children}</RecoilRoot>;
|
||||
};
|
||||
|
||||
describe('useCloseDropdownFromOutside', () => {
|
||||
it('should close open dropdown', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const { isDropdownOpen, openDropdown } = useDropdown(dropdownId);
|
||||
const { closeDropdownFromOutside } = useCloseDropdownFromOutside();
|
||||
|
||||
return { closeDropdownFromOutside, isDropdownOpen, openDropdown };
|
||||
},
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
result.current.openDropdown();
|
||||
});
|
||||
|
||||
expect(result.current.isDropdownOpen).toBe(true);
|
||||
|
||||
act(() => {
|
||||
result.current.closeDropdownFromOutside(dropdownId);
|
||||
});
|
||||
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -1,4 +1,4 @@
|
||||
import { useCloseDropdownFromOutside } from '@/ui/layout/dropdown/hooks/useCloseDropdownFromOutside';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { activeDropdownFocusIdState } from '@/ui/layout/dropdown/states/activeDropdownFocusIdState';
|
||||
import { previousDropdownFocusIdState } from '@/ui/layout/dropdown/states/previousDropdownFocusIdState';
|
||||
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
|
||||
@ -6,7 +6,7 @@ import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCloseAnyOpenDropdown = () => {
|
||||
const { closeDropdownFromOutside } = useCloseDropdownFromOutside();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
useRemoveFocusItemFromFocusStackById();
|
||||
@ -33,14 +33,14 @@ export const useCloseAnyOpenDropdown = () => {
|
||||
const thereIsOneNestedDropdownOpen = isDefined(previousDropdownFocusId);
|
||||
|
||||
if (isDefined(activeDropdownFocusId)) {
|
||||
closeDropdownFromOutside(activeDropdownFocusId);
|
||||
closeDropdown(activeDropdownFocusId);
|
||||
removeFocusItemFromFocusStackById({
|
||||
focusId: activeDropdownFocusId,
|
||||
});
|
||||
}
|
||||
|
||||
if (thereIsOneNestedDropdownOpen) {
|
||||
closeDropdownFromOutside(previousDropdownFocusId);
|
||||
closeDropdown(previousDropdownFocusId);
|
||||
removeFocusItemFromFocusStackById({
|
||||
focusId: previousDropdownFocusId,
|
||||
});
|
||||
@ -49,7 +49,7 @@ export const useCloseAnyOpenDropdown = () => {
|
||||
set(previousDropdownFocusIdState, null);
|
||||
set(activeDropdownFocusIdState, null);
|
||||
},
|
||||
[closeDropdownFromOutside, removeFocusItemFromFocusStackById],
|
||||
[closeDropdown, removeFocusItemFromFocusStackById],
|
||||
);
|
||||
|
||||
return { closeAnyOpenDropdown };
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useGoBackToPreviousDropdownFocusId } from '@/ui/layout/dropdown/hooks/useGoBackToPreviousDropdownFocusId';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
|
||||
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
|
||||
import { useAvailableComponentInstanceId } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceId';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCloseDropdown = () => {
|
||||
const { goBackToPreviousDropdownFocusId } =
|
||||
useGoBackToPreviousDropdownFocusId();
|
||||
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
useRemoveFocusItemFromFocusStackById();
|
||||
|
||||
const dropdownComponentInstanceIdFromContext =
|
||||
useAvailableComponentInstanceId(DropdownComponentInstanceContext);
|
||||
|
||||
const closeDropdown = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(dropdownComponentInstanceIdFromProps?: string) => {
|
||||
const dropdownComponentInstanceId =
|
||||
dropdownComponentInstanceIdFromProps ??
|
||||
dropdownComponentInstanceIdFromContext;
|
||||
|
||||
if (!isDefined(dropdownComponentInstanceId)) {
|
||||
throw new Error('Dropdown component instance ID is not defined');
|
||||
}
|
||||
|
||||
const isDropdownOpen = snapshot
|
||||
.getLoadable(
|
||||
isDropdownOpenComponentStateV2.atomFamily({
|
||||
instanceId: dropdownComponentInstanceId,
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
|
||||
const isDropdownOpenLegacy = snapshot
|
||||
.getLoadable(
|
||||
isDropdownOpenComponentState({
|
||||
scopeId: dropdownComponentInstanceId,
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
|
||||
if (isDropdownOpen || isDropdownOpenLegacy) {
|
||||
removeFocusItemFromFocusStackById({
|
||||
focusId: dropdownComponentInstanceId,
|
||||
});
|
||||
|
||||
goBackToPreviousDropdownFocusId();
|
||||
|
||||
set(
|
||||
isDropdownOpenComponentStateV2.atomFamily({
|
||||
instanceId: dropdownComponentInstanceId,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
|
||||
set(
|
||||
isDropdownOpenComponentState({
|
||||
scopeId: dropdownComponentInstanceId,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
}
|
||||
},
|
||||
[
|
||||
removeFocusItemFromFocusStackById,
|
||||
goBackToPreviousDropdownFocusId,
|
||||
dropdownComponentInstanceIdFromContext,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
closeDropdown,
|
||||
};
|
||||
};
|
||||
@ -1,14 +0,0 @@
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
export const useCloseDropdownFromOutside = () => {
|
||||
const closeDropdownFromOutside = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(dropdownId: string) => {
|
||||
set(isDropdownOpenComponentState({ scopeId: dropdownId }), false);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return { closeDropdownFromOutside };
|
||||
};
|
||||
@ -10,6 +10,13 @@ import { GlobalHotkeysConfig } from '@/ui/utilities/hotkey/types/GlobalHotkeysCo
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated This hook is deprecated, use a specific hook instead :
|
||||
* - `useOpenDropdown`
|
||||
* - `useCloseDropdown`
|
||||
* - `useToggleDropdown`
|
||||
*/
|
||||
export const useDropdown = (dropdownId?: string) => {
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
|
||||
@ -1,106 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useGoBackToPreviousDropdownFocusId } from '@/ui/layout/dropdown/hooks/useGoBackToPreviousDropdownFocusId';
|
||||
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
|
||||
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
import { GlobalHotkeysConfig } from '@/ui/utilities/hotkey/types/GlobalHotkeysConfig';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
|
||||
export const useDropdownV2 = () => {
|
||||
const { goBackToPreviousDropdownFocusId } =
|
||||
useGoBackToPreviousDropdownFocusId();
|
||||
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
useRemoveFocusItemFromFocusStackById();
|
||||
|
||||
const { setActiveDropdownFocusIdAndMemorizePrevious } =
|
||||
useSetActiveDropdownFocusIdAndMemorizePrevious();
|
||||
|
||||
const closeDropdown = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
(specificComponentId: string) => {
|
||||
const scopeId = specificComponentId;
|
||||
|
||||
const isDropdownOpen = snapshot
|
||||
.getLoadable(isDropdownOpenComponentState({ scopeId }))
|
||||
.getValue();
|
||||
|
||||
if (isDropdownOpen) {
|
||||
removeFocusItemFromFocusStackById({
|
||||
focusId: scopeId,
|
||||
});
|
||||
goBackToPreviousDropdownFocusId();
|
||||
set(
|
||||
isDropdownOpenComponentState({
|
||||
scopeId,
|
||||
}),
|
||||
false,
|
||||
);
|
||||
}
|
||||
},
|
||||
[removeFocusItemFromFocusStackById, goBackToPreviousDropdownFocusId],
|
||||
);
|
||||
|
||||
const openDropdown = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(
|
||||
specificComponentId: string,
|
||||
globalHotkeysConfig?: Partial<GlobalHotkeysConfig>,
|
||||
) => {
|
||||
const scopeId = specificComponentId;
|
||||
|
||||
set(
|
||||
isDropdownOpenComponentState({
|
||||
scopeId,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
setActiveDropdownFocusIdAndMemorizePrevious(specificComponentId);
|
||||
|
||||
pushFocusItemToFocusStack({
|
||||
focusId: scopeId,
|
||||
component: {
|
||||
type: FocusComponentType.DROPDOWN,
|
||||
instanceId: scopeId,
|
||||
},
|
||||
globalHotkeysConfig,
|
||||
// TODO: Remove this once we've fully migrated away from hotkey scopes
|
||||
hotkeyScope: { scope: 'dropdown' } as HotkeyScope,
|
||||
memoizeKey: 'global',
|
||||
});
|
||||
},
|
||||
[pushFocusItemToFocusStack, setActiveDropdownFocusIdAndMemorizePrevious],
|
||||
);
|
||||
|
||||
const toggleDropdown = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(
|
||||
specificComponentId: string,
|
||||
globalHotkeysConfig?: Partial<GlobalHotkeysConfig>,
|
||||
) => {
|
||||
const scopeId = specificComponentId;
|
||||
const isDropdownOpen = snapshot
|
||||
.getLoadable(isDropdownOpenComponentState({ scopeId }))
|
||||
.getValue();
|
||||
|
||||
if (isDropdownOpen) {
|
||||
closeDropdown(specificComponentId);
|
||||
} else {
|
||||
openDropdown(specificComponentId, globalHotkeysConfig);
|
||||
}
|
||||
},
|
||||
[closeDropdown, openDropdown],
|
||||
);
|
||||
|
||||
return {
|
||||
closeDropdown,
|
||||
openDropdown,
|
||||
toggleDropdown,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,77 @@
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useSetActiveDropdownFocusIdAndMemorizePrevious } from '@/ui/layout/dropdown/hooks/useSetFocusedDropdownIdAndMemorizePrevious';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
|
||||
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
import { GlobalHotkeysConfig } from '@/ui/utilities/hotkey/types/GlobalHotkeysConfig';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { useAvailableComponentInstanceId } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceId';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type OpenDropdownArgs = {
|
||||
dropdownComponentInstanceIdFromProps?: string;
|
||||
globalHotkeysConfig?: Partial<GlobalHotkeysConfig>;
|
||||
};
|
||||
|
||||
export const useOpenDropdown = () => {
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
|
||||
const { setActiveDropdownFocusIdAndMemorizePrevious } =
|
||||
useSetActiveDropdownFocusIdAndMemorizePrevious();
|
||||
const dropdownComponentInstanceIdFromContext =
|
||||
useAvailableComponentInstanceId(DropdownComponentInstanceContext);
|
||||
|
||||
const openDropdown = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(args?: OpenDropdownArgs | null | undefined) => {
|
||||
const dropdownComponentInstanceId =
|
||||
args?.dropdownComponentInstanceIdFromProps ??
|
||||
dropdownComponentInstanceIdFromContext;
|
||||
|
||||
if (!isDefined(dropdownComponentInstanceId)) {
|
||||
throw new Error('Dropdown component instance ID is not defined');
|
||||
}
|
||||
|
||||
set(
|
||||
isDropdownOpenComponentState({
|
||||
scopeId: dropdownComponentInstanceId,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
set(
|
||||
isDropdownOpenComponentStateV2.atomFamily({
|
||||
instanceId: dropdownComponentInstanceId,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
|
||||
setActiveDropdownFocusIdAndMemorizePrevious(
|
||||
dropdownComponentInstanceId,
|
||||
);
|
||||
|
||||
pushFocusItemToFocusStack({
|
||||
focusId: dropdownComponentInstanceId,
|
||||
component: {
|
||||
type: FocusComponentType.DROPDOWN,
|
||||
instanceId: dropdownComponentInstanceId,
|
||||
},
|
||||
globalHotkeysConfig: args?.globalHotkeysConfig ?? undefined,
|
||||
// TODO: Remove this once we've fully migrated away from hotkey scopes
|
||||
hotkeyScope: { scope: 'dropdown' } as HotkeyScope,
|
||||
memoizeKey: 'global',
|
||||
});
|
||||
},
|
||||
[
|
||||
pushFocusItemToFocusStack,
|
||||
setActiveDropdownFocusIdAndMemorizePrevious,
|
||||
dropdownComponentInstanceIdFromContext,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
openDropdown,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,66 @@
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { isDropdownOpenComponentStateV2 } from '@/ui/layout/dropdown/states/isDropdownOpenComponentStateV2';
|
||||
import { GlobalHotkeysConfig } from '@/ui/utilities/hotkey/types/GlobalHotkeysConfig';
|
||||
import { useAvailableComponentInstanceId } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceId';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useToggleDropdown = () => {
|
||||
const dropdownComponentInstanceIdFromContext =
|
||||
useAvailableComponentInstanceId(DropdownComponentInstanceContext);
|
||||
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const toggleDropdown = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
({
|
||||
dropdownComponentInstanceIdFromProps,
|
||||
globalHotkeysConfig,
|
||||
}: {
|
||||
dropdownComponentInstanceIdFromProps?: string;
|
||||
globalHotkeysConfig?: Partial<GlobalHotkeysConfig>;
|
||||
}) => {
|
||||
const dropdownComponentInstanceId =
|
||||
dropdownComponentInstanceIdFromProps ??
|
||||
dropdownComponentInstanceIdFromContext;
|
||||
|
||||
if (!isDefined(dropdownComponentInstanceId)) {
|
||||
throw new Error('Dropdown component instance ID is not defined');
|
||||
}
|
||||
|
||||
const isDropdownOpen = snapshot
|
||||
.getLoadable(
|
||||
isDropdownOpenComponentStateV2.atomFamily({
|
||||
instanceId: dropdownComponentInstanceId,
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
|
||||
const isDropdownOpenLegacy = snapshot
|
||||
.getLoadable(
|
||||
isDropdownOpenComponentState({
|
||||
scopeId: dropdownComponentInstanceId,
|
||||
}),
|
||||
)
|
||||
.getValue();
|
||||
|
||||
if (isDropdownOpen || isDropdownOpenLegacy) {
|
||||
closeDropdown(dropdownComponentInstanceId);
|
||||
} else {
|
||||
openDropdown({
|
||||
dropdownComponentInstanceIdFromProps: dropdownComponentInstanceId,
|
||||
globalHotkeysConfig,
|
||||
});
|
||||
}
|
||||
},
|
||||
[closeDropdown, openDropdown, dropdownComponentInstanceIdFromContext],
|
||||
);
|
||||
|
||||
return {
|
||||
toggleDropdown,
|
||||
};
|
||||
};
|
||||
@ -1,4 +1,5 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const activeDropdownFocusIdState = createState<string | null>({
|
||||
key: 'activeDropdownFocusIdState',
|
||||
defaultValue: null,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponeInstanceContext';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const dropdownMaxHeightComponentState = createComponentStateV2<
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponeInstanceContext';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const dropdownMaxWidthComponentState = createComponentStateV2<
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
/**
|
||||
* @deprecated Use `isDropdownOpenComponentStateV2` instead.
|
||||
*/
|
||||
export const isDropdownOpenComponentState = createComponentState<boolean>({
|
||||
key: 'isDropdownOpenComponentState',
|
||||
defaultValue: false,
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
|
||||
export const isDropdownOpenComponentStateV2 = createComponentStateV2<boolean>({
|
||||
key: 'isDropdownOpenComponentStateV2',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: DropdownComponentInstanceContext,
|
||||
});
|
||||
@ -1,4 +1,5 @@
|
||||
import { createState } from 'twenty-ui/utilities';
|
||||
|
||||
export const previousDropdownFocusIdState = createState<string | null>({
|
||||
key: 'previousDropdownFocusIdState',
|
||||
defaultValue: null,
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
import { useComponentInstanceStateContext } from '@/ui/utilities/state/component-state/hooks/useComponentInstanceStateContext';
|
||||
import { ComponentInstanceStateContext } from '@/ui/utilities/state/component-state/types/ComponentInstanceStateContext';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
|
||||
export const useAvailableComponentInstanceId = <
|
||||
T extends { instanceId: string },
|
||||
>(
|
||||
Context: ComponentInstanceStateContext<T>,
|
||||
): string | null => {
|
||||
const instanceStateContext = useComponentInstanceStateContext(Context);
|
||||
|
||||
const instanceIdFromContext = instanceStateContext?.instanceId;
|
||||
|
||||
if (isNonEmptyString(instanceIdFromContext)) {
|
||||
return instanceIdFromContext;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||
import { VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerKanbanFieldDropdownId';
|
||||
@ -17,7 +17,7 @@ export const useCloseAndResetViewPicker = () => {
|
||||
viewPickerIsPersistingComponentState,
|
||||
);
|
||||
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const closeAndResetViewPicker = useCallback(() => {
|
||||
setViewPickerIsPersisting(false);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/StyledDropdownButtonContainer';
|
||||
import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { WorkflowVariablesDropdownFieldItems } from '@/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems';
|
||||
@ -51,7 +51,7 @@ export const WorkflowVariablesDropdown = ({
|
||||
const isDropdownOpen = useRecoilValue(
|
||||
extractComponentState(isDropdownOpenComponentState, dropdownId),
|
||||
);
|
||||
const { closeDropdown } = useDropdownV2();
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
const availableVariablesInWorkflowStep = useAvailableVariablesInWorkflowStep({
|
||||
objectNameSingularToSelect,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user