Fix custom grid split menu
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-19 11:03:12 +08:00
parent 7a1a478eaf
commit 7ee5dbc264

View File

@ -384,6 +384,7 @@ const OFFICIAL_TEXT_RESOURCE_WIDTH = 560;
const OFFICIAL_IMAGE_TOOLBAR_SCALE = 0.7;
const OFFICIAL_COMPOSER_SCALE = 0.546;
const OFFICIAL_ZOOM_DOCK_SCALE = 0.65;
const OFFICIAL_DROPDOWN_SCALE = 0.7;
const OFFICIAL_NINE_GRID_WIDTH = 930;
const OFFICIAL_NINE_GRID_HEIGHT = 520;
const PROMPT_COMPOSER_BASE_WIDTH = 895;
@ -1139,6 +1140,12 @@ function preventNativeImageDrag(event: ReactDragEvent<HTMLImageElement>) {
function normalizeGridOption(option?: string) {
const text = String(option || "").trim();
const explicitGrid = text.match(/(\d+)\s*[x×]\s*(\d+)/i);
if (explicitGrid) {
const columns = Math.max(1, Math.min(5, Number.parseInt(explicitGrid[1] || "3", 10) || 3));
const rows = Math.max(1, Math.min(5, Number.parseInt(explicitGrid[2] || "3", 10) || 3));
return { columns, rows, tileCount: columns * rows };
}
const tileCount =
/25\s*宫格|5\s*[x×]\s*5|25/.test(text)
? 25
@ -5357,10 +5364,11 @@ function SceneToolbarPopover({
orbit: -245,
panorama: -360,
};
const popoverScale = (anchor ? OFFICIAL_IMAGE_TOOLBAR_SCALE : 1) * OFFICIAL_DROPDOWN_SCALE;
const officialPopoverStyle = {
left: anchor ? anchor.centerX + popoverOffset[menu] : `calc(50% + ${popoverOffset[menu]}px)`,
top: anchor ? anchor.topY - (24 * anchor.zoom + 10) + 8 : 168,
transform: `translateX(-50%) scale(${anchor ? OFFICIAL_IMAGE_TOOLBAR_SCALE : 1})`,
transform: `translateX(-50%) scale(${popoverScale})`,
transformOrigin: "top center",
};
const popoverSurfaceStyle = {
@ -5482,7 +5490,8 @@ function SceneToolbarPopover({
if (menu === "crop") {
return (
<div
className="pointer-events-auto absolute z-40 flex w-[300px] -translate-x-1/2 flex-col p-3 font-sans"
className="pointer-events-auto absolute z-40 flex w-[300px] -translate-x-1/2 flex-col overflow-visible p-3 font-sans"
onMouseLeave={() => setCustomGridOpen(false)}
role="menu"
style={{ ...officialPopoverStyle, ...popoverSurfaceStyle }}
>
@ -5501,7 +5510,7 @@ function SceneToolbarPopover({
</button>
))}
<div className="mx-4 my-2 h-px bg-white/12" />
<div onMouseEnter={() => setCustomGridOpen(true)} onMouseLeave={() => setCustomGridOpen(false)}>
<div onMouseEnter={() => setCustomGridOpen(true)}>
<button
className={cn(
"flex h-[70px] w-full cursor-pointer items-center justify-between rounded-[10px] px-5 text-left transition-colors duration-200 hover:bg-white/8 active:bg-white/12",
@ -5514,17 +5523,16 @@ function SceneToolbarPopover({
<span className="min-w-0 truncate text-[25px] font-normal leading-snug text-white/86">自定义</span>
<ChevronDown className="h-5 w-5 shrink-0 -rotate-90 text-white/60" />
</button>
{customGridOpen ? (
<div
className="absolute left-full top-0 ml-1.5 p-1.5"
onMouseEnter={() => setCustomGridOpen(true)}
onMouseLeave={() => setCustomGridOpen(false)}
style={popoverSurfaceStyle}
>
<CustomGridPicker onSelect={(rows, columns) => onSelect?.(`${rows} x ${columns}`)} />
</div>
) : null}
</div>
{customGridOpen ? (
<div
className="absolute left-[calc(100%+8px)] top-0 w-[420px] p-4"
onMouseEnter={() => setCustomGridOpen(true)}
style={popoverSurfaceStyle}
>
<CustomGridPicker onSelect={(rows, columns) => onSelect?.(`${columns} x ${rows}`)} />
</div>
) : null}
</div>
);
}
@ -5609,17 +5617,17 @@ function ImageToolMenuGlyph({ tool }: { tool: string }) {
}
function CustomGridPicker({ onSelect }: { onSelect: (rows: number, columns: number) => void }) {
const [hovered, setHovered] = useState({ columns: 0, rows: 0 });
const [hovered, setHovered] = useState({ columns: 3, rows: 3 });
return (
<div className="flex flex-col gap-2.5 p-2">
<div className="flex w-full flex-col gap-5">
<div className="flex items-center justify-between px-0.5">
<span className="text-[13px] text-white/52">自定义宫格</span>
<span className="text-[13px] font-medium text-white/86">
{hovered.rows > 0 && hovered.columns > 0 ? `${hovered.columns} x ${hovered.rows}` : ""}
<span className="text-[25px] font-normal leading-none text-white/52">自定义宫格</span>
<span className="text-[25px] font-semibold leading-none text-white/86">
{hovered.columns} × {hovered.rows}
</span>
</div>
<div className="grid grid-cols-5 gap-1" onMouseLeave={() => setHovered({ columns: 0, rows: 0 })}>
<div className="grid grid-cols-5 gap-3" onMouseLeave={() => setHovered({ columns: 3, rows: 3 })}>
{Array.from({ length: 25 }).map((_, index) => {
const rows = Math.floor(index / 5) + 1;
const columns = (index % 5) + 1;
@ -5627,8 +5635,8 @@ function CustomGridPicker({ onSelect }: { onSelect: (rows: number, columns: numb
return (
<button
className={cn(
"h-8 w-8 rounded border transition-colors duration-75",
active ? "border-blue-400/60 bg-blue-500/40" : "border-white/12 bg-white/8 hover:bg-white/12"
"h-[54px] w-[54px] rounded-[8px] border transition-colors duration-75",
active ? "border-[#2f8dff] bg-[#315b91]" : "border-white/0 bg-white/14 hover:bg-white/18"
)}
key={index}
onClick={() => onSelect(rows, columns)}