fixes #4365 --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
committed by
GitHub
parent
c0d0f8d78d
commit
99f8f8fedb
@ -1,15 +1,18 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { useIcons } from 'twenty-ui';
|
|
||||||
|
|
||||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||||
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
|
||||||
|
|
||||||
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
|
import { ObjectFilterDropdownFilterSelectMenuItem } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem';
|
||||||
|
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
|
||||||
|
import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter';
|
||||||
|
import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types/FiltersHotkeyScope';
|
||||||
|
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
|
||||||
|
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||||
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
|
import { isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
export const StyledInput = styled.input`
|
export const StyledInput = styled.input`
|
||||||
background: transparent;
|
background: transparent;
|
||||||
@ -39,20 +42,40 @@ export const StyledInput = styled.input`
|
|||||||
|
|
||||||
export const ObjectFilterDropdownFilterSelect = () => {
|
export const ObjectFilterDropdownFilterSelect = () => {
|
||||||
const [searchText, setSearchText] = useState('');
|
const [searchText, setSearchText] = useState('');
|
||||||
const {
|
|
||||||
setFilterDefinitionUsedInDropdown,
|
const { availableFilterDefinitionsState } = useFilterDropdown();
|
||||||
setSelectedOperandInDropdown,
|
|
||||||
setObjectFilterDropdownSearchInput,
|
|
||||||
availableFilterDefinitionsState,
|
|
||||||
} = useFilterDropdown();
|
|
||||||
|
|
||||||
const availableFilterDefinitions = useRecoilValue(
|
const availableFilterDefinitions = useRecoilValue(
|
||||||
availableFilterDefinitionsState,
|
availableFilterDefinitionsState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const { getIcon } = useIcons();
|
const sortedAvailableFilterDefinitions = [...availableFilterDefinitions]
|
||||||
|
.sort((a, b) => a.label.localeCompare(b.label))
|
||||||
|
.filter((item) =>
|
||||||
|
item.label.toLocaleLowerCase().includes(searchText.toLocaleLowerCase()),
|
||||||
|
);
|
||||||
|
|
||||||
const setHotkeyScope = useSetHotkeyScope();
|
const selectableListItemIds = sortedAvailableFilterDefinitions.map(
|
||||||
|
(item) => item.fieldMetadataId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { selectFilter } = useSelectFilter();
|
||||||
|
|
||||||
|
const { resetSelectedItem } = useSelectableList(OBJECT_FILTER_DROPDOWN_ID);
|
||||||
|
|
||||||
|
const handleEnter = (itemId: string) => {
|
||||||
|
const selectedFilterDefinition = sortedAvailableFilterDefinitions.find(
|
||||||
|
(item) => item.fieldMetadataId === itemId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isDefined(selectedFilterDefinition)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetSelectedItem();
|
||||||
|
|
||||||
|
selectFilter({ filterDefinition: selectedFilterDefinition });
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -64,39 +87,27 @@ export const ObjectFilterDropdownFilterSelect = () => {
|
|||||||
setSearchText(event.target.value)
|
setSearchText(event.target.value)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<DropdownMenuItemsContainer>
|
<SelectableList
|
||||||
{[...availableFilterDefinitions]
|
hotkeyScope={FiltersHotkeyScope.ObjectFilterDropdownButton}
|
||||||
.sort((a, b) => a.label.localeCompare(b.label))
|
selectableItemIdArray={selectableListItemIds}
|
||||||
.filter((item) =>
|
selectableListId={OBJECT_FILTER_DROPDOWN_ID}
|
||||||
item.label
|
onEnter={handleEnter}
|
||||||
.toLocaleLowerCase()
|
>
|
||||||
.includes(searchText.toLocaleLowerCase()),
|
<DropdownMenuItemsContainer>
|
||||||
)
|
{sortedAvailableFilterDefinitions.map(
|
||||||
.map((availableFilterDefinition, index) => (
|
(availableFilterDefinition, index) => (
|
||||||
<MenuItem
|
<SelectableItem
|
||||||
key={`select-filter-${index}`}
|
itemId={availableFilterDefinition.fieldMetadataId}
|
||||||
testId={`select-filter-${index}`}
|
>
|
||||||
onClick={() => {
|
<ObjectFilterDropdownFilterSelectMenuItem
|
||||||
setFilterDefinitionUsedInDropdown(availableFilterDefinition);
|
key={`select-filter-${index}`}
|
||||||
|
filterDefinition={availableFilterDefinition}
|
||||||
if (
|
/>
|
||||||
availableFilterDefinition.type === 'RELATION' ||
|
</SelectableItem>
|
||||||
availableFilterDefinition.type === 'SELECT'
|
),
|
||||||
) {
|
)}
|
||||||
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
|
</DropdownMenuItemsContainer>
|
||||||
}
|
</SelectableList>
|
||||||
|
|
||||||
setSelectedOperandInDropdown(
|
|
||||||
getOperandsForFilterType(availableFilterDefinition.type)?.[0],
|
|
||||||
);
|
|
||||||
|
|
||||||
setObjectFilterDropdownSearchInput('');
|
|
||||||
}}
|
|
||||||
LeftIcon={getIcon(availableFilterDefinition.iconName)}
|
|
||||||
text={availableFilterDefinition.label}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</DropdownMenuItemsContainer>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,43 @@
|
|||||||
|
import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdown/constants/ObjectFilterDropdownId';
|
||||||
|
import { useSelectFilter } from '@/object-record/object-filter-dropdown/hooks/useSelectFilter';
|
||||||
|
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
|
||||||
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
|
import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSelect';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { useIcons } from 'twenty-ui';
|
||||||
|
|
||||||
|
export type ObjectFilterDropdownFilterSelectMenuItemProps = {
|
||||||
|
filterDefinition: FilterDefinition;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ObjectFilterDropdownFilterSelectMenuItem = ({
|
||||||
|
filterDefinition,
|
||||||
|
}: ObjectFilterDropdownFilterSelectMenuItemProps) => {
|
||||||
|
const { selectFilter } = useSelectFilter();
|
||||||
|
|
||||||
|
const { isSelectedItemIdSelector, resetSelectedItem } = useSelectableList(
|
||||||
|
OBJECT_FILTER_DROPDOWN_ID,
|
||||||
|
);
|
||||||
|
|
||||||
|
const isSelectedItem = useRecoilValue(
|
||||||
|
isSelectedItemIdSelector(filterDefinition.fieldMetadataId),
|
||||||
|
);
|
||||||
|
|
||||||
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
resetSelectedItem();
|
||||||
|
|
||||||
|
selectFilter({ filterDefinition });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MenuItemSelect
|
||||||
|
selected={false}
|
||||||
|
hovered={isSelectedItem}
|
||||||
|
onClick={handleClick}
|
||||||
|
LeftIcon={getIcon(filterDefinition.iconName)}
|
||||||
|
text={filterDefinition.label}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -41,7 +41,7 @@ export const ObjectFilterDropdownOptionSelect = () => {
|
|||||||
selectableListScopeId: MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
selectableListScopeId: MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { handleResetSelectedPosition } = useSelectableList(
|
const { resetSelectedItem } = useSelectableList(
|
||||||
MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -90,10 +90,10 @@ export const ObjectFilterDropdownOptionSelect = () => {
|
|||||||
[Key.Escape],
|
[Key.Escape],
|
||||||
() => {
|
() => {
|
||||||
closeDropdown();
|
closeDropdown();
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
},
|
},
|
||||||
RelationPickerHotkeyScope.RelationPicker,
|
RelationPickerHotkeyScope.RelationPicker,
|
||||||
[closeDropdown, handleResetSelectedPosition],
|
[closeDropdown, resetSelectedItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleMultipleOptionSelectChange = (
|
const handleMultipleOptionSelectChange = (
|
||||||
@ -137,7 +137,7 @@ export const ObjectFilterDropdownOptionSelect = () => {
|
|||||||
value: newFilterValue,
|
value: newFilterValue,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
};
|
};
|
||||||
|
|
||||||
const optionsInDropdown = selectableOptions?.filter((option) =>
|
const optionsInDropdown = selectableOptions?.filter((option) =>
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||||
|
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
|
||||||
|
import { getOperandsForFilterType } from '@/object-record/object-filter-dropdown/utils/getOperandsForFilterType';
|
||||||
|
import { RelationPickerHotkeyScope } from '@/object-record/relation-picker/types/RelationPickerHotkeyScope';
|
||||||
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
|
|
||||||
|
type SelectFilterParams = {
|
||||||
|
filterDefinition: FilterDefinition;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useSelectFilter = () => {
|
||||||
|
const {
|
||||||
|
setFilterDefinitionUsedInDropdown,
|
||||||
|
setSelectedOperandInDropdown,
|
||||||
|
setObjectFilterDropdownSearchInput,
|
||||||
|
} = useFilterDropdown();
|
||||||
|
|
||||||
|
const setHotkeyScope = useSetHotkeyScope();
|
||||||
|
|
||||||
|
const selectFilter = ({ filterDefinition }: SelectFilterParams) => {
|
||||||
|
setFilterDefinitionUsedInDropdown(filterDefinition);
|
||||||
|
|
||||||
|
if (
|
||||||
|
filterDefinition.type === 'RELATION' ||
|
||||||
|
filterDefinition.type === 'SELECT'
|
||||||
|
) {
|
||||||
|
setHotkeyScope(RelationPickerHotkeyScope.RelationPicker);
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectedOperandInDropdown(
|
||||||
|
getOperandsForFilterType(filterDefinition.type)?.[0],
|
||||||
|
);
|
||||||
|
|
||||||
|
setObjectFilterDropdownSearchInput('');
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
selectFilter,
|
||||||
|
};
|
||||||
|
};
|
||||||
@ -33,7 +33,7 @@ export const MultiSelectFieldInput = ({
|
|||||||
const { selectedItemIdState } = useSelectableListStates({
|
const { selectedItemIdState } = useSelectableListStates({
|
||||||
selectableListScopeId: MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
selectableListScopeId: MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
||||||
});
|
});
|
||||||
const { handleResetSelectedPosition } = useSelectableList(
|
const { resetSelectedItem } = useSelectableList(
|
||||||
MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
||||||
);
|
);
|
||||||
const { persistField, fieldDefinition, fieldValues, hotkeyScope } =
|
const { persistField, fieldDefinition, fieldValues, hotkeyScope } =
|
||||||
@ -65,10 +65,10 @@ export const MultiSelectFieldInput = ({
|
|||||||
Key.Escape,
|
Key.Escape,
|
||||||
() => {
|
() => {
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
},
|
},
|
||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
[onCancel, handleResetSelectedPosition],
|
[onCancel, resetSelectedItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
useListenClickOutside({
|
useListenClickOutside({
|
||||||
@ -83,7 +83,7 @@ export const MultiSelectFieldInput = ({
|
|||||||
if (weAreNotInAnHTMLInput && isDefined(onCancel)) {
|
if (weAreNotInAnHTMLInput && isDefined(onCancel)) {
|
||||||
onCancel();
|
onCancel();
|
||||||
}
|
}
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export const SelectFieldInput = ({
|
|||||||
|
|
||||||
const [filteredOptions, setFilteredOptions] = useState<SelectOption[]>([]);
|
const [filteredOptions, setFilteredOptions] = useState<SelectOption[]>([]);
|
||||||
|
|
||||||
const { handleResetSelectedPosition } = useSelectableList(
|
const { resetSelectedItem } = useSelectableList(
|
||||||
SINGLE_ENTITY_SELECT_BASE_LIST,
|
SINGLE_ENTITY_SELECT_BASE_LIST,
|
||||||
);
|
);
|
||||||
const clearField = useClearField();
|
const clearField = useClearField();
|
||||||
@ -44,17 +44,17 @@ export const SelectFieldInput = ({
|
|||||||
const handleSubmit = (option: SelectOption) => {
|
const handleSubmit = (option: SelectOption) => {
|
||||||
onSubmit?.(() => persistField(option?.value));
|
onSubmit?.(() => persistField(option?.value));
|
||||||
|
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
};
|
};
|
||||||
|
|
||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
Key.Escape,
|
Key.Escape,
|
||||||
() => {
|
() => {
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
},
|
},
|
||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
[onCancel, handleResetSelectedPosition],
|
[onCancel, resetSelectedItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
const optionIds = [
|
const optionIds = [
|
||||||
@ -74,7 +74,7 @@ export const SelectFieldInput = ({
|
|||||||
);
|
);
|
||||||
if (isDefined(option)) {
|
if (isDefined(option)) {
|
||||||
onSubmit?.(() => persistField(option.value));
|
onSubmit?.(() => persistField(option.value));
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -48,7 +48,7 @@ export const MultiRecordSelect = ({
|
|||||||
const { objectRecordsIdsMultiSelectState, recordMultiSelectIsLoadingState } =
|
const { objectRecordsIdsMultiSelectState, recordMultiSelectIsLoadingState } =
|
||||||
useObjectRecordMultiSelectScopedStates(relationPickerScopedId);
|
useObjectRecordMultiSelectScopedStates(relationPickerScopedId);
|
||||||
|
|
||||||
const { handleResetSelectedPosition } = useSelectableList(
|
const { resetSelectedItem } = useSelectableList(
|
||||||
MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
MULTI_OBJECT_RECORD_SELECT_SELECTABLE_LIST_ID,
|
||||||
);
|
);
|
||||||
const recordMultiSelectIsLoading = useRecoilValue(
|
const recordMultiSelectIsLoading = useRecoilValue(
|
||||||
@ -79,10 +79,10 @@ export const MultiRecordSelect = ({
|
|||||||
() => {
|
() => {
|
||||||
onSubmit?.();
|
onSubmit?.();
|
||||||
goBackToPreviousHotkeyScope();
|
goBackToPreviousHotkeyScope();
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
},
|
},
|
||||||
relationPickerScopedId,
|
relationPickerScopedId,
|
||||||
[onSubmit, goBackToPreviousHotkeyScope, handleResetSelectedPosition],
|
[onSubmit, goBackToPreviousHotkeyScope, resetSelectedItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
const debouncedOnCreate = useDebouncedCallback(
|
const debouncedOnCreate = useDebouncedCallback(
|
||||||
@ -123,7 +123,7 @@ export const MultiRecordSelect = ({
|
|||||||
hotkeyScope={relationPickerScopedId}
|
hotkeyScope={relationPickerScopedId}
|
||||||
onEnter={(selectedId) => {
|
onEnter={(selectedId) => {
|
||||||
onChange?.(selectedId);
|
onChange?.(selectedId);
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{objectRecordsIdsMultiSelect?.map((recordId) => {
|
{objectRecordsIdsMultiSelect?.map((recordId) => {
|
||||||
@ -133,7 +133,7 @@ export const MultiRecordSelect = ({
|
|||||||
objectRecordId={recordId}
|
objectRecordId={recordId}
|
||||||
onChange={(recordId) => {
|
onChange={(recordId) => {
|
||||||
onChange?.(recordId);
|
onChange?.(recordId);
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -27,7 +27,6 @@ export const SelectableMenuItemSelect = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector(entity.id));
|
const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector(entity.id));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledSelectableItem itemId={entity.id} key={entity.id}>
|
<StyledSelectableItem itemId={entity.id} key={entity.id}>
|
||||||
<MenuItemSelectAvatar
|
<MenuItemSelectAvatar
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { useRef } from 'react';
|
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
import { useRef } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
import { IconComponent, IconPlus } from 'twenty-ui';
|
import { IconComponent, IconPlus } from 'twenty-ui';
|
||||||
@ -92,8 +92,9 @@ export const SingleEntitySelectMenuItems = ({
|
|||||||
isDefined(entity) && isNonEmptyString(entity.name),
|
isDefined(entity) && isNonEmptyString(entity.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { isSelectedItemIdSelector, handleResetSelectedPosition } =
|
const { isSelectedItemIdSelector, resetSelectedItem } = useSelectableList(
|
||||||
useSelectableList(SINGLE_ENTITY_SELECT_BASE_LIST);
|
SINGLE_ENTITY_SELECT_BASE_LIST,
|
||||||
|
);
|
||||||
|
|
||||||
const isSelectedAddNewButton = useRecoilValue(
|
const isSelectedAddNewButton = useRecoilValue(
|
||||||
isSelectedItemIdSelector('add-new'),
|
isSelectedItemIdSelector('add-new'),
|
||||||
@ -110,11 +111,11 @@ export const SingleEntitySelectMenuItems = ({
|
|||||||
useScopedHotkeys(
|
useScopedHotkeys(
|
||||||
[Key.Escape],
|
[Key.Escape],
|
||||||
() => {
|
() => {
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
onCancel?.();
|
onCancel?.();
|
||||||
},
|
},
|
||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
[onCancel, handleResetSelectedPosition],
|
[onCancel, resetSelectedItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectableItemIds = entitiesInDropdown.map((entity) => entity.id);
|
const selectableItemIds = entitiesInDropdown.map((entity) => entity.id);
|
||||||
@ -134,7 +135,7 @@ export const SingleEntitySelectMenuItems = ({
|
|||||||
);
|
);
|
||||||
onEntitySelected(entitiesInDropdown[entityIndex]);
|
onEntitySelected(entitiesInDropdown[entityIndex]);
|
||||||
}
|
}
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DropdownMenuItemsContainer hasMaxHeight>
|
<DropdownMenuItemsContainer hasMaxHeight>
|
||||||
|
|||||||
@ -40,7 +40,7 @@ export const MultipleRecordSelectDropdown = ({
|
|||||||
selectableListScopeId: selectableListId,
|
selectableListScopeId: selectableListId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { handleResetSelectedPosition } = useSelectableList(selectableListId);
|
const { resetSelectedItem } = useSelectableList(selectableListId);
|
||||||
|
|
||||||
const selectedItemId = useRecoilValue(selectedItemIdState);
|
const selectedItemId = useRecoilValue(selectedItemIdState);
|
||||||
|
|
||||||
@ -75,10 +75,10 @@ export const MultipleRecordSelectDropdown = ({
|
|||||||
[Key.Escape],
|
[Key.Escape],
|
||||||
() => {
|
() => {
|
||||||
closeDropdown();
|
closeDropdown();
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
},
|
},
|
||||||
hotkeyScope,
|
hotkeyScope,
|
||||||
[closeDropdown, handleResetSelectedPosition],
|
[closeDropdown, resetSelectedItem],
|
||||||
);
|
);
|
||||||
|
|
||||||
const showNoResult =
|
const showNoResult =
|
||||||
@ -105,7 +105,7 @@ export const MultipleRecordSelectDropdown = ({
|
|||||||
recordsInDropdown[record],
|
recordsInDropdown[record],
|
||||||
!recordIsSelectedInDropwdown,
|
!recordIsSelectedInDropwdown,
|
||||||
);
|
);
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DropdownMenuItemsContainer hasMaxHeight>
|
<DropdownMenuItemsContainer hasMaxHeight>
|
||||||
@ -116,7 +116,7 @@ export const MultipleRecordSelectDropdown = ({
|
|||||||
selected={record.isSelected}
|
selected={record.isSelected}
|
||||||
isKeySelected={record.id === selectedItemId}
|
isKeySelected={record.id === selectedItemId}
|
||||||
onSelectChange={(newCheckedValue) => {
|
onSelectChange={(newCheckedValue) => {
|
||||||
handleResetSelectedPosition();
|
resetSelectedItem();
|
||||||
handleRecordSelectChange(record, newCheckedValue);
|
handleRecordSelectChange(record, newCheckedValue);
|
||||||
}}
|
}}
|
||||||
avatar={
|
avatar={
|
||||||
|
|||||||
@ -10,9 +10,7 @@ import { MouseEvent, useRef } from 'react';
|
|||||||
import { Keys } from 'react-hotkeys-hook';
|
import { Keys } from 'react-hotkeys-hook';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
|
|
||||||
import { SINGLE_ENTITY_SELECT_BASE_LIST } from '@/object-record/relation-picker/constants/SingleEntitySelectBaseList';
|
|
||||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
|
||||||
import { HotkeyEffect } from '@/ui/utilities/hotkey/components/HotkeyEffect';
|
import { HotkeyEffect } from '@/ui/utilities/hotkey/components/HotkeyEffect';
|
||||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||||
@ -69,9 +67,6 @@ export const Dropdown = ({
|
|||||||
const { isDropdownOpen, toggleDropdown, closeDropdown, dropdownWidth } =
|
const { isDropdownOpen, toggleDropdown, closeDropdown, dropdownWidth } =
|
||||||
useDropdown(dropdownId);
|
useDropdown(dropdownId);
|
||||||
|
|
||||||
const { handleResetSelectedPosition } = useSelectableList(
|
|
||||||
SINGLE_ENTITY_SELECT_BASE_LIST,
|
|
||||||
);
|
|
||||||
const offsetMiddlewares = [];
|
const offsetMiddlewares = [];
|
||||||
|
|
||||||
if (isDefined(dropdownOffset.x)) {
|
if (isDefined(dropdownOffset.x)) {
|
||||||
@ -108,7 +103,6 @@ export const Dropdown = ({
|
|||||||
|
|
||||||
if (isDropdownOpen) {
|
if (isDropdownOpen) {
|
||||||
closeDropdown();
|
closeDropdown();
|
||||||
handleResetSelectedPosition();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -122,10 +116,9 @@ export const Dropdown = ({
|
|||||||
[Key.Escape],
|
[Key.Escape],
|
||||||
() => {
|
() => {
|
||||||
closeDropdown();
|
closeDropdown();
|
||||||
handleResetSelectedPosition();
|
|
||||||
},
|
},
|
||||||
dropdownHotkeyScope.scope,
|
dropdownHotkeyScope.scope,
|
||||||
[closeDropdown, handleResetSelectedPosition],
|
[closeDropdown],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -2,6 +2,12 @@ import { ReactNode, useEffect, useRef } from 'react';
|
|||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
|
||||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
const StyledContainer = styled.div`
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
export type SelectableItemProps = {
|
export type SelectableItemProps = {
|
||||||
itemId: string;
|
itemId: string;
|
||||||
@ -27,8 +33,8 @@ export const SelectableItem = ({
|
|||||||
}, [isSelectedItemId]);
|
}, [isSelectedItemId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className} ref={scrollRef}>
|
<StyledContainer className={className} ref={scrollRef}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</StyledContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,8 +1,4 @@
|
|||||||
import {
|
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||||
useRecoilCallback,
|
|
||||||
useResetRecoilState,
|
|
||||||
useSetRecoilState,
|
|
||||||
} from 'recoil';
|
|
||||||
|
|
||||||
import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates';
|
import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates';
|
||||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||||
@ -24,16 +20,11 @@ export const useSelectableList = (selectableListId?: string) => {
|
|||||||
selectableListOnEnterState,
|
selectableListOnEnterState,
|
||||||
);
|
);
|
||||||
|
|
||||||
const resetSelectedItemIdState = useResetRecoilState(selectedItemIdState);
|
const resetSelectedItem = useRecoilCallback(
|
||||||
|
|
||||||
const resetSelectedItem = () => {
|
|
||||||
resetSelectedItemIdState();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleResetSelectedPosition = useRecoilCallback(
|
|
||||||
({ snapshot, set }) =>
|
({ snapshot, set }) =>
|
||||||
() => {
|
() => {
|
||||||
const selectedItemId = getSnapshotValue(snapshot, selectedItemIdState);
|
const selectedItemId = getSnapshotValue(snapshot, selectedItemIdState);
|
||||||
|
|
||||||
if (isDefined(selectedItemId)) {
|
if (isDefined(selectedItemId)) {
|
||||||
set(selectedItemIdState, null);
|
set(selectedItemIdState, null);
|
||||||
set(isSelectedItemIdSelector(selectedItemId), false);
|
set(isSelectedItemIdSelector(selectedItemId), false);
|
||||||
@ -44,11 +35,9 @@ export const useSelectableList = (selectableListId?: string) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
selectableListId: scopeId,
|
selectableListId: scopeId,
|
||||||
|
|
||||||
setSelectableItemIds,
|
setSelectableItemIds,
|
||||||
isSelectedItemIdSelector,
|
isSelectedItemIdSelector,
|
||||||
setSelectableListOnEnter,
|
setSelectableListOnEnter,
|
||||||
resetSelectedItem,
|
resetSelectedItem,
|
||||||
handleResetSelectedPosition,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,12 +8,12 @@ export type MenuItemBaseProps = {
|
|||||||
accent?: MenuItemAccent;
|
accent?: MenuItemAccent;
|
||||||
isKeySelected?: boolean;
|
isKeySelected?: boolean;
|
||||||
isHoverBackgroundDisabled?: boolean;
|
isHoverBackgroundDisabled?: boolean;
|
||||||
|
hovered?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const StyledMenuItemBase = styled.div<MenuItemBaseProps>`
|
export const StyledMenuItemBase = styled.div<MenuItemBaseProps>`
|
||||||
--horizontal-padding: ${({ theme }) => theme.spacing(1)};
|
--horizontal-padding: ${({ theme }) => theme.spacing(1)};
|
||||||
--vertical-padding: ${({ theme }) => theme.spacing(2)};
|
--vertical-padding: ${({ theme }) => theme.spacing(2)};
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
|
|||||||
Reference in New Issue
Block a user