81 lines
2.2 KiB
TypeScript
81 lines
2.2 KiB
TypeScript
import { useCallback } from 'react'
|
|
|
|
interface UsePasteHandlerProps {
|
|
readOnly: boolean
|
|
handleAddImageFromFile: (file: File) => Promise<void>
|
|
handleAddText: (options?: {
|
|
content?: string
|
|
style?: Record<string, any>
|
|
}) => void
|
|
}
|
|
|
|
export function usePasteHandler({
|
|
readOnly,
|
|
handleAddImageFromFile,
|
|
handleAddText,
|
|
}: UsePasteHandlerProps) {
|
|
const handlePaste = useCallback(
|
|
async (e: ClipboardEvent) => {
|
|
if (readOnly) return
|
|
|
|
// 1. 尝试解析图片
|
|
const items = e.clipboardData?.items
|
|
if (items) {
|
|
for (let i = 0; i < items.length; i++) {
|
|
const item = items[i]
|
|
if (item.kind === 'file' && item.type.startsWith('image/')) {
|
|
const file = item.getAsFile()
|
|
if (file) {
|
|
e.preventDefault()
|
|
await handleAddImageFromFile(file)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. 尝试解析带有样式的文本元素或纯文本
|
|
const textHtml = e.clipboardData?.getData('text/html')
|
|
const textPlain = e.clipboardData?.getData('text/plain')
|
|
|
|
if (textHtml) {
|
|
const match = textHtml.match(/<!--DOMINO_TEXT_ELEMENT:(.*?)-->/)
|
|
if (match) {
|
|
try {
|
|
const data = JSON.parse(match[1])
|
|
if (data.type === 'domino-text-element') {
|
|
e.preventDefault()
|
|
handleAddText({
|
|
content: data.content,
|
|
style: {
|
|
fontSize: data.fontSize,
|
|
fontWeight: data.fontWeight,
|
|
color: data.color,
|
|
fontFamily: data.fontFamily,
|
|
lineHeight: data.lineHeight,
|
|
textAlign: data.textAlign,
|
|
fontStyle: data.fontStyle,
|
|
width: data.width,
|
|
height: data.height,
|
|
},
|
|
})
|
|
return
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to parse pasted text element', err)
|
|
}
|
|
}
|
|
}
|
|
|
|
if (textPlain && textPlain.trim()) {
|
|
e.preventDefault()
|
|
handleAddText({ content: textPlain })
|
|
}
|
|
},
|
|
[readOnly, handleAddImageFromFile, handleAddText],
|
|
)
|
|
|
|
return handlePaste
|
|
}
|
|
|