<script>
    'use strict';
    (function() {
        const modals = [];
        const excludedFromFocusTrapping = new Set();

        function trapFocusInNextModalWithOverlay() {
            for (let idx = modals.length - 1; idx >= 0; idx--) {
                const nextOnStack = modals[idx];
                const nextDialogElement = nextOnStack.instance.$refs[nextOnStack.name];
                if (!isOverlayDisabled(nextDialogElement)) {
                    hyva.trapFocus(nextDialogElement);
                    break;
                }
            }
        }

        function focusables(dialogElement) {
            const selector = 'button, [href], input, textarea, select, details, [tabindex]:not([tabindex="-1"])';
            return Array.from(dialogElement.querySelectorAll(selector))
                .filter(el => !el.hasAttribute('disabled'));
        }

        function firstVisible(elements) {
            const a = Array.from(elements);
            for (let i = 0; i < a.length; i++) {
                if (a[i].offsetWidth || a[i].offsetHeight || a[i].getClientRects().length) return a[i];
            }
            return null;
        }

        function isInViewport(element) {
            const rect = element && element.getBoundingClientRect();
            return rect &&
                rect.top >= 0 &&
                rect.left >= 0 &&
                rect.right <= window.innerWidth &&
                rect.bottom <= window.innerHeight;
        }

        function setFocusAfterTransition(dialogElement, duration) {
            /*
             * If the dialog contains an x-focus-first element that is not within a nested dialog, set focus
             * immediately from the trapFocus default, to avoid the switch after the transition duration.
             */
            const nested = Array.from(dialogElement.querySelectorAll('[role="dialog"]'));
            const candidates = Array.from(dialogElement.querySelectorAll('[x-focus-first]'));
            next: for (let candidate of candidates) {
                for (let child of nested) {
                    if (child.contains(candidate)) continue next;
                }
                setTimeout(() => candidate.focus(), 50);
                break;
            }
            window.setTimeout(() => {
                const focusElement = firstVisible(dialogElement.querySelectorAll('[x-focus-first]')) ||
                    focusables(dialogElement)[0] ||
                    null;
                focusElement && isInViewport(focusElement) && focusElement.focus();
            }, Math.max(1, duration));
        }

        function determineTrigger($refs, dialog, trigger) {
            /* if show() was called without arguments use the event target as open trigger */
            if (typeof trigger === 'undefined' && typeof dialog === 'object' && dialog.target instanceof HTMLElement) {
                return dialog.target;
            }
            /* if show('name', $event) was called with the event as the second argument use the event target as trigger */
            if (typeof dialog === 'string' && typeof trigger === 'object' && trigger.target instanceof HTMLElement) {
                return trigger.target;
            }
            /* if show('name', 'trigger') was called with the ref name pr selector of the trigger element */
            if (typeof trigger === 'string') {
                try {
                    return $refs[trigger] || document.querySelector(trigger)
                } catch (e) {
                    /* Intentionally left empty because we don't know if trigger is intended as a valid selector string */
                }
            }
            /* if show('name', document.querySelector('...')) was called, use that as the trigger */
            if (trigger instanceof Element) {
                return trigger;
            }
            /* unknown trigger - no focus will be set when the dialog is hidden */
            return null;
        }

        function isOverlayDisabled(dialog) {
            return dialog && dialog.hasAttribute('x-no-overlay')
        }

        function areRemainingModalsWithoutOverlay(modals) {
            const overflowDisabled = modals.map(modal => modal.instance.$refs[modal.name]).filter(isOverlayDisabled);
            return overflowDisabled.length === modals.length;
        }
        window.hyva.modal = function(options) {
            const config = Object.assign({
                dialog: 'dialog',
                duration: 300,
                /* ms before allowing subsequent hiding of modals for nested modals (see transition duration) */
                transitionEnter: 'transition ease-out duration-300',
                transitionEnterStart: 'opacity-0',
                transitionEnterEnd: 'opacity-100',
                transitionLeave: 'transition ease-in duration-300',
                transitionLeaveStart: 'opacity-100',
                transitionLeaveEnd: 'opacity-0',
            }, options);
            let lastHide = 0;
            return {
                opened: {},
                show(dialog, trigger) {
                    console.log('show');
                    const focusTargetAfterHide = determineTrigger(this.$refs, dialog, trigger);
                    const name = typeof dialog === 'string' ? dialog : config.dialog;
                    const dialogElement = this.$refs[name];
                    if (!dialogElement) {
                        console.error(`Use $modal->getShowJs() in the open trigger, or specify a custom name with\n$modal->withDialogRefName("my-name") and use show("my-name", $event).`);
                        return;
                    }
                    const useOverlay = !dialogElement.hasAttribute('x-no-overlay');
                    if (this.$refs.swiperContainer && this.$refs.swiperContainer.querySelector) {
                        const swiperWrapper = this.$refs.swiperContainer.querySelector('.swiper-wrapper');
                        if (swiperWrapper) {
                            swiperWrapper.classList.add('!transform-none');
                        }
                    }
                    dialogElement.scrollTop = 0;
                    /* Prevent adding the same modal on the stack twice */
                    if (this.opened[name]) {
                        return;
                    }
                    if (focusTargetAfterHide) {
                        focusTargetAfterHide.setAttribute('aria-expanded', 'true');
                    }
                    this.opened[name] = true;
                    useOverlay && this.$nextTick(() => hyva.trapFocus(dialogElement));
                    setFocusAfterTransition(dialogElement, config.duration);
                    const frame = {
                        name,
                        instance: this,
                        focusTarget: focusTargetAfterHide,
                        time: Date.now()
                    };
                    modals.push(frame);
                    if (useOverlay) {
                        document.body.classList.add('overflow-hidden');
                    }
                    return new Promise(resolve => frame.resolve = resolve);
                },
                cancel() {
                    this.hide(false);
                },
                ok() {
                    this.hide(true);
                },
                hide(value) {
                    // Guard against Escape being pressed multiple times before a transition is finished, otherwise
                    // this function will pop further dialogs from the stack but the display will not update.
                    console.log('Hiding modal:', value);
                    if (Date.now() - lastHide < config.duration) {
                        return;
                    }
                    lastHide = Date.now();
                    const modal = modals.pop() || {};
                    const name = modal.name;
                    this.opened[name] = false;
                    hyva.releaseFocus(modal.instance.$refs[modal.name])
                    trapFocusInNextModalWithOverlay();
                    const nextFocusAfterHide = modal.focusTarget;
                    nextFocusAfterHide && setTimeout(() => {
                        nextFocusAfterHide.setAttribute('aria-expanded', 'false');
                        nextFocusAfterHide.focus()
                    }, config.duration);
                    if (modals.length === 0 || areRemainingModalsWithoutOverlay(modals)) {
                        document.body.classList.remove('overflow-hidden');
                    }
                    if (this.$refs && this.$refs.swiperContainer && this.$refs.swiperContainer.querySelector) {
                        const swiperWrapper = this.$refs.swiperContainer.querySelector('.swiper-wrapper');
                        if (swiperWrapper) {
                            swiperWrapper.classList.remove('!transform-none');
                        }
                    }
                    modal.resolve(value);
                },
                overlay(dialog) {
                    const name = typeof dialog === 'string' ? dialog : config.dialog;
                    return {
                        ['x-show']() {
                            return this.opened[name]
                        },
                        ['x-transition:enter']: config.transitionEnter,
                        ['x-transition:enter-start']: config.transitionEnterStart,
                        ['x-transition:enter-end']: config.transitionEnterEnd,
                        ['x-transition:leave']: config.transitionLeave,
                        ['x-transition:leave-start']: config.transitionLeaveStart,
                        ['x-transition:leave-end']: config.transitionLeaveEnd,
                        ['@hyva-modal-show.window'](event) {
                            event.detail && event.detail.dialog === name && this.show(name, event.detail.focusAfterHide)
                        }
                    };
                }
            };
        }
        window.hyva.modal.peek = () => modals.length > 0 && modals[modals.length - 1]
        window.hyva.modal.pop = function() {
            if (modals.length > 0) {
                const modal = modals[modals.length - 1];
                modal.instance.hide();
            }
        }
        window.hyva.modal.excludeSelectorsFromFocusTrap = function(selectors) {
            typeof selectors === 'string' || selectors instanceof String ?
                excludedFromFocusTrapping.add(selectors) :
                selectors.map(selector => excludedFromFocusTrapping.add(selector));
        }
        window.hyva.modal.eventListeners = {
            keydown: event => {
                if (event.key === 'Escape') {
                    window.hyva.modal.pop();
                }
            },
            /* generic modal @click.outside handler */
            click: event => {
                if (modals.length > 0) {
                    const modal = modals[modals.length - 1];
                    const dialog = modal.instance.$refs[modal.name];
                    if (modal.time + 50 < Date.now() && // if last click processing is more than 50ms ago
                        !isOverlayDisabled(dialog) && // if dialog has overlay
                        !dialog.contains(event.target)) { // if click is outside of dialog
                        modal.instance.hide();
                    }
                }
            }
        };
        document.addEventListener('keydown', window.hyva.modal.eventListeners.keydown);
        document.addEventListener('click', window.hyva.modal.eventListeners.click);
    })();
