/*!
 * Built with Stencil
 * By PostNord.
 */
'use strict';

var index = require('./index-CfUQZtlH.js');
var index$1 = require('./index.cjs.js');
var arrow_right = require('./arrow_right-CABi9Wkp.js');
var close = require('./close-Bn5ieKko.js');

const translations = {
    NEXT: {
        sv: 'Nästa',
        en: 'Next',
        da: 'Næste',
        fi: 'Seuraava',
        no: 'Neste',
    },
    PREV: {
        sv: 'Föregående',
        en: 'Previous',
        da: 'Forrige',
        fi: 'Edellinen',
        no: 'Forrige',
    },
    FINISH: {
        sv: 'Slutför',
        en: 'Finish',
        da: 'Afslut',
        fi: 'Valmis',
        no: 'Fullfør',
    },
    CANCEL: {
        sv: 'Avbryt',
        en: 'Cancel',
        da: 'Annuller',
        fi: 'Peruuta',
        no: 'Avbryt',
    },
};

const pnWizardCss = () => `${index.transformTag("pn-wizard")} .pn-wizard{z-index:10000;position:absolute;top:0;border:none;margin:0;padding:0;background-color:transparent;outline:none;overflow:unset;height:100%;width:100%;max-width:unset;max-height:unset;display:none;opacity:0;transition-property:display, opacity;transition-duration:0.4s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}@media (prefers-reduced-motion: reduce){${index.transformTag("pn-wizard")} .pn-wizard{transition-duration:0s;transition-delay:0s}}${index.transformTag("pn-wizard")} .pn-wizard{transition-behavior:allow-discrete}${index.transformTag("pn-wizard")} .pn-wizard[open]{display:block;opacity:1}@starting-style{${index.transformTag("pn-wizard")} .pn-wizard[open]{display:block;opacity:0}}${index.transformTag("pn-wizard")} .pn-wizard::backdrop{background-color:transparent}${index.transformTag("pn-wizard")} .pn-wizard-sr-only{position:absolute;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);margin:-1px;white-space:nowrap}${index.transformTag("pn-wizard")} .pn-wizard-overlay{z-index:0}${index.transformTag("pn-wizard")} .pn-wizard-highlight{position:absolute;left:0;top:0;width:var(--pn-spotlight-width, 0%);height:var(--pn-spotlight-height, 0%);border-radius:var(--pn-spotlight-radius, 0.25em);box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.55);z-index:0;transform:translate(var(--pn-spotlight-x, 0%), var(--pn-spotlight-y, 0%));transition-property:transform, width, height, border-radius;transition-duration:0.4s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}@media (prefers-reduced-motion: reduce){${index.transformTag("pn-wizard")} .pn-wizard-highlight{transition-duration:0s;transition-delay:0s}}${index.transformTag("pn-wizard")} .pn-wizard-content{position:absolute;z-index:1;background:#ffffff;border-radius:2em;max-width:20em;box-shadow:0 0 0.5em rgba(0, 0, 0, 0.3);left:0;top:0;transform:translate(var(--pn-wizard-content-x), var(--pn-wizard-content-y));transition-property:transform;transition-duration:0.4s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}@media (prefers-reduced-motion: reduce){${index.transformTag("pn-wizard")} .pn-wizard-content{transition-duration:0s;transition-delay:0s}}@media (max-width: 55em){${index.transformTag("pn-wizard")} .pn-wizard-content{position:fixed;top:unset;bottom:0;left:0.5em;border-radius:2em 2em 0 0;width:calc(100vw - 1em);max-width:unset;transform:none}}${index.transformTag("pn-wizard")} .pn-wizard-cancel{position:absolute;top:1em;right:1em;z-index:10}${index.transformTag("pn-wizard")} .pn-wizard-text{padding:3em 1em 1em;text-align:center;display:flex;flex-direction:column;flex-wrap:nowrap;gap:clamp(0.5em, 5vw, 1em)}${index.transformTag("pn-wizard")} .pn-wizard-label{margin:0;font-size:clamp(1.25em, 5vw, 1.5em);font-weight:700;color:#2d2013}${index.transformTag("pn-wizard")} .pn-wizard-helpertext{margin:0;font-size:clamp(0.875em, 5vw, 1em);font-weight:400;color:#5e554a}${index.transformTag("pn-wizard")} .pn-wizard-controls{border-top:0.0625em solid #d3cecb;padding:1em;display:flex;justify-content:end;gap:0.5em;flex-wrap:wrap}${index.transformTag("pn-wizard")} .pn-wizard-indicator{margin-right:auto;align-self:center;font-size:1em;color:#5e554a;padding:0 0.625em}${index.transformTag("pn-wizard")} .pn-wizard-arrow{position:absolute;width:0;height:0;border:0.5em solid transparent;top:0;right:0;bottom:0;left:0;transition-property:top, right, bottom, left, border-color;transition-duration:0.4s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}@media (prefers-reduced-motion: reduce){${index.transformTag("pn-wizard")} .pn-wizard-arrow{transition-duration:0s;transition-delay:0s}}${index.transformTag("pn-wizard")} .pn-wizard-arrow[data-arrow=bottom]{top:100%;bottom:-1em;left:var(--pn-arrow-offset);border-top-color:#ffffff}${index.transformTag("pn-wizard")} .pn-wizard-arrow[data-arrow=top]{top:-1em;left:var(--pn-arrow-offset);border-bottom-color:#ffffff}${index.transformTag("pn-wizard")} .pn-wizard-arrow[data-arrow=right]{right:-1em;left:100%;top:var(--pn-arrow-offset);border-left-color:#ffffff}${index.transformTag("pn-wizard")} .pn-wizard-arrow[data-arrow=left]{left:-1em;top:var(--pn-arrow-offset);border-right-color:#ffffff}${index.transformTag("pn-wizard")} .pn-wizard-arrow[data-arrow=none]{display:none}`;

