From dfaa3d8c19005430f59cb81bf99a3814f9ef350f Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Mon, 29 Sep 2025 18:14:05 -0600 Subject: [PATCH] has suggestions through hook --- .../BusterChatInput/BusterChatInputBase.tsx | 4 +- .../MentionInputSuggestions.tsx | 39 ++++++++++--------- .../MentionInputSuggestionsEmpty.tsx | 11 ------ .../MentionInputSuggestionsGroup.tsx | 2 - .../MentionInputSuggestionsItem.tsx | 22 +---------- .../MentionInputSuggestionsItemSelector.tsx | 4 -- .../MentionInputSuggestionsList.tsx | 6 ++- .../MentionInputSuggestionsSeparator.tsx | 4 +- 8 files changed, 31 insertions(+), 61 deletions(-) diff --git a/apps/web/src/components/features/input/BusterChatInput/BusterChatInputBase.tsx b/apps/web/src/components/features/input/BusterChatInput/BusterChatInputBase.tsx index 0aee74105..228bcf996 100644 --- a/apps/web/src/components/features/input/BusterChatInput/BusterChatInputBase.tsx +++ b/apps/web/src/components/features/input/BusterChatInput/BusterChatInputBase.tsx @@ -132,7 +132,7 @@ const useUniqueSuggestions = ( const fourUniqueSuggestions = sampleSize(allSuggestions, 4); - const items: MentionInputSuggestionsProps['suggestionItems'] = fourUniqueSuggestions.map( + const items: MentionInputSuggestionsDropdownItem[] = fourUniqueSuggestions.map( (suggestion) => ({ type: 'item', value: suggestion.type + suggestion.value, @@ -148,7 +148,7 @@ const useUniqueSuggestions = ( addValueToInput: true, closeOnSelect: true, }, - ]; + ] satisfies MentionInputSuggestionsProps['suggestionItems']; }, [suggestedPrompts]); }; diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx index 702c1ef33..3922a2cda 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestions.tsx @@ -1,4 +1,4 @@ -import { Command } from 'cmdk'; +import { Command, useCommandState } from 'cmdk'; import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'; import { useMemoizedFn } from '@/hooks/useMemoizedFn'; import { cn } from '@/lib/utils'; @@ -51,7 +51,6 @@ export const MentionInputSuggestions = forwardRef< ) => { const [hasClickedSelect, setHasClickedSelect] = useState(false); const [value, setValue] = useState(valueProp ?? defaultValue); - const [hasResults, setHasResults] = useState(!!suggestionItems.length); const commandListNavigatedRef = useRef(false); const commandRef = useRef(null); @@ -106,7 +105,6 @@ export const MentionInputSuggestions = forwardRef< onClick?.(); if (closeSuggestionOnSelect) setHasClickedSelect(true); onSuggestionItemClick?.(params); - setHasResults(false); } ); @@ -153,14 +151,6 @@ export const MentionInputSuggestions = forwardRef< [value] ); - function customFilter(value: string, search: string, keywords?: string[]): number { - console.log(value, search, keywords); - // Example: exact matches rank higher, case insensitive includes rank lower - if (value.toLowerCase() === search.toLowerCase()) return 2; - if (value.toLowerCase().includes(search.toLowerCase())) return 1; - return 0; - } - return ( {children &&
{children}
} - {hasResults &&
} + - + ); } ); + +const SuggestionsSeperator = () => { + const hasResults = useCommandState((x) => x.filtered.count) > 0; + if (!hasResults) return null; + return
; +}; + +const customFilter = (value: string, search: string, keywords?: string[]): number => { + if (keywords?.length) { + return keywords.includes(value) ? 2 : 0; + } + // Example: exact matches rank higher, case insensitive includes rank lower + if (value.toLowerCase() === search.toLowerCase()) return 2; + if (value.toLowerCase().includes(search.toLowerCase())) return 1; + return 0; +}; diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsEmpty.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsEmpty.tsx index db35e4870..c1dcbff6d 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsEmpty.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsEmpty.tsx @@ -5,10 +5,8 @@ import { cn } from '@/lib/utils'; export const MentionInputSuggestionsEmpty = ({ emptyComponent, - setHasResults, className, }: { - setHasResults: (hasResults: boolean) => void; className?: string; emptyComponent: React.ReactNode; }) => { @@ -21,15 +19,6 @@ export const MentionInputSuggestionsEmpty = ({ )} > {emptyComponent} - ); }; - -const SetHasResults = ({ setHasResults }: { setHasResults: (hasResults: boolean) => void }) => { - useMount(() => { - setHasResults(false); - }); - - return null; -}; diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsGroup.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsGroup.tsx index 6d1cbc062..5c4451a46 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsGroup.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsGroup.tsx @@ -12,8 +12,6 @@ export type MentionInputSuggestionsGroupProps = MentionInputSuggestionsDropdownG } & { className?: string; style?: React.CSSProperties; - hasResults: boolean; - setHasResults: (hasResults: boolean) => void; }; export const MentionInputSuggestionsGroup = ({ diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItem.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItem.tsx index e32f81071..204cb020b 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItem.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItem.tsx @@ -1,4 +1,4 @@ -import { Command } from 'cmdk'; +import { Command, useCommandState } from 'cmdk'; import type React from 'react'; import { useMount } from '@/hooks/useMount'; import { cn } from '@/lib/utils'; @@ -12,8 +12,6 @@ export type MentionInputSuggestionsItemProps = { } & MentionInputSuggestionsDropdownItem & { className?: string; style?: React.CSSProperties; - hasResults: boolean; - setHasResults: (hasResults: boolean) => void; }; export const MentionInputSuggestionsItem = ({ @@ -28,8 +26,6 @@ export const MentionInputSuggestionsItem = ({ type, addValueToInput, onSelect, - hasResults, - setHasResults, className, style, }: MentionInputSuggestionsItemProps) => { @@ -42,6 +38,7 @@ export const MentionInputSuggestionsItem = ({ className )} value={value} + data-testid={`type-${type}-value-${value}`} style={style} onSelect={() => { onSelect({ @@ -62,21 +59,6 @@ export const MentionInputSuggestionsItem = ({ )} {label} - {!hasResults && } ); }; - -const SetHasResults = ({ - hasResults, - setHasResults, -}: { - hasResults: boolean; - setHasResults: (hasResults: boolean) => void; -}) => { - useMount(() => { - if (!hasResults) setHasResults(true); - }); - - return null; -}; diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItemSelector.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItemSelector.tsx index 10e4fc6c9..283fb01f1 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItemSelector.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsItemSelector.tsx @@ -16,8 +16,6 @@ export const MentionInputSuggestionsItemSelector = ({ }: { item: MentionInputSuggestionsProps['suggestionItems'][number]; onSelect: (params: MentionInputSuggestionsOnSelectParams) => void; - hasResults: boolean; - setHasResults: (hasResults: boolean) => void; } & GroupOverrideProps) => { if (item.type === 'separator') { return ; @@ -44,8 +42,6 @@ export const MentionInputSuggestionsItemsSelector = ({ }: { suggestionItems: MentionInputSuggestionsProps['suggestionItems']; onSelect: (params: MentionInputSuggestionsOnSelectParams) => void; - hasResults: boolean; - setHasResults: (hasResults: boolean) => void; } & GroupOverrideProps) => { if (!suggestionItems) return null; return suggestionItems.map((item, index) => ( diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsList.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsList.tsx index a445ec5c6..8f9d4dcdd 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsList.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsList.tsx @@ -1,4 +1,4 @@ -import { Command } from 'cmdk'; +import { Command, useCommandState } from 'cmdk'; import type React from 'react'; import { cn } from '@/lib/utils'; @@ -15,10 +15,12 @@ export const MentionInputSuggestionsList = ({ children, show = true, }: MentionInputSuggestionsListProps) => { + const hasResults = useCommandState((x) => x.filtered.count) > 0; + if (!show) return null; return ( - + {children} ); diff --git a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsSeparator.tsx b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsSeparator.tsx index 6fc19dff5..42fa49670 100644 --- a/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsSeparator.tsx +++ b/apps/web/src/components/ui/inputs/MentionInputSuggestions/MentionInputSuggestionsSeparator.tsx @@ -1,4 +1,4 @@ -import { Command } from 'cmdk'; +import { Command, useCommandState } from 'cmdk'; import type React from 'react'; import { cn } from '@/lib/utils'; @@ -6,6 +6,8 @@ export const MentionInputSuggestionsSeparator = ({ children, ...props }: React.ComponentPropsWithoutRef) => { + const hasResults = useCommandState((x) => x); + console.log(hasResults); return ( {children}