fix(model-picker): 模型选择 - 修复长列表溢出与渠道面板随动 (#706)
Co-authored-by: 天道酬秦 <tdcq@tiandaochouqindeMacBook-Air.local>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useId, useMemo, useRef, useState, type KeyboardEvent } from "react";
|
||||
import { useEffect, useId, useLayoutEffect, useMemo, useRef, useState, type CSSProperties, type KeyboardEvent } from "react";
|
||||
import { Check, ChevronDown, Coins } from "lucide-react";
|
||||
import { Popover } from "antd";
|
||||
|
||||
@@ -54,6 +54,7 @@ export function ModelPicker({
|
||||
const rawTheme = useActiveTheme();
|
||||
const theme = (canvasThemes[rawTheme as keyof typeof canvasThemes] ?? canvasThemes.dark) as CanvasTheme;
|
||||
const [open, setOpen] = useState(false);
|
||||
const [availableHeight, setAvailableHeight] = useState(0);
|
||||
const [activeGroupKey, setActiveGroupKey] = useState<string | null>(null);
|
||||
const menuRef = useRef<HTMLDivElement>(null);
|
||||
const triggerRef = useRef<HTMLButtonElement>(null);
|
||||
@@ -70,6 +71,21 @@ export function ModelPicker({
|
||||
const [routeQuote, setRouteQuote] = useState<LogicalModelQuote | undefined>();
|
||||
const creationVariant = variant === "creation";
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!open) return;
|
||||
const updateAvailableHeight = () => {
|
||||
const { top, bottom } = triggerRef.current!.getBoundingClientRect();
|
||||
setAvailableHeight(Math.max(top, window.innerHeight - bottom));
|
||||
};
|
||||
updateAvailableHeight();
|
||||
window.addEventListener("resize", updateAvailableHeight);
|
||||
window.addEventListener("scroll", updateAvailableHeight, true);
|
||||
return () => {
|
||||
window.removeEventListener("resize", updateAvailableHeight);
|
||||
window.removeEventListener("scroll", updateAvailableHeight, true);
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!showSelectedPrice || !creditsEnabled || !quoteRequest) {
|
||||
setRouteQuote(undefined);
|
||||
@@ -156,7 +172,7 @@ export function ModelPicker({
|
||||
"canvas-model-picker-menu creation-model-picker-menu max-w-[calc(100vw-24px)]",
|
||||
activeGroupKey === null ? "is-brand-list" : "is-model-list",
|
||||
)}
|
||||
style={{ background: theme.node.panel, color: theme.node.text }}
|
||||
style={{ background: theme.node.panel, color: theme.node.text, "--canvas-model-picker-available-height": `${availableHeight}px` } as CSSProperties}
|
||||
role="listbox"
|
||||
aria-label={placeholder}
|
||||
onKeyDown={handleMenuKeyDown}
|
||||
@@ -185,7 +201,7 @@ export function ModelPicker({
|
||||
</button>;
|
||||
})}
|
||||
</div>
|
||||
{optionGroups.filter((group) => group.key === activeGroupKey).map((group) => <section key={group.key} className="canvas-model-picker-group canvas-model-picker-model-pane min-w-0 overflow-hidden">
|
||||
{optionGroups.filter((group) => group.key === activeGroupKey).map((group) => <section key={group.key} className="canvas-model-picker-group canvas-model-picker-model-pane min-w-0">
|
||||
<div className="grid min-w-0 gap-1">
|
||||
{group.models.map((modelGroup) => {
|
||||
const selected = modelGroup.models.includes(current);
|
||||
@@ -243,6 +259,7 @@ export function ModelPicker({
|
||||
onOpenChange={setPickerOpen}
|
||||
trigger="click"
|
||||
placement="bottomLeft"
|
||||
align={{ overflow: { adjustY: true, shiftX: true } }}
|
||||
arrow={false}
|
||||
content={content}
|
||||
classNames={{
|
||||
|
||||
Reference in New Issue
Block a user