</script>
<script>
	'use strict';

	(function () {
		const modals = [];
		const excludedFromFocusTrapping = new Set();

		function trapFocusInNextModalWithOverlay() {
			for (let idx = modals.length - 1; idx >= 0; idx--) {
				const nextOnStack = modals[idx];
				const nextDialogElement = nextOnStack.instance.$refs[nextOnStack.name];
				if (!isOverlayDisabled(nextDialogElement)) {
					hyva.trapFocus(nextDialogElement);
					break;
				}
			}
		}

		function focusables(dialogElement) {
			const selector = 'button, [href], input, textarea, select, details, [tabindex]:not([tabindex="-1"])';
			return Array.from(dialogElement.querySelectorAll(selector))
				.filter(el => !el.hasAttribute('disabled'));
		}

		function firstVisible(elements) {
			const a = Array.from(elements);
			for (let i = 0; i < a.length; i++) {
				if (a[i].offsetWidth || a[i].offsetHeight || a[i].getClientRects().length) return a[i];
			}
			return null;
		}

		function isInViewport(element) {
			const rect = element && element.getBoundingClientRect();
			return rect &&
				rect.top >= 0 &&
				rect.left >= 0 &&
				rect.right <= window.innerWidth &&
				rect.bottom <= window.innerHeight;
		}

		function setFocusAfterTransition(dialogElement, duration) {

			/*
             * If the dialog contains an x-focus-first element that is not within a nested dialog, set focus
             * immediately from the trapFocus default, to avoid the switch after the transition duration.
             */

			const nested = Array.from(dialogElement.querySelectorAll('[role="dialog"]'));
			const candidates = Array.from(dialogElement.querySelectorAll('[x-focus-first]'));
			next: for (let candidate of candidates) {
				for (let child of nested) {
					if (child.contains(candidate)) continue next;
				}
				setTimeout(() => candidate.focus(), 50);
				break;
			}
			window.setTimeout(() => {
				const focusElement = firstVisible(dialogElement.querySelectorAll('[x-focus-first]')) ||
					focusables(dialogElement)[0] ||
					null;
				focusElement && isInViewport(focusElement) && focusElement.focus();
			}, Math.max(1, duration));
		}

		function determineTrigger($refs, dialog, trigger) {
			/* if show() was called without arguments use the event target as open trigger */
			if (typeof trigger === 'undefined' && typeof dialog === 'object' && dialog.target instanceof HTMLElement) {
				return dialog.target;
			}

			/* if show('name', $event) was called with the event as the second argument use the event target as trigger */
			if (typeof dialog === 'string' && typeof trigger === 'object' && trigger.target instanceof HTMLElement) {
				return trigger.target;
			}

			/* if show('name', 'trigger') was called with the ref name pr selector of the trigger element */
			if (typeof trigger === 'string') {
				try {
					return $refs[trigger] || document.querySelector(trigger)
				} catch (e) {
					/* Intentionally left empty because we don't know if trigger is intended as a valid selector string */
				}
			}

			/* if show('name', document.querySelector('...')) was called, use that as the trigger */
			if (trigger instanceof Element) {
				return trigger;
			}

			/* unknown trigger - no focus will be set when the dialog is hidden */
			return null;
		}

		function isOverlayDisabled(dialog) {
			return dialog && dialog.hasAttribute('x-no-overlay')
		}

		function areRemainingModalsWithoutOverlay(modals) {
			const overflowDisabled = modals.map(modal => modal.instance.$refs[modal.name]).filter(isOverlayDisabled);

			return overflowDisabled.length === modals.length;
		}

		window.hyva.modal = function (options) {

			const config = Object.assign({
				dialog: 'dialog',
				duration: 300, /* ms before allowing subsequent hiding of modals for nested modals (see transition duration) */
				transitionEnter: 'transition ease-out duration-300',
				transitionEnterStart: 'opacity-0',
				transitionEnterEnd: 'opacity-100',
				transitionLeave: 'transition ease-in duration-300',
				transitionLeaveStart: 'opacity-100',
				transitionLeaveEnd: 'opacity-0',
			}, options);
			let lastHide = 0;

			return {
				opened: {},
				show(dialog, trigger) {
					console.log('show');
					const focusTargetAfterHide = determineTrigger(this.$refs, dialog, trigger);
					const name = typeof dialog === 'string' ? dialog : config.dialog;
					const dialogElement = this.$refs[name];
					if (!dialogElement) {
						console.error(`Use $modal->getShowJs() in the open trigger, or specify a custom name with\n$modal->withDialogRefName("my-name") and use show("my-name", $event).`);
						return;
					}
					const useOverlay = !dialogElement.hasAttribute('x-no-overlay');

					if (this.$refs.swiperContainer && this.$refs.swiperContainer.querySelector) {
						const swiperWrapper = this.$refs.swiperContainer.querySelector('.swiper-wrapper');
						if (swiperWrapper) {
							swiperWrapper.classList.add('!transform-none');
						}
					}

					dialogElement.scrollTop = 0;

					/* Prevent adding the same modal on the stack twice */
					if (this.opened[name]) {
						return;
					}

					if (focusTargetAfterHide) {
						focusTargetAfterHide.setAttribute('aria-expanded', 'true');
					}

					this.opened[name] = true;
					useOverlay && this.$nextTick(() => hyva.trapFocus(dialogElement));
					setFocusAfterTransition(dialogElement, config.duration);

					const frame = {name, instance: this, focusTarget: focusTargetAfterHide, time: Date.now()};

					modals.push(frame);
					if (useOverlay) {
						document.body.classList.add('overflow-hidden');
					}
					return new Promise(resolve => frame.resolve = resolve);
				},
				cancel() {
					this.hide(false);
				},
				ok() {
					this.hide(true);
				},
				hide(value) {
					// Guard against Escape being pressed multiple times before a transition is finished, otherwise
					// this function will pop further dialogs from the stack but the display will not update.
					console.log('Hiding modal:', value);
					if (Date.now() - lastHide < config.duration) {
						return;
					}
					lastHide = Date.now();

					const modal = modals.pop() || {};
					const name = modal.name;
					this.opened[name] = false;
					hyva.releaseFocus(modal.instance.$refs[modal.name])
					trapFocusInNextModalWithOverlay();

					const nextFocusAfterHide = modal.focusTarget;
					nextFocusAfterHide && setTimeout(() => {
						nextFocusAfterHide.setAttribute('aria-expanded', 'false');
						nextFocusAfterHide.focus()
					}, config.duration);

					if (modals.length === 0 || areRemainingModalsWithoutOverlay(modals)) {
						document.body.classList.remove('overflow-hidden');
					}

					if (this.$refs && this.$refs.swiperContainer && this.$refs.swiperContainer.querySelector) {
						const swiperWrapper = this.$refs.swiperContainer.querySelector('.swiper-wrapper');
						if (swiperWrapper) {
							swiperWrapper.classList.remove('!transform-none');
						}
					}

					modal.resolve(value);
				},
				overlay(dialog) {
					const name = typeof dialog === 'string' ? dialog : config.dialog;
					return {
						['x-show']() {
							return this.opened[name]
						},
						['x-transition:enter']: config.transitionEnter,
						['x-transition:enter-start']: config.transitionEnterStart,
						['x-transition:enter-end']: config.transitionEnterEnd,
						['x-transition:leave']: config.transitionLeave,
						['x-transition:leave-start']: config.transitionLeaveStart,
						['x-transition:leave-end']: config.transitionLeaveEnd,
						['@hyva-modal-show.window'](event) {
							event.detail && event.detail.dialog === name && this.show(name, event.detail.focusAfterHide)
						}
					};
				}
			};
		}

		window.hyva.modal.peek = () => modals.length > 0 && modals[modals.length - 1]

		window.hyva.modal.pop = function () {
			if (modals.length > 0) {
				const modal = modals[modals.length - 1];
				modal.instance.hide();
			}
		}

		window.hyva.modal.excludeSelectorsFromFocusTrap = function (selectors) {
			typeof selectors === 'string' || selectors instanceof String
				? excludedFromFocusTrapping.add(selectors)
				: selectors.map(selector => excludedFromFocusTrapping.add(selector));
		}

		window.hyva.modal.eventListeners = {
			keydown: event => {
				if (event.key === 'Escape') {
					window.hyva.modal.pop();
				}
			},
			/* generic modal @click.outside handler */
			click: event => {
				if (modals.length > 0) {
					const modal = modals[modals.length - 1];
					const dialog = modal.instance.$refs[modal.name];
					if (modal.time + 50 < Date.now() && // if last click processing is more than 50ms ago
						!isOverlayDisabled(dialog) && // if dialog has overlay
						!dialog.contains(event.target)) { // if click is outside of dialog
						modal.instance.hide();
					}
				}
			}
		};

		document.addEventListener('keydown', window.hyva.modal.eventListeners.keydown);

		document.addEventListener('click', window.hyva.modal.eventListeners.click);
	})();
</script>
/* No context defined. */

No notes defined.