'use strict';

var index = require('./index-BjHIBY-I.js');
var files = require('./files-Cf615Ytp.js');
var getIconProps = require('./get-icon-props-CwpDdQDI.js');
var translations = require('./translations-Bu_0fli7.js');
var randomString = require('./random-string-BTzDB2ee.js');
var imageResize = require('./image-resize-FAwzj92q.js');
require('./file-metadata-rQ0WzFlZ.js');

const profilePictureCss = () => `@charset "UTF-8";:host(limel-profile-picture){position:relative;display:inline-flex;min-width:1.5rem;min-height:1.5rem;border-radius:var(--profile-picture-border-radius, 100vw);background-color:rgb(var(--contrast-400))}*{box-sizing:border-box}limel-file-dropzone,limel-file-input,button.avatar{display:flex;align-items:center;justify-content:center;width:100%;height:100%}button{all:unset;display:block}button:focus{outline:none}button:focus-visible{outline:none;box-shadow:var(--shadow-depth-8-focused)}button.avatar{overflow:hidden;border-radius:var(--profile-picture-border-radius, 100vw)}:host(:not([disabled]):not([disabled=true])) button.avatar{transition:color var(--limel-clickable-transition-speed, 0.4s) ease, background-color var(--limel-clickable-transition-speed, 0.4s) ease, box-shadow var(--limel-clickable-transform-speed, 0.4s) ease, transform var(--limel-clickable-transform-speed, 0.4s) var(--limel-clickable-transform-timing-function, ease);cursor:pointer;color:var(--limel-theme-on-surface-color);background-color:transparent}:host(:not([disabled]):not([disabled=true])) button.avatar:hover,:host(:not([disabled]):not([disabled=true])) button.avatar:focus,:host(:not([disabled]):not([disabled=true])) button.avatar:focus-visible{will-change:color, background-color, box-shadow, transform}:host(:not([disabled]):not([disabled=true])) button.avatar:hover,:host(:not([disabled]):not([disabled=true])) button.avatar:focus-visible{transform:translate3d(0, 0.01rem, 0);color:var(--limel-theme-on-surface-color);background-color:var(--lime-elevated-surface-background-color)}:host(:not([disabled]):not([disabled=true])) button.avatar:hover{box-shadow:var(--button-shadow-hovered)}:host(:not([disabled]):not([disabled=true])) button.avatar:active{--limel-clickable-transform-timing-function:cubic-bezier(       0.83,       -0.15,       0.49,       1.16   );transform:translate3d(0, 0.05rem, 0);box-shadow:var(--button-shadow-pressed)}:host(:not([disabled]):not([disabled=true])) button.avatar:hover,:host(:not([disabled]):not([disabled=true])) button.avatar:active{--limel-clickable-transition-speed:0.2s;--limel-clickable-transform-speed:0.16s}:host([invalid]:not([invalid=false])) button.avatar{box-shadow:var(--shadow-error-state)}button.remove{transition:color var(--limel-clickable-transition-speed, 0.4s) ease, background-color var(--limel-clickable-transition-speed, 0.4s) ease, box-shadow var(--limel-clickable-transform-speed, 0.4s) ease, transform var(--limel-clickable-transform-speed, 0.4s) var(--limel-clickable-transform-timing-function, ease);cursor:pointer;color:var(--limel-theme-on-surface-color);background-color:rgb(var(--contrast-900))}button.remove:hover,button.remove:focus,button.remove:focus-visible{will-change:color, background-color, box-shadow, transform}button.remove:hover,button.remove:focus-visible{transform:translate3d(0, 0.01rem, 0);color:rgb(var(--color-white));background-color:rgb(var(--color-red-default))}button.remove:hover{box-shadow:var(--button-shadow-hovered)}button.remove:active{--limel-clickable-transform-timing-function:cubic-bezier(       0.83,       -0.15,       0.49,       1.16   );transform:translate3d(0, 0.05rem, 0);box-shadow:var(--button-shadow-pressed)}button.remove:hover,button.remove:active{--limel-clickable-transition-speed:0.2s;--limel-clickable-transform-speed:0.16s}button.remove{cursor:pointer;height:1.25rem;width:1.25rem;border-radius:50%;background-repeat:no-repeat;background-position:center;background-size:0.75rem;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2032%2032'%3E%3Cdefs/%3E%3Cpath%20fill='rgb(255,255,255)'%20d='M7.219%205.781L5.78%207.22%2014.563%2016%205.78%2024.781%207.22%2026.22%2016%2017.437l8.781%208.782%201.438-1.438L17.437%2016l8.782-8.781L24.78%205.78%2016%2014.563z'/%3E%3C/svg%3E");position:absolute;top:0;left:0;opacity:0}:host(:hover) button.remove,:host(:focus) button.remove,:host(:focus-visible) button.remove,:host(:focus-within) button.remove,:host(:active) button.remove{animation:show 0.4s ease-in-out forwards}@keyframes show{0%{transform:scale(0.9);opacity:0}100%{transform:scale(1);opacity:1}}button.avatar,img,limel-icon{border-radius:var(--profile-picture-border-radius, 100vw)}limel-icon{width:calc(100% - 1rem);min-width:1rem;max-width:4rem;color:var(--limel-theme-text-secondary-on-background-color);margin:auto}img{object-fit:var(--limel-profile-picture-object-fit);width:100%;height:100%}:host(.has-image-error) img{border:1px dashed rgb(var(--contrast-600));background:url("data:image/svg+xml;charset=utf-8, <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8' style='fill-rule:evenodd;'><path fill='rgba(186,186,192,0.16)' d='M0 0h4v4H0zM4 4h4v4H4z'/></svg>");background-size:0.5rem}limel-spinner{position:absolute;inset:0;margin:auto}limel-popover{position:absolute;inset:auto 0 0 auto;display:block;width:2.25rem;height:2.25rem}`;

const ProfilePicture = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.change = index.createEvent(this, "change");
        this.filesRejected = index.createEvent(this, "filesRejected");
        /**
         * Defines the language for translations.
         * Will translate the translatable strings on the components.
         */
        this.language = 'en';
        /**
         * Placeholder icon of the component, displayed when no image is present.
         */
        this.icon = 'user';
        /**
         * Disables user interaction.
         * Prevents uploading new pictures or removing existing ones.
         */
        this.disabled = false;
        /**
         * Readonly prevents changing the value but allows interaction like focus.
         */
        this.readonly = false;
        /**
         * Marks the control as required.
         */
        this.required = false;
        /**
         * Marks the control as invalid.
         */
        this.invalid = false;
        /**
         * Set to `true` to put the component in the `loading` state,
         * and render an indeterminate progress indicator inside.
         * This does _not_ disable the interactivity of the component!
         */
        this.loading = false;
        /**
         * How the image should fit within the container.
         * - `cover` will fill the container and crop excess parts.
         * - `contain` will scale the image to fit within the container without cropping.
         */
        this.imageFit = 'cover';
        /**
         * A comma-separated list of accepted file types.
         */
        this.accept = 'image/jpeg,image/png,image/heic,.jpg,.jpeg,.png,.heic';
        this.imageError = false;
        this.isErrorMessagePopoverOpen = false;
        this.removeButtonId = randomString.createRandomString();
        this.browseButtonId = randomString.createRandomString();
        this.renderHelperText = () => {
            if (!this.helperText) {
                return;
            }
            return (index.h("limel-tooltip", { elementId: this.browseButtonId, label: this.helperText }));
        };
        this.handleNewFiles = async (event) => {
            var _a, _b;
            event.stopPropagation();
            if (this.disabled) {
                return;
            }
            const file = (_a = event.detail) === null || _a === void 0 ? void 0 : _a[0];
            if (!file) {
                return;
            }
            if (!files.isTypeAccepted(file, this.accept)) {
                this.filesRejected.emit([file]);
                return;
            }
            this.revokeObjectUrl();
            this.imageError = false;
            let out = file;
            // Optional client-side resize
            if (this.resize && file.fileContent instanceof File) {
                try {
                    const processed = await imageResize.resizeImage(file.fileContent, Object.assign(Object.assign({}, this.resize), { fit: (_b = this.resize.fit) !== null && _b !== void 0 ? _b : this.imageFit }));
                    out = Object.assign(Object.assign({}, file), { filename: processed.name, size: processed.size, contentType: processed.type, fileContent: processed });
                }
                catch (_c) {
                    // Fall back to original file if resize fails
                    out = file;
                }
            }
            // Create an object URL for immediate preview if no href present
            if (!out.href && out.fileContent instanceof File) {
                this.objectUrl = URL.createObjectURL(out.fileContent);
            }
            this.change.emit(out);
        };
        this.handleRejectedFiles = (event) => {
            event.stopPropagation();
            this.filesRejected.emit(event.detail);
        };
        this.handleClear = (event) => {
            event.stopPropagation();
            this.revokeObjectUrl();
            this.imageError = false;
            this.change.emit(undefined);
        };
        this.onImageError = () => {
            this.imageError = true;
        };
        this.openPopover = (event) => {
            event.stopPropagation();
            this.isErrorMessagePopoverOpen = true;
        };
        this.onPopoverClose = (event) => {
            event.stopPropagation();
            this.isErrorMessagePopoverOpen = false;
        };
        this.getTranslation = (key) => {
            return translations.translate.get(key, this.language);
        };
    }
    disconnectedCallback() {
        this.revokeObjectUrl();
    }
    handleValueChange() {
        // Clear previously created object URL when value changes
        this.revokeObjectUrl();
        this.imageError = false;
        // If a new File without href is provided, create an object URL for preview
        const currentValue = this.value;
        if (currentValue &&
            typeof currentValue !== 'string' &&
            !currentValue.href &&
            currentValue.fileContent instanceof File) {
            this.objectUrl = URL.createObjectURL(currentValue.fileContent);
        }
    }
    render() {
        const hostClassNames = {
            'has-image-error': this.imageError,
        };
        if (this.readonly) {
            return index.h(index.Host, { class: hostClassNames }, this.renderAvatar());
        }
        return (index.h(index.Host, { class: hostClassNames }, index.h("limel-file-dropzone", { disabled: this.disabled, accept: this.accept, onFilesSelected: this.handleNewFiles, onFilesRejected: this.handleRejectedFiles }, index.h("limel-file-input", { accept: this.accept, disabled: this.disabled, "aria-required": this.required ? 'true' : undefined, "aria-invalid": this.invalid ? 'true' : undefined }, this.renderBrowseButton())), this.renderClearButton(), this.renderSpinner(), this.renderErrorMessage(), this.renderHelperText()));
    }
    get hasValue() {
        if (typeof this.value === 'string') {
            return !!this.value;
        }
        if (this.value && (this.value.href || this.value.fileContent)) {
            return true;
        }
        return !!this.objectUrl;
    }
    renderBrowseButton() {
        return (index.h("button", { id: this.browseButtonId, type: "button", class: "avatar", disabled: this.disabled, "aria-label": this.label, "aria-busy": this.loading ? 'true' : 'false', "aria-live": "polite" }, this.renderAvatar()));
    }
    renderAvatar() {
        const src = this.getImageSrc();
        if (src) {
            return (index.h("img", { src: src, alt: "", style: {
                    '--limel-profile-picture-object-fit': this.imageFit,
                }, loading: "lazy", onError: this.onImageError }));
        }
        return this.renderIcon();
    }
    renderIcon() {
        var _a, _b;
        const icon = getIconProps.getIconName(this.icon);
        return (index.h("limel-icon", { name: icon, style: {
                color: `${(_a = this.icon) === null || _a === void 0 ? void 0 : _a.color}`,
                'background-color': `${(_b = this.icon) === null || _b === void 0 ? void 0 : _b.backgroundColor}`,
            } }));
    }
    renderClearButton() {
        if (!this.hasValue || this.disabled) {
            return;
        }
        return [
            index.h("button", { class: "remove", type: "button", id: this.removeButtonId, onClick: this.handleClear }),
            index.h("limel-tooltip", { label: this.getTranslation('profile-picture.remove'), elementId: this.removeButtonId }),
        ];
    }
    renderSpinner() {
        if (!this.loading) {
            return;
        }
        return index.h("limel-spinner", null);
    }
    // Collects derived flags used for deciding whether to show the unsupported preview message
    getUnsupportedPreviewContext() {
        const currentValue = this.value;
        const hasNoSrc = !this.getImageSrc();
        const hasLocalFile = !!(currentValue &&
            typeof currentValue !== 'string' &&
            currentValue.fileContent instanceof File &&
            !currentValue.href);
        const isResizeConfigured = !!this.resize;
        return { hasNoSrc, hasLocalFile, isResizeConfigured };
    }
    shouldShowErrorMessage() {
        const { hasNoSrc, hasLocalFile, isResizeConfigured } = this.getUnsupportedPreviewContext();
        return ((hasNoSrc || this.imageError) && hasLocalFile && isResizeConfigured);
    }
    // Shows a non-intrusive note when there is a File without href and no object URL, which
    // can happen if the browser failed to decode the source (e.g., HEIC in Chromium).
    renderErrorMessage() {
        if (!this.shouldShowErrorMessage()) {
            return;
        }
        const errorIcon = {
            name: 'error',
            color: 'rgb(var(--color-orange-dark))',
        };
        const errorMessageStyles = {
            maxWidth: '20rem',
            borderRadius: '0.75rem',
        };
        return (index.h("limel-popover", { open: this.isErrorMessagePopoverOpen, onClick: this.openPopover, onClose: this.onPopoverClose }, index.h("limel-icon-button", { slot: "trigger", elevated: true, icon: errorIcon, "aria-live": "polite", label: this.getTranslation('profile-picture.unsupported-preview.title') }), index.h("limel-callout", { type: "warning", style: errorMessageStyles, heading: this.getTranslation('profile-picture.unsupported-preview.title') }, this.getTranslation('profile-picture.unsupported-preview.description'))));
    }
    getImageSrc() {
        if (!this.value) {
            return this.objectUrl; // Could be set from last selection before parent consumes
        }
        if (typeof this.value === 'string') {
            return this.value;
        }
        if (this.value.href) {
            return this.value.href;
        }
        if (this.value.fileContent instanceof File) {
            return this.objectUrl;
        }
        return undefined;
    }
    revokeObjectUrl() {
        if (this.objectUrl) {
            URL.revokeObjectURL(this.objectUrl);
            this.objectUrl = undefined;
        }
    }
    static get watchers() { return {
        "value": [{
                "handleValueChange": 0
            }]
    }; }
};
ProfilePicture.style = profilePictureCss();

exports.limel_profile_picture = ProfilePicture;
