@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
1 lines • 11.8 kB
Source Map (JSON)
{"version":3,"file":"upload.cjs","sources":["../../src/components/upload/Upload.vue","../../src/components/upload/index.ts"],"sourcesContent":["<script\n setup\n lang=\"ts\"\n generic=\"\n T extends object | typeof File,\n IsMultiple extends boolean = false\n \">\nimport { computed, ref, useAttrs, useTemplateRef, watch } from \"vue\";\n\nimport { getDefault } from \"@/utils/config\";\nimport { File } from \"@/utils/ssr\";\nimport { isTrueish } from \"@/utils/helpers\";\nimport { defineClasses, useInputHandler } from \"@/composables\";\n\nimport { injectField } from \"../field/fieldInjection\";\n\nimport type { UploadProps } from \"./props\";\n\n/**\n * Upload one or more files.\n * @displayName Upload\n * @style _upload.scss\n */\ndefineOptions({\n isOruga: true,\n name: \"OUpload\",\n configField: \"upload\",\n inheritAttrs: false,\n});\n\ntype ModelValue = UploadProps<T, IsMultiple>[\"modelValue\"];\n\nconst props = withDefaults(defineProps<UploadProps<T, IsMultiple>>(), {\n override: undefined,\n modelValue: undefined,\n // multiple: false,\n variant: () => getDefault(\"upload.variant\"),\n disabled: false,\n accept: undefined,\n dragDrop: false,\n expanded: () => getDefault(\"upload.expanded\", false),\n native: true,\n useHtml5Validation: () => getDefault(\"useHtml5Validation\", true),\n customValidity: \"\",\n});\n\nconst emits = defineEmits<{\n /**\n * modelValue prop two-way binding\n * @param value {object | object[] | File | File[]} updated modelValue prop\n */\n \"update:model-value\": [value: ModelValue];\n /**\n * on input focus event\n * @param event {Event} native event\n */\n focus: [event: Event];\n /**\n * on input blur event\n * @param event {Event} native event\n */\n blur: [event: Event];\n /**\n * on input invalid event\n * @param event {Event} native event\n */\n invalid: [event: Event];\n}>();\n\nconst inputRef = useTemplateRef(\"inputElement\");\n\n// use form input functionality\nconst { checkHtml5Validity, onFocus, onBlur, onInvalid, isValid, setFocus } =\n useInputHandler(inputRef, emits, props);\n\n// inject parent field component if used inside one\nconst { parentField } = injectField();\n\nconst vmodel = defineModel<ModelValue>({ default: undefined });\n\nconst dragDropFocus = ref(false);\n\n/**\n * When v-model is changed:\n * 1. Reset interna input file value\n * 2. If it's invalid, validate again.\n */\nwatch(vmodel, (value) => {\n if (!value || (Array.isArray(value) && value.length === 0))\n if (inputRef.value) inputRef.value.value = \"\";\n if (!isValid.value && !props.dragDrop) checkHtml5Validity();\n});\n\n/**\n * Listen change event on input type 'file',\n * emit 'input' event and validate\n */\nfunction onFileChange(event: Event | DragEvent): void {\n if (props.disabled) return;\n if (props.dragDrop) updateDragDropFocus(false);\n const value =\n (event.target as HTMLInputElement).files ||\n (event as DragEvent).dataTransfer?.files ||\n [];\n // no file selected\n if (value.length === 0) {\n if (!vmodel.value) return;\n if (props.native) vmodel.value = undefined;\n }\n\n // multiple upload\n if (isTrueish(props.multiple)) {\n // always new values if native or undefined local\n const values =\n props.native || !vmodel.value || !Array.isArray(vmodel.value)\n ? []\n : [...vmodel.value];\n\n for (let i = 0; i < value.length; i++) {\n const file = value[i];\n // add file when type is valid\n if (checkType(file)) values.push(file);\n }\n vmodel.value = values as ModelValue;\n }\n // single uplaod\n else {\n // only one element in case drag drop mode and isn't multiple\n if (props.dragDrop && value.length !== 1) return;\n else {\n const file = value[0];\n // add file when type is valid\n if (checkType(file)) vmodel.value = file as ModelValue;\n // else clear input\n else if (vmodel.value) {\n vmodel.value = undefined;\n clearInput();\n } else {\n // Force input back to empty state and recheck validity\n clearInput();\n checkHtml5Validity();\n return;\n }\n }\n }\n\n if (!props.dragDrop) checkHtml5Validity();\n}\n\n/** Reset file input value */\nfunction clearInput(): void {\n if (inputRef.value) inputRef.value.value = \"\";\n}\n\n/** Listen drag-drop to update internal variable */\nfunction updateDragDropFocus(focus: boolean): void {\n if (!props.disabled) dragDropFocus.value = focus;\n}\n\n/** Check mime type of file s*/\nfunction checkType(file: File): boolean {\n if (!props.accept) return true;\n const types = props.accept.split(\",\");\n if (types.length === 0) return true;\n for (let i = 0; i < types.length; i++) {\n const type = types[i].trim();\n if (type) {\n if (type.substring(0, 1) === \".\") {\n const extension = file.name.toLowerCase().slice(-type.length);\n if (extension === type.toLowerCase()) return true;\n } else {\n // check mime type\n if (file.type.match(type)) return true;\n }\n }\n }\n return false;\n}\n\nfunction onClick(event: Event): void {\n if (props.disabled) return;\n\n // click input if not drag and drop is used\n if (!props.dragDrop) {\n event.preventDefault();\n if (inputRef.value) inputRef.value.click();\n }\n}\n\n// --- Computed Component Classes ---\n\nconst attrs = useAttrs();\n\nconst inputBind = computed(() => ({\n ...parentField?.value?.inputAttrs,\n ...attrs,\n}));\n\nconst rootClasses = defineClasses(\n [\"rootClass\", \"o-upload\"],\n [\n \"expandedClass\",\n \"o-upload--expanded\",\n null,\n computed(() => props.expanded),\n ],\n [\n \"disabledClass\",\n \"o-upload--disabled\",\n null,\n computed(() => props.disabled),\n ],\n);\n\nconst draggableClasses = defineClasses(\n [\"draggableClass\", \"o-upload__draggable\"],\n [\n \"hoveredClass\",\n \"o-upload__draggable--hovered\",\n null,\n computed(() => !props.variant && dragDropFocus.value),\n ],\n [\n \"variantClass\",\n \"o-upload__draggable--hovered-\",\n computed(() => props.variant),\n computed(() => !!props.variant && dragDropFocus.value),\n ],\n);\n\n// --- Expose Public Functionalities ---\n\n/** expose functionalities for programmatic usage */\ndefineExpose({ checkHtml5Validity, focus: setFocus, value: vmodel });\n</script>\n\n<template>\n <label data-oruga=\"upload\" :class=\"rootClasses\">\n <template v-if=\"!dragDrop\">\n <!--\n @slot Default content\n @binding {(event: Event): void} onclick - click handler, only needed if a button is used\n -->\n <slot :onclick=\"onClick\" />\n </template>\n\n <div\n v-else\n :class=\"draggableClasses\"\n role=\"button\"\n tabindex=\"0\"\n @mouseenter=\"updateDragDropFocus(true)\"\n @mouseleave=\"updateDragDropFocus(false)\"\n @dragover.prevent=\"updateDragDropFocus(true)\"\n @dragleave.prevent=\"updateDragDropFocus(false)\"\n @dragenter.prevent=\"updateDragDropFocus(true)\"\n @drop.prevent=\"onFileChange\">\n <!--\n @slot Default content\n @binding {(event: Event): void} onclick - click handler, only needed if a button is used\n -->\n <slot :onclick=\"onClick\" />\n </div>\n\n <input\n v-bind=\"inputBind\"\n ref=\"inputElement\"\n type=\"file\"\n data-oruga-input=\"file\"\n :multiple=\"props.multiple\"\n :accept=\"accept\"\n :disabled=\"disabled\"\n @change=\"onFileChange\"\n @focus=\"onFocus\"\n @blur=\"onBlur\"\n @invalid=\"onInvalid\" />\n </label>\n</template>\n","import type { App, Plugin } from \"vue\";\n\nimport Upload from \"./Upload.vue\";\n\nimport { registerComponent } from \"@/utils/plugins\";\n\n/** export upload plugin */\nexport default {\n install(app: App) {\n registerComponent(app, Upload);\n },\n} as Plugin;\n\n/** export upload components */\nexport { Upload as OUpload };\n"],"names":["useTemplateRef","useInputHandler","injectField","_useModel","ref","watch","isTrueish","useAttrs","computed","defineClasses","registerComponent","Upload"],"mappings":"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"}