{"version":3,"file":"upload.mjs","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":["_useModel","Upload"],"mappings":"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"}