{"version":3,"file":"index.mjs","names":[],"sources":["../src/utils.ts","../src/component.ts","../src/index.ts"],"sourcesContent":["export function isObject(input: unknown) : input is Record<string, any> {\n    return typeof input === 'object' &&\n        input !== null &&\n        !Array.isArray(input);\n}\n","import type {\n    DefineComponent,\n    ExtractPublicPropTypes,\n    PropType,\n    VNodeProps,\n    VNodeTypes,\n} from 'vue';\nimport {\n    computed,\n    defineComponent,\n    h,\n    resolveDynamicComponent,\n    toRef,\n} from 'vue';\nimport type { LinkQuery } from './types';\nimport { isObject } from './utils';\n\nconst linkProps = {\n    active: {\n        type: Boolean,\n        default: false,\n    },\n    disabled: {\n        type: Boolean,\n        default: false,\n    },\n    href: {\n        type: String,\n        default: undefined,\n    },\n    prefetch: {\n        type: Boolean,\n        default: true,\n    },\n    target: {\n        type: String,\n        default: '_self',\n    },\n    to: {\n        type: [String, Object] as PropType<string | Record<string, any>>,\n        default: undefined,\n    },\n    query: { type: Object as PropType<LinkQuery> },\n};\n\nexport type LinkProps = ExtractPublicPropTypes<typeof linkProps>;\n\nexport const VCLink = defineComponent({\n    name: 'VCLink',\n    props: linkProps,\n    emits: ['click', 'clicked'],\n    setup(props, { emit, slots }) {\n        const query = toRef(props, 'query');\n\n        const routerLink = resolveDynamicComponent('RouterLink');\n        const nuxtLink = resolveDynamicComponent('NuxtLink');\n\n        const computedTag = computed(() => {\n            const hasRouter = typeof routerLink !== 'string';\n\n            if (!hasRouter || props.disabled || !props.to) {\n                return 'a';\n            }\n\n            if (typeof nuxtLink !== 'string') {\n                return 'nuxt-link';\n            }\n\n            return 'router-link';\n        });\n\n        const extendLinkWithQuery = (link: string, query: Record<string, any>) => {\n            const keys = Object.keys(query);\n            if (keys.length === 0) {\n                return link;\n            }\n\n            // Split the fragment off before touching the search string. A URL's\n            // fragment is always last, so appending `?…` to a link that already\n            // ends in `#anchor` produces `/docs#install?ref=x` — the browser\n            // reads `?ref=x` as fragment text and never sends the query. The\n            // `split('?')` below would also drop the fragment outright for a\n            // link carrying both. Re-attached after the query is built.\n            let fragment = '';\n            const fragmentIndex = link.indexOf('#');\n            if (fragmentIndex !== -1) {\n                fragment = link.slice(fragmentIndex);\n                link = link.slice(0, fragmentIndex);\n            }\n\n            let searchParams : URLSearchParams;\n            if (link.includes('?')) {\n                const url = new URL(link, 'http://localhost:3000');\n                for (const key of keys) {\n                    url.searchParams.set(key, query[key]);\n                }\n\n                searchParams = url.searchParams;\n\n                [link] = link.split('?');\n            } else {\n                searchParams = new URLSearchParams(query);\n            }\n\n            return `${link}?${searchParams.toString()}${fragment}`;\n        };\n\n        const isRouterLink = computed(() => computedTag.value !== 'a');\n\n        const computedHref = computed(() => {\n            if (props.href) {\n                if (\n                    props.query &&\n                    query.value\n                ) {\n                    return extendLinkWithQuery(props.href, query.value);\n                }\n\n                return props.href;\n            }\n\n            if (isRouterLink.value) {\n                return null;\n            }\n\n            return '#';\n        });\n\n        const computedProps = computed(() => {\n            if (!isRouterLink.value) {\n                return {};\n            }\n\n            let to : Record<string, any> | string | undefined;\n\n            if (\n                props.query &&\n                query.value\n            ) {\n                if (typeof props.to === 'string') {\n                    to = extendLinkWithQuery(props.to, query.value);\n                } else if (isObject(props.to)) {\n                    to = {\n                        ...props.to,\n                        query: {\n                            ...query.value,\n                            ...(props.to.query ? { ...props.to.query } : {}),\n                        },\n                    };\n                }\n            } else {\n                to = props.to;\n            }\n\n            return {\n                ...(to ? { to } : {}),\n                ...(typeof props.prefetch !== 'undefined' ? { prefetch: props.prefetch } : {}),\n            };\n        });\n\n        const computedAttrs = computed(() => ({\n            // `computedHref`, NOT the raw `props.href` (#1705): the\n            // query-extended href was computed and then thrown away, so\n            // `:query` silently did nothing on the plain-`<a>` path — it only\n            // ever reached the DOM via `computedProps.to` in router mode.\n            // Keep the `props.href` guard so an hrefless `<VCLink>` still\n            // renders no `href` at all; `computedHref`'s `'#'` is a\n            // click-suppression sentinel and must not leak into the DOM.\n            ...(props.href ? { href: computedHref.value } : {}),\n            ...(isRouterLink.value ? {} : { target: props.target }),\n        }));\n\n        const buildVNodeProps = () => {\n            const onClick = (event: Record<string, any>) => {\n                const isEvent: boolean = typeof event.preventDefault !== 'undefined' &&\n                    typeof event.stopPropagation !== 'undefined' &&\n                    typeof event.stopImmediatePropagation !== 'undefined';\n\n                if (isEvent && props.disabled) {\n                    event.preventDefault();\n                    event.stopPropagation();\n                    event.stopImmediatePropagation();\n                } else {\n                    if (isRouterLink.value) {\n                        emit('click', event);\n                    }\n\n                    emit('clicked', event);\n                }\n\n                if (\n                    isEvent &&\n                    !isRouterLink.value &&\n                    computedHref.value === '#'\n                ) {\n                    event.preventDefault();\n                    event.stopPropagation();\n                    event.stopImmediatePropagation();\n                }\n            };\n\n            const vNodeProps: VNodeProps & Record<string, any> = {\n                class: {\n                    active: props.active,\n                    disabled: props.disabled,\n                },\n                'data-active': props.active ? '' : undefined,\n                'data-disabled': props.disabled ? '' : undefined,\n                ...computedAttrs.value,\n                ...computedProps.value,\n                onClick,\n            };\n\n            return vNodeProps;\n        };\n\n        // Resolve the rendered component INSIDE the render fn so it\n        // reacts to `to`/`disabled` changes — previously the switch\n        // ran once at setup and cached the choice, so toggling\n        // `:disabled` couldn't swap `<router-link>` → `<a>`.\n        const resolvedComponent = computed<string | VNodeTypes>(() => {\n            switch (computedTag.value) {\n                case 'router-link': return routerLink;\n                case 'nuxt-link': return nuxtLink;\n                default: return 'a';\n            }\n        });\n\n        return () => {\n            const component = resolvedComponent.value;\n            if (typeof component === 'string') {\n                return h(\n                    component,\n                    buildVNodeProps(),\n                    [\n                        (typeof slots.default === 'function' ? slots.default() : []),\n                    ],\n                );\n            }\n            return h(\n                component as DefineComponent,\n                buildVNodeProps(),\n                { default: () => (typeof slots.default === 'function' ? slots.default() : []) },\n            );\n        };\n    },\n});\n","import type { App, Plugin } from 'vue';\n\nimport './vue';\n\n// Import vue components\nimport {\n    VCLink,\n} from './component';\nimport type { Options } from './types';\n\nexport * from './component';\nexport * from './types';\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nexport function install(instance: App, options?: Options) : void {\n    instance.component('VCLink', VCLink);\n}\n\nexport default { install } satisfies Plugin<Options | undefined>;\n"],"mappings":"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"}