UNPKG

preline

Version:

Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.

365 lines (273 loc) 14.3 kB
# File Upload Tailwind CSS File Upload plugin using Dropzone library to enable drag-and-drop functionality, previews, and progress bars. [![npm](https://img.shields.io/badge/npm-v4.2.0-blue)](https://www.npmjs.com/package/@preline/file-upload) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Demo](https://img.shields.io/badge/demo-online-brightgreen)](https://preline.co/plugins/file-upload.html) ## Contents - [Overview](#overview) - [Installation](#installation) - [Basic usage](#basic-usage) - [Configuration Options](#configuration-options) - [JavaScript API](#javascript-api) - [Events](#events) - [Common Patterns](#common-patterns) - [License](#license) ## Overview The File Upload component provides a drag-and-drop file upload interface with preview functionality, progress tracking, and integration with Dropzone.js. It supports multiple file uploads, file type validation, and customizable preview templates. **Key Features:** - Drag-and-drop file upload - File previews with thumbnails - Upload progress tracking - Multiple file support - File type and extension validation - Integration with Dropzone.js - Programmatic control via JavaScript API - Event system for upload tracking ## Installation To get started, install File Upload plugin via npm, else you can skip this step if you are already using Preline UI as a package. ```bash npm i lodash dropzone @preline/file-upload ``` ### CSS Use [`@source`](https://tailwindcss.com/docs/functions-and-directives#source-directive) to register the plugin's JavaScript path for Tailwind CSS scanning, then [`@import`](https://tailwindcss.com/docs/functions-and-directives#import-directive) the plugin's CSS files into your Tailwind CSS file. ```css @import "tailwindcss"; /* @preline/file-upload */ @source "../node_modules/@preline/file-upload/*.js"; @import "./node_modules/@preline/file-upload/variants.css"; @import "./node_modules/@preline/file-upload/theme.css"; ``` ### JavaScript Include the JavaScript that powers the interactive elements near the end of your `</body>` tag: ```html <script src="./node_modules/lodash/lodash.min.js"></script> <script src="./node_modules/dropzone/dist/dropzone-min.js"></script> <script src="./node_modules/@preline/file-upload/index.js"></script> ``` ### Manual Initialization Use the `non-auto` entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly. ```html <script src="./node_modules/lodash/lodash.min.js"></script> <script src="./node_modules/dropzone/dist/dropzone-min.js"></script> <script type="module"> import HSFileUpload from "@preline/file-upload/non-auto.mjs"; new HSFileUpload(document.querySelector("#file-upload")); </script> ``` ### Via Bundler When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module. `Dropzone` and `_` (Lodash) are referenced as globals, so expose them on `window` before importing the plugin. `@preline/file-upload` is the auto-init entry: it scans the DOM and initializes matching elements automatically. ```js import _ from "lodash"; window._ = _; import Dropzone from "dropzone"; window.Dropzone = Dropzone; import "@preline/file-upload"; ``` `@preline/file-upload/non-auto` is the manual entry: use it when you want explicit control over when initialization happens, either via `autoInit()` or by creating a specific instance yourself. ```js import _ from "lodash"; window._ = _; import Dropzone from "dropzone"; window.Dropzone = Dropzone; import HSFileUpload from "@preline/file-upload/non-auto"; HSFileUpload.autoInit(); // Or initialize a specific element manually const el = document.querySelector("#file-upload"); if (el) new HSFileUpload(el); ``` ### TypeScript This package ships with TypeScript type definitions. No additional `@types/` package is needed. ## Basic usage The following example demonstrates the minimal HTML structure required for a file upload component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The component supports drag-and-drop and file previews. ```html <div id="hs-file-upload-first" data-hs-file-upload='{ "url": "/upload" }'> <template data-hs-file-upload-preview> <button type="button" data-hs-file-upload-remove> Delete! </button> <span data-hs-file-upload-file-icon> <img class="hidden" data-dz-thumbnail /> </span> <div> <span data-hs-file-upload-file-name></span>.<span data-hs-file-upload-file-ext></span> </div> <div data-hs-file-upload-file-size></div> <div role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" data-hs-file-upload-progress-bar> <div style="width: 0" data-hs-file-upload-progress-bar-pane></div> </div> <span data-hs-file-upload-progress-bar-value>0</span>% </template> <div class="cursor-pointer" data-hs-file-upload-trigger> Drop your file here or browse </div> <div data-hs-file-upload-previews></div> </div> ``` **Structure Requirements:** - `data-hs-file-upload`: Required on the container element, contains configuration options - `data-hs-file-upload-preview`: Required template element for file previews (should be a `<template>` element) - `data-hs-file-upload-trigger`: Required clickable element for file selection - `data-hs-file-upload-previews`: Required container for file preview items - Various data attributes for preview elements (file name, extension, size, progress, etc.) **Initial State:** - Upload trigger is visible - Previews container is empty - Template is hidden (it's a template element) ## Configuration Options ### Data Options > **Note:** Please note that this component requires the use of the [Dropzone.js](https://www.dropzone.dev/) plugin. Most options available in the plugin are available in our wrapper. Data options are specified in the `data-hs-file-upload` attribute as a JSON object. | Option | Target Element | Type | Default | Description | | --- | --- | --- | --- | --- | | `data-hs-file-upload` | Container | - | - | Activate a File Upload by specifying on an element. Should be added to the container. | | `:url` | Inside `data-hs-file-upload` | string | - | The URL where files will be uploaded. Required for file upload functionality. | | `:extensions` | Inside `data-hs-file-upload` | object | Includes markup. See the code. | A list of extensions and associated icons that will be added inside the container with the `data-hs-file-upload-file-icon` selector if they match the extension name. | | `:autoHideTrigger` | Inside `data-hs-file-upload` | boolean | `false` | If the attribute value is `true`, then `data-hs-file-upload-trigger` will disappear if at least one item is added to the upload and will appear if more than one item is not in the upload. | | `:singleton` | Inside `data-hs-file-upload` | boolean | `false` | If the attribute value is `true`, then the plugin will remove any previously uploaded file. It needs for emulate simple input file behavior (only one file at a time). | **Example:** ```html <div data-hs-file-upload='{ "url": "/api/upload", "autoHideTrigger": true, "singleton": false }'> <!-- File upload structure --> </div> ``` ### Required CSS Classes / Data Attributes These data attributes define the structure and must be present for the file upload to function. | Data Attribute | Required On | Purpose | | --- | --- | --- | | `data-hs-file-upload-trigger` | Clickable element | Determines which element inside the initialized element will act as a clickable element for file selection. | | `data-hs-file-upload-previews` | Container element | Determines which element inside the initialized element will act as a wrapper for uploaded items. | | `data-hs-file-upload-preview` | Template element | Determines which element inside the initialized element will act as a template for the uploading item. Should be a `template` HTML element. | ### Optional CSS Classes / Data Attributes | Data Attribute | Required On | Purpose | | --- | --- | --- | | `data-hs-file-upload-clear` | Button element | Determines which element inside the initialized element will act as a button that deletes all files. | | `data-hs-file-upload-file-icon` | Element inside preview | Determines which element inside the uploading item will act as a wrapper for the file icon defined in the `extensions` property. | | `data-hs-file-upload-file-name` | Element inside preview | Determines which element inside the uploading item will act as a wrapper for the file name. | | `data-hs-file-upload-file-ext` | Element inside preview | Determines which element inside the uploading item will act as a wrapper for the file extension. | | `data-hs-file-upload-file-size` | Element inside preview | Determines which element inside the uploading item will act as a wrapper for the file size. | | `data-hs-file-upload-remove` | Button element inside preview | Determines which element inside the uploading item will act as a remove button. | | `data-hs-file-upload-reload` | Button element inside preview | Determines which element inside the uploading item will act as a re-upload button. | | `data-hs-file-upload-progress-bar` | Element inside preview | Determines which element inside the uploading item will act as a progressbar. | | `data-hs-file-upload-progress-bar-pane` | Element inside preview | Determines which element inside the uploading item will act as a progressbar pane, which width will dynamically increase during the uploading process. | | `data-hs-file-upload-progress-bar-value` | Element inside preview | Determines which element inside the uploading item will act as a current progress value, which will dynamically increase during the uploading process. | ### Tailwind Modifiers | Name | Description | | --- | --- | | `hs-file-upload-complete:*` | A modifier that allows you to set Tailwind classes to items that successfully uploaded. | ## JavaScript API The `HSFileUpload` object is available in the global `window` object after the plugin is loaded. ### Instance Methods These methods are called on a file upload instance. | Method | Parameters | Return Type | Description | | --- | --- | --- | --- | | `destroy()` | None | `void` | Destroys the file upload instance, removes all generated markup, classes, and event listeners. Use when removing file upload from DOM. | ### Static Methods These methods are called directly on the `HSFileUpload` class. | Method | Parameters | Return Type | Description | | --- | --- | --- | --- | | `HSFileUpload.getInstance(target, isInstance)` | `target`: `HTMLElement \| string` (CSS selector)<br>`isInstance`: `boolean` (optional) | `HTMLElement \| { id: string \| number, element: HSFileUpload } \| null` | Returns the file upload instance or element associated with the target. If `isInstance` is `true`, returns collection item object `{ id, element }` where `element` is the `HSFileUpload` instance. If `isInstance` is `false` or omitted, returns the DOM element (`HTMLElement`). Returns `null` if file upload instance is not found. | ### Usage Examples **Example 1: Destroying file upload instance** ```javascript const instance = HSFileUpload.getInstance('#hs-file-upload', true); if (instance) { const { element } = instance; const destroyBtn = document.querySelector('#hs-destroy-btn'); destroyBtn.addEventListener('click', () => { element.destroy(); }); } ``` **Example 2: Accessing Dropzone instance** ```javascript const instance = HSFileUpload.getInstance('#hs-file-upload', true); if (instance) { const { element } = instance; // Access underlying Dropzone instance const { dropzone } = element; if (dropzone) { // Use Dropzone methods dropzone.removeAllFiles(); } } ``` **Example 3: Destroying file upload instance** ```javascript const instance = HSFileUpload.getInstance('#hs-file-upload', true); if (instance) { const { element } = instance; const removeBtn = document.querySelector('#hs-remove-btn'); removeBtn.addEventListener('click', () => { // Clean up before removing from DOM element.destroy(); // Now safe to remove the element document.querySelector('#hs-file-upload').remove(); }); } ``` ## Events > **Note:** Please note that this component requires the use of the [Dropzone.js](https://www.dropzone.dev/) plugin. Most events available in the plugin are available in our wrapper. File upload instances emit events through the underlying Dropzone instance. Access the Dropzone instance via `element.dropzone` to listen to events. **Common Dropzone Events:** - `addedfile` - When a file is added - `removedfile` - When a file is removed - `uploadprogress` - During file upload - `success` - When file upload succeeds - `error` - When file upload fails - `complete` - When upload completes (success or error) ### Event Usage Example ```javascript // Get file upload instance const instance = HSFileUpload.getInstance('#hs-file-upload', true); if (instance) { const { element } = instance; const { dropzone } = element; if (dropzone) { // Listen to complete event dropzone.on('complete', (file) => { console.log('File uploaded:', file); // Perform actions after file upload completes // e.g., update UI, show success message }); // Listen to error event dropzone.on('error', (file, errorMessage) => { console.log('Upload error:', errorMessage); // Handle upload errors }); // Listen to success event dropzone.on('success', (file, response) => { console.log('Upload successful:', response); // Handle successful upload }); } } ``` ## Common Patterns ### Pattern 1: Single File Upload Allow only one file at a time. ```html <div data-hs-file-upload='{ "url": "/upload", "singleton": true }'> <!-- File upload structure --> </div> ``` ### Pattern 2: Auto-hide Trigger Hide trigger after files are added. ```html <div data-hs-file-upload='{ "url": "/upload", "autoHideTrigger": true }'> <!-- File upload structure --> </div> ``` ## License Copyright (c) 2026 Preline Labs. Licensed under the [MIT License](https://opensource.org/licenses/MIT).