Files
MiragenFlow/web/src/app/(user)/canvas/components/canvas-size-picker.tsx
T
HouYunFei e319481976 style(code): 格式化代码缩进和布局样式
- 统一调整 admin.ts 文件中的接口定义缩进格式
- 优化 animated-theme-toggler.tsx 组件的代码结构和缩进
- 规范 app-config-modal.tsx 中 JSX 元素的嵌套格式
- 整理 app-providers.tsx 中的组件层级缩进
- 标准化 app-theme.ts 中的对象属性缩进格式
2026-05-22 23:19:25 +08:00

68 lines
2.4 KiB
TypeScript

"use client";
import { useEffect, useRef, useState } from "react";
import { Select } from "antd";
import { cn } from "@/lib/utils";
const sizeOptions = ["auto", "1:1", "3:2", "2:3", "4:3", "3:4", "16:9", "9:16"];
type CanvasSizePickerProps = {
value: string;
className?: string;
onChange: (value: string) => void;
};
export function CanvasSizePicker({ value, className, onChange }: CanvasSizePickerProps) {
const rootRef = useRef<HTMLDivElement>(null);
const [open, setOpen] = useState(false);
const [search, setSearch] = useState("");
const extraOptions = [value, search.trim()].filter((item) => item && !sizeOptions.includes(item));
const options = [...sizeOptions, ...Array.from(new Set(extraOptions))].map((size) => ({ value: size, label: size }));
const selectSize = (next: string) => {
onChange(next.trim());
setSearch("");
setOpen(false);
};
useEffect(() => {
if (!open) return;
const close = (event: PointerEvent) => {
const target = event.target instanceof Element ? event.target : null;
if (target && (rootRef.current?.contains(target) || target.closest(".ant-select-dropdown"))) return;
setOpen(false);
};
window.addEventListener("pointerdown", close, true);
return () => window.removeEventListener("pointerdown", close, true);
}, [open]);
return (
<div ref={rootRef} className={className}>
<Select
showSearch
open={open}
className={cn("canvas-compact-control canvas-control-select h-full w-full")}
value={value || undefined}
searchValue={search}
placeholder="比例"
options={options}
popupMatchSelectWidth={false}
popupRender={(menu) => (
<div onMouseDown={(event) => event.stopPropagation()} onPointerDown={(event) => event.stopPropagation()}>
{menu}
</div>
)}
onOpenChange={setOpen}
onSearch={setSearch}
onChange={selectSize}
onBlur={() => {
if (search.trim()) selectSize(search);
}}
onInputKeyDown={(event) => {
if (event.key === "Enter" && search.trim()) selectSize(search);
}}
/>
</div>
);
}