From b2122481ffc134ccfdde1ac9b0b2f3e84e38fc05 Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 13 Jun 2026 22:23:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8A=BD=E5=8F=96=E5=9B=BE=E7=89=87=E7=94=BB?= =?UTF-8?q?=E5=B8=83=E9=80=9A=E7=94=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增图片画布图标按钮和侧栏媒体项 primitives 让素材文件夹按钮和生成关闭按钮复用通用图标按钮 移除主画布视图内重复的按钮与列表项实现 --- .../ImageCanvasEditorPrimitives.tsx | 96 +++++++++++++ .../image-editor/ImageCanvasEditorView.tsx | 136 +++--------------- 2 files changed, 114 insertions(+), 118 deletions(-) create mode 100644 src/components/image-editor/ImageCanvasEditorPrimitives.tsx diff --git a/src/components/image-editor/ImageCanvasEditorPrimitives.tsx b/src/components/image-editor/ImageCanvasEditorPrimitives.tsx new file mode 100644 index 00000000..c84fd5a8 --- /dev/null +++ b/src/components/image-editor/ImageCanvasEditorPrimitives.tsx @@ -0,0 +1,96 @@ +import type { ComponentType, ReactNode } from 'react'; + +type IconComponent = ComponentType<{ className?: string }>; + +export type EditorIconButtonProps = { + label: string; + title?: string; + icon: IconComponent; + className?: string; + type?: 'button' | 'submit'; + disabled?: boolean; + pressed?: boolean; + expanded?: boolean; + onClick?: () => void; +}; + +export function EditorIconButton({ + label, + title = label, + icon: Icon, + className, + type = 'button', + disabled, + pressed, + expanded, + onClick, +}: EditorIconButtonProps) { + return ( + + ); +} + +export type SidebarMediaItemProps = { + title: string; + detail: string; + imageSrc: string; + imageAlt: string; + selected?: boolean; + primaryLabel: string; + onPrimaryClick: () => void; + thumbnailClassName: string; + metaClassName: string; + rowClassName: string; + primaryClassName?: string; + actions?: ReactNode; + titleNode?: ReactNode; +}; + +export function SidebarMediaItem({ + title, + detail, + imageSrc, + imageAlt, + selected = false, + primaryLabel, + onPrimaryClick, + thumbnailClassName, + metaClassName, + rowClassName, + primaryClassName, + actions, + titleNode, +}: SidebarMediaItemProps) { + return ( +
+ +
+ {titleNode ?? {title}} + {detail} +
+ {actions} +
+ ); +} diff --git a/src/components/image-editor/ImageCanvasEditorView.tsx b/src/components/image-editor/ImageCanvasEditorView.tsx index 4be77503..4f01071c 100644 --- a/src/components/image-editor/ImageCanvasEditorView.tsx +++ b/src/components/image-editor/ImageCanvasEditorView.tsx @@ -26,10 +26,8 @@ import { X, } from 'lucide-react'; import { - type ComponentType, type KeyboardEvent as ReactKeyboardEvent, type PointerEvent as ReactPointerEvent, - type ReactNode, useCallback, useEffect, useMemo, @@ -48,6 +46,10 @@ import { saveEditorProjectLayout, } from '../../services/image-editor/editorProjectClient'; import { ApiClientError } from '../../services/apiClient'; +import { + EditorIconButton, + SidebarMediaItem, +} from './ImageCanvasEditorPrimitives'; type EditorAsset = { id: string; @@ -141,34 +143,6 @@ type SnapCandidate = { distance: number; }; -type EditorIconButtonProps = { - label: string; - title?: string; - icon: ComponentType<{ className?: string }>; - className?: string; - type?: 'button' | 'submit'; - disabled?: boolean; - pressed?: boolean; - expanded?: boolean; - onClick?: () => void; -}; - -type SidebarMediaItemProps = { - title: string; - detail: string; - imageSrc: string; - imageAlt: string; - selected?: boolean; - primaryLabel: string; - onPrimaryClick: () => void; - thumbnailClassName: string; - metaClassName: string; - rowClassName: string; - primaryClassName?: string; - actions?: ReactNode; - titleNode?: ReactNode; -}; - type DragState = | { kind: 'pan'; @@ -304,71 +278,6 @@ const CANVAS_BACKGROUND_OPTIONS = [ { label: '冷蓝', value: '#eef6ff' }, ]; -function EditorIconButton({ - label, - title = label, - icon: Icon, - className, - type = 'button', - disabled, - pressed, - expanded, - onClick, -}: EditorIconButtonProps) { - return ( - - ); -} - -function SidebarMediaItem({ - title, - detail, - imageSrc, - imageAlt, - selected = false, - primaryLabel, - onPrimaryClick, - thumbnailClassName, - metaClassName, - rowClassName, - primaryClassName, - actions, - titleNode, -}: SidebarMediaItemProps) { - return ( -
- -
- {titleNode ?? {title}} - {detail} -
- {actions} -
- ); -} - function clamp(value: number, min: number, max: number) { return Math.min(max, Math.max(min, value)); } @@ -1604,32 +1513,25 @@ export function ImageCanvasEditorView() { aria-label={folder.label} >
- + /> {folder.label} {folder.assets.length} - + />
) : null} - + /> ) : null}