From e53e09dfd384dd5f4aa141b87078e957f0c72d6a Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Fri, 11 Jul 2025 16:47:52 +0200 Subject: [PATCH] Improved dropdown menu headers for filter and sorts (#13177) This PR improves dropdown menu headers for filter and sort dropdown in view bar and editable filter chips. It adds what's necessary to navigate back or close the dropdown, so that we don't rely solely on click outside to exit the dropdown. This PR also refactors the components so that we clearly identify the two code paths that can use filter dropdowns : view bar and filter chip, everything that can be DRY stays in the object-filter-dropdown module but we try to have our wrapping components in each distinct module instead of blending everything with ternaries inside object-filter-dropdown module. The vector search input value wasn't correctly handled across the different dropdowns, due to a wrong component instance management, since the dropdown menu header improvement put this into light, I also refactored the state management of the vector search input. @Bonapara please check the QA video and tell me if it's ok, I didn't add dropdown menu header on the advanced filter field list dropdown because it's a select more than a standalone dropdown, what do you think ? QA : https://github.com/user-attachments/assets/17080f32-f302-436c-937b-3577715b7e84 QA Vector search fix : https://github.com/user-attachments/assets/6367bbf6-8a98-4b53-86cf-6ba92be130eb Fixes https://github.com/twentyhq/core-team-issues/issues/640 Fixes https://github.com/twentyhq/core-team-issues/issues/1206 --- .../ObjectFilterDropdownContentWrapper.tsx | 38 +++++ .../ObjectFilterDropdownFilterInput.tsx | 28 ++-- .../ObjectFilterDropdownFilterInputHeader.tsx | 52 ++++++- ...lterDropdownInnerSelectOperandDropdown.tsx | 19 ++- .../ObjectFilterDropdownVectorSearchInput.tsx | 38 +++++ .../components/ObjectSortDropdownButton.tsx | 134 ++++++------------ .../components/DropdownMenuInnerSelect.tsx | 4 +- .../EditableFilterChipDropdownContent.tsx | 21 +++ .../EditableFilterChipDropdownMenuHeader.tsx | 45 ++++++ .../EditableFilterDropdownButton.tsx | 11 +- .../components/ViewBarFilterDropdown.tsx | 4 + .../ViewBarFilterDropdownContent.tsx | 21 ++- .../ViewBarFilterDropdownFieldSelectMenu.tsx | 16 +++ .../ViewBarFilterDropdownFilterInput.tsx | 22 +++ ...BarFilterDropdownFilterInputMenuHeader.tsx | 49 +++++++ ...iewBarFilterDropdownVectorSearchButton.tsx | 21 ++- ...ViewBarFilterDropdownVectorSearchInput.tsx | 44 +----- .../views/hooks/useClearVectorSearchInput.ts | 16 +++ .../useSetEditableFilterChipDropdownStates.ts | 26 ++-- ...ectorSearchInputValueFromExistingFilter.ts | 6 +- .../states/vectorSearchInputComponentState.ts | 4 +- 21 files changed, 422 insertions(+), 197 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownContentWrapper.tsx create mode 100644 packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput.tsx create mode 100644 packages/twenty-front/src/modules/views/components/EditableFilterChipDropdownContent.tsx create mode 100644 packages/twenty-front/src/modules/views/components/EditableFilterChipDropdownMenuHeader.tsx create mode 100644 packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFilterInput.tsx create mode 100644 packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFilterInputMenuHeader.tsx create mode 100644 packages/twenty-front/src/modules/views/hooks/useClearVectorSearchInput.ts diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownContentWrapper.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownContentWrapper.tsx new file mode 100644 index 00000000000..74d77a3a3f2 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownContentWrapper.tsx @@ -0,0 +1,38 @@ +import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { DATE_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/DateFilterTypes'; +import { DATE_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/object-record/object-filter-dropdown/constants/DatePickerDropdownContentWidth'; +import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; +import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; +import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { isDefined } from 'twenty-shared/utils'; + +export const ObjectFilterDropdownContentWrapper = ({ + children, +}: React.PropsWithChildren) => { + const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( + fieldMetadataItemUsedInDropdownComponentSelector, + ); + + if (!isDefined(fieldMetadataItemUsedInDropdown)) { + return null; + } + + const filterType = getFilterTypeFromFieldType( + fieldMetadataItemUsedInDropdown.type, + ); + + const isDateFilter = DATE_FILTER_TYPES.includes(filterType); + + return ( + + {children} + + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx index 39253f82198..4ca9a224457 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput.tsx @@ -5,22 +5,19 @@ import { ObjectFilterDropdownRatingInput } from '@/object-record/object-filter-d import { ObjectFilterDropdownRecordSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownRecordSelect'; import { ObjectFilterDropdownSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownSearchInput'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; -import { ViewBarFilterDropdownVectorSearchInput } from '@/views/components/ViewBarFilterDropdownVectorSearchInput'; + import { ViewFilterOperand } from 'twenty-shared/src/types/ViewFilterOperand'; import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; import { ObjectFilterDropdownBooleanSelect } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownBooleanSelect'; -import { ObjectFilterDropdownFilterInputHeader } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInputHeader'; import { ObjectFilterDropdownInnerSelectOperandDropdown } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownInnerSelectOperandDropdown'; import { ObjectFilterDropdownTextInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownTextInput'; +import { ObjectFilterDropdownVectorSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput'; import { DATE_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/DateFilterTypes'; -import { DATE_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/object-record/object-filter-dropdown/constants/DatePickerDropdownContentWidth'; import { NUMBER_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/NumberFilterTypes'; import { TEXT_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/TextFilterTypes'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; -import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; -import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { isDefined } from 'twenty-shared/utils'; @@ -62,11 +59,7 @@ export const ObjectFilterDropdownFilterInput = ({ selectedOperandInDropdown === ViewFilterOperand.VectorSearch; if (isVectorSearchFilter && isDefined(filterDropdownId)) { - return ( - - ); + return ; } if (!isDefined(fieldMetadataItemUsedInDropdown)) { @@ -82,24 +75,21 @@ export const ObjectFilterDropdownFilterInput = ({ if (isOnlyOperand) { return ( - - + <> - + ); } else if (isDateFilter) { return ( - - + <> - + ); } else { return ( - - + <> {TEXT_FILTER_TYPES.includes(filterType) && ( @@ -130,7 +120,7 @@ export const ObjectFilterDropdownFilterInput = ({ )} {filterType === 'BOOLEAN' && } - + ); } }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInputHeader.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInputHeader.tsx index 0d9aa2edd5f..44e52b08e8b 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInputHeader.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInputHeader.tsx @@ -1,16 +1,56 @@ -import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader'; - import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; +import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; +import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader'; +import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent'; +import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext'; +import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { ViewBarFilterDropdownFilterInputMenuHeader } from '@/views/components/ViewBarFilterDropdownFilterInputMenuHeader'; +import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId'; +import { useLingui } from '@lingui/react/macro'; +import { useContext } from 'react'; +import { ViewFilterOperand } from 'twenty-shared/types'; +import { IconX } from 'twenty-ui/display'; export const ObjectFilterDropdownFilterInputHeader = () => { + const { t } = useLingui(); + const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( fieldMetadataItemUsedInDropdownComponentSelector, ); - return ( - - {fieldMetadataItemUsedInDropdown?.label} - + const selectedOperandInDropdown = useRecoilComponentValueV2( + selectedOperandInDropdownComponentState, ); + + const { closeDropdown } = useCloseDropdown(); + + const dropdownInstanceId = useContext( + DropdownComponentInstanceContext, + )?.instanceId; + + const isInViewBarFilterDropdown = + dropdownInstanceId === VIEW_BAR_FILTER_DROPDOWN_ID; + + const isVectorSearchFilter = + selectedOperandInDropdown === ViewFilterOperand.VectorSearch; + + if (isInViewBarFilterDropdown) { + return ; + } else { + return ( + closeDropdown(dropdownInstanceId)} + Icon={IconX} + /> + } + > + {isVectorSearchFilter + ? t`Search` + : fieldMetadataItemUsedInDropdown?.label} + + ); + } }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownInnerSelectOperandDropdown.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownInnerSelectOperandDropdown.tsx index bb126ae2e36..ae9984749f3 100644 --- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownInnerSelectOperandDropdown.tsx +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownInnerSelectOperandDropdown.tsx @@ -1,4 +1,6 @@ import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { DATE_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/DateFilterTypes'; +import { DATE_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/object-record/object-filter-dropdown/constants/DatePickerDropdownContentWidth'; import { useApplyObjectFilterDropdownOperand } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownOperand'; import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; @@ -7,6 +9,7 @@ import { getOperandLabel } from '@/object-record/object-filter-dropdown/utils/ge import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand'; import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands'; import { DropdownMenuInnerSelect } from '@/ui/layout/dropdown/components/DropdownMenuInnerSelect'; +import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { isDefined } from 'twenty-shared/utils'; import { SelectOption } from 'twenty-ui/input'; @@ -54,16 +57,30 @@ export const ObjectFilterDropdownInnerSelectOperandDropdown = () => { ); }; - if (!isDefined(selectedOperandInDropdown)) { + if ( + !isDefined(selectedOperandInDropdown) || + !isDefined(fieldMetadataItemUsedInDropdown) + ) { return null; } + const filterType = getFilterTypeFromFieldType( + fieldMetadataItemUsedInDropdown.type, + ); + + const isDateFilter = DATE_FILTER_TYPES.includes(filterType); + + const widthInPixels = isDateFilter + ? DATE_PICKER_DROPDOWN_CONTENT_WIDTH + : GenericDropdownContentWidth.ExtraLarge; + return ( ); }; diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput.tsx new file mode 100644 index 00000000000..4f80772da5d --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput.tsx @@ -0,0 +1,38 @@ +import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; +import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions'; +import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState'; +import { useLingui } from '@lingui/react/macro'; +import { useDebouncedCallback } from 'use-debounce'; + +export const ObjectFilterDropdownVectorSearchInput = () => { + const { t } = useLingui(); + + const [vectorSearchInputValue, setVectorSearchInputValue] = + useRecoilComponentStateV2(vectorSearchInputComponentState); + + const { applyVectorSearchFilter } = useVectorSearchFilterActions(); + + const debouncedApplyVectorSearchFilter = useDebouncedCallback( + (value: string) => { + applyVectorSearchFilter(value); + }, + 500, + ); + + const handleSearchChange = (e: React.ChangeEvent) => { + const inputValue = e.target.value; + setVectorSearchInputValue(inputValue); + debouncedApplyVectorSearchFilter(inputValue); + }; + + return ( + + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx index 10f38851458..4f5573d21a5 100644 --- a/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx +++ b/packages/twenty-front/src/modules/object-record/object-sort-dropdown/components/ObjectSortDropdownButton.tsx @@ -1,5 +1,3 @@ -import styled from '@emotion/styled'; - import { availableFieldMetadataItemsForSortFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForSortFamilySelector'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { OBJECT_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ObjectSortDropdownId'; @@ -20,7 +18,10 @@ import { visibleTableColumnsComponentSelector } from '@/object-record/record-tab import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; 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'; +import { DropdownMenuInnerSelect } from '@/ui/layout/dropdown/components/DropdownMenuInnerSelect'; import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer'; +import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { DropdownMenuSectionLabel } from '@/ui/layout/dropdown/components/DropdownMenuSectionLabel'; import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator'; import { StyledHeaderDropdownButton } from '@/ui/layout/dropdown/components/StyledHeaderDropdownButton'; @@ -32,54 +33,12 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states 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 { useTheme } from '@emotion/react'; import { Trans, useLingui } from '@lingui/react/macro'; import { useRecoilValue } from 'recoil'; -import { IconChevronDown, useIcons } from 'twenty-ui/display'; +import { IconX, useIcons } from 'twenty-ui/display'; import { MenuItem } from 'twenty-ui/navigation'; import { v4 } from 'uuid'; -export const StyledInput = styled.input` - background: transparent; - border: none; - border-top: none; - border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; - border-radius: 0; - color: ${({ theme }) => theme.font.color.primary}; - margin: 0; - outline: none; - padding: ${({ theme }) => theme.spacing(2)}; - height: 19px; - font-family: inherit; - font-size: ${({ theme }) => theme.font.size.sm}; - - font-weight: inherit; - max-width: 100%; - overflow: hidden; - text-decoration: none; - - &::placeholder { - color: ${({ theme }) => theme.font.color.light}; - } -`; - -const StyledSelectedSortDirectionContainer = styled.div` - background: ${({ theme }) => theme.background.secondary}; - box-shadow: ${({ theme }) => theme.boxShadow.light}; - border-radius: ${({ theme }) => theme.border.radius.md}; - - position: absolute; - top: 32px; - width: 100%; - z-index: 1000; -`; - -const StyledDropdownMenuHeaderEndComponent = styled.div` - padding: ${({ theme }) => theme.spacing(1)}; - display: flex; - align-items: center; -`; - export const ObjectSortDropdownButton = () => { const { resetRecordSortDropdownSearchInput } = useResetRecordSortDropdownSearchInput(); @@ -88,10 +47,6 @@ export const ObjectSortDropdownButton = () => { objectSortDropdownSearchInputComponentState, ); - const isRecordSortDirectionMenuUnfolded = useRecoilComponentValueV2( - isRecordSortDirectionDropdownMenuUnfoldedComponentState, - ); - const { resetSortDropdown } = useResetSortDropdown(); const { recordIndexId, objectMetadataItem } = useRecordIndexContextOrThrow(); @@ -195,8 +150,6 @@ export const ObjectSortDropdownButton = () => { const { t } = useLingui(); - const theme = useTheme(); - const selectableItemIdArray = [ ...visibleFieldMetadataItems.map((item) => item.id), ...hiddenFieldMetadataItems.map((item) => item.id), @@ -227,51 +180,50 @@ export const ObjectSortDropdownButton = () => { } dropdownComponents={ + closeSortDropdown()} + Icon={IconX} + /> + } + > + {t`Sort`} + + ({ + value: sortDirection, + label: sortDirection === 'asc' ? t`Ascending` : t`Descending`, + }))} + selectedOption={{ + value: selectedRecordSortDirection, + label: + selectedRecordSortDirection === 'asc' + ? t`Ascending` + : t`Descending`, + }} + onChange={(sortDirection) => + handleSortDirectionClick( + sortDirection.value as RecordSortDirection, + ) + } + widthInPixels={GenericDropdownContentWidth.ExtraLarge} + /> + + + setObjectSortDropdownSearchInput(event.target.value) + } + /> - {isRecordSortDirectionMenuUnfolded && ( - - - {RECORD_SORT_DIRECTIONS.map((sortDirection, index) => ( - handleSortDirectionClick(sortDirection)} - text={ - sortDirection === 'asc' ? t`Ascending` : t`Descending` - } - /> - ))} - - - )} - - setIsRecordSortDirectionMenuUnfolded( - !isRecordSortDirectionMenuUnfolded, - ) - } - EndComponent={ - - - - } - > - {selectedRecordSortDirection === 'asc' - ? t`Ascending` - : t`Descending`} - - - setObjectSortDropdownSearchInput(event.target.value) - } - /> {shouldShowVisibleFields && ( <> diff --git a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInnerSelect.tsx b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInnerSelect.tsx index ff708c87dc1..0205c1ab8c6 100644 --- a/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInnerSelect.tsx +++ b/packages/twenty-front/src/modules/ui/layout/dropdown/components/DropdownMenuInnerSelect.tsx @@ -33,6 +33,7 @@ export type DropdownMenuInnerSelectProps = { onChange: (value: SelectOption) => void; options: SelectOption[]; dropdownId: string; + widthInPixels?: number; }; export const DropdownMenuInnerSelect = ({ @@ -40,6 +41,7 @@ export const DropdownMenuInnerSelect = ({ onChange, options, dropdownId, + widthInPixels, }: DropdownMenuInnerSelectProps) => { const theme = useTheme(); @@ -54,7 +56,7 @@ export const DropdownMenuInnerSelect = ({ } dropdownComponents={ - + {options.map((selectOption) => ( { + return ( + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/views/components/EditableFilterChipDropdownMenuHeader.tsx b/packages/twenty-front/src/modules/views/components/EditableFilterChipDropdownMenuHeader.tsx new file mode 100644 index 00000000000..384f9c2c52e --- /dev/null +++ b/packages/twenty-front/src/modules/views/components/EditableFilterChipDropdownMenuHeader.tsx @@ -0,0 +1,45 @@ +import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; +import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; +import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader'; +import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent'; +import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useLingui } from '@lingui/react/macro'; +import { ViewFilterOperand } from 'twenty-shared/types'; +import { IconX } from 'twenty-ui/display'; + +export const EditableFilterChipDropdownMenuHeader = () => { + const { t } = useLingui(); + + const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( + fieldMetadataItemUsedInDropdownComponentSelector, + ); + + const selectedOperandInDropdown = useRecoilComponentValueV2( + selectedOperandInDropdownComponentState, + ); + + const isVectorSearchFilter = + selectedOperandInDropdown === ViewFilterOperand.VectorSearch; + + const { closeDropdown } = useCloseDropdown(); + + const handleBackButtonClick = () => { + closeDropdown(); + }; + + return ( + + } + > + {isVectorSearchFilter + ? t`Search` + : fieldMetadataItemUsedInDropdown?.label} + + ); +}; diff --git a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx index 4f2279091e8..34d820bd97c 100644 --- a/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx +++ b/packages/twenty-front/src/modules/views/components/EditableFilterDropdownButton.tsx @@ -4,10 +4,11 @@ import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { EditableFilterChip } from '@/views/components/EditableFilterChip'; -import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput'; import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRemoveRecordFilter'; import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty'; import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown'; +import { EditableFilterChipDropdownContent } from '@/views/components/EditableFilterChipDropdownContent'; +import { useClearVectorSearchInput } from '@/views/hooks/useClearVectorSearchInput'; import { useSetEditableFilterChipDropdownStates } from '@/views/hooks/useSetEditableFilterChipDropdownStates'; type EditableFilterDropdownButtonProps = { @@ -29,13 +30,17 @@ export const EditableFilterDropdownButton = ({ removeRecordFilter({ recordFilterId: recordFilter.id }); }; + const { clearVectorSearchInput } = useClearVectorSearchInput(); + const onFilterDropdownClose = useCallback(() => { const recordFilterIsEmpty = isRecordFilterConsideredEmpty(recordFilter); if (recordFilterIsEmpty) { removeRecordFilter({ recordFilterId: recordFilter.id }); } - }, [recordFilter, removeRecordFilter]); + + clearVectorSearchInput(); + }, [recordFilter, removeRecordFilter, clearVectorSearchInput]); const { setEditableFilterChipDropdownStates } = useSetEditableFilterChipDropdownStates(); @@ -56,7 +61,7 @@ export const EditableFilterDropdownButton = ({ /> } dropdownComponents={ - + } dropdownOffset={{ y: 8, x: 0 }} dropdownPlacement="bottom-start" diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdown.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdown.tsx index 8f3101729a6..37512bddfe2 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdown.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdown.tsx @@ -8,6 +8,7 @@ import { useRemoveRecordFilter } from '@/object-record/record-filter/hooks/useRe import { isRecordFilterConsideredEmpty } from '@/object-record/record-filter/utils/isRecordFilterConsideredEmpty'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { ViewBarFilterDropdownContent } from '@/views/components/ViewBarFilterDropdownContent'; +import { useClearVectorSearchInput } from '@/views/hooks/useClearVectorSearchInput'; import { isDefined } from 'twenty-shared/utils'; import { ViewBarFilterButton } from './ViewBarFilterButton'; @@ -20,6 +21,8 @@ export const ViewBarFilterDropdown = () => { objectFilterDropdownCurrentRecordFilterComponentState, ); + const { clearVectorSearchInput } = useClearVectorSearchInput(); + const handleDropdownClickOutside = () => { const recordFilterIsEmpty = isDefined(objectFilterDropdownCurrentRecordFilter) && @@ -37,6 +40,7 @@ export const ViewBarFilterDropdown = () => { const handleDropdownClose = () => { resetFilterDropdown(); removeEmptyVectorSearchFilter(); + clearVectorSearchInput(); }; const handleDropdownOpen = () => { diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownContent.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownContent.tsx index 32dbf900323..a2a054d4757 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownContent.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownContent.tsx @@ -1,8 +1,12 @@ -import { ObjectFilterDropdownFilterInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownFilterInput'; import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownFilterIsSelectedComponentState'; +import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { ViewBarFilterDropdownFieldSelectMenu } from '@/views/components/ViewBarFilterDropdownFieldSelectMenu'; +import { ViewBarFilterDropdownFilterInput } from '@/views/components/ViewBarFilterDropdownFilterInput'; +import { ViewBarFilterDropdownVectorSearchInput } from '@/views/components/ViewBarFilterDropdownVectorSearchInput'; import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId'; +import { ViewFilterOperand } from 'twenty-shared/types'; export const ViewBarFilterDropdownContent = () => { const [objectFilterDropdownFilterIsSelected] = useRecoilComponentStateV2( @@ -10,14 +14,23 @@ export const ViewBarFilterDropdownContent = () => { VIEW_BAR_FILTER_DROPDOWN_ID, ); + const selectedOperandInDropdown = useRecoilComponentValueV2( + selectedOperandInDropdownComponentState, + ); + + const isVectorSearchFilter = + selectedOperandInDropdown === ViewFilterOperand.VectorSearch; + + if (isVectorSearchFilter) { + return ; + } + const shouldShowFilterInput = objectFilterDropdownFilterIsSelected; return ( <> {shouldShowFilterInput ? ( - + ) : ( )} diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx index 9c82c9b9512..6a54b03b625 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFieldSelectMenu.tsx @@ -16,10 +16,14 @@ import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/ import { ViewBarFilterDropdownBottomMenu } from '@/views/components/ViewBarFilterDropdownBottomMenu'; import { ViewBarFilterDropdownFieldSelectMenuItem } from '@/views/components/ViewBarFilterDropdownFieldSelectMenuItem'; +import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader'; +import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; +import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown'; import { VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS } from '@/views/constants/ViewBarFilterBottomMenuItemIds'; import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId'; import { useLingui } from '@lingui/react/macro'; +import { IconX } from 'twenty-ui/display'; export const StyledInput = styled.input` background: transparent; @@ -56,6 +60,8 @@ export const ViewBarFilterDropdownFieldSelectMenu = () => { selectableVisibleFieldMetadataItems, } = useFilterDropdownSelectableFieldMetadataItems(); + const { closeDropdown } = useCloseDropdown(); + const selectableFieldMetadataItemIds = [ ...selectableVisibleFieldMetadataItems.map( (fieldMetadataItem) => fieldMetadataItem.id, @@ -83,6 +89,16 @@ export const ViewBarFilterDropdownFieldSelectMenu = () => { return ( + closeDropdown()} + Icon={IconX} + /> + } + > + {t`Filter`} + { + return ( + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFilterInputMenuHeader.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFilterInputMenuHeader.tsx new file mode 100644 index 00000000000..0c4a179be18 --- /dev/null +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownFilterInputMenuHeader.tsx @@ -0,0 +1,49 @@ +import { useResetFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useResetFilterDropdown'; +import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector'; +import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState'; +import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader'; +import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useClearVectorSearchInput } from '@/views/hooks/useClearVectorSearchInput'; +import { useLingui } from '@lingui/react/macro'; +import { ViewFilterOperand } from 'twenty-shared/types'; +import { IconChevronLeft } from 'twenty-ui/display'; + +export const ViewBarFilterDropdownFilterInputMenuHeader = () => { + const { t } = useLingui(); + + const fieldMetadataItemUsedInDropdown = useRecoilComponentValueV2( + fieldMetadataItemUsedInDropdownComponentSelector, + ); + + const selectedOperandInDropdown = useRecoilComponentValueV2( + selectedOperandInDropdownComponentState, + ); + + const isVectorSearchFilter = + selectedOperandInDropdown === ViewFilterOperand.VectorSearch; + + const { clearVectorSearchInput } = useClearVectorSearchInput(); + + const { resetFilterDropdown } = useResetFilterDropdown(); + + const handleBackButtonClick = () => { + resetFilterDropdown(); + clearVectorSearchInput(); + }; + + return ( + + } + > + {isVectorSearchFilter + ? t`Search` + : fieldMetadataItemUsedInDropdown?.label} + + ); +}; diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownVectorSearchButton.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownVectorSearchButton.tsx index a9c4d826efc..fa8dd5336df 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownVectorSearchButton.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownVectorSearchButton.tsx @@ -9,7 +9,6 @@ import { IconSearch } from 'twenty-ui/display'; import { MenuItem } from 'twenty-ui/navigation'; import { VIEW_BAR_FILTER_BOTTOM_MENU_ITEM_IDS } from '@/views/constants/ViewBarFilterBottomMenuItemIds'; -import { VIEW_BAR_FILTER_DROPDOWN_ID } from '@/views/constants/ViewBarFilterDropdownId'; import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState'; import { useOpenVectorSearchFilter } from '@/views/hooks/useOpenVectorSearchFilter'; @@ -26,20 +25,16 @@ export const ViewBarFilterDropdownVectorSearchButton = () => { const { t } = useLingui(); const [, setVectorSearchInputValue] = useRecoilComponentStateV2( vectorSearchInputComponentState, - VIEW_BAR_FILTER_DROPDOWN_ID, ); const { setVectorSearchInputValueFromExistingFilter } = - useSetVectorSearchInputValueFromExistingFilter(VIEW_BAR_FILTER_DROPDOWN_ID); + useSetVectorSearchInputValueFromExistingFilter(); - const fieldSearchInputValue = useRecoilComponentValueV2( + const objectFilterDropdownSearchInput = useRecoilComponentValueV2( objectFilterDropdownSearchInputComponentState, - VIEW_BAR_FILTER_DROPDOWN_ID, ); const { applyVectorSearchFilter } = useVectorSearchFilterActions(); - const { openVectorSearchFilter } = useOpenVectorSearchFilter( - VIEW_BAR_FILTER_DROPDOWN_ID, - ); + const { openVectorSearchFilter } = useOpenVectorSearchFilter(); const isSelected = useRecoilComponentFamilyValueV2( isSelectedItemIdComponentFamilySelector, @@ -49,9 +44,9 @@ export const ViewBarFilterDropdownVectorSearchButton = () => { const handleSearchClick = () => { openVectorSearchFilter(); - if (fieldSearchInputValue.length > 0) { - setVectorSearchInputValue(fieldSearchInputValue); - applyVectorSearchFilter(fieldSearchInputValue); + if (objectFilterDropdownSearchInput.length > 0) { + setVectorSearchInputValue(objectFilterDropdownSearchInput); + applyVectorSearchFilter(objectFilterDropdownSearchInput); } else { setVectorSearchInputValueFromExistingFilter(); } @@ -69,8 +64,8 @@ export const ViewBarFilterDropdownVectorSearchButton = () => { text={ <> {t`Search`} - {fieldSearchInputValue && ( - {t`· ${fieldSearchInputValue}`} + {objectFilterDropdownSearchInput && ( + {t`· ${objectFilterDropdownSearchInput}`} )} } diff --git a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownVectorSearchInput.tsx b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownVectorSearchInput.tsx index 2a80c0a3e04..f41aae84d31 100644 --- a/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownVectorSearchInput.tsx +++ b/packages/twenty-front/src/modules/views/components/ViewBarFilterDropdownVectorSearchInput.tsx @@ -1,47 +1,13 @@ +import { ObjectFilterDropdownVectorSearchInput } from '@/object-record/object-filter-dropdown/components/ObjectFilterDropdownVectorSearchInput'; import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent'; -import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput'; import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth'; -import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2'; -import { useVectorSearchFilterActions } from '@/views/hooks/useVectorSearchFilterActions'; -import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState'; -import { useLingui } from '@lingui/react/macro'; -import { useDebouncedCallback } from 'use-debounce'; - -export const ViewBarFilterDropdownVectorSearchInput = ({ - filterDropdownId, -}: { - filterDropdownId: string; -}) => { - const { t } = useLingui(); - const [vectorSearchInputValue, setVectorSearchInputValue] = - useRecoilComponentStateV2( - vectorSearchInputComponentState, - filterDropdownId, - ); - const { applyVectorSearchFilter } = useVectorSearchFilterActions(); - - const debouncedApplyVectorSearchFilter = useDebouncedCallback( - (value: string) => { - applyVectorSearchFilter(value); - }, - 500, - ); - - const handleSearchChange = (e: React.ChangeEvent) => { - const inputValue = e.target.value; - setVectorSearchInputValue(inputValue); - debouncedApplyVectorSearchFilter(inputValue); - }; +import { ViewBarFilterDropdownFilterInputMenuHeader } from '@/views/components/ViewBarFilterDropdownFilterInputMenuHeader'; +export const ViewBarFilterDropdownVectorSearchInput = () => { return ( - + + ); }; diff --git a/packages/twenty-front/src/modules/views/hooks/useClearVectorSearchInput.ts b/packages/twenty-front/src/modules/views/hooks/useClearVectorSearchInput.ts new file mode 100644 index 00000000000..a1c4a66f412 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useClearVectorSearchInput.ts @@ -0,0 +1,16 @@ +import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInputComponentState'; + +export const useClearVectorSearchInput = () => { + const setVectorSearchInputValue = useSetRecoilComponentStateV2( + vectorSearchInputComponentState, + ); + + const clearVectorSearchInput = () => { + setVectorSearchInputValue(''); + }; + + return { + clearVectorSearchInput, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useSetEditableFilterChipDropdownStates.ts b/packages/twenty-front/src/modules/views/hooks/useSetEditableFilterChipDropdownStates.ts index 6dd452c4ba5..86b5de3bb09 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSetEditableFilterChipDropdownStates.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSetEditableFilterChipDropdownStates.ts @@ -24,15 +24,6 @@ export const useSetEditableFilterChipDropdownStates = () => { ? filterableFieldMetadataItems.concat(vectorSearchField) : filterableFieldMetadataItems; - const fieldMetadataItem = filterableFieldsWithVector.find( - (fieldMetadataItem) => - fieldMetadataItem.id === recordFilter.fieldMetadataId, - ); - - if (!isDefined(fieldMetadataItem)) { - return; - } - if (isVectorSearchFilter(recordFilter)) { set( vectorSearchInputComponentState.atomFamily({ @@ -42,13 +33,20 @@ export const useSetEditableFilterChipDropdownStates = () => { ); } - set( - fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({ - instanceId: recordFilter.id, - }), - fieldMetadataItem.id, + const fieldMetadataItem = filterableFieldsWithVector.find( + (fieldMetadataItem) => + fieldMetadataItem.id === recordFilter.fieldMetadataId, ); + if (isDefined(fieldMetadataItem)) { + set( + fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({ + instanceId: recordFilter.id, + }), + fieldMetadataItem.id, + ); + } + set( selectedOperandInDropdownComponentState.atomFamily({ instanceId: recordFilter.id, diff --git a/packages/twenty-front/src/modules/views/hooks/useSetVectorSearchInputValueFromExistingFilter.ts b/packages/twenty-front/src/modules/views/hooks/useSetVectorSearchInputValueFromExistingFilter.ts index 3b01c04146b..e1c985e483c 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSetVectorSearchInputValueFromExistingFilter.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSetVectorSearchInputValueFromExistingFilter.ts @@ -3,17 +3,15 @@ import { vectorSearchInputComponentState } from '@/views/states/vectorSearchInpu import { isDefined } from 'twenty-shared/utils'; import { useVectorSearchFilterState } from './useVectorSearchFilterState'; -export const useSetVectorSearchInputValueFromExistingFilter = ( - filterDropdownId: string, -) => { +export const useSetVectorSearchInputValueFromExistingFilter = () => { const [, setVectorSearchInputValue] = useRecoilComponentStateV2( vectorSearchInputComponentState, - filterDropdownId, ); const { getExistingVectorSearchFilter } = useVectorSearchFilterState(); const setVectorSearchInputValueFromExistingFilter = () => { const existingVectorSearchFilter = getExistingVectorSearchFilter(); + if (isDefined(existingVectorSearchFilter)) { setVectorSearchInputValue(existingVectorSearchFilter.value); } diff --git a/packages/twenty-front/src/modules/views/states/vectorSearchInputComponentState.ts b/packages/twenty-front/src/modules/views/states/vectorSearchInputComponentState.ts index 29c83f67401..7b9de59bc32 100644 --- a/packages/twenty-front/src/modules/views/states/vectorSearchInputComponentState.ts +++ b/packages/twenty-front/src/modules/views/states/vectorSearchInputComponentState.ts @@ -1,8 +1,8 @@ +import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext'; import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; -import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext'; export const vectorSearchInputComponentState = createComponentStateV2({ key: 'vectorSearchInputComponentState', defaultValue: '', - componentInstanceContext: ViewComponentInstanceContext, + componentInstanceContext: ObjectFilterDropdownComponentInstanceContext, });