UNPKG

@vuecs/link

Version:

A package containing a link component.

146 lines (145 loc) 4.42 kB
import { computed, defineComponent, h, resolveDynamicComponent, toRef } from "vue"; //#region src/utils.ts function isObject(input) { return typeof input === "object" && input !== null && !Array.isArray(input); } const VCLink = defineComponent({ name: "VCLink", props: { active: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, href: { type: String, default: void 0 }, prefetch: { type: Boolean, default: true }, target: { type: String, default: "_self" }, to: { type: [String, Object], default: void 0 }, query: { type: Object } }, emits: ["click", "clicked"], setup(props, { emit, slots }) { const query = toRef(props, "query"); const routerLink = resolveDynamicComponent("RouterLink"); const nuxtLink = resolveDynamicComponent("NuxtLink"); const computedTag = computed(() => { if (!(typeof routerLink !== "string") || props.disabled || !props.to) return "a"; if (typeof nuxtLink !== "string") return "nuxt-link"; return "router-link"; }); const extendLinkWithQuery = (link, query) => { const keys = Object.keys(query); if (keys.length === 0) return link; let fragment = ""; const fragmentIndex = link.indexOf("#"); if (fragmentIndex !== -1) { fragment = link.slice(fragmentIndex); link = link.slice(0, fragmentIndex); } let searchParams; if (link.includes("?")) { const url = new URL(link, "http://localhost:3000"); for (const key of keys) url.searchParams.set(key, query[key]); searchParams = url.searchParams; [link] = link.split("?"); } else searchParams = new URLSearchParams(query); return `${link}?${searchParams.toString()}${fragment}`; }; const isRouterLink = computed(() => computedTag.value !== "a"); const computedHref = computed(() => { if (props.href) { if (props.query && query.value) return extendLinkWithQuery(props.href, query.value); return props.href; } if (isRouterLink.value) return null; return "#"; }); const computedProps = computed(() => { if (!isRouterLink.value) return {}; let to; if (props.query && query.value) { if (typeof props.to === "string") to = extendLinkWithQuery(props.to, query.value); else if (isObject(props.to)) to = { ...props.to, query: { ...query.value, ...props.to.query ? { ...props.to.query } : {} } }; } else to = props.to; return { ...to ? { to } : {}, ...typeof props.prefetch !== "undefined" ? { prefetch: props.prefetch } : {} }; }); const computedAttrs = computed(() => ({ ...props.href ? { href: computedHref.value } : {}, ...isRouterLink.value ? {} : { target: props.target } })); const buildVNodeProps = () => { const onClick = (event) => { const isEvent = typeof event.preventDefault !== "undefined" && typeof event.stopPropagation !== "undefined" && typeof event.stopImmediatePropagation !== "undefined"; if (isEvent && props.disabled) { event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); } else { if (isRouterLink.value) emit("click", event); emit("clicked", event); } if (isEvent && !isRouterLink.value && computedHref.value === "#") { event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); } }; return { class: { active: props.active, disabled: props.disabled }, "data-active": props.active ? "" : void 0, "data-disabled": props.disabled ? "" : void 0, ...computedAttrs.value, ...computedProps.value, onClick }; }; const resolvedComponent = computed(() => { switch (computedTag.value) { case "router-link": return routerLink; case "nuxt-link": return nuxtLink; default: return "a"; } }); return () => { const component = resolvedComponent.value; if (typeof component === "string") return h(component, buildVNodeProps(), [typeof slots.default === "function" ? slots.default() : []]); return h(component, buildVNodeProps(), { default: () => typeof slots.default === "function" ? slots.default() : [] }); }; } }); //#endregion //#region src/index.ts function install(instance, options) { instance.component("VCLink", VCLink); } var src_default = { install }; //#endregion export { VCLink, src_default as default, install }; //# sourceMappingURL=index.mjs.map