├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .npmignore ├── .stylelintrc.json ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── angular.json ├── package-lock.json ├── package.json ├── projects ├── app │ ├── browserslist │ ├── src │ │ ├── app │ │ │ ├── app.component.css │ │ │ ├── app.component.html │ │ │ ├── app.component.ts │ │ │ └── app.module.ts │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ └── styles.css │ ├── stylelint.json │ ├── tsconfig.json │ └── tslint.json └── lib │ ├── README.md │ ├── ng-package.json │ ├── package.json │ ├── src │ ├── lib │ │ ├── dropzone.component.css │ │ ├── dropzone.component.html │ │ ├── dropzone.component.ts │ │ ├── dropzone.directive.ts │ │ ├── dropzone.interfaces.ts │ │ └── dropzone.module.ts │ └── public-api.ts │ ├── stylelint.json │ └── tsconfig.json ├── tailwind.config.js └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | max_line_length = 0 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": [ 4 | ], 5 | "overrides": [ 6 | { 7 | "files": [ 8 | "*.ts" 9 | ], 10 | "parserOptions": { 11 | "project": [ 12 | "tsconfig.json", 13 | "e2e/tsconfig.json" 14 | ], 15 | "createDefaultProgram": true 16 | }, 17 | "extends": [ 18 | "plugin:@angular-eslint/recommended", 19 | "plugin:@angular-eslint/template/process-inline-templates" 20 | ], 21 | "rules": { 22 | "@angular-eslint/no-output-rename": [ 23 | "off" 24 | ], 25 | "@angular-eslint/no-output-native": [ 26 | "off" 27 | ], 28 | "@angular-eslint/component-selector": [ 29 | "off" 30 | ], 31 | "@angular-eslint/directive-selector": [ 32 | "off" 33 | ], 34 | "@angular-eslint/no-conflicting-lifecycle": [ 35 | "off" 36 | ], 37 | "@angular-eslint/no-empty-lifecycle-method": [ 38 | "off" 39 | ] 40 | } 41 | }, 42 | { 43 | "files": [ 44 | "*.html" 45 | ], 46 | "extends": [ 47 | "plugin:@angular-eslint/template/recommended" 48 | ], 49 | "rules": {} 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | bundles/ 3 | 4 | package/ 5 | npm-debug.log 6 | node_modules/ 7 | .angular/ 8 | .vs/ 9 | 10 | example/dist/ 11 | example/npm-debug.log 12 | example/node_modules/ 13 | .idea 14 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.tgz 3 | 4 | src/ 5 | config/ 6 | example/ 7 | 8 | package/ 9 | npm-debug.log 10 | node_modules/ 11 | 12 | tslint.json 13 | tsconfig.json 14 | stylelint.json 15 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "stylelint-order" 4 | ], 5 | "extends": [ 6 | "stylelint-config-standard" 7 | ], 8 | "rules": { 9 | "color-hex-case": "lower", 10 | "color-no-invalid-hex": true, 11 | 12 | "font-family-no-missing-generic-family-keyword": null, 13 | "function-calc-no-unspaced-operator": true, 14 | "function-comma-space-after": "always-single-line", 15 | "function-comma-space-before": "never", 16 | "function-name-case": "lower", 17 | "function-url-quotes": "always", 18 | "function-whitespace-after": "always", 19 | 20 | "number-leading-zero": "always", 21 | "number-no-trailing-zeros": true, 22 | "length-zero-no-unit": true, 23 | 24 | "string-no-newline": true, 25 | "string-quotes": "single", 26 | 27 | "unit-case": "lower", 28 | "unit-no-unknown": true, 29 | "unit-whitelist": [ 30 | "px", 31 | "%", 32 | "deg", 33 | "ms", 34 | "em" 35 | ], 36 | 37 | "value-list-comma-space-after": "always-single-line", 38 | "value-list-comma-space-before": "never", 39 | 40 | "shorthand-property-no-redundant-values": true, 41 | 42 | "property-case": "lower", 43 | 44 | "at-rule-empty-line-before": [ 45 | "always", 46 | { 47 | "ignore": [ 48 | "blockless-after-blockless" 49 | ] 50 | } 51 | ], 52 | 53 | "at-rule-no-unknown": null, 54 | 55 | "declaration-block-no-duplicate-properties": true, 56 | "declaration-block-trailing-semicolon": "always", 57 | "declaration-block-single-line-max-declarations": 1, 58 | "declaration-block-semicolon-space-before": "never", 59 | "declaration-block-semicolon-space-after": "always-single-line", 60 | "declaration-block-semicolon-newline-before": "never-multi-line", 61 | "declaration-block-semicolon-newline-after": "always-multi-line", 62 | 63 | "block-closing-brace-newline-after": "always", 64 | "block-closing-brace-newline-before": "always-multi-line", 65 | "block-no-empty": true, 66 | "block-opening-brace-newline-after": "always-multi-line", 67 | "block-opening-brace-space-before": "always-multi-line", 68 | 69 | "selector-attribute-brackets-space-inside": "never", 70 | "selector-attribute-operator-space-after": "never", 71 | "selector-attribute-operator-space-before": "never", 72 | "selector-combinator-space-after": "always", 73 | "selector-combinator-space-before": "always", 74 | "selector-pseudo-class-case": "lower", 75 | "selector-pseudo-class-parentheses-space-inside": "never", 76 | "selector-pseudo-element-case": "lower", 77 | "selector-pseudo-element-colon-notation": "double", 78 | "selector-pseudo-element-no-unknown": true, 79 | "selector-type-no-unknown": null, 80 | "selector-type-case": "lower", 81 | "selector-max-id": 0, 82 | 83 | "declaration-empty-line-before": null, 84 | 85 | "no-descending-specificity": null, 86 | 87 | "order/properties-order": [ 88 | [ 89 | { 90 | "properties": [ 91 | "content", 92 | "direction" 93 | ] 94 | }, { 95 | "emptyLineBefore": "always", 96 | "properties": [ 97 | "float", 98 | "position", 99 | "z-index", 100 | "top", 101 | "right", 102 | "bottom", 103 | "left" 104 | ] 105 | }, { 106 | "emptyLineBefore": "always", 107 | "properties": [ 108 | "visibility", 109 | "opacity", 110 | "display", 111 | "overflow", 112 | "box-sizing", 113 | "flex", 114 | "flex-basis", 115 | "flex-direction", 116 | "flex-flow", 117 | "flex-grow", 118 | "flex-shrink", 119 | "flex-wrap", 120 | "align-self", 121 | "align-items", 122 | "align-content", 123 | "justify-content", 124 | "order", 125 | "width", 126 | "height", 127 | "min-width", 128 | "min-height", 129 | "max-width", 130 | "max-height", 131 | "padding", 132 | "padding-top", 133 | "padding-right", 134 | "padding-bottom", 135 | "padding-left", 136 | "margin", 137 | "margin-top", 138 | "margin-right", 139 | "margin-bottom", 140 | "margin-left", 141 | "border", 142 | "border-top", 143 | "border-right", 144 | "border-bottom", 145 | "border-left", 146 | "border-width", 147 | "border-top-width", 148 | "border-right-width", 149 | "border-bottom-width", 150 | "border-left-width", 151 | "border-style", 152 | "border-top-style", 153 | "border-right-style", 154 | "border-bottom-style", 155 | "border-left-style", 156 | "border-color", 157 | "border-top-color", 158 | "border-right-color", 159 | "border-bottom-color", 160 | "border-left-color", 161 | "border-radius", 162 | "border-top-left-radius", 163 | "border-top-right-radius", 164 | "border-bottom-right-radius", 165 | "border-bottom-left-radius", 166 | "outline" 167 | ] 168 | }, { 169 | "emptyLineBefore": "always", 170 | "properties": [ 171 | "cursor", 172 | "resize", 173 | "user-select", 174 | "touch-action", 175 | "pointer-events", 176 | "font-size", 177 | "font-style", 178 | "font-weight", 179 | "font-family", 180 | "line-height", 181 | "white-space", 182 | "text-align", 183 | "text-shadow", 184 | "text-decoration", 185 | "text-transform", 186 | "text-overflow", 187 | "letter-spacing", 188 | "list-style-type", 189 | "object-fit", 190 | "vertical-align", 191 | "color", 192 | "background", 193 | "background-size", 194 | "background-color", 195 | "background-image", 196 | "background-repeat", 197 | "background-position", 198 | "background-attachment", 199 | "box-shadow" 200 | ] 201 | }, { 202 | "emptyLineBefore": "always", 203 | "properties": [ 204 | "filter", 205 | "animation", 206 | "animation-name", 207 | "animation-delay", 208 | "animation-duration", 209 | "animation-direction", 210 | "animation-fill-mode", 211 | "animation-play-state", 212 | "animation-iteration-count", 213 | "animation-timing-function", 214 | "transform", 215 | "transform-style", 216 | "transform-origin", 217 | "transition", 218 | "transition-delay", 219 | "transition-duration", 220 | "transition-property", 221 | "transition-timing-function" 222 | ] 223 | } 224 | ], 225 | { 226 | "unspecified": "bottomAlphabetical" 227 | } 228 | ] 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing guide 2 | 3 | Want to contribute to this project? Awesome! There are many ways you can contribute, see below. 4 | 5 | ### Opening issues 6 | 7 | Open an issue to report bugs or to propose new features. If you have a general usage question please note that this is just a wrapper and most questions should be directed to the actual library in Stack Overflow etc. 8 | 9 | ### Proposing pull requests 10 | 11 | Pull requests are more than welcome. Note that if you are going to propose drastic changes or new features, be sure to open an issue for discussion first, to make sure that your PR will be accepted before you spend effort coding it. 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2016 Zef Oy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Dropzone Wrapper 2 | 3 | npm version 4 | 5 | This is an Angular wrapper library for the [Dropzone](http://www.dropzonejs.com/). To use this library you should get familiar with the Dropzone documentation as well since this documentation only explains details specific to this wrapper. 6 | 7 | This documentation is for the latest 6.x.x version which requires Angular 5 or newer. For Angular 4 you need to use the latest 4.x.x version. Documentation for the 4.x.x can be found from here. 8 | 9 | ### EOL notice 10 | 11 | Version 17.0.0 will most likely be the last release of this library. I recommend you to switch to something more maintained due to official dropzone package being unmaintained. 12 | 13 | ### Quick links 14 | 15 | [Example application](https://zefoy.github.io/ngx-dropzone-wrapper/) 16 | | 17 | [StackBlitz example](https://stackblitz.com/github/zefoy/ngx-dropzone-wrapper/tree/master) 18 | | 19 | [Dropzone documentation](http://www.dropzonejs.com/#configuration-options) 20 | 21 | ### Building the library 22 | 23 | ```bash 24 | npm install 25 | npm run build 26 | ``` 27 | 28 | ### Running the example 29 | 30 | ```bash 31 | npm install 32 | npm run start 33 | ``` 34 | 35 | ### Installing and usage 36 | 37 | ```bash 38 | npm install ngx-dropzone-wrapper --save 39 | ``` 40 | 41 | ##### Load the module for your app (with global configuration): 42 | 43 | Providing the global configuration is optional and when used you should only provide the configuration in your root module. 44 | 45 | ```javascript 46 | import { DropzoneModule } from 'ngx-dropzone-wrapper'; 47 | import { DROPZONE_CONFIG } from 'ngx-dropzone-wrapper'; 48 | import { DropzoneConfigInterface } from 'ngx-dropzone-wrapper'; 49 | 50 | const DEFAULT_DROPZONE_CONFIG: DropzoneConfigInterface = { 51 | // Change this to your upload POST address: 52 |  url: 'https://httpbin.org/post', 53 | maxFilesize: 50, 54 | acceptedFiles: 'image/*' 55 | }; 56 | 57 | @NgModule({ 58 | ... 59 | imports: [ 60 | ... 61 | DropzoneModule 62 | ], 63 | providers: [ 64 | { 65 | provide: DROPZONE_CONFIG, 66 | useValue: DEFAULT_DROPZONE_CONFIG 67 | } 68 | ] 69 | }) 70 | ``` 71 | 72 | ##### Use it in your HTML template (with custom configuration): 73 | 74 | This library provides two ways to create a Dropzone element, component for simple use cases and directive for more custom use cases. 75 | 76 | **COMPONENT USAGE** 77 | 78 | Simply replace the element that would ordinarily be passed to `Dropzone` with the dropzone component. 79 | 80 | **NOTE:** Component provides couple additional features from directive such as the placeholder image. If you don't need them or want to create custom component then you might want to use the directive instead. 81 | 82 | ```html 83 | 84 | ``` 85 | 86 | ```javascript 87 | [config] // Custom config to override the global defaults. 88 | 89 | [disabled] // Disables / detaches Dropzone from the element. 90 | 91 | [message] // Message to show for the user on the upload area. 92 | [placeholder] // Placeholder image to be shown as the upload area. 93 | 94 | [useDropzoneClass] // Use 'dropzone' class (use provided default styles). 95 | 96 | (error) // Event handler for the Dropzone upload error event. 97 | (success) // Event handler for the Dropzone upload success event. 98 | (canceled) // Event handler for the Dropzone upload canceled event. 99 | 100 | () // All Dropzone events / callbacks work as bindings. 101 | // Event names are in camel case (not lower case). 102 | // Example: maxfilesreached -> maxFilesReached 103 | ``` 104 | 105 | **DIRECTIVE USAGE** 106 | 107 | When using only the directive you need to provide your own theming or import the default theme: 108 | 109 | ```css 110 | @import '~dropzone/dist/min/dropzone.min.css'; 111 | ``` 112 | 113 | Dropzone directive can be used in form or div element with optional custom configuration: 114 | 115 | ```html 116 |
117 | ``` 118 | 119 | ```javascript 120 | [dropzone] // Can be used to provide optional custom config. 121 | 122 | [disabled] // Disables / detaches Dropzone from the element. 123 | 124 | (error) // Event handler for the Dropzone upload error event. 125 | (success) // Event handler for the Dropzone upload success event. 126 | (canceled) // Event handler for the Dropzone upload canceled event. 127 | 128 | () // All Dropzone events / callbacks work as bindings. 129 | // Event names are in camel case (not lower case). 130 | // Example: maxfilesreached -> maxFilesReached 131 | ``` 132 | 133 | ##### Available configuration options (custom / global configuration): 134 | 135 | This library supports all Dropzone configuration options and few extra options for easier usage. 136 | 137 | **LIBRARY OPTIONS** 138 | 139 | ```javascript 140 | autoReset // Time for resetting component after upload (Default: null). 141 | errorReset // Time for resetting component after an error (Default: null). 142 | cancelReset // Time for resetting component after canceling (Default: null). 143 | ``` 144 | 145 | **DROPZONE OPTIONS** 146 | 147 | ```javascript 148 | url // Upload url where to send the upload request (Default: ''). 149 | method // HTTP method to use communicating with the server (Default: 'post'). 150 | headers // Object of additional headers to send to the server (Default: null). 151 | paramName // Name of the file parameter that gets transferred (Default: 'file'). 152 | maxFilesize // Maximum file size for the upload files in megabytes (Default: null). 153 | acceptedFiles // Comma separated list of mime types or file extensions (Default: null). 154 | ``` 155 | 156 | For more detailed documentation with all the supported Dropzone events / options see the Dropzone documentation. 157 | 158 | ##### Available control / helper functions (provided by the directive): 159 | 160 | ```javascript 161 | dropzone() // Returns reference to the Dropzone instance for full API access. 162 | 163 | reset(cancel?) // Removes all processed files (optionally cancels uploads as well). 164 | ``` 165 | 166 | Above functions can be accessed through the directive reference (available as directiveRef in the component). 167 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "cli": { 4 | "analytics": false 5 | }, 6 | "version": 1, 7 | "newProjectRoot": "projects", 8 | "projects": { 9 | "app": { 10 | "projectType": "application", 11 | "schematics": {}, 12 | "root": "", 13 | "sourceRoot": "projects/app/src", 14 | "prefix": "app", 15 | "architect": { 16 | "build": { 17 | "builder": "@angular-devkit/build-angular:application", 18 | "options": { 19 | "outputPath": "dist/app", 20 | "index": "projects/app/src/index.html", 21 | "browser": "projects/app/src/main.ts", 22 | "polyfills": ["projects/app/src/polyfills.ts"], 23 | "tsConfig": "projects/app/tsconfig.json", 24 | "assets": [ 25 | "projects/app/src/favicon.ico", 26 | "projects/app/src/assets" 27 | ], 28 | "styles": [ 29 | "projects/app/src/styles.css" 30 | ], 31 | "scripts": [] 32 | }, 33 | "configurations": { 34 | "production": { 35 | "fileReplacements": [ 36 | { 37 | "replace": "projects/app/src/environments/environment.ts", 38 | "with": "projects/app/src/environments/environment.prod.ts" 39 | } 40 | ], 41 | "budgets": [ 42 | { 43 | "type": "initial", 44 | "maximumWarning": "2mb", 45 | "maximumError": "5mb" 46 | }, 47 | { 48 | "type": "anyComponentStyle", 49 | "maximumWarning": "30kb", 50 | "maximumError": "50kb" 51 | } 52 | ] 53 | }, 54 | "development": { 55 | "optimization": false, 56 | "extractLicenses": false, 57 | "sourceMap": true, 58 | "namedChunks": true 59 | } 60 | } 61 | }, 62 | "serve": { 63 | "builder": "@angular-devkit/build-angular:dev-server", 64 | "options": { 65 | "buildTarget": "app:build" 66 | }, 67 | "configurations": { 68 | "production": { 69 | "buildTarget": "app:build:production" 70 | }, 71 | "development": { 72 | "buildTarget": "app:build:development" 73 | } 74 | }, 75 | "defaultConfiguration": "development" 76 | }, 77 | "extract-i18n": { 78 | "builder": "@angular-devkit/build-angular:extract-i18n", 79 | "options": { 80 | "buildTarget": "app:build" 81 | } 82 | }, 83 | "lint": { 84 | "builder": "@angular-eslint/builder:lint", 85 | "options": { 86 | "lintFilePatterns": [ 87 | "projects/app/src/**/*.ts", 88 | "projects/app/src/**/*.html" 89 | ] 90 | } 91 | } 92 | } 93 | }, 94 | "lib": { 95 | "projectType": "library", 96 | "root": "projects/lib", 97 | "sourceRoot": "projects/lib/src", 98 | "prefix": "lib", 99 | "architect": { 100 | "build": { 101 | "builder": "@angular-devkit/build-angular:ng-packagr", 102 | "options": { 103 | "tsConfig": "projects/lib/tsconfig.json", 104 | "project": "projects/lib/ng-package.json" 105 | }, 106 | "configurations": { 107 | "production": {} 108 | } 109 | }, 110 | "lint": { 111 | "builder": "@angular-eslint/builder:lint", 112 | "options": { 113 | "lintFilePatterns": [ 114 | "projects/lib/src/**/*.ts", 115 | "projects/lib/src/**/*.html" 116 | ] 117 | } 118 | } 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-dropzone-wrapper", 3 | "description": "Angular wrapper library for Dropzone", 4 | "bugs": "https://github.com/zefoy/ngx-dropzone-wrapper/issues", 5 | "version": "17.0.0", 6 | "license": "MIT", 7 | "private": true, 8 | "scripts": { 9 | "ng": "ng", 10 | "lint": "ng lint", 11 | "start": "ng serve app", 12 | "build": "ng build lib", 13 | "deploy": "deploy-to-git", 14 | "prepare": "ng build lib --configuration production", 15 | "publish": "npm publish ./dist/lib", 16 | "predeploy": "rimraf ./dist/app && mkdirp ./dist/app" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/zefoy/ngx-dropzone-wrapper.git" 21 | }, 22 | "config": { 23 | "deployToGit": { 24 | "repository": "git@github.com:zefoy/ngx-dropzone-wrapper.git", 25 | "branch": "gh-pages", 26 | "folder": "dist/app", 27 | "script": "ng build app --configuration production --base-href=ngx-dropzone-wrapper --delete-output-path=false", 28 | "commit": "Publishing $npm_package_version", 29 | "user": { 30 | "name": "ZEF Devel", 31 | "email": "devel@zef.fi" 32 | } 33 | } 34 | }, 35 | "dependencies": { 36 | "@angular/cdk": "^17.3.0", 37 | "@angular/common": "^17.3.0", 38 | "@angular/compiler": "^17.3.0", 39 | "@angular/core": "^17.3.0", 40 | "@angular/platform-browser": "^17.3.0", 41 | "@angular/platform-browser-dynamic": "^17.3.0", 42 | "core-js": "^3.37.0", 43 | "dropzone": "^5.9.0", 44 | "rxjs": "^7.8.0", 45 | "tailwindcss": "^3.3.0", 46 | "zone.js": "^0.14.0" 47 | }, 48 | "devDependencies": { 49 | "@angular-devkit/build-angular": "^17.3.0", 50 | "@angular-eslint/builder": "^17.3.0", 51 | "@angular-eslint/eslint-plugin": "^17.3.0", 52 | "@angular-eslint/eslint-plugin-template": "^17.3.0", 53 | "@angular-eslint/schematics": "^17.3.0", 54 | "@angular-eslint/template-parser": "^17.3.0", 55 | "@angular/cli": "^17.3.0", 56 | "@angular/compiler-cli": "^17.3.0", 57 | "@typescript-eslint/eslint-plugin": "7.15.0", 58 | "@typescript-eslint/parser": "7.15.0", 59 | "cpx": "^1.5.0", 60 | "deploy-to-git": "^0.4.0", 61 | "eslint": "^8.54.0", 62 | "mkdirp": "^3.0.0", 63 | "ng-packagr": "^17.3.0", 64 | "rimraf": "^5.0.0", 65 | "stylelint": "^16.6.0", 66 | "stylelint-config-standard": "^36.0.0", 67 | "stylelint-order": "^6.0.0", 68 | "terser": "^5.31.0", 69 | "typescript": "~5.4.0", 70 | "watch": "^1.0.0" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /projects/app/browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /projects/app/src/app/app.component.css: -------------------------------------------------------------------------------- 1 | .app-title { 2 | font-size: 24px; 3 | } 4 | 5 | .box-title { 6 | font-size: 20px; 7 | } 8 | 9 | .box-container { 10 | box-sizing: border-box; 11 | width: 800px; 12 | height: 500px; 13 | max-width: 90%; 14 | max-height: 90%; 15 | padding: 24px; 16 | margin: 24px auto; 17 | border-radius: 4px; 18 | 19 | color: #555; 20 | background-color: #eee; 21 | box-shadow: 22 | 0 6px 20px rgba(0, 0, 0, 0.18), 23 | 0 6px 6px rgba(0, 0, 0, 0.25); 24 | } 25 | 26 | .info-container { 27 | padding: 12px 16px; 28 | 29 | line-height: 24px; 30 | } 31 | 32 | .action-container, 33 | .content-container { 34 | position: relative; 35 | 36 | overflow: auto; 37 | height: 300px; 38 | min-height: 0; 39 | padding: 16px; 40 | margin: 8px 16px; 41 | border-radius: 4px; 42 | 43 | background-color: #fff; 44 | } 45 | 46 | .vertical-container, 47 | .horizontal-container { 48 | min-height: 0 !important; 49 | } 50 | 51 | .action-button { 52 | box-sizing: border-box; 53 | width: calc(100% - 16px); 54 | min-height: 35px; 55 | padding: 4px 16px; 56 | margin: 8px; 57 | border: 1px solid #555; 58 | border-radius: 4px; 59 | 60 | cursor: pointer; 61 | font-size: 14px; 62 | font-weight: bold; 63 | line-height: 14px; 64 | text-align: center; 65 | } 66 | 67 | .action-button:hover { 68 | color: #fff; 69 | background-color: #555; 70 | } 71 | 72 | .dropzone-container { 73 | height: 100%; 74 | } 75 | -------------------------------------------------------------------------------- /projects/app/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |
Simple example application for the ngx-dropzone-wrapper
3 | 4 |
5 | This example does not actually upload any of the selected files, only simulates the upload process. 6 |
7 | 8 |
9 |
10 |
Controls
11 | 12 |
13 |
{{(type === "component") ? "Switch to directive" : "Switch to component"}}
14 | 15 |
Toggle disabled state
16 | 17 |
{{(config.maxFiles !== 1) ? "Upload single file" : "Upload multiple files"}}
18 | 19 |
{{config.autoReset ? "Turn off auto reset" : "Turn on auto reset"}}
20 | 21 |
{{config.clickable ? "Turn off click action" : "Turn on click action"}}
22 | 23 |
Reset upload area
24 |
25 |
26 | 27 |
28 |
Dropzone
29 | 30 |
31 | 32 | 33 |
34 |
35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /projects/app/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ViewChild } from '@angular/core'; 2 | 3 | import { DropzoneComponent , DropzoneDirective, 4 | DropzoneConfigInterface } from 'ngx-dropzone-wrapper'; 5 | 6 | @Component({ 7 | selector: 'my-app', 8 | moduleId: 'src/app/app.component', 9 | templateUrl: './app.component.html', 10 | styleUrls: [ './app.component.css' ] 11 | }) 12 | export class AppComponent { 13 | public type: string = 'component'; 14 | 15 | public disabled: boolean = false; 16 | 17 | public config: DropzoneConfigInterface = { 18 | clickable: true, 19 | maxFiles: 1, 20 | autoReset: null, 21 | errorReset: null, 22 | cancelReset: null 23 | }; 24 | 25 | @ViewChild(DropzoneComponent, { static: false }) componentRef?: DropzoneComponent; 26 | @ViewChild(DropzoneDirective, { static: false }) directiveRef?: DropzoneDirective; 27 | 28 | constructor() {} 29 | 30 | public toggleType(): void { 31 | this.type = (this.type === 'component') ? 'directive' : 'component'; 32 | } 33 | 34 | public toggleDisabled(): void { 35 | this.disabled = !this.disabled; 36 | } 37 | 38 | public toggleAutoReset(): void { 39 | this.config.autoReset = this.config.autoReset ? null : 5000; 40 | this.config.errorReset = this.config.errorReset ? null : 5000; 41 | this.config.cancelReset = this.config.cancelReset ? null : 5000; 42 | } 43 | 44 | public toggleMultiUpload(): void { 45 | this.config.maxFiles = this.config.maxFiles ? 0 : 1; 46 | } 47 | 48 | public toggleClickAction(): void { 49 | this.config.clickable = !this.config.clickable; 50 | } 51 | 52 | public resetDropzoneUploads(): void { 53 | if (this.type === 'directive' && this.directiveRef) { 54 | this.directiveRef.reset(); 55 | } else if (this.type === 'component' && this.componentRef && this.componentRef.directiveRef) { 56 | this.componentRef.directiveRef.reset(); 57 | } 58 | } 59 | 60 | public onUploadInit(args: any): void { 61 | console.log('onUploadInit:', args); 62 | } 63 | 64 | public onUploadError(args: any): void { 65 | console.log('onUploadError:', args); 66 | } 67 | 68 | public onUploadSuccess(args: any): void { 69 | console.log('onUploadSuccess:', args); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /projects/app/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | 3 | import { BrowserModule } from '@angular/platform-browser'; 4 | 5 | import { DropzoneModule, DropzoneConfigInterface, 6 | DROPZONE_CONFIG } from 'ngx-dropzone-wrapper'; 7 | 8 | import { AppComponent } from './app.component'; 9 | 10 | const DEFAULT_DROPZONE_CONFIG: DropzoneConfigInterface = { 11 | // Change this to your upload POST address: 12 | url: 'https://httpbin.org/post', 13 | acceptedFiles: 'image/*', 14 | createImageThumbnails: true 15 | }; 16 | 17 | @NgModule({ 18 | bootstrap: [ 19 | AppComponent 20 | ], 21 | declarations: [ 22 | AppComponent 23 | ], 24 | imports: [ 25 | DropzoneModule, 26 | BrowserModule 27 | ], 28 | exports: [ 29 | ], 30 | providers: [ 31 | { 32 | provide: DROPZONE_CONFIG, 33 | useValue: DEFAULT_DROPZONE_CONFIG 34 | } 35 | ] 36 | }) 37 | export class AppModule {} 38 | -------------------------------------------------------------------------------- /projects/app/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /projects/app/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /projects/app/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zefoy/ngx-dropzone-wrapper/9b5a1a66fa4de4271b5bf772ae572d16e5b6540e/projects/app/src/favicon.ico -------------------------------------------------------------------------------- /projects/app/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Example app 8 | 9 | 10 | 11 | 12 | 13 | 65 | 66 | 67 | 68 | 69 | 70 |
71 | 72 | 73 | -------------------------------------------------------------------------------- /projects/app/src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | 3 | import { AppModule } from './app/app.module'; 4 | 5 | platformBrowserDynamic().bootstrapModule(AppModule); 6 | -------------------------------------------------------------------------------- /projects/app/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | import 'zone.js'; 2 | -------------------------------------------------------------------------------- /projects/app/src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | @tailwind base; 4 | @tailwind utilities; 5 | @tailwind components; 6 | -------------------------------------------------------------------------------- /projects/app/stylelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "stylelint-order" 4 | ], 5 | "extends": [ 6 | "stylelint-config-standard" 7 | ], 8 | "rules": { 9 | "color-hex-case": "lower", 10 | "color-no-invalid-hex": true, 11 | 12 | "font-family-no-missing-generic-family-keyword": null, 13 | "function-calc-no-unspaced-operator": true, 14 | "function-comma-space-after": "always-single-line", 15 | "function-comma-space-before": "never", 16 | "function-name-case": "lower", 17 | "function-url-quotes": "always", 18 | "function-whitespace-after": "always", 19 | 20 | "number-leading-zero": "always", 21 | "number-no-trailing-zeros": true, 22 | "length-zero-no-unit": true, 23 | 24 | "string-no-newline": true, 25 | "string-quotes": "single", 26 | 27 | "unit-case": "lower", 28 | "unit-no-unknown": true, 29 | "unit-whitelist": [ 30 | "px", 31 | "%", 32 | "deg", 33 | "ms", 34 | "em" 35 | ], 36 | 37 | "value-list-comma-space-after": "always-single-line", 38 | "value-list-comma-space-before": "never", 39 | 40 | "shorthand-property-no-redundant-values": true, 41 | 42 | "property-case": "lower", 43 | 44 | "at-rule-empty-line-before": [ 45 | "always", 46 | { 47 | "ignore": [ 48 | "blockless-after-blockless" 49 | ] 50 | } 51 | ], 52 | 53 | "at-rule-no-unknown": null, 54 | 55 | "declaration-block-no-duplicate-properties": true, 56 | "declaration-block-trailing-semicolon": "always", 57 | "declaration-block-single-line-max-declarations": 1, 58 | "declaration-block-semicolon-space-before": "never", 59 | "declaration-block-semicolon-space-after": "always-single-line", 60 | "declaration-block-semicolon-newline-before": "never-multi-line", 61 | "declaration-block-semicolon-newline-after": "always-multi-line", 62 | 63 | "block-closing-brace-newline-after": "always", 64 | "block-closing-brace-newline-before": "always-multi-line", 65 | "block-no-empty": true, 66 | "block-opening-brace-newline-after": "always-multi-line", 67 | "block-opening-brace-space-before": "always-multi-line", 68 | 69 | "selector-attribute-brackets-space-inside": "never", 70 | "selector-attribute-operator-space-after": "never", 71 | "selector-attribute-operator-space-before": "never", 72 | "selector-combinator-space-after": "always", 73 | "selector-combinator-space-before": "always", 74 | "selector-pseudo-class-case": "lower", 75 | "selector-pseudo-class-parentheses-space-inside": "never", 76 | "selector-pseudo-element-case": "lower", 77 | "selector-pseudo-element-colon-notation": "double", 78 | "selector-pseudo-element-no-unknown": true, 79 | "selector-type-no-unknown": null, 80 | "selector-type-case": "lower", 81 | "selector-max-id": 0, 82 | 83 | "declaration-empty-line-before": null, 84 | 85 | "no-descending-specificity": null, 86 | 87 | "order/properties-order": [ 88 | [ 89 | { 90 | "properties": [ 91 | "content", 92 | "direction" 93 | ] 94 | }, { 95 | "emptyLineBefore": "always", 96 | "properties": [ 97 | "float", 98 | "position", 99 | "z-index", 100 | "top", 101 | "right", 102 | "bottom", 103 | "left" 104 | ] 105 | }, { 106 | "emptyLineBefore": "always", 107 | "properties": [ 108 | "visibility", 109 | "opacity", 110 | "display", 111 | "overflow", 112 | "box-sizing", 113 | "flex", 114 | "flex-basis", 115 | "flex-direction", 116 | "flex-flow", 117 | "flex-grow", 118 | "flex-shrink", 119 | "flex-wrap", 120 | "align-self", 121 | "align-items", 122 | "align-content", 123 | "justify-content", 124 | "order", 125 | "width", 126 | "height", 127 | "min-width", 128 | "min-height", 129 | "max-width", 130 | "max-height", 131 | "padding", 132 | "padding-top", 133 | "padding-right", 134 | "padding-bottom", 135 | "padding-left", 136 | "margin", 137 | "margin-top", 138 | "margin-right", 139 | "margin-bottom", 140 | "margin-left", 141 | "border", 142 | "border-top", 143 | "border-right", 144 | "border-bottom", 145 | "border-left", 146 | "border-width", 147 | "border-top-width", 148 | "border-right-width", 149 | "border-bottom-width", 150 | "border-left-width", 151 | "border-style", 152 | "border-top-style", 153 | "border-right-style", 154 | "border-bottom-style", 155 | "border-left-style", 156 | "border-color", 157 | "border-top-color", 158 | "border-right-color", 159 | "border-bottom-color", 160 | "border-left-color", 161 | "border-radius", 162 | "border-top-left-radius", 163 | "border-top-right-radius", 164 | "border-bottom-right-radius", 165 | "border-bottom-left-radius", 166 | "outline" 167 | ] 168 | }, { 169 | "emptyLineBefore": "always", 170 | "properties": [ 171 | "cursor", 172 | "resize", 173 | "user-select", 174 | "touch-action", 175 | "pointer-events", 176 | "font-size", 177 | "font-style", 178 | "font-weight", 179 | "font-family", 180 | "line-height", 181 | "white-space", 182 | "text-align", 183 | "text-shadow", 184 | "text-decoration", 185 | "text-transform", 186 | "text-overflow", 187 | "letter-spacing", 188 | "list-style-type", 189 | "object-fit", 190 | "vertical-align", 191 | "color", 192 | "background", 193 | "background-size", 194 | "background-color", 195 | "background-image", 196 | "background-repeat", 197 | "background-position", 198 | "background-attachment", 199 | "box-shadow" 200 | ] 201 | }, { 202 | "emptyLineBefore": "always", 203 | "properties": [ 204 | "filter", 205 | "animation", 206 | "animation-name", 207 | "animation-delay", 208 | "animation-duration", 209 | "animation-direction", 210 | "animation-fill-mode", 211 | "animation-play-state", 212 | "animation-iteration-count", 213 | "animation-timing-function", 214 | "transform", 215 | "transform-style", 216 | "transform-origin", 217 | "transition", 218 | "transition-delay", 219 | "transition-duration", 220 | "transition-property", 221 | "transition-timing-function" 222 | ] 223 | } 224 | ], 225 | { 226 | "unspecified": "bottomAlphabetical" 227 | } 228 | ] 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /projects/app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts", 9 | "src/polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /projects/app/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json" 3 | } 4 | -------------------------------------------------------------------------------- /projects/lib/README.md: -------------------------------------------------------------------------------- 1 | # Angular Dropzone Wrapper 2 | 3 | npm version 4 | 5 | This is an Angular wrapper library for the [Dropzone](http://www.dropzonejs.com/). To use this library you should get familiar with the Dropzone documentation as well since this documentation only explains details specific to this wrapper. 6 | 7 | This documentation is for the latest 6.x.x version which requires Angular 5 or newer. For Angular 4 you need to use the latest 4.x.x version. Documentation for the 4.x.x can be found from here. 8 | 9 | ### Quick links 10 | 11 | [Example application](https://zefoy.github.io/ngx-dropzone-wrapper/) 12 | | 13 | [StackBlitz example](https://stackblitz.com/github/zefoy/ngx-dropzone-wrapper/tree/master) 14 | | 15 | [Dropzone documentation](http://www.dropzonejs.com/#configuration-options) 16 | 17 | ### Building the library 18 | 19 | ```bash 20 | npm install 21 | npm run build 22 | ``` 23 | 24 | ### Running the example 25 | 26 | ```bash 27 | npm install 28 | npm run start 29 | ``` 30 | 31 | ### Installing and usage 32 | 33 | ```bash 34 | npm install ngx-dropzone-wrapper --save 35 | ``` 36 | 37 | ##### Load the module for your app (with global configuration): 38 | 39 | Providing the global configuration is optional and when used you should only provide the configuration in your root module. 40 | 41 | ```javascript 42 | import { DropzoneModule } from 'ngx-dropzone-wrapper'; 43 | import { DROPZONE_CONFIG } from 'ngx-dropzone-wrapper'; 44 | import { DropzoneConfigInterface } from 'ngx-dropzone-wrapper'; 45 | 46 | const DEFAULT_DROPZONE_CONFIG: DropzoneConfigInterface = { 47 | // Change this to your upload POST address: 48 |  url: 'https://httpbin.org/post', 49 | maxFilesize: 50, 50 | acceptedFiles: 'image/*' 51 | }; 52 | 53 | @NgModule({ 54 | ... 55 | imports: [ 56 | ... 57 | DropzoneModule 58 | ], 59 | providers: [ 60 | { 61 | provide: DROPZONE_CONFIG, 62 | useValue: DEFAULT_DROPZONE_CONFIG 63 | } 64 | ] 65 | }) 66 | ``` 67 | 68 | ##### Use it in your HTML template (with custom configuration): 69 | 70 | This library provides two ways to create a Dropzone element, component for simple use cases and directive for more custom use cases. 71 | 72 | **COMPONENT USAGE** 73 | 74 | Simply replace the element that would ordinarily be passed to `Dropzone` with the dropzone component. 75 | 76 | **NOTE:** Component provides couple additional features from directive such as the placeholder image. If you don't need them or want to create custom component then you might want to use the directive instead. 77 | 78 | ```html 79 | 80 | ``` 81 | 82 | ```javascript 83 | [config] // Custom config to override the global defaults. 84 | 85 | [disabled] // Disables / detaches Dropzone from the element. 86 | 87 | [message] // Message to show for the user on the upload area. 88 | [placeholder] // Placeholder image to be shown as the upload area. 89 | 90 | [useDropzoneClass] // Use 'dropzone' class (use provided default styles). 91 | 92 | (error) // Event handler for the Dropzone upload error event. 93 | (success) // Event handler for the Dropzone upload success event. 94 | (canceled) // Event handler for the Dropzone upload canceled event. 95 | 96 | () // All Dropzone events / callbacks work as bindings. 97 | // Event names are in camel case (not lower case). 98 | // Example: maxfilesreached -> maxFilesReached 99 | ``` 100 | 101 | **DIRECTIVE USAGE** 102 | 103 | When using only the directive you need to provide your own theming or import the default theme: 104 | 105 | ```css 106 | @import '~dropzone/dist/min/dropzone.min.css'; 107 | ``` 108 | 109 | Dropzone directive can be used in form or div element with optional custom configuration: 110 | 111 | ```html 112 |
113 | ``` 114 | 115 | ```javascript 116 | [dropzone] // Can be used to provide optional custom config. 117 | 118 | [disabled] // Disables / detaches Dropzone from the element. 119 | 120 | (error) // Event handler for the Dropzone upload error event. 121 | (success) // Event handler for the Dropzone upload success event. 122 | (canceled) // Event handler for the Dropzone upload canceled event. 123 | 124 | () // All Dropzone events / callbacks work as bindings. 125 | // Event names are in camel case (not lower case). 126 | // Example: maxfilesreached -> maxFilesReached 127 | ``` 128 | 129 | ##### Available configuration options (custom / global configuration): 130 | 131 | This library supports all Dropzone configuration options and few extra options for easier usage. 132 | 133 | **LIBRARY OPTIONS** 134 | 135 | ```javascript 136 | autoReset // Time for resetting component after upload (Default: null). 137 | errorReset // Time for resetting component after an error (Default: null). 138 | cancelReset // Time for resetting component after canceling (Default: null). 139 | ``` 140 | 141 | **DROPZONE OPTIONS** 142 | 143 | ```javascript 144 | url // Upload url where to send the upload request (Default: ''). 145 | method // HTTP method to use communicating with the server (Default: 'post'). 146 | headers // Object of additional headers to send to the server (Default: null). 147 | paramName // Name of the file parameter that gets transferred (Default: 'file'). 148 | maxFilesize // Maximum file size for the upload files in megabytes (Default: null). 149 | acceptedFiles // Comma separated list of mime types or file extensions (Default: null). 150 | ``` 151 | 152 | For more detailed documentation with all the supported Dropzone events / options see the Dropzone documentation. 153 | 154 | ##### Available control / helper functions (provided by the directive): 155 | 156 | ```javascript 157 | dropzone() // Returns reference to the Dropzone instance for full API access. 158 | 159 | reset(cancel?) // Removes all processed files (optionally cancels uploads as well). 160 | ``` 161 | 162 | Above functions can be accessed through the directive reference (available as directiveRef in the component). 163 | -------------------------------------------------------------------------------- /projects/lib/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/lib", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | }, 7 | "allowedNonPeerDependencies": [ 8 | "dropzone" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /projects/lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "license": "MIT", 3 | "version": "17.0.0", 4 | "name": "ngx-dropzone-wrapper", 5 | "description": "Angular wrapper library for Dropzone", 6 | "bugs": "https://github.com/zefoy/ngx-dropzone-wrapper/issues", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/zefoy/ngx-dropzone-wrapper.git" 10 | }, 11 | "dependencies": { 12 | "dropzone": "^5.9.0" 13 | }, 14 | "peerDependencies": { 15 | "@angular/common": ">=9.0.0", 16 | "@angular/core": ">=9.0.0" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /projects/lib/src/lib/dropzone.component.css: -------------------------------------------------------------------------------- 1 | dropzone { 2 | display: block; 3 | width: 100%; 4 | height: auto; 5 | } 6 | 7 | dropzone.flex { 8 | display: flex; 9 | flex-direction: inherit; 10 | min-width: 0; 11 | min-height: 0; 12 | 13 | -webkit-box-direction: inherit; 14 | -webkit-box-orient: inherit; 15 | } 16 | 17 | dropzone.flex > .dropzone.dz-wrapper { 18 | flex: 1 1 auto; 19 | min-width: 0; 20 | min-height: 0; 21 | 22 | -webkit-box-flex: 1; 23 | } 24 | 25 | dropzone.flex { 26 | align-items: inherit; 27 | align-content: inherit; 28 | justify-content: inherit; 29 | 30 | -webkit-box-align: inherit; 31 | -webkit-box-pack: inherit; 32 | } 33 | 34 | dropzone.flex > .dropzone.dz-wrapper.dz-single { 35 | display: flex; 36 | flex-direction: column; 37 | align-items: center; 38 | align-content: center; 39 | justify-content: center; 40 | 41 | -webkit-box-align: center; 42 | -webkit-box-direction: column; 43 | -webkit-box-orient: column; 44 | -webkit-box-pack: center; 45 | } 46 | 47 | dropzone.flex > .dropzone.dz-wrapper.dz-multiple { 48 | display: flex; 49 | flex-flow: row wrap; 50 | align-items: flex-start; 51 | align-content: flex-start; 52 | justify-content: space-between; 53 | 54 | -webkit-box-align: flex-start; 55 | -webkit-box-direction: row; 56 | -webkit-box-orient: row; 57 | -webkit-box-pack: flex-start; 58 | } 59 | 60 | dropzone > .dropzone.dz-wrapper { 61 | position: relative; 62 | 63 | overflow: auto; 64 | width: 100%; 65 | min-height: 0; 66 | max-height: 100%; 67 | padding: 0; 68 | border: none; 69 | 70 | color: #666; 71 | background: transparent; 72 | } 73 | 74 | dropzone > .dropzone.dz-wrapper .dz-message { 75 | position: relative; 76 | 77 | display: inline-block; 78 | overflow: auto; 79 | width: calc(100% - 16px); 80 | min-width: calc(100% - 16px); 81 | min-height: 40px; 82 | max-width: calc(100% - 16px); 83 | max-height: 100%; 84 | margin: 8px; 85 | border: 2px dashed #aaa; 86 | 87 | background-color: #eee; 88 | } 89 | 90 | dropzone > .dropzone.dz-wrapper .dz-message .dz-text { 91 | position: absolute; 92 | top: 50%; 93 | 94 | width: 100%; 95 | padding: 8px 16px; 96 | 97 | text-align: center; 98 | 99 | transform: translateY(-50%); 100 | } 101 | 102 | dropzone > .dropzone.dz-wrapper .dz-message .dz-image { 103 | width: 100%; 104 | height: 100%; 105 | 106 | background-size: contain; 107 | background-repeat: no-repeat; 108 | background-position: 50% 50%; 109 | } 110 | 111 | dropzone > .dropzone.dz-wrapper .dz-message.disabled { 112 | cursor: not-allowed; 113 | } 114 | 115 | dropzone > .dropzone.dz-wrapper .dz-message.disabled .dz-text { 116 | opacity: 0.5; 117 | } 118 | 119 | dropzone > .dropzone.dz-wrapper .dz-message.dz-placeholder { 120 | border-color: rgba(#aaa, 0); 121 | } 122 | 123 | dropzone > .dropzone.dz-wrapper .dz-message.dz-placeholder .dz-text { 124 | position: absolute; 125 | z-index: 1; 126 | top: 0; 127 | right: 10%; 128 | left: 10%; 129 | 130 | opacity: 0; 131 | 132 | font-weight: bold; 133 | background-color: rgba(#fff, 0.5); 134 | 135 | transform: translateY(-50%); 136 | transition: 137 | filter 250ms ease-in-out, 138 | opacity 250ms ease-in-out, 139 | border-color 250ms ease-in-out; 140 | } 141 | 142 | dropzone > .dropzone.dz-wrapper .dz-message.dz-placeholder:hover:not(.disabled) { 143 | border-color: #aaa; 144 | } 145 | 146 | dropzone > .dropzone.dz-wrapper .dz-message.dz-placeholder:hover:not(.disabled) .dz-text { 147 | opacity: 1; 148 | } 149 | 150 | dropzone > .dropzone.dz-wrapper .dz-message.dz-placeholder:hover:not(.disabled) .dz-image { 151 | -webkit-filter: blur(8px); 152 | 153 | filter: blur(8px); 154 | } 155 | 156 | dropzone > .dropzone.dz-wrapper .dz-preview { 157 | margin: 8px; 158 | } 159 | 160 | dropzone > .dropzone.dz-wrapper .dz-preview .dz-details { 161 | padding: 24px; 162 | } 163 | 164 | dropzone > .dropzone.dz-wrapper .dz-preview .dz-progress { 165 | width: 80%; 166 | margin-left: -40%; 167 | border: 1px solid #aaa; 168 | border-radius: 4px; 169 | } 170 | 171 | dropzone > .dropzone.dz-wrapper .dz-preview .dz-progress .dz-upload { 172 | background-color: #666; 173 | } 174 | 175 | dropzone > .dropzone.dz-wrapper .dz-preview .dz-filename span { 176 | display: block; 177 | overflow: hidden; 178 | width: 100%; 179 | max-width: 100%; 180 | 181 | text-overflow: ellipsis; 182 | } 183 | 184 | dropzone > .dropzone.dz-wrapper .dz-preview .dz-filename span:hover { 185 | overflow: visible; 186 | 187 | white-space: normal; 188 | word-wrap: break-word; 189 | } 190 | 191 | dropzone > .dropzone.dz-wrapper.dz-single .dz-message { 192 | width: 100%; 193 | height: 100%; 194 | } 195 | 196 | dropzone > .dropzone.dz-wrapper.dz-single.dz-started .dz-message { 197 | display: none; 198 | } 199 | 200 | dropzone > .dropzone.dz-wrapper.dz-single .dz-preview { 201 | width: calc(100% - 16px); 202 | height: 100%; 203 | } 204 | 205 | dropzone > .dropzone.dz-wrapper.dz-single .dz-preview .dz-image { 206 | width: 100%; 207 | height: 100%; 208 | border-radius: 0; 209 | } 210 | 211 | dropzone > .dropzone.dz-wrapper.dz-single .dz-preview .dz-image img { 212 | display: block; 213 | width: 100%; 214 | height: auto; 215 | margin: 0; 216 | } 217 | 218 | dropzone > .dropzone.dz-wrapper.dz-single .dz-error-message { 219 | top: 50%; 220 | left: 50%; 221 | 222 | transform: translateX(-50%) translateY(100%); 223 | } 224 | 225 | dropzone > .dropzone.dz-wrapper.dz-multiple.dz-started .dz-message { 226 | display: inline-block; 227 | } 228 | -------------------------------------------------------------------------------- /projects/lib/src/lib/dropzone.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |
7 | 8 | 9 |
10 | -------------------------------------------------------------------------------- /projects/lib/src/lib/dropzone.component.ts: -------------------------------------------------------------------------------- 1 | import { PLATFORM_ID } from '@angular/core'; 2 | import { isPlatformBrowser } from '@angular/common'; 3 | import { Inject, Component, 4 | OnInit, Input, Output, EventEmitter, 5 | ViewChild, ViewEncapsulation } from '@angular/core'; 6 | 7 | import { DropzoneDirective } from './dropzone.directive'; 8 | 9 | import { DropzoneEvent, DropzoneEvents, DropzoneConfigInterface } from './dropzone.interfaces'; 10 | 11 | @Component({ 12 | selector: 'dropzone', 13 | exportAs: 'ngxDropzone', 14 | templateUrl: './dropzone.component.html', 15 | styleUrls: [ 16 | './dropzone.component.css', 17 | '../../../../node_modules/dropzone/dist/min/dropzone.min.css' 18 | ], 19 | encapsulation: ViewEncapsulation.None 20 | }) 21 | export class DropzoneComponent implements OnInit { 22 | @Input() disabled: boolean = false; 23 | 24 | @Input() config?: DropzoneConfigInterface; 25 | 26 | @Input() message: string = 'Click or drag files to upload'; 27 | @Input() placeholder: string = ''; 28 | 29 | @Input() useDropzoneClass: boolean = true; 30 | 31 | @Output('init' ) DZ_INIT = new EventEmitter(); 32 | 33 | @Output('error' ) DZ_ERROR = new EventEmitter(); 34 | @Output('success' ) DZ_SUCCESS = new EventEmitter(); 35 | @Output('sending' ) DZ_SENDING = new EventEmitter(); 36 | @Output('canceled' ) DZ_CANCELED = new EventEmitter(); 37 | @Output('complete' ) DZ_COMPLETE = new EventEmitter(); 38 | @Output('processing' ) DZ_PROCESSING = new EventEmitter(); 39 | 40 | @Output('drop' ) DZ_DROP = new EventEmitter(); 41 | @Output('dragStart' ) DZ_DRAGSTART = new EventEmitter(); 42 | @Output('dragEnd' ) DZ_DRAGEND = new EventEmitter(); 43 | @Output('dragEnter' ) DZ_DRAGENTER = new EventEmitter(); 44 | @Output('dragOver' ) DZ_DRAGOVER = new EventEmitter(); 45 | @Output('dragLeave' ) DZ_DRAGLEAVE = new EventEmitter(); 46 | 47 | @Output('thumbnail' ) DZ_THUMBNAIL = new EventEmitter(); 48 | @Output('addedFile' ) DZ_ADDEDFILE = new EventEmitter(); 49 | @Output('addedFiles' ) DZ_ADDEDFILES = new EventEmitter(); 50 | @Output('removedFile' ) DZ_REMOVEDFILE = new EventEmitter(); 51 | @Output('uploadProgress' ) DZ_UPLOADPROGRESS = new EventEmitter(); 52 | @Output('maxFilesReached' ) DZ_MAXFILESREACHED = new EventEmitter(); 53 | @Output('maxFilesExceeded' ) DZ_MAXFILESEXCEEDED = new EventEmitter(); 54 | 55 | @Output('errorMultiple' ) DZ_ERRORMULTIPLE = new EventEmitter(); 56 | @Output('successMultiple' ) DZ_SUCCESSMULTIPLE = new EventEmitter(); 57 | @Output('sendingMultiple' ) DZ_SENDINGMULTIPLE = new EventEmitter(); 58 | @Output('canceledMultiple' ) DZ_CANCELEDMULTIPLE = new EventEmitter(); 59 | @Output('completeMultiple' ) DZ_COMPLETEMULTIPLE = new EventEmitter(); 60 | @Output('processingMultiple' ) DZ_PROCESSINGMULTIPLE = new EventEmitter(); 61 | 62 | @Output('reset' ) DZ_RESET = new EventEmitter(); 63 | @Output('queueComplete' ) DZ_QUEUECOMPLETE = new EventEmitter(); 64 | @Output('totalUploadProgress' ) DZ_TOTALUPLOADPROGRESS = new EventEmitter(); 65 | 66 | @ViewChild(DropzoneDirective, { static: true }) directiveRef?: DropzoneDirective; 67 | 68 | constructor(@Inject(PLATFORM_ID) private platformId: Object) {} 69 | 70 | ngOnInit(): void { 71 | if (!isPlatformBrowser(this.platformId)) { 72 | return; 73 | } 74 | 75 | window.setTimeout(() => { 76 | DropzoneEvents.forEach((eventName: DropzoneEvent) => { 77 | if (this.directiveRef) { 78 | const output = `DZ_${eventName.toUpperCase()}`; 79 | 80 | const directiveOutput = output as keyof DropzoneDirective; 81 | const componentOutput = output as keyof DropzoneComponent; 82 | 83 | this.directiveRef[directiveOutput] = this[componentOutput] as any; 84 | } 85 | }); 86 | }, 0); 87 | } 88 | 89 | public getPlaceholder(): string { 90 | return 'url(' + encodeURI(this.placeholder) + ')'; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /projects/lib/src/lib/dropzone.directive.ts: -------------------------------------------------------------------------------- 1 | import { Dropzone } from "dropzone"; 2 | 3 | import { PLATFORM_ID } from "@angular/core"; 4 | import { isPlatformBrowser } from "@angular/common"; 5 | import { 6 | NgZone, 7 | Inject, 8 | Optional, 9 | ElementRef, 10 | Renderer2, 11 | Directive, 12 | OnInit, 13 | OnDestroy, 14 | DoCheck, 15 | OnChanges, 16 | Input, 17 | Output, 18 | EventEmitter, 19 | SimpleChanges, 20 | KeyValueDiffer, 21 | KeyValueDiffers, 22 | } from "@angular/core"; 23 | 24 | import { 25 | DROPZONE_CONFIG, 26 | DropzoneConfig, 27 | DropzoneConfigInterface, 28 | DropzoneEvent, 29 | DropzoneEvents, 30 | } from "./dropzone.interfaces"; 31 | 32 | @Directive({ 33 | selector: "[dropzone]", 34 | exportAs: "ngxDropzone", 35 | }) 36 | export class DropzoneDirective 37 | implements OnInit, OnDestroy, DoCheck, OnChanges 38 | { 39 | private instance: any; 40 | 41 | private configDiff: KeyValueDiffer | null = null; 42 | 43 | @Input() disabled: boolean = false; 44 | 45 | @Input("dropzone") config?: DropzoneConfigInterface; 46 | 47 | @Output("init") DZ_INIT = new EventEmitter(); 48 | 49 | @Output("error") DZ_ERROR = new EventEmitter(); 50 | @Output("success") DZ_SUCCESS = new EventEmitter(); 51 | @Output("sending") DZ_SENDING = new EventEmitter(); 52 | @Output("canceled") DZ_CANCELED = new EventEmitter(); 53 | @Output("complete") DZ_COMPLETE = new EventEmitter(); 54 | @Output("processing") DZ_PROCESSING = new EventEmitter(); 55 | 56 | @Output("drop") DZ_DROP = new EventEmitter(); 57 | @Output("dragStart") DZ_DRAGSTART = new EventEmitter(); 58 | @Output("dragEnd") DZ_DRAGEND = new EventEmitter(); 59 | @Output("dragEnter") DZ_DRAGENTER = new EventEmitter(); 60 | @Output("dragOver") DZ_DRAGOVER = new EventEmitter(); 61 | @Output("dragLeave") DZ_DRAGLEAVE = new EventEmitter(); 62 | 63 | @Output("thumbnail") DZ_THUMBNAIL = new EventEmitter(); 64 | @Output("addedFile") DZ_ADDEDFILE = new EventEmitter(); 65 | @Output("addedFiles") DZ_ADDEDFILES = new EventEmitter(); 66 | @Output("removedFile") DZ_REMOVEDFILE = new EventEmitter(); 67 | @Output("uploadProgress") DZ_UPLOADPROGRESS = new EventEmitter(); 68 | @Output("maxFilesReached") DZ_MAXFILESREACHED = new EventEmitter(); 69 | @Output("maxFilesExceeded") DZ_MAXFILESEXCEEDED = new EventEmitter(); 70 | 71 | @Output("errorMultiple") DZ_ERRORMULTIPLE = new EventEmitter(); 72 | @Output("successMultiple") DZ_SUCCESSMULTIPLE = new EventEmitter(); 73 | @Output("sendingMultiple") DZ_SENDINGMULTIPLE = new EventEmitter(); 74 | @Output("canceledMultiple") DZ_CANCELEDMULTIPLE = new EventEmitter(); 75 | @Output("completeMultiple") DZ_COMPLETEMULTIPLE = new EventEmitter(); 76 | @Output("processingMultiple") DZ_PROCESSINGMULTIPLE = new EventEmitter(); 77 | 78 | @Output("reset") DZ_RESET = new EventEmitter(); 79 | @Output("queueComplete") DZ_QUEUECOMPLETE = new EventEmitter(); 80 | @Output("totalUploadProgress") DZ_TOTALUPLOADPROGRESS = 81 | new EventEmitter(); 82 | 83 | constructor( 84 | private zone: NgZone, 85 | private renderer: Renderer2, 86 | private elementRef: ElementRef, 87 | private differs: KeyValueDiffers, 88 | @Inject(PLATFORM_ID) private platformId: Object, 89 | @Optional() 90 | @Inject(DROPZONE_CONFIG) 91 | private defaults: DropzoneConfigInterface 92 | ) { 93 | const dz = Dropzone; 94 | 95 | dz.autoDiscover = false; 96 | } 97 | 98 | ngOnInit(): void { 99 | if (!isPlatformBrowser(this.platformId)) { 100 | return; 101 | } 102 | 103 | const params = new DropzoneConfig(this.defaults); 104 | 105 | params.assign(this.config); // Custom configuration 106 | 107 | this.renderer.addClass( 108 | this.elementRef.nativeElement, 109 | params.maxFiles === 1 ? "dz-single" : "dz-multiple" 110 | ); 111 | 112 | this.renderer.removeClass( 113 | this.elementRef.nativeElement, 114 | params.maxFiles === 1 ? "dz-multiple" : "dz-single" 115 | ); 116 | 117 | Object.keys(params).forEach(key => params[key] === undefined && delete params[key]) 118 | 119 | this.zone.runOutsideAngular(() => { 120 | this.instance = new Dropzone(this.elementRef.nativeElement, params); 121 | }); 122 | 123 | if (this.disabled) { 124 | this.instance.disable(); 125 | } 126 | 127 | if (this.DZ_INIT.observers.length) { 128 | this.zone.run(() => { 129 | this.DZ_INIT.emit(this.instance); 130 | }); 131 | } 132 | 133 | // Add auto reset handling for events 134 | this.instance.on("success", () => { 135 | if (params.autoReset != null) { 136 | setTimeout(() => this.reset(), params.autoReset); 137 | } 138 | }); 139 | 140 | this.instance.on("error", () => { 141 | if (params.errorReset != null) { 142 | setTimeout(() => this.reset(), params.errorReset); 143 | } 144 | }); 145 | 146 | this.instance.on("canceled", () => { 147 | if (params.cancelReset != null) { 148 | setTimeout(() => this.reset(), params.cancelReset); 149 | } 150 | }); 151 | 152 | // Add native Dropzone event handling 153 | DropzoneEvents.forEach((eventName: DropzoneEvent) => { 154 | this.instance.on(eventName.toLowerCase(), (...args: any[]) => { 155 | args = args.length === 1 ? args[0] : args; 156 | 157 | const output = `DZ_${eventName.toUpperCase()}`; 158 | 159 | const emitter = this[ 160 | output as keyof DropzoneDirective 161 | ] as EventEmitter; 162 | 163 | if (emitter.observers.length > 0) { 164 | this.zone.run(() => { 165 | emitter.emit(args); 166 | }); 167 | } 168 | }); 169 | }); 170 | 171 | if (!this.configDiff) { 172 | this.configDiff = this.differs.find(this.config || {}).create(); 173 | 174 | this.configDiff.diff(this.config || {}); 175 | } 176 | } 177 | 178 | ngOnDestroy(): void { 179 | if (this.instance) { 180 | this.zone.runOutsideAngular(() => { 181 | this.instance.destroy(); 182 | }); 183 | 184 | this.instance = null; 185 | } 186 | } 187 | 188 | ngDoCheck(): void { 189 | if (!this.disabled && this.configDiff) { 190 | const changes = this.configDiff.diff(this.config || {}); 191 | 192 | if (changes && this.instance) { 193 | this.ngOnDestroy(); 194 | 195 | this.ngOnInit(); 196 | } 197 | } 198 | } 199 | 200 | ngOnChanges(changes: SimpleChanges): void { 201 | if (this.instance && changes["disabled"]) { 202 | if ( 203 | changes["disabled"].currentValue !== changes["disabled"].previousValue 204 | ) { 205 | if (changes["disabled"].currentValue === false) { 206 | this.zone.runOutsideAngular(() => { 207 | this.instance.enable(); 208 | }); 209 | } else if (changes["disabled"].currentValue === true) { 210 | this.zone.runOutsideAngular(() => { 211 | this.instance.disable(); 212 | }); 213 | } 214 | } 215 | } 216 | } 217 | 218 | public dropzone(): any { 219 | return this.instance; 220 | } 221 | 222 | public reset(cancel?: boolean): void { 223 | if (this.instance) { 224 | this.zone.runOutsideAngular(() => { 225 | this.instance.removeAllFiles(cancel); 226 | }); 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /projects/lib/src/lib/dropzone.interfaces.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from '@angular/core'; 2 | 3 | export const DROPZONE_CONFIG = new InjectionToken('DROPZONE_CONFIG'); 4 | 5 | export type DropzoneEvent = 'error' | 'success' | 'sending' | 'canceled' | 'complete' | 6 | 'processing' | 'drop' | 'dragStart' | 'dragEnd' | 'dragEnter' | 'dragOver' | 'dragLeave' | 7 | 'thumbnail' | 'addedFile' | 'addedFiles' | 'removedFile' | 'uploadProgress' | 'maxFilesReached' | 8 | 'maxFilesExceeded' | 'errorMultiple' | 'successMultiple' | 'sendingMultiple' | 'canceledMultiple' | 9 | 'completeMultiple' | 'processingMultiple' | 'reset' | 'queueComplete' | 'totalUploadProgress'; 10 | 11 | export const DropzoneEvents: DropzoneEvent[] = [ 12 | 'error', 13 | 'success', 14 | 'sending', 15 | 'canceled', 16 | 'complete', 17 | 'processing', 18 | 19 | 'drop', 20 | 'dragStart', 21 | 'dragEnd', 22 | 'dragEnter', 23 | 'dragOver', 24 | 'dragLeave', 25 | 26 | 'thumbnail', 27 | 'addedFile', 28 | 'addedFiles', 29 | 'removedFile', 30 | 'uploadProgress', 31 | 'maxFilesReached', 32 | 'maxFilesExceeded', 33 | 34 | 'errorMultiple', 35 | 'successMultiple', 36 | 'sendingMultiple', 37 | 'canceledMultiple', 38 | 'completeMultiple', 39 | 'processingMultiple', 40 | 41 | 'reset', 42 | 'queueComplete', 43 | 'totalUploadProgress' 44 | ]; 45 | 46 | export interface DropzoneConfigInterface { 47 | timeout?: number, 48 | 49 | autoReset?: number | null, 50 | errorReset?: number | null, 51 | cancelReset?: number | null, 52 | 53 | url?: string | DropzoneUrlFunction, 54 | method?: string | DropzoneMethodFunction, 55 | 56 | params?: any | DropzoneParamsFunction, 57 | headers?: any | DropzoneHeadersFunction, 58 | 59 | init?: DropzoneInitFunction, 60 | accept?: DropzoneAcceptFunction, 61 | resize?: DropzoneResizeFunction, 62 | fallback?: DropzoneFallbackFunction, 63 | renameFile?: DropzoneRenameFileFunction, 64 | transformFile?: DropzoneTransformFileFunction, 65 | chunksUploaded?: DropzoneChunksUploadedFunction, 66 | 67 | withCredentials?: boolean, 68 | 69 | previewsContainer?: any, 70 | hiddenInputContainer?: any, 71 | 72 | clickable?: string | string[] | boolean, 73 | paramName?: any, 74 | capture?: string, 75 | maxFiles?: number, 76 | maxFilesize?: number, 77 | filesizeBase?: number, 78 | acceptedFiles?: string, 79 | forceFallback?: boolean, 80 | addRemoveLinks?: boolean, 81 | uploadMultiple?: boolean, 82 | parallelUploads?: number, 83 | resizeWidth?: number, 84 | resizeHeight?: number, 85 | resizeMethod?: 'contain' | 'crop', 86 | resizeQuality?: number, 87 | resizeMimeType?: string, 88 | thumbnailWidth?: number, 89 | thumbnailHeight?: number, 90 | thumbnailMethod?: 'contain' | 'crop', 91 | previewTemplate?: string, 92 | autoQueue?: boolean, 93 | autoProcessQueue?: boolean, 94 | ignoreHiddenFiles?: boolean, 95 | maxThumbnailFilesize?: number, 96 | createImageThumbnails?: boolean, 97 | 98 | chunking?: boolean, 99 | chunkSize?: number, 100 | retryChunks?: boolean, 101 | forceChunking?: boolean, 102 | retryChunksLimit?: number, 103 | parallelChunkUploads?: boolean, 104 | 105 | dictFileSizeUnits?: any, 106 | 107 | dictDefaultMessage?: string, 108 | dictFallbackMessage?: string, 109 | 110 | dictFileTooBig?: string, 111 | dictResponseError?: string, 112 | dictInvalidFileType?: string, 113 | 114 | dictRemoveFile?: string, 115 | dictCancelUpload?: string, 116 | dictUploadCanceled?: string, 117 | dictFallbackText?: string, 118 | dictMaxFilesExceeded?: string, 119 | dictRemoveFileConfirmation?: string, 120 | dictCancelUploadConfirmation?: string 121 | } 122 | 123 | export class DropzoneConfig implements DropzoneConfigInterface { 124 | timeout?: number; 125 | 126 | autoReset?: number; 127 | errorReset?: number; 128 | cancelReset?: number; 129 | 130 | url?: string | DropzoneUrlFunction; 131 | method?: string | DropzoneMethodFunction; 132 | 133 | params?: any | DropzoneParamsFunction; 134 | headers?: any | DropzoneHeadersFunction; 135 | 136 | init?: DropzoneInitFunction; 137 | accept?: DropzoneAcceptFunction; 138 | resize?: DropzoneResizeFunction; 139 | fallback?: DropzoneFallbackFunction; 140 | renameFile?: DropzoneRenameFileFunction; 141 | transformFile?: DropzoneTransformFileFunction; 142 | chunksUploaded?: DropzoneChunksUploadedFunction; 143 | 144 | withCredentials?: boolean; 145 | 146 | previewsContainer?: any; 147 | hiddenInputContainer?: any; 148 | 149 | clickable?: string | string[] | boolean; 150 | paramName?: any; 151 | capture?: string; 152 | maxFiles?: number; 153 | maxFilesize?: number; 154 | filesizeBase?: number; 155 | acceptedFiles?: string; 156 | forceFallback?: boolean; 157 | addRemoveLinks?: boolean; 158 | uploadMultiple?: boolean; 159 | parallelUploads?: number; 160 | resizeWidth?: number; 161 | resizeHeight?: number; 162 | resizeMethod?: 'contain' | 'crop'; 163 | resizeQuality?: number; 164 | resizeMimeType?: string; 165 | thumbnailWidth?: number; 166 | thumbnailHeight?: number; 167 | thumbnailMethod?: 'contain' | 'crop'; 168 | previewTemplate?: string; 169 | autoQueue?: boolean; 170 | autoProcessQueue?: boolean; 171 | ignoreHiddenFiles?: boolean; 172 | maxThumbnailFilesize?: number; 173 | createImageThumbnails?: boolean; 174 | 175 | chunking?: boolean; 176 | chunkSize?: number; 177 | retryChunks?: boolean; 178 | forceChunking?: boolean; 179 | retryChunksLimit?: number; 180 | parallelChunkUploads?: boolean; 181 | 182 | dictFileSizeUnits?: any; 183 | 184 | dictDefaultMessage?: string; 185 | dictFallbackMessage?: string; 186 | 187 | dictFileTooBig?: string; 188 | dictResponseError?: string; 189 | dictInvalidFileType?: string; 190 | 191 | dictRemoveFile?: string; 192 | dictCancelUpload?: string; 193 | dictUploadCanceled?: string; 194 | dictFallbackText?: string; 195 | dictMaxFilesExceeded?: string; 196 | dictRemoveFileConfirmation?: string; 197 | dictCancelUploadConfirmation?: string; 198 | 199 | constructor(config: DropzoneConfigInterface = {}) { 200 | this.assign(config); 201 | } 202 | 203 | assign(config: DropzoneConfigInterface | any = {}, target?: any) { 204 | target = target || this; 205 | 206 | for (const key in config) { 207 | if (config[key] != null && !(Array.isArray(config[key])) && 208 | typeof config[key] === 'object' && !(config[key] instanceof HTMLElement)) 209 | { 210 | target[key] = {}; 211 | 212 | this.assign(config[key], target[key]); 213 | } else { 214 | target[key] = config[key]; 215 | } 216 | } 217 | } 218 | } 219 | 220 | export type DropzoneUrlFunction = (files: any) => string; 221 | export type DropzoneMethodFunction = (files: any) => string; 222 | 223 | export type DropzoneParamsFunction = (files: any, xhr: any, chunk?: any) => any; 224 | export type DropzoneHeadersFunction = () => any; 225 | 226 | export type DropzoneInitFunction = () => any; 227 | export type DropzoneFallbackFunction = () => HTMLElement; 228 | 229 | export type DropzoneAcceptFunction = (file: File, done: Function) => any; 230 | export type DropzoneResizeFunction = (file: File, width: number, height: number, resizeMethod: string) => any; 231 | 232 | export type DropzoneRenameFileFunction = (file: File) => string; 233 | export type DropzoneTransformFileFunction = (file: File, done: Function) => any; 234 | export type DropzoneChunksUploadedFunction = (file: File, done: Function) => any; 235 | -------------------------------------------------------------------------------- /projects/lib/src/lib/dropzone.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { DropzoneComponent } from './dropzone.component'; 5 | import { DropzoneDirective } from './dropzone.directive'; 6 | 7 | @NgModule({ 8 | imports: [CommonModule], 9 | declarations: [DropzoneComponent, DropzoneDirective], 10 | exports: [CommonModule, DropzoneComponent, DropzoneDirective] 11 | }) 12 | export class DropzoneModule { 13 | } 14 | -------------------------------------------------------------------------------- /projects/lib/src/public-api.ts: -------------------------------------------------------------------------------- 1 | export { DropzoneComponent } from './lib/dropzone.component'; 2 | export { DropzoneDirective } from './lib/dropzone.directive'; 3 | 4 | export { 5 | DROPZONE_CONFIG, 6 | 7 | DropzoneConfig, 8 | DropzoneConfigInterface, 9 | 10 | DropzoneUrlFunction, 11 | DropzoneMethodFunction, 12 | DropzoneParamsFunction, 13 | DropzoneHeadersFunction, 14 | 15 | DropzoneInitFunction, 16 | DropzoneFallbackFunction, 17 | DropzoneAcceptFunction, 18 | DropzoneResizeFunction, 19 | DropzoneRenameFileFunction, 20 | DropzoneTransformFileFunction, 21 | DropzoneChunksUploadedFunction 22 | } from './lib/dropzone.interfaces'; 23 | 24 | export { DropzoneModule } from './lib/dropzone.module'; 25 | -------------------------------------------------------------------------------- /projects/lib/stylelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "stylelint-order" 4 | ], 5 | "extends": [ 6 | "stylelint-config-standard" 7 | ], 8 | "rules": { 9 | "color-hex-case": "lower", 10 | "color-no-invalid-hex": true, 11 | 12 | "font-family-no-missing-generic-family-keyword": null, 13 | "function-calc-no-unspaced-operator": true, 14 | "function-comma-space-after": "always-single-line", 15 | "function-comma-space-before": "never", 16 | "function-name-case": "lower", 17 | "function-url-quotes": "always", 18 | "function-whitespace-after": "always", 19 | 20 | "number-leading-zero": "always", 21 | "number-no-trailing-zeros": true, 22 | "length-zero-no-unit": true, 23 | 24 | "string-no-newline": true, 25 | "string-quotes": "single", 26 | 27 | "unit-case": "lower", 28 | "unit-no-unknown": true, 29 | "unit-whitelist": [ 30 | "px", 31 | "%", 32 | "deg", 33 | "ms", 34 | "em" 35 | ], 36 | 37 | "value-list-comma-space-after": "always-single-line", 38 | "value-list-comma-space-before": "never", 39 | 40 | "shorthand-property-no-redundant-values": true, 41 | 42 | "property-case": "lower", 43 | 44 | "at-rule-empty-line-before": [ 45 | "always", 46 | { 47 | "ignore": [ 48 | "blockless-after-blockless" 49 | ] 50 | } 51 | ], 52 | 53 | "at-rule-no-unknown": null, 54 | 55 | "declaration-block-no-duplicate-properties": true, 56 | "declaration-block-trailing-semicolon": "always", 57 | "declaration-block-single-line-max-declarations": 1, 58 | "declaration-block-semicolon-space-before": "never", 59 | "declaration-block-semicolon-space-after": "always-single-line", 60 | "declaration-block-semicolon-newline-before": "never-multi-line", 61 | "declaration-block-semicolon-newline-after": "always-multi-line", 62 | 63 | "block-closing-brace-newline-after": "always", 64 | "block-closing-brace-newline-before": "always-multi-line", 65 | "block-no-empty": true, 66 | "block-opening-brace-newline-after": "always-multi-line", 67 | "block-opening-brace-space-before": "always-multi-line", 68 | 69 | "selector-attribute-brackets-space-inside": "never", 70 | "selector-attribute-operator-space-after": "never", 71 | "selector-attribute-operator-space-before": "never", 72 | "selector-combinator-space-after": "always", 73 | "selector-combinator-space-before": "always", 74 | "selector-pseudo-class-case": "lower", 75 | "selector-pseudo-class-parentheses-space-inside": "never", 76 | "selector-pseudo-element-case": "lower", 77 | "selector-pseudo-element-colon-notation": "double", 78 | "selector-pseudo-element-no-unknown": true, 79 | "selector-type-no-unknown": null, 80 | "selector-type-case": "lower", 81 | "selector-max-id": 0, 82 | 83 | "declaration-empty-line-before": null, 84 | 85 | "no-descending-specificity": null, 86 | 87 | "order/properties-order": [ 88 | [ 89 | { 90 | "properties": [ 91 | "content", 92 | "direction" 93 | ] 94 | }, { 95 | "emptyLineBefore": "always", 96 | "properties": [ 97 | "float", 98 | "position", 99 | "z-index", 100 | "top", 101 | "right", 102 | "bottom", 103 | "left" 104 | ] 105 | }, { 106 | "emptyLineBefore": "always", 107 | "properties": [ 108 | "visibility", 109 | "opacity", 110 | "display", 111 | "overflow", 112 | "box-sizing", 113 | "flex", 114 | "flex-basis", 115 | "flex-direction", 116 | "flex-flow", 117 | "flex-grow", 118 | "flex-shrink", 119 | "flex-wrap", 120 | "align-self", 121 | "align-items", 122 | "align-content", 123 | "justify-content", 124 | "order", 125 | "width", 126 | "height", 127 | "min-width", 128 | "min-height", 129 | "max-width", 130 | "max-height", 131 | "padding", 132 | "padding-top", 133 | "padding-right", 134 | "padding-bottom", 135 | "padding-left", 136 | "margin", 137 | "margin-top", 138 | "margin-right", 139 | "margin-bottom", 140 | "margin-left", 141 | "border", 142 | "border-top", 143 | "border-right", 144 | "border-bottom", 145 | "border-left", 146 | "border-width", 147 | "border-top-width", 148 | "border-right-width", 149 | "border-bottom-width", 150 | "border-left-width", 151 | "border-style", 152 | "border-top-style", 153 | "border-right-style", 154 | "border-bottom-style", 155 | "border-left-style", 156 | "border-color", 157 | "border-top-color", 158 | "border-right-color", 159 | "border-bottom-color", 160 | "border-left-color", 161 | "border-radius", 162 | "border-top-left-radius", 163 | "border-top-right-radius", 164 | "border-bottom-right-radius", 165 | "border-bottom-left-radius", 166 | "outline" 167 | ] 168 | }, { 169 | "emptyLineBefore": "always", 170 | "properties": [ 171 | "cursor", 172 | "resize", 173 | "user-select", 174 | "touch-action", 175 | "pointer-events", 176 | "font-size", 177 | "font-style", 178 | "font-weight", 179 | "font-family", 180 | "line-height", 181 | "white-space", 182 | "text-align", 183 | "text-shadow", 184 | "text-decoration", 185 | "text-transform", 186 | "text-overflow", 187 | "letter-spacing", 188 | "list-style-type", 189 | "object-fit", 190 | "vertical-align", 191 | "color", 192 | "background", 193 | "background-size", 194 | "background-color", 195 | "background-image", 196 | "background-repeat", 197 | "background-position", 198 | "background-attachment", 199 | "box-shadow" 200 | ] 201 | }, { 202 | "emptyLineBefore": "always", 203 | "properties": [ 204 | "filter", 205 | "animation", 206 | "animation-name", 207 | "animation-delay", 208 | "animation-duration", 209 | "animation-direction", 210 | "animation-fill-mode", 211 | "animation-play-state", 212 | "animation-iteration-count", 213 | "animation-timing-function", 214 | "transform", 215 | "transform-style", 216 | "transform-origin", 217 | "transition", 218 | "transition-delay", 219 | "transition-duration", 220 | "transition-property", 221 | "transition-timing-function" 222 | ] 223 | } 224 | ], 225 | { 226 | "unspecified": "bottomAlphabetical" 227 | } 228 | ] 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /projects/lib/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "target": "es2022", 6 | "declaration": true, 7 | "inlineSources": true, 8 | "stripInternal": true, 9 | "types": [], 10 | "lib": [ 11 | "dom", 12 | "es2022" 13 | ] 14 | }, 15 | "angularCompilerOptions": { 16 | "skipTemplateCodegen": true, 17 | "strictMetadataEmit": true, 18 | "enableResourceInlining": true, 19 | "compilationMode": "partial" 20 | }, 21 | "exclude": [ 22 | "src/test.ts", 23 | "**/*.spec.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | "./projects/app/src/**/*.{html,ts}", 5 | ], 6 | theme: { 7 | extend: {}, 8 | }, 9 | plugins: [], 10 | } 11 | 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "allowSyntheticDefaultImports": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "importHelpers": true, 14 | "target": "es2022", 15 | "typeRoots": [ 16 | "node_modules/@types" 17 | ], 18 | "lib": [ 19 | "dom", 20 | "es2022" 21 | ], 22 | "paths": { 23 | "ngx-dropzone-wrapper": [ 24 | "./projects/lib/src/public-api.ts" 25 | ] 26 | } 27 | }, 28 | "angularCompilerOptions": { 29 | "fullTemplateTypeCheck": true, 30 | "strictInjectionParameters": true 31 | } 32 | } 33 | --------------------------------------------------------------------------------