diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuDefaultSelectionEffect.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuDefaultSelectionEffect.tsx index 2d6acdac0..e7939c38a 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenuDefaultSelectionEffect.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuDefaultSelectionEffect.tsx @@ -1,5 +1,7 @@ import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useEffect } from 'react'; import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared/utils'; @@ -9,10 +11,12 @@ export const CommandMenuDefaultSelectionEffect = ({ }: { selectableItemIds: string[]; }) => { - const { setSelectedItemId, selectedItemIdState } = - useSelectableList('command-menu-list'); + const { setSelectedItemId } = useSelectableList('command-menu-list'); - const selectedItemId = useRecoilValue(selectedItemIdState); + const selectedItemId = useRecoilComponentValueV2( + selectedItemIdComponentState, + 'command-menu-list', + ); const hasUserSelectedCommand = useRecoilValue(hasUserSelectedCommandState); diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuItem.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuItem.tsx index c7c199bca..e1988b303 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenuItem.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuItem.tsx @@ -1,8 +1,8 @@ import { isNonEmptyString } from '@sniptt/guards'; -import { useRecoilValue } from 'recoil'; import { useCommandMenuOnItemClick } from '@/command-menu/hooks/useCommandMenuOnItemClick'; -import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector'; +import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; import { ReactNode } from 'react'; import { IconArrowUpRight, IconComponent } from 'twenty-ui/display'; import { MenuItemCommand } from 'twenty-ui/navigation'; @@ -35,8 +35,10 @@ export const CommandMenuItem = ({ Icon = IconArrowUpRight; } - const { isSelectedItemIdSelector } = useSelectableList(); - const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector(id)); + const isSelectedItemId = useRecoilComponentFamilyValueV2( + isSelectedItemIdComponentFamilySelector, + id, + ); return ( { diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterFieldSelectMenu.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterFieldSelectMenu.tsx index 1ea4f94fe..8f3e4e095 100644 --- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterFieldSelectMenu.tsx +++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterFieldSelectMenu.tsx @@ -144,7 +144,7 @@ export const AdvancedFilterFieldSelectMenu = ({ diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx index e612805d3..9cb5f1980 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect.tsx @@ -90,7 +90,7 @@ export const ObjectFilterDropdownBooleanSelect = () => { return ( option.toString())} hotkeyScope={SingleRecordPickerHotkeyScope.SingleRecordPicker} onEnter={(itemId) => { diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx index f8e67b905..34d630beb 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelect.tsx @@ -150,7 +150,7 @@ export const ObjectFilterDropdownFilterSelect = ({ diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx index 9e4fd5d87..ad6a6142e 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItem.tsx @@ -15,14 +15,15 @@ import { findDuplicateRecordFilterInNonAdvancedRecordFilters } from '@/object-re import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; +import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; -import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared/utils'; -import { MenuItemSelect } from 'twenty-ui/navigation'; import { useIcons } from 'twenty-ui/display'; +import { MenuItemSelect } from 'twenty-ui/navigation'; export type ObjectFilterDropdownFilterSelectMenuItemProps = { fieldMetadataItemToSelect: FieldMetadataItem; @@ -48,12 +49,11 @@ export const ObjectFilterDropdownFilterSelectMenuItem = ({ objectFilterDropdownFilterIsSelectedComponentState, ); - const { isSelectedItemIdSelector, resetSelectedItem } = useSelectableList( - OBJECT_FILTER_DROPDOWN_ID, - ); + const { resetSelectedItem } = useSelectableList(OBJECT_FILTER_DROPDOWN_ID); - const isSelectedItem = useRecoilValue( - isSelectedItemIdSelector(fieldMetadataItemToSelect.id), + const isSelectedItem = useRecoilComponentFamilyValueV2( + isSelectedItemIdComponentFamilySelector, + fieldMetadataItemToSelect.id, ); const setSelectedOperandInDropdown = useSetRecoilComponentStateV2( diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItemV2.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItemV2.tsx index 97bbba6cf..267725671 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItemV2.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterSelectMenuItemV2.tsx @@ -3,9 +3,10 @@ import { OBJECT_FILTER_DROPDOWN_ID } from '@/object-record/object-filter-dropdow import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { isCompositeField } from '@/object-record/object-filter-dropdown/utils/isCompositeField'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; -import { useRecoilValue } from 'recoil'; -import { MenuItemSelect } from 'twenty-ui/navigation'; +import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector'; +import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; import { useIcons } from 'twenty-ui/display'; +import { MenuItemSelect } from 'twenty-ui/navigation'; export type ObjectFilterDropdownFilterSelectMenuItemV2Props = { fieldMetadataItemToSelect: FieldMetadataItem; @@ -16,12 +17,11 @@ export const ObjectFilterDropdownFilterSelectMenuItemV2 = ({ fieldMetadataItemToSelect, onClick, }: ObjectFilterDropdownFilterSelectMenuItemV2Props) => { - const { isSelectedItemIdSelector, resetSelectedItem } = useSelectableList( - OBJECT_FILTER_DROPDOWN_ID, - ); + const { resetSelectedItem } = useSelectableList(OBJECT_FILTER_DROPDOWN_ID); - const isSelectedItem = useRecoilValue( - isSelectedItemIdSelector(fieldMetadataItemToSelect.id), + const isSelectedItem = useRecoilComponentFamilyValueV2( + isSelectedItemIdComponentFamilySelector, + fieldMetadataItemToSelect.id, ); const { getIcon } = useIcons(); diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx index 53bf03bdc..5cfdfc526 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownOptionSelect.tsx @@ -1,5 +1,4 @@ import { useEffect, useState } from 'react'; -import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { v4 } from 'uuid'; @@ -8,7 +7,7 @@ import { useOptionsForSelect } from '@/object-record/object-filter-dropdown/hook import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; -import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; + import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; @@ -20,6 +19,7 @@ import { selectedFilterComponentState } from '@/object-record/object-filter-drop import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { useApplyRecordFilter } from '@/object-record/record-filter/hooks/useApplyRecordFilter'; import { SingleRecordPickerHotkeyScope } from '@/object-record/record-picker/single-record-picker/types/SingleRecordPickerHotkeyScope'; +import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; @@ -62,13 +62,12 @@ export const ObjectFilterDropdownOptionSelect = () => { const { closeDropdown } = useDropdown(); - const { selectedItemIdState } = useSelectableListStates({ - selectableListScopeId: componentInstanceId, - }); - const { resetSelectedItem } = useSelectableList(componentInstanceId); - const selectedItemId = useRecoilValue(selectedItemIdState); + const selectedItemId = useRecoilComponentValueV2( + selectedItemIdComponentState, + componentInstanceId, + ); const fieldMetaDataId = fieldMetadataItemUsedInDropdown?.id ?? ''; @@ -164,7 +163,7 @@ export const ObjectFilterDropdownOptionSelect = () => { return ( { diff --git a/packages/twenty-front/src/modules/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerMenuItemContent.tsx b/packages/twenty-front/src/modules/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerMenuItemContent.tsx index 359d945ad..b20094847 100644 --- a/packages/twenty-front/src/modules/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerMenuItemContent.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerMenuItemContent.tsx @@ -1,5 +1,4 @@ import styled from '@emotion/styled'; -import { useRecoilValue } from 'recoil'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { getAvatarType } from '@/object-metadata/utils/getAvatarType'; @@ -8,12 +7,12 @@ import { multipleRecordPickerIsSelectedComponentFamilySelector } from '@/object- import { getMultipleRecordPickerSelectableListId } from '@/object-record/record-picker/multiple-record-picker/utils/getMultipleRecordPickerSelectableListId'; import { RecordPickerPickableMorphItem } from '@/object-record/record-picker/types/RecordPickerPickableMorphItem'; import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem'; -import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector'; import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; -import { SearchRecord } from '~/generated-metadata/graphql'; import { Avatar } from 'twenty-ui/display'; import { MenuItemMultiSelectAvatar } from 'twenty-ui/navigation'; +import { SearchRecord } from '~/generated-metadata/graphql'; export const StyledSelectableItem = styled(SelectableItem)` height: 100%; @@ -38,14 +37,12 @@ export const MultipleRecordPickerMenuItemContent = ({ const selectableListComponentInstanceId = getMultipleRecordPickerSelectableListId(componentInstanceId); - const { isSelectedItemIdSelector } = useSelectableList( + const isSelectedByKeyboard = useRecoilComponentFamilyValueV2( + isSelectedItemIdComponentFamilySelector, + searchRecord.recordId, selectableListComponentInstanceId, ); - const isSelectedByKeyboard = useRecoilValue( - isSelectedItemIdSelector(searchRecord.recordId), - ); - const isRecordSelectedWithObjectItem = useRecoilComponentFamilyValueV2( multipleRecordPickerIsSelectedComponentFamilySelector, searchRecord.recordId, diff --git a/packages/twenty-front/src/modules/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerMenuItems.tsx b/packages/twenty-front/src/modules/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerMenuItems.tsx index a391fafdb..60f4a256e 100644 --- a/packages/twenty-front/src/modules/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerMenuItems.tsx +++ b/packages/twenty-front/src/modules/object-record/record-picker/multiple-record-picker/components/MultipleRecordPickerMenuItems.tsx @@ -114,7 +114,7 @@ export const MultipleRecordPickerMenuItems = ({ return ( { @@ -51,7 +49,7 @@ export const SingleRecordPicker = ({ - + { diff --git a/packages/twenty-front/src/modules/object-record/select/components/MultipleSelectDropdown.tsx b/packages/twenty-front/src/modules/object-record/select/components/MultipleSelectDropdown.tsx index a711a1181..dcedda2d9 100644 --- a/packages/twenty-front/src/modules/object-record/select/components/MultipleSelectDropdown.tsx +++ b/packages/twenty-front/src/modules/object-record/select/components/MultipleSelectDropdown.tsx @@ -1,5 +1,4 @@ import { useEffect, useState } from 'react'; -import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { StyledMultipleSelectDropdownAvatarChip } from '@/object-record/select/components/StyledMultipleSelectDropdownAvatarChip'; @@ -8,9 +7,10 @@ import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; -import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { MenuItem, MenuItemMultiSelectAvatar } from 'twenty-ui/navigation'; export const MultipleSelectDropdown = ({ @@ -35,13 +35,13 @@ export const MultipleSelectDropdown = ({ loadingItems: boolean; }) => { const { closeDropdown } = useDropdown(); - const { selectedItemIdState } = useSelectableListStates({ - selectableListScopeId: selectableListId, - }); const { resetSelectedItem } = useSelectableList(selectableListId); - const selectedItemId = useRecoilValue(selectedItemIdState); + const selectedItemId = useRecoilComponentValueV2( + selectedItemIdComponentState, + selectableListId, + ); const handleItemSelectChange = ( itemToSelect: SelectableItem, @@ -90,7 +90,7 @@ export const MultipleSelectDropdown = ({ return ( { diff --git a/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx index 68ad23567..94b107793 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/MultiSelectInput.tsx @@ -1,5 +1,4 @@ import { useRef, useState } from 'react'; -import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; import { FieldMultiSelectValue } from '@/object-record/record-field/types/FieldMetadata'; @@ -8,14 +7,16 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList'; -import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; + import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { isDefined } from 'twenty-shared/utils'; -import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; -import { MenuItemMultiSelectTag } from 'twenty-ui/navigation'; import { SelectOption } from 'twenty-ui/input'; +import { MenuItemMultiSelectTag } from 'twenty-ui/navigation'; +import { turnIntoEmptyStringIfWhitespacesOnly } from '~/utils/string/turnIntoEmptyStringIfWhitespacesOnly'; type MultiSelectInputProps = { selectableListComponentInstanceId: string; @@ -34,14 +35,14 @@ export const MultiSelectInput = ({ onCancel, onOptionSelected, }: MultiSelectInputProps) => { - const { selectedItemIdState } = useSelectableListStates({ - selectableListScopeId: selectableListComponentInstanceId, - }); const { resetSelectedItem } = useSelectableList( selectableListComponentInstanceId, ); - const selectedItemId = useRecoilValue(selectedItemIdState); + const selectedItemId = useRecoilComponentValueV2( + selectedItemIdComponentState, + selectableListComponentInstanceId, + ); const [searchFilter, setSearchFilter] = useState(''); const containerRef = useRef(null); @@ -97,7 +98,7 @@ export const MultiSelectInput = ({ return ( { diff --git a/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx b/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx index 0c96c05a9..1ffc12a56 100644 --- a/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx +++ b/packages/twenty-front/src/modules/ui/field/input/components/SelectInput.tsx @@ -31,7 +31,7 @@ export const SelectInput = ({ }: SelectInputProps) => { return ( { - const { isSelectedItemIdSelector } = useSelectableList(); - - const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector(iconKey)); + const isSelectedItemId = useRecoilComponentValueV2( + selectedItemIdComponentState, + iconKey, + ); return ( @@ -175,7 +176,7 @@ export const IconPicker = ({ dropdownWidth={176} dropdownComponents={ { diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableItem.tsx b/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableItem.tsx index de7114062..1e7c89d94 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableItem.tsx +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableItem.tsx @@ -1,7 +1,7 @@ import { ReactNode, useEffect, useRef } from 'react'; -import { useRecoilValue } from 'recoil'; -import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector'; +import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2'; import styled from '@emotion/styled'; const StyledContainer = styled.div` @@ -20,9 +20,10 @@ export const SelectableItem = ({ children, className, }: SelectableItemProps) => { - const { isSelectedItemIdSelector } = useSelectableList(); - - const isSelectedItemId = useRecoilValue(isSelectedItemIdSelector(itemId)); + const isSelectedItemId = useRecoilComponentFamilyValueV2( + isSelectedItemIdComponentFamilySelector, + itemId, + ); const scrollRef = useRef(null); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableList.tsx b/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableList.tsx index dd1ea9363..6361efca1 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableList.tsx +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/components/SelectableList.tsx @@ -1,34 +1,43 @@ import { ReactNode, useEffect } from 'react'; import { useSelectableListHotKeys } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys'; -import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; -import { SelectableListScope } from '@/ui/layout/selectable-list/scopes/SelectableListScope'; -import { arrayToChunks } from '~/utils/array/arrayToChunks'; +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { selectableItemIdsComponentState } from '@/ui/layout/selectable-list/states/selectableItemIdsComponentState'; +import { selectableListOnEnterComponentState } from '@/ui/layout/selectable-list/states/selectableListOnEnterComponentState'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; import { isDefined } from 'twenty-shared/utils'; +import { arrayToChunks } from '~/utils/array/arrayToChunks'; type SelectableListProps = { children: ReactNode; - selectableListId: string; selectableItemIdArray?: string[]; selectableItemIdMatrix?: string[][]; onSelect?: (selected: string) => void; hotkeyScope: string; onEnter?: (itemId: string) => void; + selectableListInstanceId: string; }; export const SelectableList = ({ children, - selectableListId, hotkeyScope, selectableItemIdArray, selectableItemIdMatrix, + selectableListInstanceId, onEnter, onSelect, }: SelectableListProps) => { - useSelectableListHotKeys(selectableListId, hotkeyScope, onSelect); + useSelectableListHotKeys(selectableListInstanceId, hotkeyScope, onSelect); - const { setSelectableItemIds, setSelectableListOnEnter, setSelectedItemId } = - useSelectableList(selectableListId); + const setSelectableListOnEnter = useSetRecoilComponentStateV2( + selectableListOnEnterComponentState, + selectableListInstanceId, + ); + + const setSelectableItemIds = useSetRecoilComponentStateV2( + selectableItemIdsComponentState, + selectableListInstanceId, + ); useEffect(() => { setSelectableListOnEnter(() => onEnter); @@ -48,16 +57,15 @@ export const SelectableList = ({ if (isDefined(selectableItemIdArray)) { setSelectableItemIds(arrayToChunks(selectableItemIdArray, 1)); } - }, [ - selectableItemIdArray, - selectableItemIdMatrix, - setSelectableItemIds, - setSelectedItemId, - ]); + }, [selectableItemIdArray, selectableItemIdMatrix, setSelectableItemIds]); return ( - + {children} - + ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/__tests__/useSelectableList.test.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/__tests__/useSelectableList.test.ts index 930ea10ad..764735e93 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/__tests__/useSelectableList.test.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/__tests__/useSelectableList.test.ts @@ -1,9 +1,12 @@ -import { act } from 'react-dom/test-utils'; import { renderHook } from '@testing-library/react'; -import { RecoilRoot, useRecoilState, useRecoilValue } from 'recoil'; +import { act } from 'react-dom/test-utils'; +import { RecoilRoot } from 'recoil'; -import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { selectableItemIdsComponentState } from '@/ui/layout/selectable-list/states/selectableItemIdsComponentState'; +import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; const selectableListScopeId = 'testId'; const testArr = [['1'], ['2'], ['3']]; @@ -13,15 +16,15 @@ describe('useSelectableList', () => { it('Should setSelectableItemIds', async () => { const { result } = renderHook( () => { - const { setSelectableItemIds } = useSelectableList( + const setSelectableItemIds = useSetRecoilComponentStateV2( + selectableItemIdsComponentState, selectableListScopeId, ); - const { selectableItemIdsState } = useSelectableListStates({ + const selectableItemIds = useRecoilComponentValueV2( + selectableItemIdsComponentState, selectableListScopeId, - }); - - const selectableItemIds = useRecoilValue(selectableItemIdsState); + ); return { setSelectableItemIds, @@ -47,13 +50,14 @@ describe('useSelectableList', () => { () => { const { resetSelectedItem } = useSelectableList(selectableListScopeId); - const { selectedItemIdState } = useSelectableListStates({ + const selectedItemId = useRecoilComponentValueV2( + selectedItemIdComponentState, selectableListScopeId, - }); - - const [selectedItemId, setSelectedItemId] = - useRecoilState(selectedItemIdState); - + ); + const setSelectedItemId = useSetRecoilComponentStateV2( + selectedItemIdComponentState, + selectableListScopeId, + ); return { resetSelectedItem, selectedItemId, diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys.ts index e034f47d1..66df15c7f 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListHotKeys.ts @@ -2,14 +2,17 @@ import { isNonEmptyString } from '@sniptt/guards'; import { useRecoilCallback } from 'recoil'; import { Key } from 'ts-key-enum'; -import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; +import { selectableItemIdsComponentState } from '@/ui/layout/selectable-list/states/selectableItemIdsComponentState'; +import { selectableListOnEnterComponentState } from '@/ui/layout/selectable-list/states/selectableListOnEnterComponentState'; +import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; +import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; type Direction = 'up' | 'down' | 'left' | 'right'; export const useSelectableListHotKeys = ( - scopeId: string, + instanceId: string, hotkeyScope: string, onSelect?: (itemId: string) => void, ) => { @@ -29,22 +32,20 @@ export const useSelectableListHotKeys = ( } }; - const { - selectedItemIdState, - selectableItemIdsState, - isSelectedItemIdSelector, - selectableListOnEnterState, - } = useSelectableListStates({ - selectableListScopeId: scopeId, - }); - const handleSelect = useRecoilCallback( ({ snapshot, set }) => (direction: Direction) => { - const selectedItemId = getSnapshotValue(snapshot, selectedItemIdState); + const selectedItemId = getSnapshotValue( + snapshot, + selectedItemIdComponentState.atomFamily({ + instanceId: instanceId, + }), + ); const selectableItemIds = getSnapshotValue( snapshot, - selectableItemIdsState, + selectableItemIdsComponentState.atomFamily({ + instanceId: instanceId, + }), ); const currentPosition = findPosition(selectableItemIds, selectedItemId); @@ -104,22 +105,34 @@ export const useSelectableListHotKeys = ( if (selectedItemId !== nextId) { if (isNonEmptyString(nextId)) { - set(isSelectedItemIdSelector(nextId), true); - set(selectedItemIdState, nextId); + set( + isSelectedItemIdComponentFamilySelector.selectorFamily({ + instanceId: instanceId, + familyKey: nextId, + }), + true, + ); + set( + selectedItemIdComponentState.atomFamily({ + instanceId: instanceId, + }), + nextId, + ); onSelect?.(nextId); } if (isNonEmptyString(selectedItemId)) { - set(isSelectedItemIdSelector(selectedItemId), false); + set( + isSelectedItemIdComponentFamilySelector.selectorFamily({ + instanceId: instanceId, + familyKey: selectedItemId, + }), + false, + ); } } }, - [ - isSelectedItemIdSelector, - onSelect, - selectableItemIdsState, - selectedItemIdState, - ], + [instanceId, onSelect], ); useScopedHotkeys(Key.ArrowUp, () => handleSelect('up'), hotkeyScope, []); @@ -142,18 +155,22 @@ export const useSelectableListHotKeys = ( () => { const selectedItemId = getSnapshotValue( snapshot, - selectedItemIdState, + selectedItemIdComponentState.atomFamily({ + instanceId: instanceId, + }), ); const onEnter = getSnapshotValue( snapshot, - selectableListOnEnterState, + selectableListOnEnterComponentState.atomFamily({ + instanceId: instanceId, + }), ); if (isNonEmptyString(selectedItemId)) { onEnter?.(selectedItemId); } }, - [selectableListOnEnterState, selectedItemIdState], + [instanceId], ), hotkeyScope, [], diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListStates.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListStates.ts deleted file mode 100644 index 004132921..000000000 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/internal/useSelectableListStates.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { SelectableListScopeInternalContext } from '@/ui/layout/selectable-list/scopes/scope-internal-context/SelectableListScopeInternalContext'; -import { selectableItemIdsComponentState } from '@/ui/layout/selectable-list/states/selectableItemIdsComponentState'; -import { selectableListOnEnterComponentState } from '@/ui/layout/selectable-list/states/selectableListOnEnterComponentState'; -import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; -import { isSelectedItemIdFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdFamilySelector'; -import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; -import { extractComponentFamilyState } from '@/ui/utilities/state/component-state/utils/extractComponentFamilyState'; -import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState'; - -type useSelectableListStatesProps = { - selectableListScopeId?: string; -}; - -export const useSelectableListStates = ({ - selectableListScopeId, -}: useSelectableListStatesProps) => { - const scopeId = useAvailableScopeIdOrThrow( - SelectableListScopeInternalContext, - selectableListScopeId, - ); - - return { - scopeId, - isSelectedItemIdSelector: extractComponentFamilyState( - isSelectedItemIdFamilySelector, - scopeId, - ), - selectableItemIdsState: extractComponentState( - selectableItemIdsComponentState, - scopeId, - ), - selectableListOnEnterState: extractComponentState( - selectableListOnEnterComponentState, - scopeId, - ), - selectedItemIdState: extractComponentState( - selectedItemIdComponentState, - scopeId, - ), - }; -}; diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useListenToEnterHotkeyOnListItem.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useListenToEnterHotkeyOnListItem.ts index 7bafc6d77..b62f1417f 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useListenToEnterHotkeyOnListItem.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useListenToEnterHotkeyOnListItem.ts @@ -1,4 +1,4 @@ -import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList'; +import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; import { isNonEmptyString } from '@sniptt/guards'; @@ -7,15 +7,15 @@ import { Key } from 'ts-key-enum'; export const useListenToEnterHotkeyOnListItem = ({ hotkeyScope, + itemId, onEnter, }: { hotkeyScope: string; + itemId: string; onEnter: () => void; }) => { - const { selectedItemIdState } = useSelectableList(); - useScopedHotkeys( Key.Enter, useRecoilCallback( @@ -23,17 +23,19 @@ export const useListenToEnterHotkeyOnListItem = ({ () => { const selectedItemId = getSnapshotValue( snapshot, - selectedItemIdState, + selectedItemIdComponentState.atomFamily({ + instanceId: itemId, + }), ); if (isNonEmptyString(selectedItemId) && selectedItemId === itemId) { onEnter?.(); } }, - [itemId, onEnter, selectedItemIdState], + [itemId, onEnter], ), hotkeyScope, - [selectedItemIdState, itemId, onEnter], + [itemId, onEnter], { preventDefault: false, }, diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts index a8b310c6e..7fc543aec 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/hooks/useSelectableList.ts @@ -1,60 +1,85 @@ -import { useRecoilCallback, useSetRecoilState } from 'recoil'; +import { useRecoilCallback } from 'recoil'; -import { useSelectableListStates } from '@/ui/layout/selectable-list/hooks/internal/useSelectableListStates'; +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState'; +import { isSelectedItemIdComponentFamilySelector } from '@/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector'; import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue'; +import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; import { isDefined } from 'twenty-shared/utils'; -export const useSelectableList = (selectableListId?: string) => { - const { - scopeId, - selectableItemIdsState, - selectableListOnEnterState, - isSelectedItemIdSelector, - selectedItemIdState, - } = useSelectableListStates({ - selectableListScopeId: selectableListId, - }); - - const setSelectableItemIds = useSetRecoilState(selectableItemIdsState); - const setSelectableListOnEnter = useSetRecoilState( - selectableListOnEnterState, +export const useSelectableList = (instanceId?: string) => { + const selectableListInstanceId = useAvailableComponentInstanceIdOrThrow( + SelectableListComponentInstanceContext, + instanceId, ); - const resetSelectedItem = useRecoilCallback( ({ snapshot, set }) => () => { - const selectedItemId = getSnapshotValue(snapshot, selectedItemIdState); + const selectedItemId = getSnapshotValue( + snapshot, + selectedItemIdComponentState.atomFamily({ + instanceId: selectableListInstanceId, + }), + ); if (isDefined(selectedItemId)) { - set(selectedItemIdState, null); - set(isSelectedItemIdSelector(selectedItemId), false); + set( + selectedItemIdComponentState.atomFamily({ + instanceId: selectableListInstanceId, + }), + null, + ); + set( + isSelectedItemIdComponentFamilySelector.selectorFamily({ + instanceId: selectableListInstanceId, + familyKey: selectedItemId, + }), + false, + ); } }, - [selectedItemIdState, isSelectedItemIdSelector], + [selectableListInstanceId], ); const setSelectedItemId = useRecoilCallback( ({ set, snapshot }) => (itemId: string) => { - const selectedItemId = getSnapshotValue(snapshot, selectedItemIdState); + const selectedItemId = getSnapshotValue( + snapshot, + selectedItemIdComponentState.atomFamily({ + instanceId: selectableListInstanceId, + }), + ); if (isDefined(selectedItemId)) { - set(isSelectedItemIdSelector(selectedItemId), false); + set( + isSelectedItemIdComponentFamilySelector.selectorFamily({ + instanceId: selectableListInstanceId, + familyKey: selectedItemId, + }), + false, + ); } - set(selectedItemIdState, itemId); - set(isSelectedItemIdSelector(itemId), true); + set( + selectedItemIdComponentState.atomFamily({ + instanceId: selectableListInstanceId, + }), + itemId, + ); + set( + isSelectedItemIdComponentFamilySelector.selectorFamily({ + instanceId: selectableListInstanceId, + familyKey: itemId, + }), + true, + ); }, - [selectedItemIdState, isSelectedItemIdSelector], + [selectableListInstanceId], ); return { - selectableListId: scopeId, - setSelectableItemIds, - isSelectedItemIdSelector, - setSelectableListOnEnter, resetSelectedItem, setSelectedItemId, - selectedItemIdState, }; }; diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/SelectableListScope.tsx b/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/SelectableListScope.tsx deleted file mode 100644 index 59af4bde4..000000000 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/SelectableListScope.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { ReactNode } from 'react'; - -import { SelectableListScopeInternalContext } from './scope-internal-context/SelectableListScopeInternalContext'; - -type SelectableListScopeProps = { - children: ReactNode; - selectableListScopeId: string; -}; - -export const SelectableListScope = ({ - children, - selectableListScopeId, -}: SelectableListScopeProps) => { - return ( - - {children} - - ); -}; diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/scope-internal-context/SelectableListScopeInternalContext.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/scope-internal-context/SelectableListScopeInternalContext.ts deleted file mode 100644 index b28f36103..000000000 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/scopes/scope-internal-context/SelectableListScopeInternalContext.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext'; -import { RecoilComponentStateKey } from '@/ui/utilities/state/component-state/types/RecoilComponentStateKey'; - -type SelectableListScopeInternalContextProps = RecoilComponentStateKey; - -export const SelectableListScopeInternalContext = - createScopeInternalContext(); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext.ts new file mode 100644 index 000000000..f12a01180 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext.ts @@ -0,0 +1,4 @@ +import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext'; + +export const SelectableListComponentInstanceContext = + createComponentInstanceContext(); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState.ts index 8dcbeb829..a063722a7 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState.ts @@ -1,9 +1,9 @@ -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2'; -export const isSelectedItemIdComponentFamilyState = createComponentFamilyState< - boolean, - string ->({ - key: 'isSelectedItemIdComponentFamilyState', - defaultValue: false, -}); +export const isSelectedItemIdComponentFamilyState = + createComponentFamilyStateV2({ + key: 'isSelectedItemIdComponentFamilyState', + defaultValue: false, + componentInstanceContext: SelectableListComponentInstanceContext, + }); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableItemIdsComponentState.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableItemIdsComponentState.ts index 05a239e56..07a11f38f 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableItemIdsComponentState.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableItemIdsComponentState.ts @@ -1,8 +1,10 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; -export const selectableItemIdsComponentState = createComponentState( - { - key: 'selectableItemIdsComponentState', - defaultValue: [[]], - }, -); +export const selectableItemIdsComponentState = createComponentStateV2< + string[][] +>({ + key: 'selectableItemIdsComponentState', + defaultValue: [[]], + componentInstanceContext: SelectableListComponentInstanceContext, +}); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableListOnEnterComponentState.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableListOnEnterComponentState.ts index f0cbc21ea..356553596 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableListOnEnterComponentState.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableListOnEnterComponentState.ts @@ -1,8 +1,10 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; -export const selectableListOnEnterComponentState = createComponentState< +export const selectableListOnEnterComponentState = createComponentStateV2< ((itemId: string) => void) | undefined >({ key: 'selectableListOnEnterComponentState', defaultValue: undefined, + componentInstanceContext: SelectableListComponentInstanceContext, }); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectedItemIdComponentState.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectedItemIdComponentState.ts index 8587373a1..d0632df95 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectedItemIdComponentState.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectedItemIdComponentState.ts @@ -1,8 +1,10 @@ -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; -export const selectedItemIdComponentState = createComponentState( - { - key: 'selectedItemIdComponentState', - defaultValue: null, - }, -); +export const selectedItemIdComponentState = createComponentStateV2< + string | null +>({ + key: 'selectedItemIdComponentState', + defaultValue: null, + componentInstanceContext: SelectableListComponentInstanceContext, +}); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector.ts new file mode 100644 index 000000000..ece39bb40 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectors/isSelectedItemIdComponentFamilySelector.ts @@ -0,0 +1,28 @@ +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { isSelectedItemIdComponentFamilyState } from '@/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState'; +import { createComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2'; + +export const isSelectedItemIdComponentFamilySelector = + createComponentFamilySelectorV2({ + key: 'isSelectedItemIdComponentFamilySelector', + componentInstanceContext: SelectableListComponentInstanceContext, + get: + ({ instanceId, familyKey }: { instanceId: string; familyKey: string }) => + ({ get }) => + get( + isSelectedItemIdComponentFamilyState.atomFamily({ + instanceId: instanceId, + familyKey: familyKey, + }), + ), + set: + ({ instanceId, familyKey }: { instanceId: string; familyKey: string }) => + ({ set }, newValue) => + set( + isSelectedItemIdComponentFamilyState.atomFamily({ + instanceId: instanceId, + familyKey: familyKey, + }), + newValue, + ), + }); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectors/isSelectedItemIdFamilySelector.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectors/isSelectedItemIdFamilySelector.ts deleted file mode 100644 index a93df20ce..000000000 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectors/isSelectedItemIdFamilySelector.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { isSelectedItemIdComponentFamilyState } from '@/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState'; -import { createComponentFamilySelector } from '@/ui/utilities/state/component-state/utils/createComponentFamilySelector'; - -export const isSelectedItemIdFamilySelector = createComponentFamilySelector< - boolean, - string ->({ - key: 'isSelectedItemIdFamilySelector', - get: - ({ scopeId, familyKey }: { scopeId: string; familyKey: string }) => - ({ get }) => - get( - isSelectedItemIdComponentFamilyState({ - scopeId: scopeId, - familyKey: familyKey, - }), - ), - set: - ({ scopeId, familyKey }: { scopeId: string; familyKey: string }) => - ({ set }, newValue) => - set( - isSelectedItemIdComponentFamilyState({ - scopeId: scopeId, - familyKey: familyKey, - }), - newValue, - ), -}); diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2.ts index 1286621e1..0e7c6a2a7 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2.ts @@ -1,4 +1,5 @@ import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; +import { ComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilySelectorV2'; import { ComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateV2'; import { globalComponentInstanceContextMap } from '@/ui/utilities/state/component-state/utils/globalComponentInstanceContextMap'; import { SerializableParam, useRecoilState } from 'recoil'; @@ -7,7 +8,9 @@ export const useRecoilComponentFamilyStateV2 = < StateType, FamilyKey extends SerializableParam, >( - componentState: ComponentFamilyStateV2, + componentState: + | ComponentFamilyStateV2 + | ComponentFamilySelectorV2, familyKey: FamilyKey, instanceIdFromProps?: string, ) => { @@ -26,5 +29,10 @@ export const useRecoilComponentFamilyStateV2 = < instanceIdFromProps, ); - return useRecoilState(componentState.atomFamily({ instanceId, familyKey })); + const familySelector = + componentState.type === 'ComponentFamilyState' + ? componentState.atomFamily({ instanceId, familyKey }) + : componentState.selectorFamily({ instanceId, familyKey }); + + return useRecoilState(familySelector); }; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2.ts index 49f034bd8..e2b482dc2 100644 --- a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2.ts +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2.ts @@ -16,6 +16,7 @@ export function createComponentFamilySelectorV2< >(options: { key: string; get: SelectorGetter>; + set?: never; componentInstanceContext: ComponentInstanceStateContext | null; }): ComponentFamilyReadOnlySelectorV2;