refactor(frontend): 用通用 Select 替换旧下拉选择器
This commit is contained in:
parent
4afba86bcb
commit
a721091476
|
|
@ -1,106 +0,0 @@
|
||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
import {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuRadioGroup,
|
|
||||||
DropdownMenuRadioItem,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
} from "@/components/ui/dropdown-menu";
|
|
||||||
import { cn, truncateMiddle } from "@/lib/utils";
|
|
||||||
|
|
||||||
export interface DropdownSelectorOption<T extends string> {
|
|
||||||
value: T;
|
|
||||||
label: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DropdownSelectorProps<T extends string> {
|
|
||||||
value: T;
|
|
||||||
options: DropdownSelectorOption<T>[];
|
|
||||||
onChange: (value: T) => void;
|
|
||||||
triggerClassName?: string;
|
|
||||||
contentClassName?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ChevronDownIcon() {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
width="10"
|
|
||||||
height="6"
|
|
||||||
viewBox="0 0 10 6"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M0.75 0.75L4.75 4.75L8.75 0.75"
|
|
||||||
stroke="#666666"
|
|
||||||
strokeWidth="1.5"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ChevronUpIcon() {
|
|
||||||
return (
|
|
||||||
<svg
|
|
||||||
width="10"
|
|
||||||
height="6"
|
|
||||||
viewBox="0 0 10 6"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M0.75 4.75L4.75 0.75L8.75 4.75"
|
|
||||||
stroke="#666666"
|
|
||||||
strokeWidth="1.5"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function DropdownSelector<T extends string>({
|
|
||||||
value,
|
|
||||||
options,
|
|
||||||
onChange,
|
|
||||||
triggerClassName,
|
|
||||||
contentClassName,
|
|
||||||
}: DropdownSelectorProps<T>) {
|
|
||||||
const selectedOption = options.find((opt) => opt.value === value);
|
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownMenu open={isOpen} onOpenChange={setIsOpen}>
|
|
||||||
<DropdownMenuTrigger
|
|
||||||
className={
|
|
||||||
triggerClassName ??
|
|
||||||
"border-none bg-transparent flex justify-center w-full overflow-hidden text-ellipsis whitespace-nowrap shadow-none select-none focus:outline-none"
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span className="flex w-full justify-center items-center gap-1">
|
|
||||||
{truncateMiddle(selectedOption?.label ?? value, 50)}
|
|
||||||
{isOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
|
|
||||||
</span>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent className={cn(contentClassName, "max-w-80")}>
|
|
||||||
<DropdownMenuRadioGroup
|
|
||||||
value={value}
|
|
||||||
onValueChange={(v) => onChange(v as T)}
|
|
||||||
>
|
|
||||||
{options.map((option) => (
|
|
||||||
<DropdownMenuRadioItem
|
|
||||||
key={option.value}
|
|
||||||
value={option.value}
|
|
||||||
title={option.label}
|
|
||||||
>
|
|
||||||
{truncateMiddle(option.label)}
|
|
||||||
</DropdownMenuRadioItem>
|
|
||||||
))}
|
|
||||||
</DropdownMenuRadioGroup>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -23,7 +23,14 @@ import {
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/ui/dropdown-menu";
|
||||||
import { DropdownSelector } from "@/components/ui/dropdown-selector";
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectGroup,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue,
|
||||||
|
} from "@/components/ui/select";
|
||||||
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
|
||||||
import { CodeEditor } from "@/components/workspace/code-editor";
|
import { CodeEditor } from "@/components/workspace/code-editor";
|
||||||
import { useArtifactContent } from "@/core/artifacts/hooks";
|
import { useArtifactContent } from "@/core/artifacts/hooks";
|
||||||
|
|
@ -247,11 +254,20 @@ export function ArtifactFileDetail({
|
||||||
{isWriteFile ? (
|
{isWriteFile ? (
|
||||||
<div className=" w-full text-center overflow-hidden text-ellipsis whitespace-nowrap px-2">{truncateMiddle(getFileName(filepath), 50)}</div>
|
<div className=" w-full text-center overflow-hidden text-ellipsis whitespace-nowrap px-2">{truncateMiddle(getFileName(filepath), 50)}</div>
|
||||||
) : (
|
) : (
|
||||||
<DropdownSelector
|
<Select value={filepath} onValueChange={select}>
|
||||||
value={filepath}
|
<SelectTrigger className="border-none bg-transparent! shadow-none select-none focus:outline-0 active:outline-0">
|
||||||
options={artifactOptions}
|
<SelectValue placeholder="Select a file" />
|
||||||
onChange={select}
|
</SelectTrigger>
|
||||||
/>
|
<SelectContent className="select-none">
|
||||||
|
<SelectGroup>
|
||||||
|
{artifactOptions.map((option) => (
|
||||||
|
<SelectItem key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
)}
|
)}
|
||||||
</ArtifactTitle>
|
</ArtifactTitle>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue