import { p as proxyCustomElement, H, c as createEvent, h } from './index.js';
import { i as isNestedInIfxComponent, d as detectFramework, t as trackComponent } from './p-bqYaVeZb.js';
import { d as defineCustomElement$5 } from './p-R79iWjuc.js';
import { d as defineCustomElement$4 } from './p-DhNY6ZGA.js';
import { d as defineCustomElement$3 } from './p-F-WOWp_H.js';
import { d as defineCustomElement$2 } from './p-CDq1_QJF.js';

const fileUploadCss = ":root{--ifx-font-family:\"Source Sans 3\", \"Arial, sans-serif\"}:host{font-family:var(--ifx-font-family, sans-serif)}.file-upload-wrapper{display:flex;flex-direction:column}.file-upload-wrapper.disabled{pointer-events:none}.file-upload-wrapper.disabled label,.file-upload-wrapper.disabled .file-upload-info{color:#575352}.file-upload-label{font-style:normal;font-weight:400;font-size:1rem;line-height:1.5rem;color:#1D1D1D}.file-upload-label .required{display:inline-block;margin-left:4px}.file-upload-label .required.error{color:#CD002F}.upload-dropzone{border:1px dashed #BFBBBB;padding:40px;text-align:center;cursor:pointer;color:#1D1D1D;transition:border-color 0.3s ease;border-radius:1px;background:#FFFFFF}.upload-dropzone ifx-icon{color:#0A8276}.upload-dropzone:hover{border:1px dashed #8D8786}.upload-dropzone.drag-over{border:1px solid #0A8276;background:#F7F7F7}.upload-dropzone.drag-over.error{border:1px solid #0A8276}.upload-dropzone.error{border-color:#CD002F}.disabled .upload-dropzone{pointer-events:none;border-color:#BFBBBB;color:#BFBBBB}.disabled .upload-dropzone ifx-icon{color:#BFBBBB}.upload-dropzone input{display:none}.file-upload-info{font-style:normal;font-weight:400;font-size:0.75rem;line-height:1rem;letter-spacing:0em;color:#1D1D1D;margin:0;margin-top:4px}.file-upload-status{font-style:normal;font-weight:400;font-size:0.75rem;line-height:1rem;letter-spacing:0.2px;margin-top:8px}.file-upload-status.file-upload-status__error{display:flex;align-items:center;color:#CD002F}.file-upload-status.file-upload-status__error ifx-icon{position:relative;top:-1px;color:#CD002F;margin-right:8px}.upload-heading{font:600 1.125rem/1.625rem \"Source Sans 3\";margin-bottom:8px}.file-list-wrapper{margin-top:16px}.file-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:16px}.file-item{border:1px solid #BFBBBB;padding-top:12px;padding-right:16px;padding-bottom:8px;padding-left:16px;display:flex;gap:8px}.file-info{width:100%;min-width:0}.file-top-row{display:flex;align-items:center;justify-content:space-between;gap:16px;margin-top:-8px}.file-top-row ifx-icon{flex-shrink:0}.file-name-wrapper{display:flex;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;font-weight:400;font-size:0.875rem}.file-name-base{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex-shrink:1;min-width:0}.file-name-ext{flex-shrink:0;margin-left:0}.file-middle-row{display:flex;align-items:center;font-size:0.75rem;line-height:1rem;flex-wrap:wrap;color:#575352}.file-middle-row .file-status{margin-left:12px}.file-middle-row .file-status ifx-icon{margin-right:8px}.file-progress-row{margin-top:4px}.file-progress-row ifx-progress-bar{width:100%}.upload-success{border-color:#0A8276}.upload-success .file-status ifx-icon{position:relative;top:1px;color:#4CA460}.upload-failed{border-color:#CD002F}.upload-failed .file-status{color:#CD002F;margin-left:0}";

