import { ClipboardList, ImagePlus } from 'lucide-react'; import { type CSSProperties, type Dispatch, type ReactNode, type RefObject, type SetStateAction, } from 'react'; import { PlatformFloatingMenu, PlatformFloatingMenuItem, } from '../common/PlatformFloatingMenu'; import { PlatformStatusMessage } from '../common/PlatformStatusMessage'; import { PlatformTextField } from '../common/PlatformTextField'; import { ImageCanvasReferenceSlot } from './ImageCanvasReferenceSlot'; import type { CharacterReferenceImage, GenerateDialogState, SpecGenerationType, UploadTarget, } from './ImageCanvasEditorTypes'; import { ImageCanvasGenerationImageOptionsView } from './ImageCanvasGenerationImageOptionsView'; import { calculateEditorImageGenerationPrice } from './ImageCanvasGenerationModel'; import { useImageCanvasFloatingOptionDismiss } from './useImageCanvasFloatingOptionDismiss'; type ImageCanvasCharacterGenerationComposerViewProps = { dialog: GenerateDialogState; style: CSSProperties; characterSpecButtonRef: RefObject; characterReferenceButtonRef: RefObject; isCharacterSpecMenuOpen: boolean; isCharacterReferenceMenuOpen: boolean; setGenerateDialog: Dispatch>; setIsCharacterSpecMenuOpen: Dispatch>; setIsCharacterReferenceMenuOpen: Dispatch>; setIsPickingCharacterSpecFromCanvas: Dispatch>; setIsPickingCharacterReferenceFromCanvas: Dispatch>; renderEditorPortal: (node: ReactNode) => ReactNode; buildPortalMenuStyle: ( anchor: HTMLElement | null, placement: 'above' | 'below', ) => CSSProperties; onOpenSpecDialog: (specType: SpecGenerationType) => void; onRequestUpload: (target: UploadTarget) => void; onRememberImageModel: (model: string) => void; onSubmit: (dialog: GenerateDialogState) => void; }; function resetFailedDialogStatus(dialog: GenerateDialogState) { return { ...dialog, status: dialog.status === 'failed' ? 'idle' : dialog.status, errorMessage: dialog.status === 'failed' ? undefined : dialog.errorMessage, }; } function ReferenceChip({ reference, index, onRemove, }: { reference: CharacterReferenceImage; index: number; onRemove: () => void; }) { const label = reference.label || `参考图${index + 1}`; return (