Files
archived-linsa/web/shared/editor/extensions/file-handler/index.ts
Aslam a440828f8c chore: Enhancement + New Feature (#185)
* wip

* wip page

* chore: style

* wip pages

* wip pages

* chore: toggle

* chore: link

* feat: topic search

* chore: page section

* refactor: apply tailwind class ordering

* fix: handle loggedIn user for guest route

* feat: folder & image schema

* chore: move utils to shared

* refactor: tailwind class ordering

* feat: img ext for editor

* refactor: remove qa

* fix: tanstack start

* fix: wrong import

* chore: use toast

* chore: schema
2024-10-18 21:18:20 +07:00

117 lines
2.7 KiB
TypeScript

import { type Editor, Extension } from "@tiptap/core"
import { Plugin, PluginKey } from "@tiptap/pm/state"
import type { FileError, FileValidationOptions } from "@shared/editor/lib/utils"
import { filterFiles } from "@shared/editor/lib/utils"
type FileHandlePluginOptions = {
key?: PluginKey
editor: Editor
onPaste?: (editor: Editor, files: File[], pasteContent?: string) => void
onDrop?: (editor: Editor, files: File[], pos: number) => void
onValidationError?: (errors: FileError[]) => void
} & FileValidationOptions
const FileHandlePlugin = (options: FileHandlePluginOptions) => {
const {
key,
editor,
onPaste,
onDrop,
onValidationError,
allowedMimeTypes,
maxFileSize,
} = options
return new Plugin({
key: key || new PluginKey("fileHandler"),
props: {
handleDrop(view, event) {
event.preventDefault()
event.stopPropagation()
const { dataTransfer } = event
if (!dataTransfer?.files.length) {
return
}
const pos = view.posAtCoords({
left: event.clientX,
top: event.clientY,
})
const [validFiles, errors] = filterFiles(
Array.from(dataTransfer.files),
{
allowedMimeTypes,
maxFileSize,
allowBase64: options.allowBase64,
},
)
if (errors.length > 0 && onValidationError) {
onValidationError(errors)
}
if (validFiles.length > 0 && onDrop) {
onDrop(editor, validFiles, pos?.pos ?? 0)
}
},
handlePaste(_, event) {
event.preventDefault()
event.stopPropagation()
const { clipboardData } = event
if (!clipboardData?.files.length) {
return
}
const [validFiles, errors] = filterFiles(
Array.from(clipboardData.files),
{
allowedMimeTypes,
maxFileSize,
allowBase64: options.allowBase64,
},
)
const html = clipboardData.getData("text/html")
if (errors.length > 0 && onValidationError) {
onValidationError(errors)
}
if (validFiles.length > 0 && onPaste) {
onPaste(editor, validFiles, html)
}
},
},
})
}
export const FileHandler = Extension.create<
Omit<FileHandlePluginOptions, "key" | "editor">
>({
name: "fileHandler",
addOptions() {
return {
allowBase64: false,
allowedMimeTypes: [],
maxFileSize: 0,
}
},
addProseMirrorPlugins() {
return [
FileHandlePlugin({
key: new PluginKey(this.name),
editor: this.editor,
...this.options,
}),
]
},
})