const FileUpload = /*@__PURE__*/ proxyCustomElement(class FileUpload extends H {
    constructor() {
        super();
        this.__registerHost();
        this.__attachShadow();
        this.ifxFileUploadAdd = createEvent(this, "ifxFileUploadAdd", 7);
        this.ifxFileUploadRemove = createEvent(this, "ifxFileUploadRemove", 7);
        this.ifxFileUploadChange = createEvent(this, "ifxFileUploadChange", 7);
        this.ifxFileUploadError = createEvent(this, "ifxFileUploadError", 7);
        this.ifxFileUploadInvalid = createEvent(this, "ifxFileUploadInvalid", 7);
        this.ifxFileUploadStart = createEvent(this, "ifxFileUploadStart", 7);
        this.ifxFileUploadComplete = createEvent(this, "ifxFileUploadComplete", 7);
        this.ifxFileUploadAllComplete = createEvent(this, "ifxFileUploadAllComplete", 7);
        this.ifxFileUploadAbort = createEvent(this, "ifxFileUploadAbort", 7);
        this.ifxFileUploadDrop = createEvent(this, "ifxFileUploadDrop", 7);
        this.ifxFileUploadClick = createEvent(this, "ifxFileUploadClick", 7);
        this.ifxFileUploadMaxFilesExceeded = createEvent(this, "ifxFileUploadMaxFilesExceeded", 7);
        this.ifxFileUploadValidation = createEvent(this, "ifxFileUploadValidation", 7);
        this.ifxFileUploadRetry = createEvent(this, "ifxFileUploadRetry", 7);
        this.dragAndDrop = false;
        this.required = false;
        this.disabled = false;
        this.maxFileSizeMB = 7;
        /** Default set of allowed file extensions (used internally). Can be extended using `additionalAllowedFileTypes`. */
        this.allowedFileTypes = undefined;
        this.additionalAllowedFileTypes = [];
        /** When set to true, allows any file type to be uploaded (no file type restrictions). */
        this.allowAnyFileType = false;
        /** Custom file extensions to allow (e.g., 'xml', 'asc', 'cfg'). Recommended format: without dots. Also accepts format with dots like '.xml'. Do not use wildcards like '*.xml'. */
        this.allowedFileExtensions = [];
        this.label = 'Label';
        this.labelRequiredError = 'At least one file must be uploaded';
        this.labelBrowseFiles = 'Browse files';
        this.labelDragAndDrop = 'Drag & Drop or browse files to upload';
        this.labelUploadedFilesHeading = 'Uploaded files';
        this.labelFileTooLarge = 'Upload failed. Max file size: {{size}}MB.';
        this.labelUnsupportedFileType = 'Unsupported file type.';
        this.labelUploaded = 'Successfully uploaded';
        this.labelUploadFailed = 'Upload failed. Please try again.';
        this.labelSupportedFormatsTemplate = 'Supported file formats: {{types}}. Max file size: {{size}}MB.';
        this.labelFileSingular = 'file';
        this.labelFilePlural = 'files';
        this.labelMaxFilesInfo = 'Up to {{count}} {{files}}.';
        this.labelMaxFilesExceeded = 'Upload limit exceeded. Only {{count}} {{files}} allowed.';
        this.ariaLabelBrowseFiles = 'Browse files';
        this.ariaLabelDropzone = 'Upload area. Click to browse or drag and drop files.';
        this.ariaLabelFileInput = 'Upload file';
        this.ariaLabelRemoveFile = 'Remove file';
        this.ariaLabelCancelUpload = 'Cancel upload';
        this.ariaLabelRetryUpload = 'Retry upload';
        this.ariaLabelUploadingStatus = 'Upload in progress';
        this.ariaLabelUploadedStatus = 'Upload completed';
        this.ariaLabelUploadFailedStatus = 'Upload failed';
        this.internalId = `ifx-file-upload-${Math.random().toString(36).substr(2, 9)}`;
        this.isDragOver = false;
        this.files = [];
        this.uploadTasks = [];
        this.rejectedSizeFiles = [];
        this.rejectedTypeFiles = [];
        this.requiredError = false;
        this.statusMessage = null;
        this.fileInputEl = null;
        this.extensionToMimeMap = {
            /**
             * Maps file extensions to MIME types.
             * This is only used for translating `allowedFileTypes` (extensions) into MIME types,
             * and for labeling in the UI. It does NOT define which files are globally allowed.
             */
            // Images
            jpg: 'image/jpeg',
            jpeg: 'image/jpeg',
            png: 'image/png',
            gif: 'image/gif',
            svg: 'image/svg+xml',
            webp: 'image/webp',
            // Documents
            pdf: 'application/pdf',
            doc: 'application/msword',
            docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            xls: 'application/vnd.ms-excel',
            xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            ppt: 'application/vnd.ms-powerpoint',
            pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            txt: 'text/plain',
            csv: 'text/csv',
            json: 'application/json',
            // Audio/Video
            mp3: 'audio/mpeg',
            wav: 'audio/wav',
            mp4: 'video/mp4',
            mov: 'video/quicktime',
            webm: 'video/webm',
            // Archive / Code
            zip: 'application/zip',
            rar: 'application/vnd.rar',
            tar: 'application/x-tar',
            gz: 'application/gzip',
            // Sonstiges
            xml: 'application/xml',
            html: 'text/html',
            css: 'text/css',
            js: 'application/javascript',
        };
    }
    get maxFiles() {
        return this._maxFiles;
    }
    set maxFiles(value) {
        if (typeof value === 'number' && value < 1) {
            console.warn('Invalid `maxFiles` value. Must be >= 1. Value ignored.');
            this._maxFiles = undefined;
        }
        else {
            this._maxFiles = value;
        }
    }
    validateRequired() {
        var _a, _b;
        if (this.required && this.files.length === 0) {
            this.requiredError = true;
            if (((_a = this.statusMessage) === null || _a === void 0 ? void 0 : _a.text) !== this.labelRequiredError) {
                this.statusMessage = {
                    type: 'error',
                    text: this.labelRequiredError,
                };
            }
            this.ifxFileUploadValidation.emit({ valid: false });
        }
        else {
            this.requiredError = false;
            if (((_b = this.statusMessage) === null || _b === void 0 ? void 0 : _b.text) === this.labelRequiredError) {
                this.statusMessage = null;
            }
            this.ifxFileUploadValidation.emit({ valid: true });
        }
    }
    pluralize(count) {
        // If allowAnyFileType is true, use generic terms
        if (this.allowAnyFileType) {
            return count === 1 ? 'file' : 'files';
        }
        return count === 1 ? this.labelFileSingular : this.labelFilePlural;
    }
    getNormalizedFileTypes() {
        // If allowedFileTypes is not set and allowedFileExtensions is set, return empty array
        if (!this.allowedFileTypes && this.allowedFileExtensions && this.getNormalizedFileExtensions().length > 0) {
            return [];
        }
        // If allowedFileTypes is not set and no allowedFileExtensions, use defaults
        if (!this.allowedFileTypes) {
            return ['jpg', 'jpeg', 'png', 'pdf', 'mov', 'mp3', 'mp4'];
        }
        if (Array.isArray(this.allowedFileTypes)) {
            return this.allowedFileTypes;
        }
        try {
            return JSON.parse(this.allowedFileTypes);
        }
        catch (_a) {
            return this.allowedFileTypes.split(',').map(t => t.trim());
        }
    }
    getNormalizedFileExtensions() {
        if (!this.allowedFileExtensions)
            return [];
        if (Array.isArray(this.allowedFileExtensions)) {
            return this.allowedFileExtensions;
        }
        try {
            return JSON.parse(this.allowedFileExtensions);
        }
        catch (_a) {
            return this.allowedFileExtensions.split(',').map(t => t.trim());
        }
    }
    /**
     * Enhanced file type validation that supports:
     * - allowAnyFileType flag for unrestricted uploads (overrides all restrictions)
     * - allowedFileTypes (predefined extensions mapped to MIME types) - if not set and allowedFileExtensions is set, ignored
     * - additionalAllowedFileTypes (MIME types)
     * - allowedFileExtensions (custom extensions) - if only this is set, only these extensions are allowed
     */
    isFileTypeAllowed(file) {
        // If allowAnyFileType is true, accept all files (overrides all restrictions)
        if (this.allowAnyFileType) {
            return true;
        }
        const fileExtension = this.getFileExtension(file.name);
        // Check against allowedFileTypes (predefined extensions)
        const normalizedTypes = this.getNormalizedFileTypes();
        const allowedMimes = normalizedTypes.map(ext => this.extensionToMimeMap[ext.toLowerCase()]).filter(Boolean);
        if (allowedMimes.includes(file.type)) {
            return true;
        }
        // Check against additionalAllowedFileTypes (MIME types)
        const additionalMimeTypes = this.getAdditionalMimeTypes();
        if (additionalMimeTypes.includes(file.type)) {
            return true;
        }
        // Check against allowedFileExtensions (custom extensions)
        const customExtensions = this.getNormalizedFileExtensions();
        if (customExtensions.length > 0 && fileExtension) {
            for (const ext of customExtensions) {
                const normalizedExt = ext.startsWith('.') ? ext.substring(1).toLowerCase() : ext.toLowerCase();
                if (fileExtension === normalizedExt) {
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * Extracts file extension from filename (without dot)
     */
    getFileExtension(filename) {
        const lastDotIndex = filename.lastIndexOf('.');
        if (lastDotIndex === -1 || lastDotIndex === filename.length - 1) {
            return null;
        }
        return filename.substring(lastDotIndex + 1).toLowerCase();
    }
    getLabelFromMimeType(mime) {
        for (const [ext, knownMime] of Object.entries(this.extensionToMimeMap)) {
            if (knownMime === mime) {
                return ext.toUpperCase();
            }
        }
        return mime; // fallback: show raw MIME
    }
    handleFileChange(event) {
        const input = event.target;
        if (!input.files)
            return;
        this.processFiles(input.files);
    }
    handleDrop(event) {
        var _a;
        if (this.disabled)
            return;
        event.preventDefault();
        event.stopPropagation();
        this.isDragOver = false;
        if ((_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) {
            const droppedFiles = Array.from(event.dataTransfer.files);
            const acceptedFiles = [];
            const rejectedFiles = [];
            droppedFiles.forEach(file => {
                const isValidType = this.isFileTypeAllowed(file);
                const isValidSize = file.size <= this.maxFileSizeMB * 1024 * 1024;
                if (isValidType && isValidSize)
                    acceptedFiles.push(file);
                else
                    rejectedFiles.push(file);
            });
            this.ifxFileUploadDrop.emit({
                droppedFiles,
                acceptedFiles,
                rejectedFiles,
            });
            this.processFiles(event.dataTransfer.files);
        }
    }
    handleDragOver(event) {
        if (this.disabled)
            return;
        event.preventDefault();
        this.isDragOver = true;
    }
    handleDragLeave(event) {
        if (this.disabled)
            return;
        event.preventDefault();
        this.isDragOver = false;
    }
    processFiles(fileList) {
        const selectedFiles = Array.from(fileList);
        const validFiles = [];
        const rejectedSize = [];
        const rejectedType = [];
        selectedFiles.forEach(file => {
            const isValidType = this.isFileTypeAllowed(file);
            const isValidSize = file.size <= this.maxFileSizeMB * 1024 * 1024;
            const isDuplicate = this.files.some(existing => existing.name === file.name && existing.size === file.size);
            if (isDuplicate) {
                this.ifxFileUploadInvalid.emit({ file, reason: 'duplicate' });
                this.ifxFileUploadError.emit({
                    file,
                    errorType: 'duplicate',
                    message: `File "${file.name}" is already added`,
                    reason: 'duplicate',
                });
                return;
            }
            if (isValidType && isValidSize) {
                validFiles.push(file);
            }
            else {
                if (!isValidType) {
                    rejectedType.push(file.name);
                    this.ifxFileUploadInvalid.emit({ file, reason: 'invalid-type' });
                }
                if (!isValidSize) {
                    rejectedSize.push(file.name);
                    this.ifxFileUploadInvalid.emit({ file, reason: 'invalid-size' });
                }
                this.ifxFileUploadError.emit({
                    file,
                    errorType: !isValidType ? 'invalid-type' : 'file-too-large',
                    message: 'Invalid file rejected',
                    reason: !isValidType ? 'unsupported-type' : 'file-too-large',
                });
            }
        });
        this.rejectedSizeFiles = [...this.rejectedSizeFiles, ...rejectedSize];
        this.rejectedTypeFiles = [...this.rejectedTypeFiles, ...rejectedType];
        if (this.maxFiles && this.files.length + validFiles.length > this.maxFiles) {
            const availableSlots = this.maxFiles - this.files.length;
            const limitedFiles = validFiles.slice(0, Math.max(availableSlots, 0));
            const overflowFiles = validFiles.slice(availableSlots);
            this.files = [...this.files, ...limitedFiles];
            limitedFiles.forEach(file => this.startUpload(file));
            if (limitedFiles.length > 0) {
                this.ifxFileUploadAdd.emit({ addedFiles: limitedFiles, files: this.files });
                this.ifxFileUploadChange.emit({ files: this.files });
            }
            overflowFiles.forEach(file => {
                this.ifxFileUploadInvalid.emit({ file, reason: 'too-many-files' });
                this.ifxFileUploadError.emit({
                    file,
                    errorType: 'too-many-files',
                    message: `Upload limit exceeded. Max ${this.maxFiles} files allowed.`,
                    reason: 'too-many-files',
                });
            });
            if (overflowFiles.length > 0) {
                this.statusMessage = {
                    type: 'error',
                    text: this.labelMaxFilesExceeded.replace('{{count}}', this.maxFiles.toString()).replace('{{files}}', this.pluralize(this.maxFiles)),
                };
                this.ifxFileUploadMaxFilesExceeded.emit({
                    maxFiles: this.maxFiles,
                    attempted: this.files.length + validFiles.length,
                });
            }
            return;
        }
        validFiles.forEach(file => this.startUpload(file));
        this.files = [...this.files, ...validFiles];
        if (validFiles.length > 0) {
            this.ifxFileUploadAdd.emit({ addedFiles: validFiles, files: this.files });
            this.ifxFileUploadChange.emit({ files: this.files });
        }
        this.validateRequired();
    }
    retryUpload(file) {
        const taskIndex = this.uploadTasks.findIndex(t => t.file.name === file.name);
        if (taskIndex !== -1) {
            this.uploadTasks.splice(taskIndex, 1);
            this.uploadTasks = [...this.uploadTasks];
        }
        this.ifxFileUploadRetry.emit({ file });
        this.startUpload(file);
    }
    checkAndEmitAllComplete() {
        if (this.uploadTasks.every(t => t.completed || t.error)) {
            const hasSuccessfulUploads = this.uploadTasks.some(t => t.completed && !t.error);
            if (hasSuccessfulUploads) {
                const successfulFiles = this.uploadTasks.filter(t => t.completed && !t.error).map(t => t.file);
                this.ifxFileUploadAllComplete.emit({ files: successfulFiles });
            }
        }
    }
    resetFileInput() {
        if (this.fileInputEl) {
            this.fileInputEl.value = '';
        }
    }
    updateTaskProgress(file, progress) {
        const task = this.uploadTasks.find(t => t.file === file);
        if (task) {
            const newProgress = Math.max(task.progress, Math.min(100, progress));
            if (newProgress !== task.progress) {
                task.progress = newProgress;
                this.uploadTasks = [...this.uploadTasks];
            }
        }
    }
    startUpload(file) {
        this.ifxFileUploadStart.emit({ file });
        const task = {
            file,
            progress: 3, // Start with initial progress for better UX
            intervalId: null,
            completed: false,
        };
        this.uploadTasks = [...this.uploadTasks, task];
        if (this.uploadHandler) {
            this.uploadHandler(file, (percent) => {
                this.updateTaskProgress(file, percent);
            })
                .then(() => {
                task.progress = 100;
                task.completed = true;
                this.uploadTasks = [...this.uploadTasks];
                this.ifxFileUploadComplete.emit({ file });
                this.ifxFileUploadChange.emit({ files: this.files });
                this.checkAndEmitAllComplete();
            })
                .catch(() => {
                task.error = true;
                this.uploadTasks = [...this.uploadTasks];
                this.ifxFileUploadError.emit({
                    file,
                    errorType: 'upload-failed',
                    message: 'Upload handler rejected file',
                    reason: 'custom',
                });
                this.checkAndEmitAllComplete();
            });
        }
        else {
            const totalSize = file.size;
            const fakeUploadSpeed = 100000;
            let uploaded = 0;
            task.intervalId = window.setInterval(() => {
                uploaded += fakeUploadSpeed / 5;
                const progress = Math.min(100, Math.round((uploaded / totalSize) * 100));
                this.updateTaskProgress(file, progress);
                if (progress >= 100) {
                    clearInterval(task.intervalId);
                    task.completed = true;
                    task.intervalId = null;
                    this.uploadTasks = [...this.uploadTasks];
                    this.ifxFileUploadComplete.emit({ file });
                    this.ifxFileUploadChange.emit({ files: this.files });
                    this.checkAndEmitAllComplete();
                }
            }, 200);
        }
    }
    cancelUpload(file) {
        const taskIndex = this.uploadTasks.findIndex(t => t.file.name === file.name);
        if (taskIndex !== -1) {
            const task = this.uploadTasks[taskIndex];
            if ((task === null || task === void 0 ? void 0 : task.intervalId) !== null) {
                clearInterval(task.intervalId);
            }
            this.uploadTasks = this.uploadTasks.filter((_, i) => i !== taskIndex);
        }
        this.files = this.files.filter(f => f.name !== file.name);
        this.ifxFileUploadAbort.emit({ file });
        this.ifxFileUploadChange.emit({ files: this.files });
        this.resetFileInput();
        this.validateRequired();
    }
    removeFile(file) {
        var _a;
        this.uploadTasks = this.uploadTasks.filter(task => task.file.name !== file.name);
        this.files = this.files.filter(f => f.name !== file.name);
        this.ifxFileUploadRemove.emit({ removedFile: file, files: this.files });
        this.ifxFileUploadChange.emit({ files: this.files });
        this.validateRequired();
        this.resetFileInput();
        if (this.maxFiles && this.files.length < this.maxFiles && ((_a = this.statusMessage) === null || _a === void 0 ? void 0 : _a.text) !== this.labelRequiredError) {
            this.statusMessage = null;
        }
    }
    clearRejectedFile(fileName, type) {
        if (type === 'size') {
            this.rejectedSizeFiles = this.rejectedSizeFiles.filter(f => f !== fileName);
        }
        else {
            this.rejectedTypeFiles = this.rejectedTypeFiles.filter(f => f !== fileName);
        }
        this.resetFileInput();
        if (this.maxFiles && this.files.length < this.maxFiles) {
            this.statusMessage = null;
        }
        this.validateRequired();
    }
    splitFileNameParts(file) {
        const name = file.name;
        const dotIndex = name.lastIndexOf('.');
        if (dotIndex === -1)
            return { base: name, ext: '' };
        return {
            base: name.substring(0, dotIndex),
            ext: name.substring(dotIndex),
        };
    }
    getFileIcon(file) {
        var _a;
        const extension = (_a = file.name.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase();
        switch (extension) {
            case 'pdf':
                return 'file-pdf-16';
            case 'jpg':
            case 'jpeg':
                return 'file-jpg-16';
            case 'png':
                return 'file-png-16';
            case 'mov':
                return 'file-mov-16';
            case 'mp3':
                return 'file-mp3-16';
            case 'mp4':
                return 'file-mp4-16';
            default:
                return 'file-16';
        }
    }
    formatSize(bytes) {
        if (bytes >= 1024 * 1024 * 1024) {
            return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
        }
        else if (bytes >= 1024 * 1024) {
            return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
        }
        else if (bytes >= 1024) {
            return `${(bytes / 1024).toFixed(0)} KB`;
        }
        else {
            return `${bytes} B`;
        }
    }
    getAcceptAttribute() {
        // If allowAnyFileType is true, don't restrict the input
        if (this.allowAnyFileType) {
            return '';
        }
        const acceptValues = [];
        // Add extensions from allowedFileTypes
        const extensionTypes = this.getNormalizedFileTypes().map(ext => '.' + ext.toLowerCase());
        acceptValues.push(...extensionTypes);
        // Add MIME types from additionalAllowedFileTypes
        const mimeTypes = this.getAdditionalMimeTypes();
        acceptValues.push(...mimeTypes);
        // Add custom file extensions
        const customExtensions = this.getNormalizedFileExtensions();
        customExtensions.forEach(ext => {
            const normalizedExt = ext.startsWith('.') ? ext : '.' + ext;
            acceptValues.push(normalizedExt);
        });
        return acceptValues.join(',');
    }
    getFormattedProgressText(task) {
        const uploadedSize = Math.round((task.progress / 100) * task.file.size);
        const uploadedText = this.formatSize(uploadedSize);
        const totalText = this.formatSize(task.file.size);
        return `${uploadedText} / ${totalText} uploaded`;
    }
    getAdditionalMimeTypes() {
        if (!this.additionalAllowedFileTypes)
            return [];
        if (Array.isArray(this.additionalAllowedFileTypes))
            return this.additionalAllowedFileTypes;
        return this.additionalAllowedFileTypes.split(',').map(t => t.trim());
    }
    getSupportedFileText() {
        if (this.allowAnyFileType) {
            let text = `All file types allowed. Max file size: ${this.maxFileSizeMB}MB.`;
            if (this.labelMaxFilesInfo && this.maxFiles) {
                const fileWord = this.pluralize(this.maxFiles);
                const maxFilesText = this.labelMaxFilesInfo.replace('{{count}}', this.maxFiles.toString()).replace('{{files}}', fileWord);
                text += ` ${maxFilesText}`;
            }
            return text;
        }
        const allTypes = [];
        // Add extensions from allowedFileTypes
        const extensions = this.getNormalizedFileTypes().map(ext => ext.toUpperCase());
        allTypes.push(...extensions);
        // Add MIME types from additionalAllowedFileTypes
        const mimeTypes = this.getAdditionalMimeTypes().map(mime => this.getLabelFromMimeType(mime));
        allTypes.push(...mimeTypes);
        // Add custom file extensions
        const customExtensions = this.getNormalizedFileExtensions().map(ext => {
            const cleanExt = ext.startsWith('.') ? ext.substring(1) : ext;
            return cleanExt.toUpperCase();
        });
        allTypes.push(...customExtensions);
        const typesLabel = allTypes.join(', ');
        let text = this.labelSupportedFormatsTemplate.replace('{{types}}', typesLabel).replace('{{size}}', this.maxFileSizeMB.toString());
        if (this.labelMaxFilesInfo && this.maxFiles) {
            const fileWord = this.pluralize(this.maxFiles);
            const maxFilesText = this.labelMaxFilesInfo.replace('{{count}}', this.maxFiles.toString()).replace('{{files}}', fileWord);
            text += ` ${maxFilesText}`;
        }
        return text;
    }
    getFormattedFileTooLargeText() {
        return this.labelFileTooLarge.replace('{{size}}', this.maxFileSizeMB.toString());
    }
    renderStatusMessage() {
        if (!this.statusMessage)
            return null;
        return (h("div", { class: `file-upload-status file-upload-status__${this.statusMessage.type}` }, this.statusMessage.type === 'error' && h("ifx-icon", { icon: "c-warning-16" }), this.statusMessage.text));
    }
    isInputDisabled() {
        return this.disabled || (this.maxFiles !== undefined && this.files.length >= this.maxFiles);
    }
    async componentDidLoad() {
        if (!isNestedInIfxComponent(this.hostElement)) {
            const framework = detectFramework();
            trackComponent('ifx-file-upload', await framework);
        }
        if (this.hostElement.hasAttribute('show-demo-states')) {
            this.showDemoStates = true;
        }
        if (this.showDemoStates) {
            this.injectDemoState();
        }
    }
    // Storybook Demo
    async injectDemoState() {
        const dummyContent = new Array(50000).fill('a').join(''); // ~50 KB
        const bigContent = dummyContent + dummyContent; // ~100 KB
        const uploading = new File([dummyContent], 'Image.jpg', { type: 'image/jpeg' }); // ~50 KB
        const uploaded = new File([bigContent], 'File.pdf', { type: 'application/pdf' }); // ~100 KB
        const failed = new File([dummyContent], 'Text.docx', { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); // ~50 KB
        const tooLarge = new File([bigContent + bigContent + bigContent], 'Video.mp4', { type: 'video/mp4' }); // ~300 KB
        const unsupported = new File(['demo'], 'Script.exe', { type: 'application/x-msdownload' }); // very small
        this.files = [uploaded, uploading, failed];
        this.uploadTasks = [
            { file: uploaded, progress: 100, intervalId: null, completed: true },
            { file: uploading, progress: 40, intervalId: null, completed: false },
            { file: failed, progress: 80, intervalId: null, completed: false, error: true },
        ];
        this.rejectedSizeFiles = [tooLarge.name];
        this.rejectedTypeFiles = [unsupported.name];
    }
    // Storybook Demo
    async triggerDemoValidation() {
        this.validateRequired();
    }
    render() {
        return (h("div", { key: 'ef6b20aec846cdb005bbf42292a6d38a6ed1a503', class: {
                'file-upload-wrapper': true,
                'disabled': this.disabled,
            } }, this.label && (h("label", { key: '91b547b30348f765a3542c88c50790d84affaa8a', class: "file-upload-label", htmlFor: this.internalId }, this.label, this.required && h("span", { key: 'bef4e9628b629bacfc729a962b37a009185eb374', class: `required ${this.requiredError ? 'error' : ''}` }, "*"))), this.dragAndDrop ? this.renderDragAndDropArea() : this.renderUploadArea(), (this.files.length > 0 || this.rejectedSizeFiles.length > 0 || this.rejectedTypeFiles.length > 0) && (h("div", { key: '0bbe459c523c0a9077f23c458fb59e03b5ae0134', class: "file-list-wrapper" }, h("div", { key: 'e01f3966e8a3d5697da4d57ea7eb711d026177b9', class: "upload-heading" }, this.labelUploadedFilesHeading), h("ul", { key: '7c3c8ce0f8a4ebdac12c843b120482140adf93c2', class: "file-list" }, this.rejectedSizeFiles.map(fileName => (h("li", { class: "file-item upload-failed", key: `rejected-size-${fileName}` }, h("div", { class: "file-icon" }, h("ifx-icon", { icon: "file-16" })), h("div", { class: "file-info" }, h("div", { class: "file-top-row" }, h("span", { class: "file-name-wrapper" }, h("span", { class: "file-name-base" }, this.splitFileNameParts({ name: fileName }).base), h("span", { class: "file-name-ext" }, this.splitFileNameParts({ name: fileName }).ext)), h("div", { class: "file-actions" }, h("ifx-icon-button", { shape: "square", variant: "tertiary", icon: "delete-forever-16", size: "s", "aria-label": this.ariaLabelRemoveFile, onClick: () => this.clearRejectedFile(fileName, 'size') }))), h("div", { class: "file-middle-row" }, h("span", { class: "file-status", "aria-label": this.labelFileTooLarge.replace('{{size}}', this.maxFileSizeMB.toString()) }, this.getFormattedFileTooLargeText())))))), this.rejectedTypeFiles.map(fileName => (h("li", { class: "file-item upload-failed", key: `rejected-type-${fileName}` }, h("div", { class: "file-icon" }, h("ifx-icon", { icon: "file-16" })), h("div", { class: "file-info" }, h("div", { class: "file-top-row" }, h("span", { class: "file-name-wrapper" }, h("span", { class: "file-name-base" }, this.splitFileNameParts({ name: fileName }).base), h("span", { class: "file-name-ext" }, this.splitFileNameParts({ name: fileName }).ext)), h("div", { class: "file-actions" }, h("ifx-icon-button", { shape: "square", variant: "tertiary", icon: "delete-forever-16", size: "s", "aria-label": this.ariaLabelRemoveFile, onClick: () => this.clearRejectedFile(fileName, 'type') }))), h("div", { class: "file-middle-row" }, h("span", { class: "file-status", "aria-label": this.labelUnsupportedFileType }, this.labelUnsupportedFileType)))))), this.files.map(file => {
            var _a;
            const task = this.uploadTasks.find(t => t.file.name === file.name);
            const progress = (_a = task === null || task === void 0 ? void 0 : task.progress) !== null && _a !== void 0 ? _a : 100;
            const isUploading = task && !task.completed;
            const isError = (task === null || task === void 0 ? void 0 : task.error) === true;
            const itemClass = isError ? 'file-item upload-failed' : isUploading ? 'file-item uploading' : 'file-item upload-success';
            const uniqueKey = `${file.name}-${file.size}`;
            const { base, ext } = this.splitFileNameParts(file);
            return (h("li", { class: itemClass, key: uniqueKey }, h("div", { class: "file-icon" }, h("ifx-icon", { icon: this.getFileIcon(file) })), h("div", { class: "file-info" }, h("div", { class: "file-top-row" }, h("span", { class: "file-name-wrapper" }, h("span", { class: "file-name-base" }, base), h("span", { class: "file-name-ext" }, ext)), h("div", { class: "file-actions" }, h("ifx-icon-button", { shape: "square", variant: "tertiary", icon: "refresh-16", size: "s", "aria-label": this.ariaLabelRetryUpload, onClick: () => this.retryUpload(file), style: { display: isError ? 'inline-flex' : 'none' } }), h("ifx-icon-button", { shape: "square", variant: "tertiary", icon: "cross-16", size: "s", "aria-label": this.ariaLabelCancelUpload, onClick: () => this.cancelUpload(file), style: { display: isUploading ? 'inline-flex' : 'none' } }), h("ifx-icon-button", { shape: "square", variant: "tertiary", icon: "delete-forever-16", size: "s", "aria-label": this.ariaLabelRemoveFile, onClick: () => this.removeFile(file), style: { display: !isUploading ? 'inline-flex' : 'none' } }))), h("div", { class: "file-middle-row" }, isUploading && task && !task.error && (h("span", { class: "file-uploading", "aria-label": this.ariaLabelUploadingStatus }, this.getFormattedProgressText(task))), !isUploading && !isError && (h("span", null, h("span", { class: "file-size" }, this.formatSize(file.size)), h("span", { class: "file-status", "aria-label": this.ariaLabelUploadedStatus }, h("ifx-icon", { icon: "check-16" }), this.labelUploaded))), isError && (h("span", { class: "file-status", "aria-label": this.ariaLabelUploadFailedStatus }, this.labelUploadFailed))), isUploading && task && !task.error && (h("div", { class: "file-progress-row" }, h("ifx-progress-bar", { size: "s", value: progress, "show-label": "true" }))))));
        }))))));
    }
    renderUploadArea() {
        const handleInputRef = (el) => {
            this.fileInputEl = el;
        };
        return (h("div", { class: { 'upload-button': true } }, h("ifx-button", { variant: "secondary", onClick: () => { var _a; return (_a = this.fileInputEl) === null || _a === void 0 ? void 0 : _a.click(); }, disabled: this.isInputDisabled(), "aria-label": this.ariaLabelBrowseFiles }, h("ifx-icon", { icon: "upload-16" }), this.labelBrowseFiles), h("input", { id: this.internalId, ref: handleInputRef, type: "file", accept: this.getAcceptAttribute(), multiple: true, onChange: e => this.handleFileChange(e), style: { display: 'none' }, disabled: this.isInputDisabled(), "aria-label": this.ariaLabelFileInput }), h("p", { class: "file-upload-info" }, this.getSupportedFileText()), this.renderStatusMessage()));
    }
    renderDragAndDropArea() {
        const handleInputRef = (el) => {
            this.fileInputEl = el;
        };
        const triggerInputClick = () => {
            if (this.fileInputEl) {
                this.fileInputEl.click();
            }
        };
        return (h("div", { class: { disabled: this.isInputDisabled() } }, h("div", { class: { 'upload-dropzone': true, 'drag-over': this.isDragOver, 'error': this.requiredError }, onClick: triggerInputClick, onDragOver: e => this.handleDragOver(e), onDragLeave: e => this.handleDragLeave(e), onDrop: e => this.handleDrop(e), role: "button", tabIndex: 0, "aria-label": this.ariaLabelDropzone }, h("ifx-icon", { icon: "upload-16", class: "custom-icon" }), h("p", null, this.labelDragAndDrop), h("p", { class: "file-upload-info" }, this.getSupportedFileText()), h("div", { style: { height: '0px', overflow: 'hidden' } }, h("input", { id: this.internalId, ref: handleInputRef, type: "file", accept: this.getAcceptAttribute(), multiple: true, onChange: e => this.handleFileChange(e), disabled: this.isInputDisabled(), "aria-label": this.ariaLabelFileInput }))), this.renderStatusMessage()));
    }
    get hostElement() { return this; }
    static get style() { return fileUploadCss; }
}, [257, "ifx-file-upload", {
        "dragAndDrop": [4, "drag-and-drop"],
        "required": [4],
        "disabled": [4],
        "maxFileSizeMB": [2, "max-file-size-m-b"],
        "allowedFileTypes": [1, "allowed-file-types"],
        "additionalAllowedFileTypes": [1, "additional-allowed-file-types"],
        "allowAnyFileType": [4, "allow-any-file-type"],
        "allowedFileExtensions": [1, "allowed-file-extensions"],
        "uploadHandler": [16, "upload-handler"],
        "maxFiles": [6146, "max-files"],
        "label": [1],
        "labelRequiredError": [1, "label-required-error"],
        "labelBrowseFiles": [1, "label-browse-files"],
        "labelDragAndDrop": [1, "label-drag-and-drop"],
        "labelUploadedFilesHeading": [1, "label-uploaded-files-heading"],
        "labelFileTooLarge": [1, "label-file-too-large"],
        "labelUnsupportedFileType": [1, "label-unsupported-file-type"],
        "labelUploaded": [1, "label-uploaded"],
        "labelUploadFailed": [1, "label-upload-failed"],
        "labelSupportedFormatsTemplate": [1, "label-supported-formats-template"],
        "labelFileSingular": [1, "label-file-singular"],
        "labelFilePlural": [1, "label-file-plural"],
        "labelMaxFilesInfo": [1, "label-max-files-info"],
        "labelMaxFilesExceeded": [1, "label-max-files-exceeded"],
        "ariaLabelBrowseFiles": [1, "aria-label-browse-files"],
        "ariaLabelDropzone": [1, "aria-label-dropzone"],
        "ariaLabelFileInput": [1, "aria-label-file-input"],
        "ariaLabelRemoveFile": [1, "aria-label-remove-file"],
        "ariaLabelCancelUpload": [1, "aria-label-cancel-upload"],
        "ariaLabelRetryUpload": [1, "aria-label-retry-upload"],
        "ariaLabelUploadingStatus": [1, "aria-label-uploading-status"],
        "ariaLabelUploadedStatus": [1, "aria-label-uploaded-status"],
        "ariaLabelUploadFailedStatus": [1, "aria-label-upload-failed-status"],
        "isDragOver": [32],
        "files": [32],
        "uploadTasks": [32],
        "rejectedSizeFiles": [32],
        "rejectedTypeFiles": [32],
        "requiredError": [32],
        "statusMessage": [32],
        "injectDemoState": [64],
        "triggerDemoValidation": [64]
    }]);
function defineCustomElement$1() {
    if (typeof customElements === "undefined") {
        return;
    }
    const components = ["ifx-file-upload", "ifx-button", "ifx-icon", "ifx-icon-button", "ifx-progress-bar"];
    components.forEach(tagName => { switch (tagName) {
        case "ifx-file-upload":
            if (!customElements.get(tagName)) {
                customElements.define(tagName, FileUpload);
            }
            break;
        case "ifx-button":
            if (!customElements.get(tagName)) {
                defineCustomElement$5();
            }
            break;
        case "ifx-icon":
            if (!customElements.get(tagName)) {
                defineCustomElement$4();
            }
            break;
        case "ifx-icon-button":
            if (!customElements.get(tagName)) {
                defineCustomElement$3();
            }
            break;
        case "ifx-progress-bar":
            if (!customElements.get(tagName)) {
                defineCustomElement$2();
            }
            break;
    } });
}

const IfxFileUpload = FileUpload;
const defineCustomElement = defineCustomElement$1;

export { IfxFileUpload, defineCustomElement };
//# sourceMappingURL=ifx-file-upload.js.map

//# sourceMappingURL=ifx-file-upload.js.map