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 000000000..74d77a3a3 --- /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 39253f821..4ca9a2244 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 0d9aa2edd..44e52b08e 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 bb126ae2e..ae9984749 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 000000000..4f80772da --- /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 10f388514..4f5573d21 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 ff708c87d..0205c1ab8 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 000000000..384f9c2c5 --- /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 4f2279091..34d820bd9 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 8f3101729..37512bddf 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 32dbf9003..a2a054d47 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 9c82c9b95..6a54b03b6 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 000000000..0c4a179be --- /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 a9c4d826e..fa8dd5336 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 2a80c0a3e..f41aae84d 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 000000000..a1c4a66f4 --- /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 6dd452c4b..86b5de3bb 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 3b01c0414..e1c985e48 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 29c83f674..7b9de59bc 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, });