Files

70 lines
2.6 KiB
Plaintext

---
import type { HTMLTag } from 'astro/types'
import CaptureScript from '../components/CaptureScript.astro'
interface Props {
id: string
multiple?: boolean
custom?: boolean
text?: string
description?: string
/** heading level for the custom message title; match it to the surrounding context */
titleAs?: HTMLTag
}
const { id, multiple, custom, text, description, titleAs: Title = 'h3' } = Astro.props
const label = 'Upload file'
const dropzoneId = `dropzone-${id}`
const dropzoneSelector = `#dropzone-${id}`
const fileInputId = `${dropzoneId}-file`
---
<form class="dropzone" id={dropzoneId} action="./" autocomplete="off" novalidate>
<div class="fallback">
<label class="visually-hidden" for={fileInputId}>{label}</label>
<input id={fileInputId} name="file" type="file" multiple={multiple ? '' : undefined} />
</div>
{
custom && (
<div class="dz-message">
<Title>{text}</Title>
<span>{description}</span>
</div>
)
}
</form>
<CaptureScript>
<!-- BEGIN DROPZONE -->
<script is:inline define:vars={{ dropzoneId, dropzoneSelector }}>
window.tabler_dropzone ??= {}
function initDropzone() {
const dropzoneEl = document.querySelector(dropzoneSelector)
const instance = new Dropzone(dropzoneSelector)
window.tabler_dropzone[dropzoneId] = instance
// Dropzone.js hides the .fallback label/input once it initializes, which is why
// role="button" + tabindex only get added here rather than in the static markup —
// adding them upfront would nest one focusable control (the fallback input) inside
// another (this "button"). Dropzone.js is also click/drag-only by default: it binds
// a click handler on the whole element but never wires a keyboard equivalent, so
// forward Enter/Space to a programmatic click on Dropzone's own hidden file input.
// Note: that input is appended to <body> (hiddenInputContainer default), not inside
// dropzoneEl, so it must be reached via the instance rather than a DOM query here.
dropzoneEl?.setAttribute('role', 'button')
dropzoneEl?.setAttribute('tabindex', '0')
dropzoneEl?.setAttribute('aria-label', 'Click or drag files to upload')
dropzoneEl?.addEventListener('keydown', (event) => {
if (event.target !== dropzoneEl) return
if (event.key !== 'Enter' && event.key !== ' ' && event.key !== 'Spacebar') return
event.preventDefault()
instance.hiddenFileInput?.click()
})
}
document.readyState !== 'loading' ? initDropzone() : document.addEventListener('DOMContentLoaded', initDropzone, { once: true })
</script>
<!-- END DROPZONE -->
</CaptureScript>