ultisuite-client/lib/drive/extensions/docs-graphic-paste-drop.ts
R3D347HR4Y 2a7c153748
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
wrap page
2026-06-10 12:48:27 +02:00

72 lines
2.2 KiB
TypeScript

"use client"
import { Extension } from "@tiptap/core"
import { Plugin, PluginKey } from "@tiptap/pm/state"
import { buildInsertGraphicAttrs } 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((src) => {
editor
.chain()
.focus()
.insertDocsGraphic(
buildInsertGraphicAttrs("image", { src, width: 280, height: 180 })
)
.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((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(
buildInsertGraphicAttrs("image", { src, width: 280, height: 180 })
)
.run()
})
return true
},
},
}),
]
},
})