progress on implementation

This commit is contained in:
jamie
2024-09-22 00:50:58 -07:00
parent 506e6c19d1
commit ca6d5efc43
20 changed files with 435 additions and 168 deletions

View File

@@ -1,48 +1,18 @@
// Import icons
import { Folder } from '@phosphor-icons/react';
import { useLibraryQuery } from '@sd/client';
import { RenderSearchFilter } from '.';
import i18n from '../../../I18n';
import { FilterOptionList } from './components/FilterOptionList';
import { createInOrNotInFilter } from './factories/createInOrNotInFilter';
import { filePathDateCreated } from './registry/DateFilters';
import { kindFilter } from './registry/KindFilter';
import { locationFilter } from './registry/LocationFilter';
import { tagsFilter } from './registry/TagsFilter';
import { extensionFilter, nameFilter } from './registry/TextFilters';
// Range Filters
export const filterRegistry = [
createInOrNotInFilter<number>({
name: i18n.t('location'),
translationKey: 'location',
icon: Folder,
create: (locations) => ({ filePath: { locations } }),
extract: (arg) => {
if ('filePath' in arg && 'locations' in arg.filePath) return arg.filePath.locations;
},
argsToFilterOptions(values, options) {
return values
.map((value) => {
const option = options.get(this.name)?.find((o) => o.value === value);
if (!option) return;
return {
...option,
type: this.name
};
})
.filter(Boolean) as any;
},
useOptions: () => {
const query = useLibraryQuery(['locations.list'], { keepPreviousData: true });
const locations = query.data;
return (locations ?? []).map((location) => ({
name: location.name!,
value: location.id,
icon: 'Folder'
}));
},
Render: ({ filter, options, search }) => (
<FilterOptionList filter={filter} options={options} search={search} />
)
})
] as const satisfies ReadonlyArray<RenderSearchFilter<any>>;
export const filterRegistry: ReadonlyArray<RenderSearchFilter<any>> = [
// Put filters here
locationFilter,
filePathDateCreated,
tagsFilter,
kindFilter,
nameFilter,
extensionFilter
] as const;
export type FilterType = (typeof filterRegistry)[number]['name'];

View File

@@ -24,11 +24,11 @@
// import { SearchOptionItem, SearchOptionSubMenu } from '.';
// import { translateKindName } from '../Explorer/util';
// import { FilterTypeCondition, filterTypeCondition } from './Filters';
// import { FilterTypeCondition, filterTypeCondition } from './FiltersOld';
// import { AllKeys, FilterOption, getKey } from './store';
// import { UseSearch } from './useSearch';
// export interface SearchFilter<
// interface SearchFilter<
// TConditions extends FilterTypeCondition[keyof FilterTypeCondition] = any
// > {
// name: string;
@@ -37,7 +37,7 @@
// translationKey?: string;
// }
// export interface SearchFilterCRUD<
// interface SearchFilterCRUD<
// TConditions extends FilterTypeCondition[keyof FilterTypeCondition] = any, // TConditions represents the available conditions for a specific filter, it defaults to any condition from the FilterTypeCondition
// T = any // T is the type of the data that is being filtered. This can be any type.
// > extends SearchFilter<TConditions> {
@@ -77,7 +77,7 @@
// merge: (left: T, right: T) => T;
// }
// export interface RenderSearchFilter<
// interface RenderSearchFilter<
// TConditions extends FilterTypeCondition[keyof FilterTypeCondition] = any,
// T = any
// > extends SearchFilterCRUD<TConditions, T> {
@@ -91,7 +91,7 @@
// useOptions: (props: { search: string }) => FilterOption[];
// }
// export function useToggleOptionSelected({ search }: { search: UseSearch<any> }) {
// function useToggleOptionSelected({ search }: { search: UseSearch<any> }) {
// return ({
// filter,
// option,
@@ -581,7 +581,7 @@
// });
// }
// export const filterRegistry = [
// const filterRegistry = [
// createGenericRangeFilter(
// i18n.t('date_created_range'),
// 'date_created_range',
@@ -887,4 +887,4 @@
// // })
// ] as const satisfies ReadonlyArray<RenderSearchFilter<any>>;
// export type FilterType = (typeof filterRegistry)[number]['name'];
// type FilterType = (typeof filterRegistry)[number]['name'];

View File

