@vuecs/link
Version:
A package containing a link component.
146 lines (145 loc) • 4.42 kB
JavaScript
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