64 lines
2.1 KiB
TypeScript
64 lines
2.1 KiB
TypeScript
"use client"
|
|
|
|
import { Extension } from "@tiptap/core"
|
|
import { Plugin, PluginKey } from "@tiptap/pm/state"
|
|
import { buildImageInsertGraphicAttrs } from "@/lib/drive/extensions/docs-graphic"
|
|
|
|
function readImageFile(file: File): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader()
|
|
reader.onload = () => resolve(reader.result as string)
|
|
reader.onerror = reject
|
|
reader.readAsDataURL(file)
|
|
})
|
|
}
|
|
|
|
export const DocsGraphicPasteDrop = Extension.create({
|
|
name: "docsGraphicPasteDrop",
|
|
|
|
addProseMirrorPlugins() {
|
|
const editor = this.editor
|
|
return [
|
|
new Plugin({
|
|
key: new PluginKey("docsGraphicPasteDrop"),
|
|
props: {
|
|
handlePaste(view, event) {
|
|
const items = event.clipboardData?.items
|
|
if (!items) return false
|
|
for (const item of items) {
|
|
if (!item.type.startsWith("image/")) continue
|
|
const file = item.getAsFile()
|
|
if (!file) continue
|
|
event.preventDefault()
|
|
void readImageFile(file).then(async (src) => {
|
|
const attrs = await buildImageInsertGraphicAttrs({ src })
|
|
editor.chain().focus().insertDocsGraphic(attrs).run()
|
|
})
|
|
return true
|
|
}
|
|
return false
|
|
},
|
|
handleDrop(view, event) {
|
|
const files = event.dataTransfer?.files
|
|
if (!files?.length) return false
|
|
const file = [...files].find((f) => f.type.startsWith("image/"))
|
|
if (!file) return false
|
|
event.preventDefault()
|
|
void readImageFile(file).then(async (src) => {
|
|
const attrs = await buildImageInsertGraphicAttrs({ src })
|
|
const coords = view.posAtCoords({
|
|
left: event.clientX,
|
|
top: event.clientY,
|
|
})
|
|
const chain = editor.chain().focus()
|
|
if (coords?.pos != null) chain.setTextSelection(coords.pos)
|
|
chain.insertDocsGraphic(attrs).run()
|
|
})
|
|
return true
|
|
},
|
|
},
|
|
}),
|
|
]
|
|
},
|
|
})
|