{"version":3,"file":"modal.mjs","sources":["../../src/components/modal/Modal.vue","../../src/components/modal/useModalProgrammatic.ts","../../src/components/modal/index.ts"],"sourcesContent":["<script setup lang=\"ts\" generic=\"C extends Component\">\nimport {\n    ref,\n    computed,\n    watch,\n    nextTick,\n    onMounted,\n    useTemplateRef,\n    type Component,\n} from \"vue\";\n\nimport OIcon from \"../icon/Icon.vue\";\n\nimport { getDefault } from \"@/utils/config\";\nimport { toCssDimension } from \"@/utils/helpers\";\nimport { isClient } from \"@/utils/ssr\";\nimport {\n    defineClasses,\n    useClickOutside,\n    useMatchMedia,\n    usePreventScrolling,\n    useTeleportDefault,\n    useTrapFocus,\n} from \"@/composables\";\nimport type { CloseEventArgs } from \"../programmatic\";\n\nimport type { ModalProps } from \"./props\";\n\n/**\n * Classic modal overlay to include any content you may need.\n * @displayName Modal\n * @style _modal.scss\n */\ndefineOptions({\n    isOruga: true,\n    name: \"OModal\",\n    configField: \"modal\",\n    inheritAttrs: false,\n});\n\nconst props = withDefaults(defineProps<ModalProps<C>>(), {\n    override: undefined,\n    active: false,\n    fullScreen: false,\n    content: undefined,\n    width: () => getDefault(\"modal.width\", 960),\n    animation: () => getDefault(\"modal.animation\", \"zoom-out\"),\n    overlay: () => getDefault(\"modal.overlay\", true),\n    cancelable: () =>\n        getDefault(\"modal.cancelable\", [\"escape\", \"x\", \"outside\"]),\n    trapFocus: () => getDefault(\"modal.trapFocus\", true),\n    alert: () => getDefault(\"modal.alert\", false),\n    ariaLabel: () => getDefault(\"modal.ariaLabel\"),\n    autoFocus: () => getDefault(\"modal.autoFocus\", true),\n    closeIcon: () => getDefault(\"modal.closeIcon\", \"close\"),\n    closeIconSize: () => getDefault(\"modal.closeIconSize\", \"medium\"),\n    ariaCloseLabel: () => getDefault(\"modal.ariaCloseLabel\", \"Close\"),\n    mobileBreakpoint: () => getDefault(\"modal.mobileBreakpoint\"),\n    teleport: () => getDefault(\"modal.teleport\", false),\n    clipScroll: () => getDefault(\"modal.clipScroll\", false),\n    component: undefined,\n    props: undefined,\n    events: undefined,\n});\n\nconst emits = defineEmits<{\n    /**\n     * active prop two-way binding\n     * @param value {boolean} - updated active prop\n     */\n    \"update:active\": [value: boolean];\n    /**\n     * on component close event\n     * @param value {string} - close event method\n     */\n    close: [...args: [] | [string] | CloseEventArgs<C>];\n}>();\n\nconst { vTrapFocus } = useTrapFocus();\n\nconst rootRef = useTemplateRef(\"rootElement\");\nconst contentRef = useTemplateRef(\"contentElement\");\n\nconst isActive = defineModel<boolean>(\"active\", { default: false });\n\nconst { isMobile } = useMatchMedia(props.mobileBreakpoint);\n\nconst _teleport = computed(() =>\n    typeof props.teleport === \"boolean\"\n        ? { to: useTeleportDefault(), disabled: !props.teleport }\n        : { to: props.teleport, disabled: false },\n);\n\nconst showX = computed(() =>\n    Array.isArray(props.cancelable)\n        ? props.cancelable.indexOf(\"x\") >= 0\n        : props.cancelable,\n);\n\nconst customStyle = computed(() =>\n    !props.fullScreen ? { maxWidth: toCssDimension(props.width) } : null,\n);\n\nconst toggleScroll = usePreventScrolling(props.clipScroll);\n\nwatch(isActive, (value) => {\n    if (props.overlay) toggleScroll(value);\n    // if autoFocus focus the element\n    if (value && props.autoFocus)\n        nextTick(() => {\n            if (rootRef.value) rootRef.value.focus();\n        });\n});\n\nonMounted(() => {\n    if (isActive.value && props.overlay) toggleScroll(isActive.value);\n});\n\n// --- Events Feature ---\n\nif (isClient)\n    if (!props.overlay)\n        // register outside click event listener when is active\n        useClickOutside(contentRef, onClickedOutside, {\n            trigger: isActive,\n        });\n\n/** Close fixed sidebar if clicked outside. */\nfunction onClickedOutside(event: Event): void {\n    if (!isActive.value || isAnimating.value) return;\n    if (\n        props.overlay ||\n        (contentRef.value && !event.composedPath().includes(contentRef.value))\n    )\n        event.preventDefault();\n    cancel(\"outside\");\n}\n\n/** Escape key press event bound to the component root. */\nfunction onEscapePress(): void {\n    if (!isActive.value) return;\n    cancel(\"escape\");\n}\n\n/**\n * Check if method is cancelable.\n * Call close() with action `cancel`.\n * @param method Cancel method\n */\nfunction cancel(method: string): void {\n    // check if method is cancelable\n    if (\n        (typeof props.cancelable === \"boolean\" && !props.cancelable) ||\n        !props.cancelable ||\n        (Array.isArray(props.cancelable) && !props.cancelable.includes(method))\n    )\n        return;\n    close(method);\n}\n\n/** set active to false and emit close event */\nfunction close(...args: [] | [string] | CloseEventArgs<C>): void {\n    isActive.value = false;\n    emits(\"close\", ...args);\n}\n\n// --- Animation Feature ---\n\nconst isAnimating = ref(!props.active);\n\n/** Transition after-enter hook */\nfunction afterEnter(): void {\n    isAnimating.value = false;\n}\n\n/** Transition before-leave hook */\nfunction beforeLeave(): void {\n    isAnimating.value = true;\n}\n\n// --- Computed Component Classes ---\n\nconst rootClasses = defineClasses(\n    [\"rootClass\", \"o-modal\"],\n    [\"mobileClass\", \"o-modal--mobile\", null, isMobile],\n    [\"activeClass\", \"o-modal--active\", null, isActive],\n);\n\nconst overlayClasses = defineClasses([\"overlayClass\", \"o-modal__overlay\"]);\n\nconst contentClasses = defineClasses(\n    [\"contentClass\", \"o-modal__content\"],\n    [\n        \"fullScreenClass\",\n        \"o-modal__content--full-screen\",\n        null,\n        computed(() => props.fullScreen),\n    ],\n);\n\nconst closeClasses = defineClasses([\"closeClass\", \"o-modal__close\"]);\n\n// --- Expose Public Functionalities ---\n\n/** expose functionalities for programmatic usage */\ndefineExpose({ close });\n</script>\n\n<template>\n    <Teleport :to=\"_teleport.to\" :disabled=\"_teleport.disabled\">\n        <transition\n            :name=\"animation\"\n            @after-enter=\"afterEnter\"\n            @before-leave=\"beforeLeave\">\n            <div\n                v-show=\"isActive\"\n                ref=\"rootElement\"\n                v-bind=\"$attrs\"\n                v-trap-focus=\"trapFocus && isActive\"\n                data-oruga=\"modal\"\n                :class=\"rootClasses\"\n                :tabindex=\"-1\"\n                :role=\"alert ? 'alertdialog' : 'dialog'\"\n                :aria-label=\"ariaLabel\"\n                :aria-modal=\"isActive\"\n                @keyup.escape=\"onEscapePress\">\n                <div\n                    v-if=\"overlay\"\n                    :class=\"overlayClasses\"\n                    tabindex=\"-1\"\n                    @click=\"onClickedOutside\" />\n\n                <div\n                    ref=\"contentElement\"\n                    :class=\"contentClasses\"\n                    :style=\"customStyle\">\n                    <!-- injected component for programmatic usage -->\n                    <component\n                        :is=\"component\"\n                        v-if=\"component\"\n                        v-bind=\"$props.props\"\n                        v-on=\"$props.events || {}\"\n                        @close=\"close\" />\n                    <!--\n                        @slot Modal default content, default is content prop\n                        @binding {(...args): void} close - function to close the component\n                    -->\n                    <slot v-else :close=\"close\">\n                        <div v-if=\"content\">{{ content }}</div>\n                    </slot>\n\n                    <o-icon\n                        v-if=\"showX\"\n                        v-show=\"!isAnimating\"\n                        :class=\"closeClasses\"\n                        :icon=\"closeIcon\"\n                        :size=\"closeIconSize\"\n                        clickable\n                        :aria-label=\"ariaCloseLabel\"\n                        @click=\"cancel('x')\" />\n                </div>\n            </div>\n        </transition>\n    </Teleport>\n</template>\n","import {\n    type Component,\n    type ComponentInternalInstance,\n    type MaybeRefOrGetter,\n} from \"vue\";\nimport {\n    InstanceRegistry,\n    ComponentProgrammatic,\n    type ProgrammaticComponentOptions,\n    type ProgrammaticExpose,\n} from \"../programmatic\";\n\nimport Modal from \"./Modal.vue\";\n\nimport type { ModalProps } from \"./props\";\n\ndeclare module \"../../index\" {\n    interface OrugaProgrammatic {\n        modal: typeof ModalProgrammatic;\n    }\n}\n\n/** modal component programmatic instance registry **/\nconst registry = new InstanceRegistry<ComponentInternalInstance>();\n\n/** useModalProgrammatic composable options */\nexport type ModalProgrammaticOptions<C extends Component> = Readonly<\n    ModalProps<C>\n> &\n    ProgrammaticComponentOptions<typeof Modal<C>>;\n\nconst ModalProgrammatic = {\n    /** Returns the number of registered active instances. */\n    count: registry.count,\n    /**\n     * Create a new programmatic modal component instance.\n     * @param options modal content string or modal component props object\n     * @param target specify a target the component get rendered into - default is `document.body`\n     * @returns ProgrammaticExpose\n     */\n    open<C extends Component>(\n        options: string | ModalProgrammaticOptions<C>,\n        target?: MaybeRefOrGetter<string | HTMLElement | null>,\n    ): ProgrammaticExpose<typeof Modal<C>> {\n        const _options: ModalProgrammaticOptions<C> =\n            typeof options === \"string\" ? { content: options } : options;\n\n        const componentProps: ModalProps<C> = {\n            active: true, // set the active default state to true\n            ...(_options as ModalProps<C>),\n        };\n\n        // create programmatic component\n        return ComponentProgrammatic.open(Modal, {\n            registry, // custom programmatic instance registry\n            target, // target the component get rendered into\n            props: componentProps, // component specific props\n            onClose: _options.onClose, // on close event handler\n        });\n    },\n    /** Close the last registred instance in the modal programmatic instance registry. */\n    close(...args: unknown[]): void {\n        registry.last()?.exposed?.close(...args);\n    },\n    /** Close all instances in the programmatic modal instance registry. */\n    closeAll(...args: unknown[]): void {\n        registry.walk((entry) => entry.exposed?.close(...args));\n    },\n};\n\nexport default ModalProgrammatic;\n","import type { App, Plugin } from \"vue\";\n\nimport Modal from \"./Modal.vue\";\nimport ModalProgrammatic from \"./useModalProgrammatic\";\n\nimport {\n    registerComponent,\n    registerComponentProgrammatic,\n} from \"@/utils/plugins\";\n\n/** export modal specific types */\nexport type { ModalProgrammaticOptions } from \"./useModalProgrammatic\";\n\n/** export modal plugin */\nexport default {\n    install(app: App) {\n        registerComponent(app, Modal);\n        registerComponentProgrammatic(app, \"modal\", ModalProgrammatic);\n    },\n} as Plugin;\n\n/** export modal components & composables */\nexport { Modal as OModal, ModalProgrammatic };\n"],"names":["_useModel","Modal"],"mappings":"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"}