Skip to content

Drop Zone

Create drop zone area

๐ŸŽฌ Usage

<script>
    import {dropzone} from "@sveu/actions"

    function hover(data){
        ...
    }

    function on_file_drop(data){
        ...
    }

</script>

<div use:dropzone on:hover="{hover}" on:files="{on_file_drop}">
    Drop files here
</div>

๐Ÿ‘ฉโ€๐Ÿ’ปAPI

๐Ÿ‘ป Arguments

Name Description Type Required
fn A function to be called when the dropzone is hovered or files are dropped. (data: DropzoneData) => void No

๐Ÿ™ˆ Events

Name Description Type Return
hover An event will fire once a file is over the dropzone. CustomEvent<boolean A custom event with detail as boolean
files An event will fire once a file is dropped. CustomEvent<File[]> A custom event with detail as array of files
Note

If you use typescript, you need to add ./node_modules/@sveu/actions/events.d.ts to your tsconfig.json file.

    {
        ...

        "include": [
            ...
            "./node_modules/@sveu/actions/events.d.ts"
        ]
        ...

    }

๐Ÿงช Playground

Source Code ๐Ÿ‘€

Source Code
import { on } from "@sveu/browser"

import type { DropzoneData } from "../utils"

/**
 * Create a dropzone area.
 *
 * @param element - The element to make as dropzone.
 *
 * @param fn - A function to be called when the dropzone is hovered or files are dropped.
 * - `over_dropzone` - Whether the dropzone is hovered. Type: `boolean`.
 * - `files` - The files dropped. Type: `File[]` or `undefined`.
 */
export function dropzone(
    element: HTMLElement,
    fn?: (data: DropzoneData) => void
) {
    let counter = 0

    const dragenter_cleanup = on<DragEvent>(element, "dragenter", (event) => {
        event.preventDefault()

        counter += 1

        if (fn) fn({ over_dropzone: true })

        element.dispatchEvent(new CustomEvent("hover", { detail: true }))
    })

    const dragover_cleanup = on<DragEvent>(element, "dragover", (event) => {
        event.preventDefault()
    })

    const dragleave_cleanup = on<DragEvent>(element, "dragleave", (event) => {
        event.preventDefault()

        counter -= 1

        if (counter === 0) {
            if (fn) fn({ over_dropzone: false })

            element.dispatchEvent(new CustomEvent("hover", { detail: false }))
        }
    })

    const drop_cleanup = on<DragEvent>(element, "drop", (event) => {
        event.preventDefault()

        counter = 0

        const files = Array.from(event.dataTransfer?.files ?? [])

        if (fn) fn({ over_dropzone: false, files: files })

        element.dispatchEvent(new CustomEvent("hover", { detail: false }))

        element.dispatchEvent(new CustomEvent("files", { detail: files }))
    })

    return {
        destroy() {
            dragenter_cleanup()
            dragover_cleanup()
            dragleave_cleanup()
            drop_cleanup()
        },
    }
}

Last update: 2023-03-08