const PnWizard = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.wizardStep = index.createEvent(this, "wizardStep");
        this.wizardHighlightClick = index.createEvent(this, "wizardHighlightClick");
        this.wizardClose = index.createEvent(this, "wizardClose");
    }
    id = `pn-wizard-${index$1.uuidv4()}`;
    wizardIdLabel;
    wizardIdHelpertext;
    wizardElement;
    wizardContent;
    wizardArrow;
    timeoutRerender;
    get hostElement() { return index.getElement(this); }
    /** Set a title for the wizard. */
    label = '';
    /** Set a helpertext for the wizard. */
    helpertext = '';
    /** Manually set the language. */
    language = null;
    /** Set a custom HTML id. */
    pnId = this.id;
    /**
     * Assign the current step.
     * Any value above -1 is valid and will start the wizard.
     * @category Wizard steps
     **/
    step = -1;
    /**
     * The list of querySelectors that the wizards will highlight.
     * Recommended maximum of 7 steps.
     * @category Wizard steps
     **/
    steps = [];
    /**
     * Choose to display one of 2 built in progress steppers.
     * - `dots`: The pn-progress-stepper with the `dots` prop.
     * - `text`: simple text indicator "current/total"
     * @category Features
     */
    progress = '';
    /** Choose where the scrolling will focus on the highlighted elements. @category Features */
    scrollBlock = 'center';
    /**
     * By default, the component will hide the overflow on the body element when active.
     * You may wish to disable this if your HTML/CSS structure is not compatible with this behavior.
     * @category Features
     */
    displayOverflow = false;
    /** Hide the back button. @category Buttons */
    hideBack = false;
    /** Hide the next button. @category Buttons */
    hideNext = false;
    /** Hide the finish button. @category Buttons */
    hideFinish = false;
    /** Set a custom label for the back button. @category Buttons */
    labelBack = '';
    /** Set a custom label for the next button. @category Buttons */
    labelNext = '';
    /** Set a custom label for the finish button. @category Buttons */
    labelFinish = '';
    /** Emitted when the wizard step changes. */
    wizardStep;
    /** Emitted when the highlighted area is clicked. */
    wizardHighlightClick;
    /** Emitted when the wizard is canceled or finished. */
    wizardClose;
    handleStepChange(step, prevStep) {
        if (prevStep === -1) {
            this.highlightElement();
            this.positionModal();
        }
        if (step === -1) {
            const finished = prevStep === this.steps.length;
            this.wizardClose.emit({ step: finished ? prevStep - 1 : prevStep, finished });
        }
        if (!this.isActive()) {
            this.wizardElement?.close();
            setTimeout(() => this.handleDisplayOverflow(), index$1.reduceMotion() ? 0 : 400);
            return;
        }
        if (!this.wizardElement.open) {
            this.handleDisplayOverflow();
            this.wizardElement?.showModal();
        }
        this.wizardStep.emit({
            step,
            next: step > (prevStep ?? -1),
            prev: step < (prevStep ?? -1),
        });
    }
    handleIdChange() {
        this.wizardIdLabel = `${this.pnId || this.id}-label`;
        this.wizardIdHelpertext = `${this.pnId || this.id}-helpertext`;
    }
    handleOverflow() {
        if (!this.isActive())
            return;
        clearTimeout(this.timeoutRerender);
        this.timeoutRerender = setTimeout(() => {
            this.highlightElement();
            this.positionModal();
        }, 250);
    }
    async componentWillLoad() {
        this.handleIdChange();
        if (this.language === null)
            await index$1.awaitTopbar(this.hostElement);
    }
    componentDidRender() {
        this.runStepLogic();
    }
    getRect(element) {
        return element.getBoundingClientRect();
    }
    translate(prop) {
        return translations?.[prop]?.[this.language || index$1.en] || prop;
    }
    handleDisplayOverflow() {
        if (this.displayOverflow)
            return;
        const body = document.body;
        const scrollbarWidth = innerWidth - document.documentElement.clientWidth;
        if (this.isActive()) {
            body.style.setProperty('overflow', 'hidden');
            body.style.marginRight = `${scrollbarWidth}px`;
        }
        else {
            body.style.removeProperty('overflow');
            body.style.removeProperty('margin-right');
        }
    }
    /** Is the step within the valid range of available {@link steps}. */
    isActive(step = this.step) {
        return step >= 0 && step < this.steps.length;
    }
    isOpen() {
        return this.isActive() && this.wizardElement?.open;
    }
    isClosed(step = this.step) {
        return step === -1;
    }
    isFirstStep() {
        return this.step === 0;
    }
    isLastStep(step = this.step) {
        if (this.steps.length === 1)
            return true;
        return step === this.steps.length - 1;
    }
    isProgressDots() {
        return this.progress === 'dots';
    }
    isProgressText() {
        return this.progress === 'text';
    }
    /**
     * By default, the `pn-progress-stepper` will always render,
     * but is hidden from view unless `dots` is assinged to {@link progress}.
     *
     * The only exception is when there are more than 7 steps. Something that the stepper does not allow.
     */
    renderProgress() {
        return 7 >= this.steps.length && (this.isProgressDots() || this.isProgressText());
    }
    showBackButton() {
        if (this.hideBack || this.isClosed() || this.isFirstStep())
            return false;
        return true;
    }
    showNextButton() {
        if (this.hideNext)
            return false;
        return !this.isLastStep() || this.showFinishButton();
    }
    showFinishButton() {
        return !this.hideFinish && this.isLastStep();
    }
    runStepLogic() {
        if (this.isOpen()) {
            requestAnimationFrame(() => {
                this.highlightElement();
                this.positionModal();
                this.scrollToElement();
            });
        }
    }
    nextStep() {
        const next = this.step + 1;
        this.step = next;
    }
    prevStep() {
        const prev = this.step - 1;
        this.step = prev;
    }
    endWizard() {
        this.step = -1;
    }
    getNextLabel() {
        const finish = this.labelFinish || 'FINISH';
        const next = this.labelNext || 'NEXT';
        const prop = this.isLastStep() ? finish : next;
        return this.translate(prop);
    }
    getHighlightTarget() {
        const selector = this.steps[this.step];
        const target = document.querySelector(selector);
        return target;
    }
    getHighlightRect() {
        const target = this.getHighlightTarget();
        if (!target)
            return;
        const rect = this.getRect(target);
        const margin = parseFloat(getComputedStyle(target).margin) || 0;
        const top = rect.top + window.scrollY - margin;
        const left = rect.left + window.scrollX - margin;
        const width = rect.width + margin * 2;
        const height = rect.height + margin * 2;
        const radius = parseFloat(getComputedStyle(target).borderRadius) || 4;
        return { top, left, width, height, radius };
    }
    scrollToElement() {
        const target = this.getHighlightTarget();
        if (!target)
            return;
        target.scrollIntoView({ behavior: 'smooth', block: this.scrollBlock });
    }
    highlightElement() {
        const target = this.getHighlightTarget();
        if (!target)
            return;
        this.setHighlightVars(this.getHighlightRect());
    }
    positionModal() {
        const target = this.getHighlightTarget();
        if (!target)
            return;
        const gap = 16;
        // Target = Highlighted element
        const { top: targetTop, left: targetLeft, width: targetWidth, height: targetHeight } = this.getHighlightRect();
        // Modal = Wizard content
        const { width: modalWidth, height: modalHeight } = this.getRect(this.wizardContent);
        const targetCenter = targetLeft + targetWidth / 2;
        let contentX = 0;
        let contentY = 0;
        // Get viewport dimensions and scroll position
        const { scrollY, scrollX, innerWidth, innerHeight } = window;
        const scrollbarWidth = innerWidth - document.documentElement.clientWidth;
        // If highlight is very tall, position wizardContent left or right
        // const highlightIsTall = modalHeight > targetTop && modalHeight > innerHeight - (targetTop + targetHeight);
        // Where does the modal fit?
        const modalFitsDown = targetTop + targetHeight + gap + modalHeight < scrollY + innerHeight;
        const modalFitsUp = targetTop - gap - modalHeight > scrollY;
        const modalFitsLeft = targetLeft - gap - modalWidth > scrollX;
        const modalFitsRight = targetLeft + targetWidth + gap + modalWidth < scrollX + innerWidth;
        const modalFitsNone = !modalFitsDown && !modalFitsUp && !modalFitsLeft && !modalFitsRight;
        const fitsY = modalFitsDown || modalFitsUp;
        const fitsX = modalFitsLeft || modalFitsRight;
        let maxY = 8;
        let maxX = 8;
        maxY = modalFitsDown ? targetTop + targetHeight + gap : targetTop - modalHeight - gap;
        maxX = scrollX + innerWidth - modalWidth - scrollbarWidth - 8;
        // Arrow stuff
        let arrowOffset = 0;
        let arrowDirection = 'top';
        if (fitsY) {
            contentX = targetCenter - modalWidth / 2;
            contentY = modalFitsDown ? targetTop + targetHeight + gap : targetTop - modalHeight - gap;
            arrowDirection = modalFitsDown ? 'top' : 'bottom';
            arrowOffset = targetCenter - contentX;
        }
        else if (fitsX) {
            contentX = modalFitsRight ? targetLeft + targetWidth + gap : targetLeft - modalWidth - gap;
            contentY = targetTop + targetHeight / 2 - modalHeight / 2;
            maxY = targetTop + targetHeight / 2;
            arrowDirection = modalFitsRight ? 'left' : 'right';
            arrowOffset = modalHeight / 2;
        }
        else if (modalFitsNone) {
            contentX = targetCenter - modalWidth / 2;
            contentY = targetTop + targetHeight - modalHeight / 2;
            maxY = innerHeight - modalHeight - 8;
            arrowDirection = 'top';
            arrowOffset = targetCenter - contentX;
        }
        // Clamp horizontally within viewport
        const minX = scrollX + scrollbarWidth || 8;
        contentX = Math.max(minX, Math.min(contentX, maxX));
        // Clamp vertically within viewport
        const minY = 8;
        contentY = Math.max(minY, Math.min(contentY, maxY));
        this.setModalVars({ top: contentY, left: contentX });
        if (index$1.isSmallScreen()) {
            arrowDirection = 'top';
        }
        // Adjust arrow offset based on final position
        if (arrowDirection === 'top' || arrowDirection === 'bottom') {
            arrowOffset = targetCenter - contentX;
        }
        else {
            arrowOffset = targetTop + targetHeight / 2 - contentY;
        }
        arrowOffset = Math.max(32, // Minimum offset from edge
        Math.min(arrowOffset - 8, (fitsX ? modalHeight : modalWidth) - 32));
        this.setArrowVars(arrowDirection, arrowOffset);
    }
    setHighlightVars({ top, left, width, height, radius, }) {
        // Center and scale the highlight using transform
        this.hostElement.style.setProperty('--pn-spotlight-x', `${Math.round(left)}px`);
        this.hostElement.style.setProperty('--pn-spotlight-y', `${Math.round(top)}px`);
        this.hostElement.style.setProperty('--pn-spotlight-width', `${Math.round(width)}px`);
        this.hostElement.style.setProperty('--pn-spotlight-height', `${Math.round(height)}px`);
        this.hostElement.style.setProperty('--pn-spotlight-radius', `${Math.round(radius)}px`);
    }
    setModalVars({ top, left }) {
        this.hostElement.style.setProperty('--pn-wizard-content-x', `${Math.round(left)}px`);
        this.hostElement.style.setProperty('--pn-wizard-content-y', `${Math.round(top)}px`);
    }
    setArrowVars(direction, offset) {
        this.wizardArrow.setAttribute('data-arrow', direction);
        this.hostElement.style.setProperty('--pn-arrow-offset', `${Math.round(offset)}px`);
    }
    render() {
        return (index.h(index.Host, { key: '08f0d484f684188c7283535da328d6bd681b74d5' }, index.h("dialog", { key: '56810278e58795390973a9ebbe0bd797b731b1f8', id: this.pnId, "aria-labelledby": this.label ? this.wizardIdLabel : null, "aria-describedby": this.helpertext ? this.wizardIdHelpertext : null, class: "pn-wizard", ref: el => (this.wizardElement = el), onCancel: () => this.endWizard(), onClose: () => this.endWizard() }, index.h("div", { key: '824bbd673177648865e9328ee5aa51e157aa7347', class: "pn-wizard-overlay" }, index.h("div", { key: 'a2236247ba49e18de2a4aa2666fa1e07e6aaa1c4', class: "pn-wizard-highlight", onClick: e => this.wizardHighlightClick.emit(e) })), index.h("div", { key: '77d5f6e74c49b2a92a8c9c8f9207594bec0545c7', class: "pn-wizard-content", ref: el => (this.wizardContent = el) }, index.h("pn-button", { key: '28fdec2fa470ff03b916325d0085a7bd4cd8f504', class: "pn-wizard-cancel", arialabel: this.translate('CANCEL'), icon: close.close, iconOnly: true, small: true, appearance: "light", variant: "borderless", onPnClick: () => this.endWizard() }), index.h("div", { key: 'ff7e6051e041c008c639e392896e885e4dcb0364', class: "pn-wizard-text" }, this.label && (index.h("h2", { key: '9b8098099707558b66f1b422dc6ada70084d9829', class: "pn-wizard-label", id: this.wizardIdLabel }, this.label)), this.helpertext && (index.h("p", { key: '4db3b8ab391daf06f5731be43c9c116acd934b1f', class: "pn-wizard-helpertext", id: this.wizardIdHelpertext }, this.helpertext)), index.h("slot", { key: '5f72315df3102a605d2d4a220cfebfa216101f8c' }), this.renderProgress() && (index.h("pn-progress-stepper", { key: 'becee14c8d2ad3fe3a9d902dd080f4df760e227e', class: !this.isProgressDots() && 'pn-wizard-sr-only', totalSteps: this.steps.length, currentStep: this.step > 0 ? this.step + 1 : 1, dots: true }))), index.h("div", { key: '264270d944373b1570a09a330bef6c6e8ad07e4d', class: "pn-wizard-arrow", ref: el => (this.wizardArrow = el) }), index.h("div", { key: '1420663b8cc3996eb67f640d3a7f981f1fafff82', class: "pn-wizard-controls" }, this.isProgressText() && (index.h("span", { key: '99cd61e352d16b15129239c8c1932a1e8ff3d675', class: "pn-wizard-indicator", "aria-hidden": "true" }, this.step + 1, "/", this.steps.length)), index.h("slot", { key: 'f48e48097089a24ed48726046e5bb9b8a36ca1ec', name: "buttons" }), this.showBackButton() && (index.h("pn-button", { key: '9504536c3602f6280d30aa6f95043d2a66c2ac98', label: this.labelBack || this.translate('PREV'), small: true, appearance: "light", variant: "outlined", onPnClick: () => this.prevStep() })), this.showNextButton() && (index.h("pn-button", { key: 'c5997f60733d2f220138fbf3caf24f44271d63f3', label: this.getNextLabel(), small: true, icon: arrow_right.arrow_right, onPnClick: () => this.nextStep() })))))));
    }
    static get watchers() { return {
        "step": [{
                "handleStepChange": 0
            }],
        "pnId": [{
                "handleIdChange": 0
            }]
    }; }
};
PnWizard.style = pnWizardCss();

exports.pn_wizard = PnWizard;
