Files
Genarrative/src/components/image-editor/ImageCanvasEditorShellView.tsx
T
kdletters 73121f18ba 修复图片信息文本复制
移除图片信息弹窗的整段复制按钮

保留选中文本时的浏览器原生 Ctrl+C

放行图片信息弹窗内的浏览器右键菜单

补充文本复制与右键菜单回归测试
2026-06-28 17:43:52 +08:00

93 lines
2.6 KiB
TypeScript

import type {
ChangeEventHandler,
ComponentProps,
RefObject,
} from 'react';
import { ImageCanvasMetadataModalView } from './ImageCanvasMetadataModalView';
import { ImageCanvasSidebarView } from './ImageCanvasSidebarView';
import { ImageCanvasStageView } from './ImageCanvasStageView';
import { ImageCanvasTopbarView } from './ImageCanvasTopbarView';
type AssetDragPreview = {
x: number;
y: number;
label: string;
};
type ImageCanvasEditorShellViewProps = {
editorRootRef: RefObject<HTMLElement | null>;
uploadInputRef: RefObject<HTMLInputElement | null>;
uploadAccept?: string;
onUploadInputChange: ChangeEventHandler<HTMLInputElement>;
assetDragPreview: AssetDragPreview | null;
sidebarProps: ComponentProps<typeof ImageCanvasSidebarView>;
topbarProps: ComponentProps<typeof ImageCanvasTopbarView>;
stageProps: ComponentProps<typeof ImageCanvasStageView>;
metadataProps: ComponentProps<typeof ImageCanvasMetadataModalView>;
};
export function ImageCanvasEditorShellView({
editorRootRef,
uploadInputRef,
uploadAccept = 'image/*',
onUploadInputChange,
assetDragPreview,
sidebarProps,
topbarProps,
stageProps,
metadataProps,
}: ImageCanvasEditorShellViewProps) {
const uploadInputLabel =
uploadAccept.includes('video') || uploadAccept.includes('audio')
? '上传媒体文件'
: '上传图片文件';
return (
<section
ref={editorRootRef}
className="image-canvas-editor"
aria-label="图片画布编辑器"
onContextMenu={(event) => {
if (
event.target instanceof Element &&
event.target.closest('.image-canvas-editor__metadata-dialog')
) {
return;
}
event.preventDefault();
}}
>
<input
ref={uploadInputRef}
type="file"
accept={uploadAccept}
multiple
aria-label={uploadInputLabel}
hidden
onChange={onUploadInputChange}
/>
{assetDragPreview ? (
<div
className="image-canvas-editor__asset-drag-preview"
style={{
left: Number.isFinite(assetDragPreview.x) ? assetDragPreview.x : 0,
top: Number.isFinite(assetDragPreview.y) ? assetDragPreview.y : 0,
}}
aria-hidden="true"
>
{assetDragPreview.label}
</div>
) : null}
<ImageCanvasSidebarView {...sidebarProps} />
<div className="image-canvas-editor__main">
<ImageCanvasTopbarView {...topbarProps} />
<ImageCanvasStageView {...stageProps} />
</div>
<ImageCanvasMetadataModalView {...metadataProps} />
</section>
);
}