Add search field to dropdown

This commit is contained in:
Saoud Rizwan
2024-10-03 23:40:25 -04:00
parent f6a14fdfb9
commit cfefd1b798

View File

@@ -1,25 +1,26 @@
import { VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react"
import React, { useMemo } from "react"
import { useMount } from "react-use"
import React, { useMemo, useState, useRef, useEffect, memo } from "react"
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
import styled from "styled-components"
import { useExtensionState } from "../../context/ExtensionStateContext"
import { useMount } from "react-use"
import { vscode } from "../../utils/vscode"
import { ModelInfoView, normalizeApiConfiguration } from "./ApiOptions"
import { memo, useEffect } from "react"
import { useRemark } from "react-remark"
import styled from "styled-components"
interface OpenRouterModelPickerProps {}
const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = () => {
const OpenRouterModelPicker: React.FC = () => {
const { apiConfiguration, setApiConfiguration, openRouterModels } = useExtensionState()
const [searchTerm, setSearchTerm] = useState("")
const [isDropdownVisible, setIsDropdownVisible] = useState(false)
const dropdownRef = useRef<HTMLDivElement>(null)
const handleModelChange = (event: any) => {
const newModelId = event.target.value
const handleModelChange = (newModelId: string) => {
setApiConfiguration({
...apiConfiguration,
openRouterModelId: newModelId,
openRouterModelInfo: openRouterModels[newModelId],
})
setSearchTerm(newModelId)
setIsDropdownVisible(false)
}
const { selectedModelId, selectedModelInfo } = useMemo(() => {
@@ -30,36 +31,52 @@ const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = () => {
vscode.postMessage({ type: "refreshOpenRouterModels" })
})
const modelIds = useMemo(() => {
return Object.keys(openRouterModels).sort((a, b) => a.localeCompare(b))
}, [openRouterModels])
const filteredModelIds = useMemo(() => {
return Object.keys(openRouterModels)
.filter((modelId) => modelId.toLowerCase().includes(searchTerm.toLowerCase()))
.sort((a, b) => a.localeCompare(b))
}, [openRouterModels, searchTerm])
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsDropdownVisible(false)
}
}
document.addEventListener("mousedown", handleClickOutside)
return () => {
document.removeEventListener("mousedown", handleClickOutside)
}
}, [])
return (
<>
<div className="dropdown-container">
<label htmlFor="model-id">
<DropdownWrapper ref={dropdownRef}>
<label htmlFor="model-search">
<span style={{ fontWeight: 500 }}>Model</span>
</label>
<VSCodeDropdown
id="model-id"
value={selectedModelId}
onChange={handleModelChange}
style={{ width: "100%" }}>
<VSCodeOption value="">Select a model...</VSCodeOption>
{modelIds.map((modelId) => (
<VSCodeOption
key={modelId}
value={modelId}
style={{
whiteSpace: "normal",
wordWrap: "break-word",
maxWidth: "100%",
}}>
<VSCodeTextField
id="model-search"
placeholder="Search and select a model..."
value={searchTerm}
onChange={(e) => {
setSearchTerm((e.target as HTMLInputElement).value)
setIsDropdownVisible(true)
}}
onFocus={() => setIsDropdownVisible(true)}
style={{ width: "100%", zIndex: 1001 }}
/>
{isDropdownVisible && (
<DropdownList>
{filteredModelIds.map((modelId) => (
<DropdownItem key={modelId} onClick={() => handleModelChange(modelId)}>
{modelId}
</VSCodeOption>
</DropdownItem>
))}
</VSCodeDropdown>
</div>
</DropdownList>
)}
</DropdownWrapper>
<ModelInfoView selectedModelId={selectedModelId} modelInfo={selectedModelInfo} />
</>
@@ -68,6 +85,37 @@ const OpenRouterModelPicker: React.FC<OpenRouterModelPickerProps> = () => {
export default OpenRouterModelPicker
// Dropdown
const DropdownWrapper = styled.div`
position: relative;
width: 100%;
`
const DropdownList = styled.div`
position: absolute;
top: calc(100% - 3px);
left: 0;
width: calc(100% - 2px);
max-height: 200px;
overflow-y: auto;
background-color: var(--vscode-dropdown-background);
border: 1px solid var(--vscode-list-activeSelectionBackground);
z-index: 1000;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
`
const DropdownItem = styled.div`
padding: 5px 10px;
cursor: pointer;
&:hover {
background-color: var(--vscode-list-activeSelectionBackground);
}
`
// Markdown
const StyledMarkdown = styled.div`
font-family: var(--vscode-font-family), system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;