primevue
Version:
PrimeVue is an open source UI library for Vue featuring a rich set of 80+ components, a theme designer, various theme alternatives such as Material, Bootstrap, Tailwind, premium templates and professional support. In addition, it integrates with PrimeBloc
1 lines • 79.5 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","sources":["../../src/fileupload/BaseFileUpload.vue","../../src/fileupload/FileContent.vue","../../src/fileupload/FileContent.vue?vue&type=template&id=4b9f1ffb&lang.js","../../src/fileupload/FileUpload.vue","../../src/fileupload/FileUpload.vue?vue&type=template&id=4070c2f4&lang.js"],"sourcesContent":["<script>\nimport BaseComponent from '@primevue/core/basecomponent';\nimport FileUploadStyle from 'primevue/fileupload/style';\n\nexport default {\n name: 'BaseFileUpload',\n extends: BaseComponent,\n props: {\n name: {\n type: String,\n default: null\n },\n url: {\n type: String,\n default: null\n },\n mode: {\n type: String,\n default: 'advanced'\n },\n multiple: {\n type: Boolean,\n default: false\n },\n accept: {\n type: String,\n default: null\n },\n disabled: {\n type: Boolean,\n default: false\n },\n auto: {\n type: Boolean,\n default: false\n },\n maxFileSize: {\n type: Number,\n default: null\n },\n invalidFileSizeMessage: {\n type: String,\n default: '{0}: Invalid file size, file size should be smaller than {1}.'\n },\n invalidFileTypeMessage: {\n type: String,\n default: '{0}: Invalid file type, allowed file types: {1}.'\n },\n fileLimit: {\n type: Number,\n default: null\n },\n invalidFileLimitMessage: {\n type: String,\n default: 'Maximum number of files exceeded, limit is {0} at most.'\n },\n withCredentials: {\n type: Boolean,\n default: false\n },\n previewWidth: {\n type: Number,\n default: 50\n },\n chooseLabel: {\n type: String,\n default: null\n },\n uploadLabel: {\n type: String,\n default: null\n },\n cancelLabel: {\n type: String,\n default: null\n },\n customUpload: {\n type: Boolean,\n default: false\n },\n showUploadButton: {\n type: Boolean,\n default: true\n },\n showCancelButton: {\n type: Boolean,\n default: true\n },\n chooseIcon: {\n type: String,\n default: undefined\n },\n uploadIcon: {\n type: String,\n default: undefined\n },\n cancelIcon: {\n type: String,\n default: undefined\n },\n style: null,\n class: null,\n chooseButtonProps: {\n type: null,\n default: null\n },\n uploadButtonProps: {\n type: Object,\n default() {\n return { severity: 'secondary' };\n }\n },\n cancelButtonProps: {\n type: Object,\n default() {\n return { severity: 'secondary' };\n }\n }\n },\n style: FileUploadStyle,\n provide() {\n return {\n $pcFileUpload: this,\n $parentInstance: this\n };\n }\n};\n</script>\n","<template>\n <div v-for=\"(file, index) of files\" :key=\"file.name + file.type + file.size\" :class=\"cx('file')\" v-bind=\"ptm('file')\">\n <img role=\"presentation\" :class=\"cx('fileThumbnail')\" :alt=\"file.name\" :src=\"file.objectURL\" :width=\"previewWidth\" v-bind=\"ptm('fileThumbnail')\" />\n <div :class=\"cx('fileInfo')\" v-bind=\"ptm('fileInfo')\">\n <div :class=\"cx('fileName')\" v-bind=\"ptm('fileName')\">{{ file.name }}</div>\n <span :class=\"cx('fileSize')\" v-bind=\"ptm('fileSize')\">{{ formatSize(file.size) }}</span>\n </div>\n <Badge :value=\"badgeValue\" :class=\"cx('pcFileBadge')\" :severity=\"badgeSeverity\" :unstyled=\"unstyled\" :pt=\"ptm('pcFileBadge')\" />\n <div :class=\"cx('fileActions')\" v-bind=\"ptm('fileActions')\">\n <Button @click=\"$emit('remove', index)\" text rounded severity=\"danger\" :class=\"cx('pcFileRemoveButton')\" :unstyled=\"unstyled\" :pt=\"ptm('pcFileRemoveButton')\">\n <template #icon=\"iconProps\">\n <component v-if=\"templates.fileremoveicon\" :is=\"templates.fileremoveicon\" :class=\"iconProps.class\" :file=\"file\" :index=\"index\" />\n <TimesIcon v-else :class=\"iconProps.class\" aria-hidden=\"true\" v-bind=\"ptm('pcFileRemoveButton')['icon']\" />\n </template>\n </Button>\n </div>\n </div>\n</template>\n\n<script>\nimport BaseComponent from '@primevue/core/basecomponent';\nimport TimesIcon from '@primevue/icons/times';\nimport Badge from 'primevue/badge';\nimport Button from 'primevue/button';\n\nexport default {\n name: 'FileContent',\n hostName: 'FileUpload',\n extends: BaseComponent,\n emits: ['remove'],\n props: {\n files: {\n type: Array,\n default: () => []\n },\n badgeSeverity: {\n type: String,\n default: 'warn'\n },\n badgeValue: {\n type: String,\n default: null\n },\n previewWidth: {\n type: Number,\n default: 50\n },\n templates: {\n type: null,\n default: null\n }\n },\n methods: {\n formatSize(bytes) {\n const k = 1024;\n const dm = 3;\n const sizes = this.$primevue.config.locale?.fileSizeTypes || ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n\n if (bytes === 0) {\n return `0 ${sizes[0]}`;\n }\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));\n\n return `${formattedSize} ${sizes[i]}`;\n }\n },\n components: {\n Button,\n Badge,\n TimesIcon\n }\n};\n</script>\n","<template>\n <div v-for=\"(file, index) of files\" :key=\"file.name + file.type + file.size\" :class=\"cx('file')\" v-bind=\"ptm('file')\">\n <img role=\"presentation\" :class=\"cx('fileThumbnail')\" :alt=\"file.name\" :src=\"file.objectURL\" :width=\"previewWidth\" v-bind=\"ptm('fileThumbnail')\" />\n <div :class=\"cx('fileInfo')\" v-bind=\"ptm('fileInfo')\">\n <div :class=\"cx('fileName')\" v-bind=\"ptm('fileName')\">{{ file.name }}</div>\n <span :class=\"cx('fileSize')\" v-bind=\"ptm('fileSize')\">{{ formatSize(file.size) }}</span>\n </div>\n <Badge :value=\"badgeValue\" :class=\"cx('pcFileBadge')\" :severity=\"badgeSeverity\" :unstyled=\"unstyled\" :pt=\"ptm('pcFileBadge')\" />\n <div :class=\"cx('fileActions')\" v-bind=\"ptm('fileActions')\">\n <Button @click=\"$emit('remove', index)\" text rounded severity=\"danger\" :class=\"cx('pcFileRemoveButton')\" :unstyled=\"unstyled\" :pt=\"ptm('pcFileRemoveButton')\">\n <template #icon=\"iconProps\">\n <component v-if=\"templates.fileremoveicon\" :is=\"templates.fileremoveicon\" :class=\"iconProps.class\" :file=\"file\" :index=\"index\" />\n <TimesIcon v-else :class=\"iconProps.class\" aria-hidden=\"true\" v-bind=\"ptm('pcFileRemoveButton')['icon']\" />\n </template>\n </Button>\n </div>\n </div>\n</template>\n\n<script>\nimport BaseComponent from '@primevue/core/basecomponent';\nimport TimesIcon from '@primevue/icons/times';\nimport Badge from 'primevue/badge';\nimport Button from 'primevue/button';\n\nexport default {\n name: 'FileContent',\n hostName: 'FileUpload',\n extends: BaseComponent,\n emits: ['remove'],\n props: {\n files: {\n type: Array,\n default: () => []\n },\n badgeSeverity: {\n type: String,\n default: 'warn'\n },\n badgeValue: {\n type: String,\n default: null\n },\n previewWidth: {\n type: Number,\n default: 50\n },\n templates: {\n type: null,\n default: null\n }\n },\n methods: {\n formatSize(bytes) {\n const k = 1024;\n const dm = 3;\n const sizes = this.$primevue.config.locale?.fileSizeTypes || ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n\n if (bytes === 0) {\n return `0 ${sizes[0]}`;\n }\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));\n\n return `${formattedSize} ${sizes[i]}`;\n }\n },\n components: {\n Button,\n Badge,\n TimesIcon\n }\n};\n</script>\n","<template>\n <div v-if=\"isAdvanced\" :class=\"cx('root')\" v-bind=\"ptmi('root')\">\n <input ref=\"fileInput\" type=\"file\" @change=\"onFileSelect\" :multiple=\"multiple\" :accept=\"accept\" :disabled=\"chooseDisabled\" v-bind=\"ptm('input')\" />\n <div :class=\"cx('header')\" v-bind=\"ptm('header')\">\n <slot name=\"header\" :files=\"files\" :uploadedFiles=\"uploadedFiles\" :chooseCallback=\"choose\" :uploadCallback=\"uploader\" :clearCallback=\"clear\">\n <Button\n :label=\"chooseButtonLabel\"\n :class=\"chooseButtonClass\"\n :style=\"style\"\n :disabled=\"disabled\"\n :unstyled=\"unstyled\"\n @click=\"choose\"\n @keydown.enter=\"choose\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n v-bind=\"chooseButtonProps\"\n :pt=\"ptm('pcChooseButton')\"\n >\n <template #icon=\"iconProps\">\n <slot name=\"chooseicon\">\n <component :is=\"chooseIcon ? 'span' : 'PlusIcon'\" :class=\"[iconProps.class, chooseIcon]\" aria-hidden=\"true\" v-bind=\"ptm('pcChooseButton')['icon']\" />\n </slot>\n </template>\n </Button>\n <Button v-if=\"showUploadButton\" :class=\"cx('pcUploadButton')\" :label=\"uploadButtonLabel\" @click=\"uploader\" :disabled=\"uploadDisabled\" :unstyled=\"unstyled\" v-bind=\"uploadButtonProps\" :pt=\"ptm('pcUploadButton')\">\n <template #icon=\"iconProps\">\n <slot name=\"uploadicon\">\n <component :is=\"uploadIcon ? 'span' : 'UploadIcon'\" :class=\"[iconProps.class, uploadIcon]\" aria-hidden=\"true\" v-bind=\"ptm('pcUploadButton')['icon']\" data-pc-section=\"uploadbuttonicon\" />\n </slot>\n </template>\n </Button>\n <Button v-if=\"showCancelButton\" :class=\"cx('pcCancelButton')\" :label=\"cancelButtonLabel\" @click=\"clear\" :disabled=\"cancelDisabled\" :unstyled=\"unstyled\" v-bind=\"cancelButtonProps\" :pt=\"ptm('pcCancelButton')\">\n <template #icon=\"iconProps\">\n <slot name=\"cancelicon\">\n <component :is=\"cancelIcon ? 'span' : 'TimesIcon'\" :class=\"[iconProps.class, cancelIcon]\" aria-hidden=\"true\" v-bind=\"ptm('pcCancelButton')['icon']\" data-pc-section=\"cancelbuttonicon\" />\n </slot>\n </template>\n </Button>\n </slot>\n </div>\n <div ref=\"content\" :class=\"cx('content')\" @dragenter=\"onDragEnter\" @dragover=\"onDragOver\" @dragleave=\"onDragLeave\" @drop=\"onDrop\" v-bind=\"ptm('content')\" :data-p-highlight=\"false\">\n <slot name=\"content\" :files=\"files\" :uploadedFiles=\"uploadedFiles\" :removeUploadedFileCallback=\"removeUploadedFile\" :removeFileCallback=\"remove\" :progress=\"progress\" :messages=\"messages\">\n <ProgressBar v-if=\"hasFiles\" :value=\"progress\" :showValue=\"false\" :unstyled=\"unstyled\" :pt=\"ptm('pcProgressbar')\" />\n <Message v-for=\"msg of messages\" :key=\"msg\" severity=\"error\" @close=\"onMessageClose\" :unstyled=\"unstyled\" :pt=\"ptm('pcMessage')\">{{ msg }}</Message>\n <div v-if=\"hasFiles\" :class=\"cx('fileList')\">\n <FileContent :files=\"files\" @remove=\"remove\" :badgeValue=\"pendingLabel\" :previewWidth=\"previewWidth\" :templates=\"$slots\" :unstyled=\"unstyled\" :pt=\"pt\" />\n </div>\n <div v-if=\"hasUploadedFiles\" :class=\"cx('fileList')\">\n <FileContent :files=\"uploadedFiles\" @remove=\"removeUploadedFile\" :badgeValue=\"completedLabel\" badgeSeverity=\"success\" :previewWidth=\"previewWidth\" :templates=\"$slots\" :unstyled=\"unstyled\" :pt=\"pt\" />\n </div>\n </slot>\n <div v-if=\"$slots.empty && !hasFiles && !hasUploadedFiles\" v-bind=\"ptm('empty')\">\n <slot name=\"empty\"></slot>\n </div>\n </div>\n </div>\n <div v-else-if=\"isBasic\" :class=\"cx('root')\" v-bind=\"ptmi('root')\">\n <Message v-for=\"msg of messages\" :key=\"msg\" severity=\"error\" @close=\"onMessageClose\" :unstyled=\"unstyled\" :pt=\"ptm('pcMessage')\">{{ msg }}</Message>\n <Button\n :label=\"chooseButtonLabel\"\n :class=\"chooseButtonClass\"\n :style=\"style\"\n :disabled=\"disabled\"\n :unstyled=\"unstyled\"\n @mouseup=\"onBasicUploaderClick\"\n @keydown.enter=\"choose\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n v-bind=\"chooseButtonProps\"\n :pt=\"ptm('pcChooseButton')\"\n >\n <template #icon=\"iconProps\">\n <slot name=\"chooseicon\">\n <component :is=\"chooseIcon ? 'span' : 'PlusIcon'\" :class=\"[iconProps.class, chooseIcon]\" aria-hidden=\"true\" v-bind=\"ptm('pcChooseButton')['icon']\" />\n </slot>\n </template>\n </Button>\n <slot v-if=\"!auto\" name=\"filelabel\" :class=\"cx('filelabel')\">\n <span :class=\"cx('filelabel')\" :files=\"files\">\n {{ basicFileChosenLabel }}\n </span>\n </slot>\n <input ref=\"fileInput\" type=\"file\" :accept=\"accept\" :disabled=\"disabled\" :multiple=\"multiple\" @change=\"onFileSelect\" @focus=\"onFocus\" @blur=\"onBlur\" v-bind=\"ptm('input')\" />\n </div>\n</template>\n\n<script>\nimport { addClass, removeClass } from '@primeuix/utils/dom';\nimport PlusIcon from '@primevue/icons/plus';\nimport TimesIcon from '@primevue/icons/times';\nimport UploadIcon from '@primevue/icons/upload';\nimport Button from 'primevue/button';\nimport Message from 'primevue/message';\nimport ProgressBar from 'primevue/progressbar';\nimport Ripple from 'primevue/ripple';\nimport BaseFileUpload from './BaseFileUpload.vue';\nimport FileContent from './FileContent.vue';\n\nexport default {\n name: 'FileUpload',\n extends: BaseFileUpload,\n inheritAttrs: false,\n emits: ['select', 'uploader', 'before-upload', 'progress', 'upload', 'error', 'before-send', 'clear', 'remove', 'remove-uploaded-file'],\n duplicateIEEvent: false,\n data() {\n return {\n uploadedFileCount: 0,\n files: [],\n messages: [],\n focused: false,\n progress: null,\n uploadedFiles: []\n };\n },\n methods: {\n upload() {\n if (this.hasFiles) this.uploader();\n },\n onBasicUploaderClick(event) {\n if (event.button === 0) this.$refs.fileInput.click();\n },\n onFileSelect(event) {\n if (event.type !== 'drop' && this.isIE11() && this.duplicateIEEvent) {\n this.duplicateIEEvent = false;\n\n return;\n }\n\n if (this.isBasic && this.hasFiles) {\n this.files = [];\n }\n\n this.messages = [];\n this.files = this.files || [];\n let files = event.dataTransfer ? event.dataTransfer.files : event.target.files;\n\n for (let file of files) {\n if (!this.isFileSelected(file) && !this.isFileLimitExceeded()) {\n if (this.validate(file)) {\n if (this.isImage(file)) {\n file.objectURL = window.URL.createObjectURL(file);\n }\n\n this.files.push(file);\n }\n }\n }\n\n this.$emit('select', { originalEvent: event, files: this.files });\n\n if (this.fileLimit) {\n this.checkFileLimit();\n }\n\n if (this.auto && this.hasFiles && !this.isFileLimitExceeded()) {\n this.uploader();\n }\n\n if (event.type !== 'drop' && this.isIE11()) {\n this.clearIEInput();\n } else {\n this.clearInputElement();\n }\n },\n choose() {\n this.$refs.fileInput.click();\n },\n uploader() {\n if (this.customUpload) {\n if (this.fileLimit) {\n this.uploadedFileCount += this.files.length;\n }\n\n this.$emit('uploader', { files: this.files });\n this.clear();\n } else {\n let xhr = new XMLHttpRequest();\n let formData = new FormData();\n\n this.$emit('before-upload', {\n xhr: xhr,\n formData: formData\n });\n\n for (let file of this.files) {\n formData.append(this.name, file, file.name);\n }\n\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable) {\n this.progress = Math.round((event.loaded * 100) / event.total);\n }\n\n this.$emit('progress', {\n originalEvent: event,\n progress: this.progress\n });\n });\n\n xhr.onreadystatechange = () => {\n if (xhr.readyState === 4) {\n this.progress = 0;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n if (this.fileLimit) {\n this.uploadedFileCount += this.files.length;\n }\n\n this.$emit('upload', {\n xhr: xhr,\n files: this.files\n });\n this.uploadedFiles.push(...this.files);\n } else {\n this.$emit('error', {\n xhr: xhr,\n files: this.files\n });\n }\n\n this.clear();\n }\n };\n\n if (this.url) {\n xhr.open('POST', this.url, true);\n\n this.$emit('before-send', {\n xhr: xhr,\n formData: formData\n });\n\n xhr.withCredentials = this.withCredentials;\n\n xhr.send(formData);\n }\n }\n },\n clear() {\n this.files = [];\n this.messages = null;\n this.$emit('clear');\n\n if (this.isAdvanced) {\n this.clearInputElement();\n }\n },\n onFocus() {\n this.focused = true;\n },\n onBlur() {\n this.focused = false;\n },\n isFileSelected(file) {\n if (this.files && this.files.length) {\n for (let sFile of this.files) {\n if (sFile.name + sFile.type + sFile.size === file.name + file.type + file.size) return true;\n }\n }\n\n return false;\n },\n isIE11() {\n return !!window['MSInputMethodContext'] && !!document['documentMode'];\n },\n validate(file) {\n if (this.accept && !this.isFileTypeValid(file)) {\n this.messages.push(this.invalidFileTypeMessage.replace('{0}', file.name).replace('{1}', this.accept));\n\n return false;\n }\n\n if (this.maxFileSize && file.size > this.maxFileSize) {\n this.messages.push(this.invalidFileSizeMessage.replace('{0}', file.name).replace('{1}', this.formatSize(this.maxFileSize)));\n\n return false;\n }\n\n return true;\n },\n isFileTypeValid(file) {\n let acceptableTypes = this.accept.split(',').map((type) => type.trim());\n\n for (let type of acceptableTypes) {\n let acceptable = this.isWildcard(type) ? this.getTypeClass(file.type) === this.getTypeClass(type) : file.type == type || this.getFileExtension(file).toLowerCase() === type.toLowerCase();\n\n if (acceptable) {\n return true;\n }\n }\n\n return false;\n },\n getTypeClass(fileType) {\n return fileType.substring(0, fileType.indexOf('/'));\n },\n isWildcard(fileType) {\n return fileType.indexOf('*') !== -1;\n },\n getFileExtension(file) {\n return '.' + file.name.split('.').pop();\n },\n isImage(file) {\n return /^image\\//.test(file.type);\n },\n onDragEnter(event) {\n if (!this.disabled) {\n event.stopPropagation();\n event.preventDefault();\n }\n },\n onDragOver(event) {\n if (!this.disabled) {\n !this.isUnstyled && addClass(this.$refs.content, 'p-fileupload-highlight');\n this.$refs.content.setAttribute('data-p-highlight', true);\n event.stopPropagation();\n event.preventDefault();\n }\n },\n onDragLeave() {\n if (!this.disabled) {\n !this.isUnstyled && removeClass(this.$refs.content, 'p-fileupload-highlight');\n this.$refs.content.setAttribute('data-p-highlight', false);\n }\n },\n onDrop(event) {\n if (!this.disabled) {\n !this.isUnstyled && removeClass(this.$refs.content, 'p-fileupload-highlight');\n this.$refs.content.setAttribute('data-p-highlight', false);\n event.stopPropagation();\n event.preventDefault();\n\n const files = event.dataTransfer ? event.dataTransfer.files : event.target.files;\n const allowDrop = this.multiple || (files && files.length === 1);\n\n if (allowDrop) {\n this.onFileSelect(event);\n }\n }\n },\n remove(index) {\n this.clearInputElement();\n let removedFile = this.files.splice(index, 1)[0];\n\n this.files = [...this.files];\n this.$emit('remove', {\n file: removedFile,\n files: this.files\n });\n },\n removeUploadedFile(index) {\n let removedFile = this.uploadedFiles.splice(index, 1)[0];\n\n this.uploadedFiles = [...this.uploadedFiles];\n this.$emit('remove-uploaded-file', {\n file: removedFile,\n files: this.uploadedFiles\n });\n },\n clearInputElement() {\n this.$refs.fileInput.value = '';\n },\n clearIEInput() {\n if (this.$refs.fileInput) {\n this.duplicateIEEvent = true; //IE11 fix to prevent onFileChange trigger again\n this.$refs.fileInput.value = '';\n }\n },\n formatSize(bytes) {\n const k = 1024;\n const dm = 3;\n const sizes = this.$primevue.config.locale?.fileSizeTypes || ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n\n if (bytes === 0) {\n return `0 ${sizes[0]}`;\n }\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));\n\n return `${formattedSize} ${sizes[i]}`;\n },\n isFileLimitExceeded() {\n if (this.fileLimit && this.fileLimit <= this.files.length + this.uploadedFileCount && this.focused) {\n this.focused = false;\n }\n\n return this.fileLimit && this.fileLimit < this.files.length + this.uploadedFileCount;\n },\n checkFileLimit() {\n if (this.isFileLimitExceeded()) {\n this.messages.push(this.invalidFileLimitMessage.replace('{0}', this.fileLimit.toString()));\n }\n },\n onMessageClose() {\n this.messages = null;\n }\n },\n computed: {\n isAdvanced() {\n return this.mode === 'advanced';\n },\n isBasic() {\n return this.mode === 'basic';\n },\n chooseButtonClass() {\n return [this.cx('pcChooseButton'), this.class];\n },\n basicFileChosenLabel() {\n if (this.auto) return this.chooseButtonLabel;\n else if (this.hasFiles) {\n if (this.files && this.files.length === 1) return this.files[0].name;\n\n return this.$primevue.config.locale?.fileChosenMessage?.replace('{0}', this.files.length);\n }\n\n return this.$primevue.config.locale?.noFileChosenMessage || '';\n },\n hasFiles() {\n return this.files && this.files.length > 0;\n },\n hasUploadedFiles() {\n return this.uploadedFiles && this.uploadedFiles.length > 0;\n },\n chooseDisabled() {\n return this.disabled || (this.fileLimit && this.fileLimit <= this.files.length + this.uploadedFileCount);\n },\n uploadDisabled() {\n return this.disabled || !this.hasFiles || (this.fileLimit && this.fileLimit < this.files.length);\n },\n cancelDisabled() {\n return this.disabled || !this.hasFiles;\n },\n chooseButtonLabel() {\n return this.chooseLabel || this.$primevue.config.locale.choose;\n },\n uploadButtonLabel() {\n return this.uploadLabel || this.$primevue.config.locale.upload;\n },\n cancelButtonLabel() {\n return this.cancelLabel || this.$primevue.config.locale.cancel;\n },\n completedLabel() {\n return this.$primevue.config.locale.completed;\n },\n pendingLabel() {\n return this.$primevue.config.locale.pending;\n }\n },\n components: {\n Button,\n ProgressBar,\n Message,\n FileContent,\n PlusIcon,\n UploadIcon,\n TimesIcon\n },\n directives: {\n ripple: Ripple\n }\n};\n</script>\n","<template>\n <div v-if=\"isAdvanced\" :class=\"cx('root')\" v-bind=\"ptmi('root')\">\n <input ref=\"fileInput\" type=\"file\" @change=\"onFileSelect\" :multiple=\"multiple\" :accept=\"accept\" :disabled=\"chooseDisabled\" v-bind=\"ptm('input')\" />\n <div :class=\"cx('header')\" v-bind=\"ptm('header')\">\n <slot name=\"header\" :files=\"files\" :uploadedFiles=\"uploadedFiles\" :chooseCallback=\"choose\" :uploadCallback=\"uploader\" :clearCallback=\"clear\">\n <Button\n :label=\"chooseButtonLabel\"\n :class=\"chooseButtonClass\"\n :style=\"style\"\n :disabled=\"disabled\"\n :unstyled=\"unstyled\"\n @click=\"choose\"\n @keydown.enter=\"choose\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n v-bind=\"chooseButtonProps\"\n :pt=\"ptm('pcChooseButton')\"\n >\n <template #icon=\"iconProps\">\n <slot name=\"chooseicon\">\n <component :is=\"chooseIcon ? 'span' : 'PlusIcon'\" :class=\"[iconProps.class, chooseIcon]\" aria-hidden=\"true\" v-bind=\"ptm('pcChooseButton')['icon']\" />\n </slot>\n </template>\n </Button>\n <Button v-if=\"showUploadButton\" :class=\"cx('pcUploadButton')\" :label=\"uploadButtonLabel\" @click=\"uploader\" :disabled=\"uploadDisabled\" :unstyled=\"unstyled\" v-bind=\"uploadButtonProps\" :pt=\"ptm('pcUploadButton')\">\n <template #icon=\"iconProps\">\n <slot name=\"uploadicon\">\n <component :is=\"uploadIcon ? 'span' : 'UploadIcon'\" :class=\"[iconProps.class, uploadIcon]\" aria-hidden=\"true\" v-bind=\"ptm('pcUploadButton')['icon']\" data-pc-section=\"uploadbuttonicon\" />\n </slot>\n </template>\n </Button>\n <Button v-if=\"showCancelButton\" :class=\"cx('pcCancelButton')\" :label=\"cancelButtonLabel\" @click=\"clear\" :disabled=\"cancelDisabled\" :unstyled=\"unstyled\" v-bind=\"cancelButtonProps\" :pt=\"ptm('pcCancelButton')\">\n <template #icon=\"iconProps\">\n <slot name=\"cancelicon\">\n <component :is=\"cancelIcon ? 'span' : 'TimesIcon'\" :class=\"[iconProps.class, cancelIcon]\" aria-hidden=\"true\" v-bind=\"ptm('pcCancelButton')['icon']\" data-pc-section=\"cancelbuttonicon\" />\n </slot>\n </template>\n </Button>\n </slot>\n </div>\n <div ref=\"content\" :class=\"cx('content')\" @dragenter=\"onDragEnter\" @dragover=\"onDragOver\" @dragleave=\"onDragLeave\" @drop=\"onDrop\" v-bind=\"ptm('content')\" :data-p-highlight=\"false\">\n <slot name=\"content\" :files=\"files\" :uploadedFiles=\"uploadedFiles\" :removeUploadedFileCallback=\"removeUploadedFile\" :removeFileCallback=\"remove\" :progress=\"progress\" :messages=\"messages\">\n <ProgressBar v-if=\"hasFiles\" :value=\"progress\" :showValue=\"false\" :unstyled=\"unstyled\" :pt=\"ptm('pcProgressbar')\" />\n <Message v-for=\"msg of messages\" :key=\"msg\" severity=\"error\" @close=\"onMessageClose\" :unstyled=\"unstyled\" :pt=\"ptm('pcMessage')\">{{ msg }}</Message>\n <div v-if=\"hasFiles\" :class=\"cx('fileList')\">\n <FileContent :files=\"files\" @remove=\"remove\" :badgeValue=\"pendingLabel\" :previewWidth=\"previewWidth\" :templates=\"$slots\" :unstyled=\"unstyled\" :pt=\"pt\" />\n </div>\n <div v-if=\"hasUploadedFiles\" :class=\"cx('fileList')\">\n <FileContent :files=\"uploadedFiles\" @remove=\"removeUploadedFile\" :badgeValue=\"completedLabel\" badgeSeverity=\"success\" :previewWidth=\"previewWidth\" :templates=\"$slots\" :unstyled=\"unstyled\" :pt=\"pt\" />\n </div>\n </slot>\n <div v-if=\"$slots.empty && !hasFiles && !hasUploadedFiles\" v-bind=\"ptm('empty')\">\n <slot name=\"empty\"></slot>\n </div>\n </div>\n </div>\n <div v-else-if=\"isBasic\" :class=\"cx('root')\" v-bind=\"ptmi('root')\">\n <Message v-for=\"msg of messages\" :key=\"msg\" severity=\"error\" @close=\"onMessageClose\" :unstyled=\"unstyled\" :pt=\"ptm('pcMessage')\">{{ msg }}</Message>\n <Button\n :label=\"chooseButtonLabel\"\n :class=\"chooseButtonClass\"\n :style=\"style\"\n :disabled=\"disabled\"\n :unstyled=\"unstyled\"\n @mouseup=\"onBasicUploaderClick\"\n @keydown.enter=\"choose\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n v-bind=\"chooseButtonProps\"\n :pt=\"ptm('pcChooseButton')\"\n >\n <template #icon=\"iconProps\">\n <slot name=\"chooseicon\">\n <component :is=\"chooseIcon ? 'span' : 'PlusIcon'\" :class=\"[iconProps.class, chooseIcon]\" aria-hidden=\"true\" v-bind=\"ptm('pcChooseButton')['icon']\" />\n </slot>\n </template>\n </Button>\n <slot v-if=\"!auto\" name=\"filelabel\" :class=\"cx('filelabel')\">\n <span :class=\"cx('filelabel')\" :files=\"files\">\n {{ basicFileChosenLabel }}\n </span>\n </slot>\n <input ref=\"fileInput\" type=\"file\" :accept=\"accept\" :disabled=\"disabled\" :multiple=\"multiple\" @change=\"onFileSelect\" @focus=\"onFocus\" @blur=\"onBlur\" v-bind=\"ptm('input')\" />\n </div>\n</template>\n\n<script>\nimport { addClass, removeClass } from '@primeuix/utils/dom';\nimport PlusIcon from '@primevue/icons/plus';\nimport TimesIcon from '@primevue/icons/times';\nimport UploadIcon from '@primevue/icons/upload';\nimport Button from 'primevue/button';\nimport Message from 'primevue/message';\nimport ProgressBar from 'primevue/progressbar';\nimport Ripple from 'primevue/ripple';\nimport BaseFileUpload from './BaseFileUpload.vue';\nimport FileContent from './FileContent.vue';\n\nexport default {\n name: 'FileUpload',\n extends: BaseFileUpload,\n inheritAttrs: false,\n emits: ['select', 'uploader', 'before-upload', 'progress', 'upload', 'error', 'before-send', 'clear', 'remove', 'remove-uploaded-file'],\n duplicateIEEvent: false,\n data() {\n return {\n uploadedFileCount: 0,\n files: [],\n messages: [],\n focused: false,\n progress: null,\n uploadedFiles: []\n };\n },\n methods: {\n upload() {\n if (this.hasFiles) this.uploader();\n },\n onBasicUploaderClick(event) {\n if (event.button === 0) this.$refs.fileInput.click();\n },\n onFileSelect(event) {\n if (event.type !== 'drop' && this.isIE11() && this.duplicateIEEvent) {\n this.duplicateIEEvent = false;\n\n return;\n }\n\n if (this.isBasic && this.hasFiles) {\n this.files = [];\n }\n\n this.messages = [];\n this.files = this.files || [];\n let files = event.dataTransfer ? event.dataTransfer.files : event.target.files;\n\n for (let file of files) {\n if (!this.isFileSelected(file) && !this.isFileLimitExceeded()) {\n if (this.validate(file)) {\n if (this.isImage(file)) {\n file.objectURL = window.URL.createObjectURL(file);\n }\n\n this.files.push(file);\n }\n }\n }\n\n this.$emit('select', { originalEvent: event, files: this.files });\n\n if (this.fileLimit) {\n this.checkFileLimit();\n }\n\n if (this.auto && this.hasFiles && !this.isFileLimitExceeded()) {\n this.uploader();\n }\n\n if (event.type !== 'drop' && this.isIE11()) {\n this.clearIEInput();\n } else {\n this.clearInputElement();\n }\n },\n choose() {\n this.$refs.fileInput.click();\n },\n uploader() {\n if (this.customUpload) {\n if (this.fileLimit) {\n this.uploadedFileCount += this.files.length;\n }\n\n this.$emit('uploader', { files: this.files });\n this.clear();\n } else {\n let xhr = new XMLHttpRequest();\n let formData = new FormData();\n\n this.$emit('before-upload', {\n xhr: xhr,\n formData: formData\n });\n\n for (let file of this.files) {\n formData.append(this.name, file, file.name);\n }\n\n xhr.upload.addEventListener('progress', (event) => {\n if (event.lengthComputable) {\n this.progress = Math.round((event.loaded * 100) / event.total);\n }\n\n this.$emit('progress', {\n originalEvent: event,\n progress: this.progress\n });\n });\n\n xhr.onreadystatechange = () => {\n if (xhr.readyState === 4) {\n this.progress = 0;\n\n if (xhr.status >= 200 && xhr.status < 300) {\n if (this.fileLimit) {\n this.uploadedFileCount += this.files.length;\n }\n\n this.$emit('upload', {\n xhr: xhr,\n files: this.files\n });\n this.uploadedFiles.push(...this.files);\n } else {\n this.$emit('error', {\n xhr: xhr,\n files: this.files\n });\n }\n\n this.clear();\n }\n };\n\n if (this.url) {\n xhr.open('POST', this.url, true);\n\n this.$emit('before-send', {\n xhr: xhr,\n formData: formData\n });\n\n xhr.withCredentials = this.withCredentials;\n\n xhr.send(formData);\n }\n }\n },\n clear() {\n this.files = [];\n this.messages = null;\n this.$emit('clear');\n\n if (this.isAdvanced) {\n this.clearInputElement();\n }\n },\n onFocus() {\n this.focused = true;\n },\n onBlur() {\n this.focused = false;\n },\n isFileSelected(file) {\n if (this.files && this.files.length) {\n for (let sFile of this.files) {\n if (sFile.name + sFile.type + sFile.size === file.name + file.type + file.size) return true;\n }\n }\n\n return false;\n },\n isIE11() {\n return !!window['MSInputMethodContext'] && !!document['documentMode'];\n },\n validate(file) {\n if (this.accept && !this.isFileTypeValid(file)) {\n this.messages.push(this.invalidFileTypeMessage.replace('{0}', file.name).replace('{1}', this.accept));\n\n return false;\n }\n\n if (this.maxFileSize && file.size > this.maxFileSize) {\n this.messages.push(this.invalidFileSizeMessage.replace('{0}', file.name).replace('{1}', this.formatSize(this.maxFileSize)));\n\n return false;\n }\n\n return true;\n },\n isFileTypeValid(file) {\n let acceptableTypes = this.accept.split(',').map((type) => type.trim());\n\n for (let type of acceptableTypes) {\n let acceptable = this.isWildcard(type) ? this.getTypeClass(file.type) === this.getTypeClass(type) : file.type == type || this.getFileExtension(file).toLowerCase() === type.toLowerCase();\n\n if (acceptable) {\n return true;\n }\n }\n\n return false;\n },\n getTypeClass(fileType) {\n return fileType.substring(0, fileType.indexOf('/'));\n },\n isWildcard(fileType) {\n return fileType.indexOf('*') !== -1;\n },\n getFileExtension(file) {\n return '.' + file.name.split('.').pop();\n },\n isImage(file) {\n return /^image\\//.test(file.type);\n },\n onDragEnter(event) {\n if (!this.disabled) {\n event.stopPropagation();\n event.preventDefault();\n }\n },\n onDragOver(event) {\n if (!this.disabled) {\n !this.isUnstyled && addClass(this.$refs.content, 'p-fileupload-highlight');\n this.$refs.content.setAttribute('data-p-highlight', true);\n event.stopPropagation();\n event.preventDefault();\n }\n },\n onDragLeave() {\n if (!this.disabled) {\n !this.isUnstyled && removeClass(this.$refs.content, 'p-fileupload-highlight');\n this.$refs.content.setAttribute('data-p-highlight', false);\n }\n },\n onDrop(event) {\n if (!this.disabled) {\n !this.isUnstyled && removeClass(this.$refs.content, 'p-fileupload-highlight');\n this.$refs.content.setAttribute('data-p-highlight', false);\n event.stopPropagation();\n event.preventDefault();\n\n const files = event.dataTransfer ? event.dataTransfer.files : event.target.files;\n const allowDrop = this.multiple || (files && files.length === 1);\n\n if (allowDrop) {\n this.onFileSelect(event);\n }\n }\n },\n remove(index) {\n this.clearInputElement();\n let removedFile = this.files.splice(index, 1)[0];\n\n this.files = [...this.files];\n this.$emit('remove', {\n file: removedFile,\n files: this.files\n });\n },\n removeUploadedFile(index) {\n let removedFile = this.uploadedFiles.splice(index, 1)[0];\n\n this.uploadedFiles = [...this.uploadedFiles];\n this.$emit('remove-uploaded-file', {\n file: removedFile,\n files: this.uploadedFiles\n });\n },\n clearInputElement() {\n this.$refs.fileInput.value = '';\n },\n clearIEInput() {\n if (this.$refs.fileInput) {\n this.duplicateIEEvent = true; //IE11 fix to prevent onFileChange trigger again\n this.$refs.fileInput.value = '';\n }\n },\n formatSize(bytes) {\n const k = 1024;\n const dm = 3;\n const sizes = this.$primevue.config.locale?.fileSizeTypes || ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n\n if (bytes === 0) {\n return `0 ${sizes[0]}`;\n }\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n const formattedSize = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));\n\n return `${formattedSize} ${sizes[i]}`;\n },\n isFileLimitExceeded() {\n if (this.fileLimit && this.fileLimit <= this.files.length + this.uploadedFileCount && this.focused) {\n this.focused = false;\n }\n\n return this.fileLimit && this.fileLimit < this.files.length + this.uploadedFileCount;\n },\n checkFileLimit() {\n if (this.isFileLimitExceeded()) {\n this.messages.push(this.invalidFileLimitMessage.replace('{0}', this.fileLimit.toString()));\n }\n },\n onMessageClose() {\n this.messages = null;\n }\n },\n computed: {\n isAdvanced() {\n return this.mode === 'advanced';\n },\n isBasic() {\n return this.mode === 'basic';\n },\n chooseButtonClass() {\n return [this.cx('pcChooseButton'), this.class];\n },\n basicFileChosenLabel() {\n if (this.auto) return this.chooseButtonLabel;\n else if (this.hasFiles) {\n if (this.files && this.files.length === 1) return this.files[0].name;\n\n return this.$primevue.config.locale?.fileChosenMessage?.replace('{0}', this.files.length);\n }\n\n return this.$primevue.config.locale?.noFileChosenMessage || '';\n },\n hasFiles() {\n return this.files && this.files.length > 0;\n },\n hasUploadedFiles() {\n return this.uploadedFiles && this.uploadedFiles.length > 0;\n },\n chooseDisabled() {\n return this.disabled || (this.fileLimit && this.fileLimit <= this.files.length + this.uploadedFileCount);\n },\n uploadDisabled() {\n return this.disabled || !this.hasFiles || (this.fileLimit && this.fileLimit < this.files.length);\n },\n cancelDisabled() {\n return this.disabled || !this.hasFiles;\n },\n chooseButtonLabel() {\n return this.chooseLabel || this.$primevue.config.locale.choose;\n },\n uploadButtonLabel() {\n return this.uploadLabel || this.$primevue.config.locale.upload;\n },\n cancelButtonLabel() {\n return this.cancelLabel || this.$primevue.config.locale.cancel;\n },\n completedLabel() {\n return this.$primevue.config.locale.completed;\n },\n pendingLabel() {\n return this.$primevue.config.locale.pending;\n }\n },\n components: {\n Button,\n ProgressBar,\n Message,\n FileContent,\n PlusIcon,\n UploadIcon,\n TimesIcon\n },\n directives: {\n ripple: Ripple\n }\n};\n</script>\n"],"names":["name","BaseComponent","props","type","String","url","mode","multiple","Boolean","accept","disabled","auto","maxFileSize","Number","invalidFileSizeMessage","invalidFileTypeMessage","fileLimit","invalidFileLimitMessage","withCredentials","previewWidth","chooseLabel","uploadLabel","cancelLabel","customUpload","showUploadButton","showCancelButton","chooseIcon","undefined","uploadIcon","cancelIcon","style","chooseButtonProps","uploadButtonProps","Object","default","severity","cancelButtonProps","FileUploadStyle","provide","$pcFileUpload","$parentInstance","hostName","emits","files","Array","badgeSeverity","badgeValue","templates","methods","formatSize","bytes","_this$$primevue$confi","k","dm","sizes","$primevue","config","locale","fileSizeTypes","concat","i","Math","floor","log","formattedSize","parseFloat","pow","toFixed","components","Button","Badge","TimesIcon","_openBlock","_createElementBlock","_Fragment","_renderList","$props","file","index","_mergeProps","key","size","_ctx","cx","ptm","_createElementVNode","role","alt","src","objectURL","width","_hoisted_1","_toDisplayString","$options","_createVNode","_component_Badge","value","unstyled","pt","_component_Button","onClick","$event","$emit","text","rounded","icon","_withCtx","iconProps","fileremoveicon","_createBlock","_resolveDynamicComponent","_normalizeClass","_component_TimesIcon","BaseFileUpload","inheritAttrs","duplicateIEEvent","data","uploadedFileCount","messages","focused","progress","uploadedFiles","upload","hasFiles","uploader","onBasicUploaderClick","event","button","$refs","fileInput","click","onFileSelect","isIE11","isBasic","dataTransfer","target","_iterator","_createForOfIteratorHelper","_step","s","n","done","isFileSelected","isFileLimitExceeded","validate","isImage","window","URL","createObjectURL","push","err","e","f","originalEvent","checkFileLimit","clearIEInput","clearInputElement","choose","_this","length","clear","xhr","XMLHttpRequest","formData","FormData","_iterator2","_step2","append","addEventListener","lengthComputable","round","loaded","total","onreadystatechange","readyState","status","_this$uploadedFiles","apply","_toConsumableArray","open","send","isAdvanced","onFocus","onBlur","_iterator3","_step3","sFile","document","isFileTypeValid","replace","acceptableTypes","split","map","trim","_iterator4","_step4","acceptable","isWildcard","getTypeClass","getFileExtension","toLowerCase","fileType","substring","indexOf","pop","test","onDragEnter","stopPropagation","preventDefault","onDragOver","isUnstyled","addClass","content","setAttribute","onDragLeave","removeClass","onDrop","allowDrop","remove","removedFile","splice","removeUploadedFile","toString","onMessageClose","computed","chooseButtonClass","basicFileChosenLabel","_this$$primevue$confi3","chooseButtonLabel","_this$$primevue$confi2","fileChosenMessage","noFileChosenMessage","hasUploadedFiles","chooseDisabled","uploadDisabled","cancelDisabled","uploadButtonLabel","cancelButtonLabel","cancel","completedLabel","completed","pendingLabel","pending","ProgressBar","Message","FileContent","PlusIcon","UploadIcon"