diff --git a/src/search/components/pillar-items-dropdown-content.tsx b/src/search/components/pillar-items-dropdown-content.tsx
index c6b13c3..2c562c9 100644
--- a/src/search/components/pillar-items-dropdown-content.tsx
+++ b/src/search/components/pillar-items-dropdown-content.tsx
@@ -6,7 +6,7 @@ import { useInView } from 'react-intersection-observer';
import { useAsyncList } from 'react-stately';
import { Input } from '@nextui-org/input';
-import { Listbox, ListboxItem } from '@nextui-org/listbox';
+import { Listbox, ListboxItem, ListboxSection } from '@nextui-org/listbox';
import { ScrollShadow } from '@nextui-org/scroll-shadow';
import { Spinner } from '@nextui-org/spinner';
import { useQueryClient } from '@tanstack/react-query';
@@ -76,8 +76,6 @@ export const PillarItemsDropdownContent = (props: Props) => {
const pageOffset = !debouncedQuery ? 1 : 0;
const page = Math.floor(cursor / ITEMS_PER_PAGE) + pageOffset;
- console.log({ cursor, pageOffset, page });
-
const queryProps: GetPillarItemsProps = {
nav,
pillar: pillarSlug,
@@ -101,19 +99,53 @@ export const PillarItemsDropdownContent = (props: Props) => {
},
});
- const pillarItemsSet = useMemo(
- () => new Set(pillarItems.map(({ label }) => normalizeString(label))),
- [pillarItems],
+ const activeItemsSet = useMemo(
+ () => new Set(activeItems.map(({ label }) => normalizeString(label))),
+ [activeItems],
+ );
+
+ const activePillarItems = useMemo(
+ () =>
+ pillarItems
+ .filter((pillarItem) =>
+ activeItemsSet.has(normalizeString(pillarItem.label)),
+ )
+ .map((pillarItem) => pillarItem.label),
+ [activeItemsSet, pillarItems],
+ );
+
+ const activeDropdownItems = useMemo(
+ () => {
+ const activeDedupedItems = list.items.filter(
+ (label) =>
+ activeItemsSet.has(normalizeString(label)) &&
+ !activePillarItems.includes(label),
+ );
+
+ if (!debouncedQuery) return [...activePillarItems, ...activeDedupedItems];
+
+ const filteredItems = [
+ ...activePillarItems,
+ ...activeDedupedItems,
+ ].filter((item) =>
+ item.toLowerCase().includes(debouncedQuery.toLowerCase()),
+ );
+
+ return filteredItems;
+ },
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [list.items.length, debouncedQuery, hiddenItems.length],
);
const dropdownItems = useMemo(
() => {
- const hiddenItemsCopy = [...hiddenItems];
- hiddenItemsCopy.reverse();
+ const hiddenItemsCopy = [...hiddenItems]
+ .reverse()
+ .filter((label) => !activeDropdownItems.includes(label));
const dedupedItems = list.items.filter(
(label) =>
- !pillarItemsSet.has(normalizeString(label)) &&
+ !activeDropdownItems.includes(label) &&
!hiddenItemsCopy.includes(label),
);
@@ -132,17 +164,12 @@ export const PillarItemsDropdownContent = (props: Props) => {
useEffect(() => {
list.reload();
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [hiddenItems.length]);
-
- const itemSlugsSet = useMemo(
- () => new Set(activeItems.map(({ label }) => normalizeString(label))),
- [activeItems],
- );
+ }, [activeItems.length, hiddenItems.length]);
const onAction = (key: React.Key) => {
if (key) {
const itemSlug = normalizeString(key as string);
- const isActive = itemSlugsSet.has(itemSlug);
+ const isActive = activeItemsSet.has(itemSlug);
const newSearchParams = createToggledPillarItemSearchParam({
itemSlug,
pillarParamKey,
@@ -200,39 +227,42 @@ export const PillarItemsDropdownContent = (props: Props) => {
>
- {dropdownItems.length > 0 ? (
- dropdownItems.map((label, i) => {
- const isActive = itemSlugsSet.has(normalizeString(label));
-
- return (
-
+ {activeDropdownItems.map((label, i) => (
+ : }
+ >
+ {label}
+
+ ))}
+
+
+
+ {dropdownItems.map((label, i) => (
+
+ : null}
- textValue={label}
+ ref={i === dropdownItems.length - 1 ? inViewRef : undefined}
>
-
- {label}
-
-
- );
- })
- ) : (
-
- {list.isLoading ? 'Loading items ...' : 'No results found'}
-
- )}
+ {label}
+
+
+ ))}
+
>
@@ -256,3 +286,21 @@ const CheckmarkIcon = () => (
/>
);
+
+const LockIcon = () => (
+
+);