Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 1x 1x 1x 1x 1x 1x 41x 41x 41x 1x 1x 1x 1x 1x 1x 1x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x 8x | import { ModelInfo } from "@shared/api"
import { VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react"
import styled from "styled-components"
import { DebouncedTextField } from "./DebouncedTextField"
/**
* Container for dropdowns that ensures proper z-index handling
* This is necessary to ensure dropdown opens downward
*/
export const DropdownContainer = styled.div.attrs<{ zIndex?: number }>(({ zIndex }) => ({
style: {
zIndex: zIndex || 1000,
},
}))`
position: relative;
// Force dropdowns to open downward
& vscode-dropdown::part(listbox) {
position: absolute !important;
top: 100% !important;
bottom: auto !important;
}
`
/**
* Props for the ModelSelector component
*/
interface ModelSelectorProps {
models: Record<string, ModelInfo>
selectedModelId: string | undefined
onChange: (e: any) => void
zIndex?: number
label?: string
}
/*
OG Saoud Note:
VSCodeDropdown has an open bug where dynamically rendered options don't auto select the provided value prop. You can see this for yourself by comparing it with normal select/option elements, which work as expected.
https://github.com/microsoft/vscode-webview-ui-toolkit/issues/433
In our case, when the user switches between providers, we recalculate the selectedModelId depending on the provider, the default model for that provider, and a modelId that the user may have selected. Unfortunately, the VSCodeDropdown component wouldn't select this calculated value, and would default to the first "Select a model..." option instead, which makes it seem like the model was cleared out when it wasn't.
As a workaround, we create separate instances of the dropdown for each provider, and then conditionally render the one that matches the current provider.
*/
/**
* A reusable component for selecting models from a dropdown
*/
export const ModelSelector = ({ models, selectedModelId, onChange, zIndex, label = "Model" }: ModelSelectorProps) => {
const hasCustomSelection = !!selectedModelId && !(selectedModelId in models)
const sortedModelIds = Object.keys(models).sort((a, b) => a.localeCompare(b))
return (
<div style={{ marginBottom: 10 }}>
<DebouncedTextField
initialValue={selectedModelId || ""}
onChange={(value) => onChange({ target: { value } })}
placeholder="Enter Model ID..."
style={{ width: "100%", marginBottom: 10 }}>
<span style={{ fontWeight: 500 }}>Model ID</span>
</DebouncedTextField>
<DropdownContainer className="dropdown-container" zIndex={zIndex}>
<label htmlFor="model-id">
<span style={{ fontWeight: 500 }}>{label}</span>
</label>
<VSCodeDropdown id="model-id" onChange={onChange} style={{ width: "100%" }} value={selectedModelId}>
<VSCodeOption value="">Select a model...</VSCodeOption>
{hasCustomSelection && <VSCodeOption value={selectedModelId}>{selectedModelId}</VSCodeOption>}
{sortedModelIds.map((modelId) => (
<VSCodeOption
key={modelId}
style={{
whiteSpace: "normal",
wordWrap: "break-word",
maxWidth: "100%",
}}
value={modelId}>
{modelId}
</VSCodeOption>
))}
</VSCodeDropdown>
</DropdownContainer>
</div>
)
}
|