修复画布素材标签菜单交互
素材标签菜单拦截滚轮事件,避免画布滚动抢占 点击菜单外空白区域自动关闭素材标签菜单 补充画布素材标签菜单交互测试
This commit is contained in:
@@ -823,6 +823,34 @@ describe('ImageCanvasWorldView', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the layer type menu scrollable and closes it when clicking outside', () => {
|
||||
const layer = createLayer({ assetKind: 'character' });
|
||||
const documentWheel = vi.fn();
|
||||
document.addEventListener('wheel', documentWheel);
|
||||
|
||||
try {
|
||||
renderWorldView({ layers: [layer] });
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: '素材标签:角色' }));
|
||||
|
||||
const menu = screen.getByRole('menu', { name: '选择素材标签' });
|
||||
fireEvent.wheel(menu, { deltaY: 120 });
|
||||
|
||||
expect(documentWheel).not.toHaveBeenCalled();
|
||||
expect(screen.getByRole('menu', { name: '选择素材标签' })).toBeTruthy();
|
||||
|
||||
fireEvent.pointerDown(menu);
|
||||
expect(screen.getByRole('menu', { name: '选择素材标签' })).toBeTruthy();
|
||||
|
||||
fireEvent.pointerDown(document.body);
|
||||
expect(
|
||||
screen.queryByRole('menu', { name: '选择素材标签' }),
|
||||
).toBeNull();
|
||||
} finally {
|
||||
document.removeEventListener('wheel', documentWheel);
|
||||
}
|
||||
});
|
||||
|
||||
it('hides resolution and duration text for focused audio generation frames', () => {
|
||||
const dialog = createGenerationDialog({
|
||||
id: 'dialog-audio',
|
||||
|
||||
@@ -651,6 +651,8 @@ export function ImageCanvasWorldView({
|
||||
const [openLayerKindMenuId, setOpenLayerKindMenuId] = useState<string | null>(
|
||||
null,
|
||||
);
|
||||
const openLayerKindTriggerRef = useRef<HTMLSpanElement | null>(null);
|
||||
const openLayerKindMenuRef = useRef<HTMLDivElement | null>(null);
|
||||
const visibleLayers = useMemo(
|
||||
() =>
|
||||
layers
|
||||
@@ -660,6 +662,34 @@ export function ImageCanvasWorldView({
|
||||
[layers],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!openLayerKindMenuId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const closeKindMenuWhenClickingOutside = (event: PointerEvent) => {
|
||||
const target = event.target;
|
||||
if (!(target instanceof Node)) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
openLayerKindMenuRef.current?.contains(target) ||
|
||||
openLayerKindTriggerRef.current?.contains(target)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
setOpenLayerKindMenuId(null);
|
||||
};
|
||||
|
||||
document.addEventListener('pointerdown', closeKindMenuWhenClickingOutside);
|
||||
return () => {
|
||||
document.removeEventListener(
|
||||
'pointerdown',
|
||||
closeKindMenuWhenClickingOutside,
|
||||
);
|
||||
};
|
||||
}, [openLayerKindMenuId]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="image-canvas-editor__world"
|
||||
@@ -755,6 +785,11 @@ export function ImageCanvasWorldView({
|
||||
)}
|
||||
{kindLabel ? (
|
||||
<span
|
||||
ref={
|
||||
openLayerKindMenuId === layer.id
|
||||
? openLayerKindTriggerRef
|
||||
: undefined
|
||||
}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label={`素材标签:${kindLabel}`}
|
||||
@@ -812,6 +847,7 @@ export function ImageCanvasWorldView({
|
||||
</LayerElement>
|
||||
{openLayerKindMenuId === layer.id ? (
|
||||
<div
|
||||
ref={openLayerKindMenuRef}
|
||||
className="image-canvas-editor__kind-menu-anchor"
|
||||
style={{
|
||||
left: layer.x + layer.width,
|
||||
@@ -824,6 +860,8 @@ export function ImageCanvasWorldView({
|
||||
label="选择素材标签"
|
||||
placement="bottom-end"
|
||||
className="image-canvas-editor__kind-menu"
|
||||
onWheelCapture={(event) => event.stopPropagation()}
|
||||
onWheel={(event) => event.stopPropagation()}
|
||||
>
|
||||
{CANVAS_ASSET_KIND_TAG_OPTIONS.map((option) => (
|
||||
<PlatformFloatingMenuItem
|
||||
|
||||
Reference in New Issue
Block a user