@@ -7,8 +7,8 @@ import { useLocale } from '~/hooks';
import { useSearchContext } from '../..';
import HorizontalScroll from '../../../overview/Layout/HorizontalScroll';
import { filterRegistry } from '../../Filters/index';
import { useSearchStore } from '../../store';
import { RenderIcon } from '../../util';
import { useFilterOptionStore } from '../store';
export const FilterContainer = tw.div`flex flex-row items-center rounded bg-app-box overflow-hidden shrink-0 h-6`;
@@ -75,7 +75,7 @@ export const AppliedFilters = () => {
};
export function FilterArg({ arg, onDelete }: { arg: SearchFilterArgs; onDelete?: () => void }) {
const searchStore = useSearchStore();
const filterStore = useFilterOptionStore();
const { t } = useLocale();
const filter = filterRegistry.find((f) => f.extract(arg));
@@ -83,7 +83,7 @@ export function FilterArg({ arg, onDelete }: { arg: SearchFilterArgs; onDelete?:
const activeOptions = filter.argsToFilterOptions(
filter.extract(arg)! as any,
searchStore.filterOptions
filterStore.filterOptions
);
function isFilterDescriptionDisplayed() {

View File

@@ -1,7 +1,7 @@
import { SearchFilterCRUD } from '..';
import { SearchOptionItem } from '../../SearchOptions';
import { getKey } from '../../store';
import { UseSearch } from '../../useSearch';
import { getKey } from '../store';
export const FilterOptionBoolean = ({
filter,

View File

@@ -0,0 +1,45 @@
import { Range } from '@sd/client';
import { SearchFilterCRUD } from '..';
import { SearchOptionItem } from '../../SearchOptions';
import { UseSearch } from '../../useSearch';
import { getKey } from '../store';
export const FilterOptionDateRange = ({
filter,
search
}: {
filter: SearchFilterCRUD;
search: UseSearch<any>;
}) => {
const { allFiltersKeys } = search;
const key = getKey({
type: filter.name,
name: filter.name,
value: { start: new Date(), end: new Date() } // Example default range
});
return (
<SearchOptionItem
icon={filter.icon}
selected={allFiltersKeys?.has(key)}
setSelected={() => {
search.setFilters?.((filters = []) => {
const index = filters.findIndex((f) => filter.extract(f) !== undefined);
if (index !== -1) {
filters.splice(index, 1);
} else {
const arg = filter.create({ start: new Date(), end: new Date() }); // Example default range
filters.push(arg);
}
return filters;
});
}}
>
{filter.name}
</SearchOptionItem>
);
};

View File

@@ -1,8 +1,8 @@
import { SearchFilterCRUD } from '..';
import { SearchOptionItem, SearchOptionSubMenu } from '../../SearchOptions';
import { FilterOption, getKey } from '../../store';
import { UseSearch } from '../../useSearch';
import { useToggleOptionSelected } from '../hooks/useToggleOptionSelected';
import { FilterOption, getKey } from '../store';
export const FilterOptionList = ({
filter,

View File

@@ -4,8 +4,8 @@ import { useLocale } from '~/hooks';
import { SearchFilterCRUD } from '..';
import { SearchOptionSubMenu } from '../../SearchOptions';
import { getKey } from '../../store';
import { UseSearch } from '../../useSearch';
import { getKey } from '../store';
export const FilterOptionText = ({
filter,

View File

@@ -9,7 +9,7 @@ import { createFilter, CreateFilterFunction, filterTypeCondition, FilterTypeCond
* @param filter - The initial filter configuration, including the create method, argsToFilterOptions, and other specific behaviors.
* @returns A filter object that supports CRUD operations for range conditions.
*/
export function createRangeFilter<T>(
export function createDateRangeFilter<T extends string | number>(
filter: CreateFilterFunction<FilterTypeCondition['dateRange'], Range<T>>
): ReturnType<typeof createFilter<FilterTypeCondition['dateRange'], Range<T>>> {
return {

View File

@@ -1,5 +1,5 @@
import { SearchFilterCRUD } from '..';
import { FilterOption } from '../../store';
import { FilterOption } from '../';
import { UseSearch } from '../../useSearch';
export function useToggleOptionSelected({ search }: { search: UseSearch<any> }) {

View File

@@ -1,8 +1,8 @@
/**
* This module defines an abstraction layer for search filters, reducing redundancy and improving scalability.
* This module defines an abstraction layer for search filters.
*
* Instead of duplicating logic for every type of filter, we use generic factory patterns to create filters dynamically.
* The core idea is to define reusable "conditions" for each filter type (e.g., `TextMatch`, `Range`, `InOrNotIn`) and
* The core idea is to define reusable "conditions" for each filter type (e.g., `TextMatch`, `DateRange`, `InOrNotIn`) and
* allow filters to be created via factory functions. The interface for CRUD operations remains the same across all filters,
* but the condition logic varies depending on the type of filter.
*
@@ -21,15 +21,15 @@
import { Icon } from '@phosphor-icons/react';
import { SearchFilterArgs } from '@sd/client';
import i18n from '~/app/I18n';
import i18n from '../../../I18n';
import { AllKeys, FilterOption } from '../store';
import { UseSearch } from '../useSearch';
import { AllKeys, type FilterOption } from './store';
import { OmitCommonFilterProperties } from './typeGuards';
export { filterRegistry, FilterType } from './FilterRegistry';
export { filterRegistry, type FilterType } from './FilterRegistry';
export { FilterOption };
export type { FilterOption };
export { useToggleOptionSelected } from './hooks/useToggleOptionSelected';

View File

@@ -0,0 +1,58 @@
import type {} from '@sd/client'; // required for type inference of createDateRangeFilter
import { Calendar } from '@phosphor-icons/react';
import i18n from '~/app/I18n';
import { FilterOption } from '..';
import { FilterOptionList } from '../components/FilterOptionList';
import { createDateRangeFilter } from '../factories/createDateRangeFilter';
export const useCommonDateOptions = (): FilterOption[] => {
return [
{
name: i18n.t('Last 7 Days'),
value: { from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString() },
icon: Calendar
},
{
name: i18n.t('Last 30 Days'),
value: { from: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString() },
icon: Calendar
},
{
name: i18n.t('This Year'),
value: { from: new Date(new Date().getFullYear(), 0, 1).toISOString() },
icon: Calendar
}
];
};
export const filePathDateCreated = createDateRangeFilter<string>({
name: i18n.t('Date Created'),
translationKey: 'dateCreated',
icon: Calendar,
create: (dateRange) => ({ filePath: { createdAt: dateRange } }),
extract: (arg) => {
if ('filePath' in arg && 'createdAt' in arg.filePath) return arg.filePath.createdAt;
},
argsToFilterOptions: (dateRange) => {
return dateRange.map((value) => ({
name: value,
value: value
}));
},
useOptions: (): FilterOption[] => useCommonDateOptions(),
Render: ({ filter, options, search }) => (
<FilterOptionList filter={filter} options={options} search={search} />
)
});
// export const filePathDateModified = createDateRangeFilter({});
// export const filePathDateAccessed = createDateRangeFilter({});
// export const objectDateAccessed = createDateRangeFilter({});
// export const dateFilters = [
// filePathDateCreated,
// filePathDateModified,
// filePathDateAccessed
// ] as const;

View File

@@ -0,0 +1,43 @@
import { Cube } from '@phosphor-icons/react';
import { ObjectKind } from '@sd/client'; // Assuming ObjectKind is an enum or set of constants
import i18n from '~/app/I18n';
import { FilterOptionList } from '../components/FilterOptionList';
import { createInOrNotInFilter } from '../factories/createInOrNotInFilter';
export const kindFilter = createInOrNotInFilter<number>({
name: i18n.t('kind'),
translationKey: 'kind',
icon: Cube,
extract: (arg) => {
if ('object' in arg && 'kind' in arg.object) return arg.object.kind;
},
create: (kind) => ({ object: { kind } }),
argsToFilterOptions(values, options) {
return values
.map((value) => {
const option = options.get(this.name)?.find((o) => o.value === value);
if (!option) return;
return {
...option,
type: this.name
};
})
.filter(Boolean) as any;
},
useOptions: () =>
Object.keys(ObjectKind)
.filter((key) => !isNaN(Number(key)) && ObjectKind[Number(key)] !== undefined)
.map((key) => {
const kind = ObjectKind[Number(key)] as string;
return {
name: i18n.t(kind), // Assuming translations for kinds
value: Number(key),
icon: Cube // You can customize this based on the kind if needed
};
}),
Render: ({ filter, options, search }) => (
<FilterOptionList filter={filter} options={options} search={search} />
)
});

View File

@@ -0,0 +1,42 @@
// Import icons
import { Folder } from '@phosphor-icons/react';
import { useLibraryQuery } from '@sd/client';
import i18n from '~/app/I18n';
import { FilterOptionList } from '../components/FilterOptionList';
import { createInOrNotInFilter } from '../factories/createInOrNotInFilter';
export const locationFilter = createInOrNotInFilter<number>({
name: i18n.t('location'),
translationKey: 'location',
icon: Folder,
create: (locations) => ({ filePath: { locations } }),
extract: (arg) => {
if ('filePath' in arg && 'locations' in arg.filePath) return arg.filePath.locations;
},
argsToFilterOptions(values, options) {
return values
.map((value) => {
const option = options.get(this.name)?.find((o) => o.value === value);
if (!option) return;
return {
...option,
type: this.name
};
})
.filter(Boolean) as any;
},
useOptions: () => {
const query = useLibraryQuery(['locations.list'], { keepPreviousData: true });
const locations = query.data;
return (locations ?? []).map((location) => ({
name: location.name!,
value: location.id,
icon: 'Folder'
}));
},
Render: ({ filter, options, search }) => (
<FilterOptionList filter={filter} options={options} search={search} />
)
});

View File

@@ -0,0 +1,51 @@
import { CircleDashed } from '@phosphor-icons/react';
import { useLibraryQuery } from '@sd/client';
import i18n from '~/app/I18n';
import { FilterOptionList } from '../components/FilterOptionList';
import { createInOrNotInFilter } from '../factories/createInOrNotInFilter';
export const tagsFilter = createInOrNotInFilter<number>({
name: i18n.t('tags'),
translationKey: 'tag',
icon: CircleDashed,
extract: (arg) => {
if ('object' in arg && 'tags' in arg.object) return arg.object.tags;
},
create: (tags) => ({ object: { tags } }),
argsToFilterOptions(values, options) {
return values
.map((value) => {
const option = options.get(this.name)?.find((o) => o.value === value);
if (!option) return;
return {
...option,
type: this.name
};
})
.filter(Boolean) as any;
},
useOptions: () => {
const query = useLibraryQuery(['tags.list'], { keepPreviousData: true });
const tags = query.data;
return (tags ?? []).map((tag) => ({
name: tag.name!,
value: tag.id,
icon: tag.color || 'CircleDashed'
}));
},
Render: ({ filter, options, search }) => (
<FilterOptionList
empty={() => (
<div className="flex flex-col items-center justify-center gap-2 p-2">
<span className="icon-tag size-4" />
<p className="w-4/5 text-center text-xs text-ink-dull">{i18n.t('no_tags')}</p>
</div>
)}
filter={filter}
options={options}
search={search}
/>
)
});

View File

@@ -0,0 +1,34 @@
import type {} from '@sd/client'; // required for type inference of createDateRangeFilter
import { Textbox } from '@phosphor-icons/react';
import i18n from '~/app/I18n';
import { FilterOptionText } from '../components/FilterOptionText';
import { createInOrNotInFilter } from '../factories/createInOrNotInFilter';
import { createTextMatchFilter } from '../factories/createTextMatchFilter';
// Name Filter
export const nameFilter = createTextMatchFilter({
name: i18n.t('name'),
translationKey: 'name',
icon: Textbox,
extract: (arg) => {
if ('filePath' in arg && 'name' in arg.filePath) return arg.filePath.name;
},
create: (name) => ({ filePath: { name } }),
useOptions: ({ search }) => [{ name: search, value: search, icon: Textbox }],
Render: ({ filter, search }) => <FilterOptionText filter={filter} search={search} />
});
// Extension Filter
export const extensionFilter = createInOrNotInFilter({
name: i18n.t('extension'),
translationKey: 'extension',
icon: Textbox,
extract: (arg) => {
if ('filePath' in arg && 'extension' in arg.filePath) return arg.filePath.extension;
},
create: (extension) => ({ filePath: { extension } }),
useOptions: ({ search }) => [{ name: search, value: search, icon: Textbox }],
Render: ({ filter, search }) => <FilterOptionText filter={filter} search={search} />
});

View File

@@ -0,0 +1,97 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { Icon } from '@phosphor-icons/react';
import { useEffect, useMemo } from 'react';
import { proxy, ref, useSnapshot } from 'valtio';
import { proxyMap } from 'valtio/utils';
import { Range, SearchFilterArgs } from '@sd/client';
import { FilterType, RenderSearchFilter } from '.';
import { filterRegistry } from './FilterRegistry';
// Define filter option interface
export interface FilterOption<T = any> {
value: string | Range<T> | any;
name: string;
icon?: string | Icon;
}
export interface FilterOptionWithType extends FilterOption {
type: FilterType;
}
const filterOptionStore = proxy({
filterOptions: ref(new Map<string, FilterOptionWithType[]>()),
registeredFilters: proxyMap() as Map<string, FilterOptionWithType>
});
// Generate a unique key for a filter option
export const getKey = (filter: FilterOptionWithType) =>
`${filter.type}-${filter.name}-${filter.value}`;
// Hook to register filter options into the local store
export const useRegisterFilterOptions = (
filter: RenderSearchFilter,
options: (FilterOption & { type: FilterType })[]
) => {
const optionsAsKeys = useMemo(() => options.map(getKey), [options]);
useEffect(() => {
filterOptionStore.filterOptions.set(filter.name, options);
filterOptionStore.filterOptions = ref(new Map(filterOptionStore.filterOptions));
}, [optionsAsKeys]);
useEffect(() => {
const keys = options.map((option) => {
const key = getKey(option);
if (!filterOptionStore.registeredFilters.has(key)) {
filterOptionStore.registeredFilters.set(key, option);
return key;
}
});
return () => {
keys.forEach((key) => {
if (key) filterOptionStore.registeredFilters.delete(key);
});
};
}, [optionsAsKeys]);
};
// Function to retrieve registered filters based on a query
export const useSearchRegisteredFilters = (query: string) => {
const { registeredFilters } = useFilterOptionStore();
return useMemo(() => {
if (!query) return [];
// Filter the registered filters by matching the query string
return [...registeredFilters.entries()]
.filter(([key, _]) => key.toLowerCase().includes(query.toLowerCase()))
.map(([key, filter]) => ({ ...filter, key }));
}, [registeredFilters, query]);
};
// Get snapshot of the filter option store
export const useFilterOptionStore = () => useSnapshot(filterOptionStore);
// Function to reset filter options (if needed)
export const resetFilterOptionStore = () => {
filterOptionStore.filterOptions.clear();
filterOptionStore.registeredFilters.clear();
};
// Helper to convert arguments to filter options
export function argsToFilterOptions(
args: SearchFilterArgs[],
options: Map<string, FilterOption[]>
) {
return args.flatMap((fixedArg) => {
const filter = filterRegistry.find((f) => f.extract(fixedArg));
if (!filter) return [];
return filter
.argsToFilterOptions(filter.extract(fixedArg) as any, options)
.map((arg) => ({ arg, filter }));
});
}
export type AllKeys<T> = T extends any ? keyof T : never;

View File

@@ -23,11 +23,11 @@ import { useSearchContext } from './context';
import { AppliedFilters, InteractiveSection } from './Filters/components/AppliedFilters';
import { filterRegistry, SearchFilterCRUD, useToggleOptionSelected } from './Filters/index';
import {
getSearchStore,
useRegisterSearchFilterOptions,
useSearchRegisteredFilters,
useSearchStore
} from './store';
useFilterOptionStore,
useRegisterFilterOptions,
useSearchRegisteredFilters
} from './Filters/store';
import { getSearchStore, useSearchStore } from './store';
import { UseSearch } from './useSearch';
import { RenderIcon } from './util';
@@ -209,7 +209,7 @@ const SearchResults = memo(
function AddFilterButton() {
const search = useSearchContext();
const searchState = useSearchStore();
const filterStore = useFilterOptionStore();
const [searchQuery, setSearch] = useState('');
@@ -261,7 +261,7 @@ function AddFilterButton() {
<filter.Render
key={filter.name}
filter={filter as any}
options={searchState.filterOptions.get(filter.name)!}
options={filterStore.filterOptions.get(filter.name)!}
search={search}
/>
))
@@ -373,7 +373,7 @@ function RegisterSearchFilterOptions(props: {
}) {
const options = props.filter.useOptions({ search: props.searchQuery });
useRegisterSearchFilterOptions(
useRegisterFilterOptions(
props.filter,
useMemo(
() => options.map((o) => ({ ...o, type: props.filter.name })),

View File

@@ -1,99 +1,27 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { Icon } from '@phosphor-icons/react';
import { useEffect, useMemo } from 'react';
import { proxy, ref, useSnapshot } from 'valtio';
import { proxyMap } from 'valtio/utils';
import { SearchFilterArgs } from '@sd/client';
import { filterRegistry, FilterType, RenderSearchFilter } from './Filters/index';
import { proxy, useSnapshot } from 'valtio';
export type SearchType = 'paths' | 'objects';
export interface FilterOption {
value: string | any;
name: string;
icon?: string | Icon; // "Folder" or "#efefef"
}
export interface FilterOptionWithType extends FilterOption {
type: FilterType;
}
export type AllKeys<T> = T extends any ? keyof T : never;
const searchStore = proxy({
interactingWithSearchOptions: false,
searchType: 'paths' as SearchType,
filterOptions: ref(new Map<string, FilterOptionWithType[]>()),
// we register filters so we can search them
registeredFilters: proxyMap() as Map<string, FilterOptionWithType>
searchQuery: '' // Search query to track user input
// Any other search-specific state can go here
});
// this makes the filter unique and easily searchable using .includes
export const getKey = (filter: FilterOptionWithType) =>
`${filter.type}-${filter.name}-${filter.value}`;
// this hook allows us to register filters to the search store
// and returns the filters with the correct type
export const useRegisterSearchFilterOptions = (
filter: RenderSearchFilter,
options: (FilterOption & { type: FilterType })[]
) => {
const optionsAsKeys = useMemo(() => options.map(getKey), [options]);
useEffect(() => {
searchStore.filterOptions.set(filter.name, options);
searchStore.filterOptions = ref(new Map(searchStore.filterOptions));
}, [optionsAsKeys]);
useEffect(() => {
const keys = options.map((option) => {
const key = getKey(option);
if (!searchStore.registeredFilters.has(key)) {
searchStore.registeredFilters.set(key, option);
return key;
}
});
return () =>
keys.forEach((key) => {
if (key) searchStore.registeredFilters.delete(key);
});
}, [optionsAsKeys]);
};
export function argsToFilterOptions(
args: SearchFilterArgs[],
options: Map<string, FilterOption[]>
) {
return args.flatMap((fixedArg) => {
const filter = filterRegistry.find((f) => f.extract(fixedArg));
if (!filter) return [];
return filter
.argsToFilterOptions(filter.extract(fixedArg) as any, options)
.map((arg) => ({ arg, filter }));
});
}
export const useSearchRegisteredFilters = (query: string) => {
const { registeredFilters } = useSearchStore();
return useMemo(
() =>
!query
? []
: [...registeredFilters.entries()]
.filter(([key, _]) => key.toLowerCase().includes(query.toLowerCase()))
.map(([key, filter]) => ({ ...filter, key })),
[registeredFilters, query]
);
};
export const resetSearchStore = () => {};
// Hook to interact with the search store
export const useSearchStore = () => useSnapshot(searchStore);
// Function to set the search query
export const setSearchQuery = (query: string) => {
searchStore.searchQuery = query;
};
// Function to reset search state (if needed)
export const resetSearchStore = () => {
searchStore.interactingWithSearchOptions = false;
searchStore.searchQuery = '';
};
// Function to retrieve the search store directly
export const getSearchStore = () => searchStore;

View File

@@ -4,7 +4,7 @@ import { useSearchParams as useRawSearchParams } from 'react-router-dom';
import { useDebouncedValue } from 'rooks';
import { SearchFilterArgs } from '@sd/client';
import { argsToFilterOptions, getKey, useSearchStore } from './store';
import { argsToFilterOptions, getKey, useFilterOptionStore } from './Filters/store';
export type SearchTarget = 'paths' | 'objects';
@@ -120,11 +120,11 @@ export function useSearch<TSource extends UseSearchSource>(props: UseSearchProps
const [searchBarFocused, setSearchBarFocused] = useState(false);
const searchState = useSearchStore();
const filterStore = useFilterOptionStore();
const filtersAsOptions = useMemo(
() => argsToFilterOptions(filters ?? [], searchState.filterOptions),
[filters, searchState.filterOptions]
() => argsToFilterOptions(filters ?? [], filterStore.filterOptions),
[filters, filterStore.filterOptions]
);
const filtersKeys: Set<string> = useMemo(() => {
@@ -140,7 +140,6 @@ export function useSearch<TSource extends UseSearchSource>(props: UseSearchProps
}, [filtersAsOptions]);
// Merging of filters that should be ORed
const mergedFilters = useMemo(
() => filters?.map((arg, removalIndex) => ({ arg, removalIndex })),
[filters]
@@ -166,8 +165,8 @@ export function useSearch<TSource extends UseSearchSource>(props: UseSearchProps
);
const allFiltersAsOptions = useMemo(
() => argsToFilterOptions(allFilters, searchState.filterOptions),
[searchState.filterOptions, allFilters]
() => argsToFilterOptions(allFilters, filterStore.filterOptions),
[filterStore.filterOptions, allFilters]
);
const allFiltersKeys: Set<string> = useMemo(() => {