From 6593e05fcbe0c5e09ba005b8441a8f06c7ded204 Mon Sep 17 00:00:00 2001 From: Hk-Gosuto Date: Wed, 23 Oct 2024 11:04:55 +0800 Subject: [PATCH] feat: model selection add search input --- app/components/chat.tsx | 3 +- app/components/ui-lib.module.scss | 17 +++++ app/components/ui-lib.tsx | 101 ++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) diff --git a/app/components/chat.tsx b/app/components/chat.tsx index fcac4b32b..b4edfca8f 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -96,6 +96,7 @@ import { List, ListItem, Modal, + SearchSelector, Selector, showConfirm, showPrompt, @@ -678,7 +679,7 @@ export function ChatActions(props: { /> {showModelSelector && ( - ({ title: `${m.displayName}${ diff --git a/app/components/ui-lib.module.scss b/app/components/ui-lib.module.scss index 83c02f92a..1f1e6a333 100644 --- a/app/components/ui-lib.module.scss +++ b/app/components/ui-lib.module.scss @@ -311,4 +311,21 @@ } } } + + &-search { + border-bottom: 1px solid var(--gray-200); + } + + &-search-input { + width: 100% !important; + max-width: 100% !important; + padding: 8px 12px; + border: none; + outline: none; + font-size: 14px; + } + + &-search-input:focus { + background-color: var(--gray-50); + } } diff --git a/app/components/ui-lib.tsx b/app/components/ui-lib.tsx index 2754473ce..ee78126b5 100644 --- a/app/components/ui-lib.tsx +++ b/app/components/ui-lib.tsx @@ -465,7 +465,108 @@ export function showImageModal( ), }); } +export function SearchSelector(props: { + items: Array<{ + title: string; + subTitle?: string; + value: T; + disable?: boolean; + }>; + defaultSelectedValue?: T[] | T; + onSelection?: (selection: T[]) => void; + onClose?: () => void; + multiple?: boolean; +}) { + const [selectedValues, setSelectedValues] = useState( + Array.isArray(props.defaultSelectedValue) + ? props.defaultSelectedValue + : props.defaultSelectedValue !== undefined + ? [props.defaultSelectedValue] + : [], + ); + // 添加搜索状态 + const [searchQuery, setSearchQuery] = useState(""); + + const handleSelection = (e: MouseEvent, value: T) => { + if (props.multiple) { + e.stopPropagation(); + const newSelectedValues = selectedValues.includes(value) + ? selectedValues.filter((v) => v !== value) + : [...selectedValues, value]; + setSelectedValues(newSelectedValues); + props.onSelection?.(newSelectedValues); + } else { + setSelectedValues([value]); + props.onSelection?.([value]); + props.onClose?.(); + } + }; + + // 过滤列表项 + const filteredItems = props.items.filter( + (item) => + item.title.toLowerCase().includes(searchQuery.toLowerCase()) || + (item.subTitle && + item.subTitle.toLowerCase().includes(searchQuery.toLowerCase())), + ); + + return ( +
props.onClose?.()}> +
e.stopPropagation()} + > + + {/* 搜索框 */} +
+ setSearchQuery(e.target.value)} + onClick={(e) => e.stopPropagation()} + /> +
+ {filteredItems.map((item, i) => { + const selected = selectedValues.includes(item.value); + return ( + { + if (item.disable) { + e.stopPropagation(); + } else { + handleSelection(e, item.value); + } + }} + > + {selected ? ( +
+ ) : ( + <> + )} +
+ ); + })} +
+
+
+ ); +} export function Selector(props: { items: Array<{ title: string;