@vuecs/link
Version:
A package containing a link component.
189 lines (184 loc) • 6.03 kB
JavaScript
import { defineComponent, toRef, resolveDynamicComponent, computed, h } from 'vue';
function isObject(input) {
return typeof input === 'object' && input !== null && !Array.isArray(input);
}
const VCLink = defineComponent({
props: {
active: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
href: {
type: String,
default: undefined
},
prefetch: {
type: Boolean,
default: true
},
target: {
type: String,
default: '_self'
},
to: {
type: [
String,
Object
],
default: undefined
},
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(()=>{
const hasRouter = typeof routerLink !== 'string';
if (!hasRouter || 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 searchParams;
if (link.includes('?')) {
const url = new URL(link, 'http://localhost:3000');
for(let i = 0; i < keys.length; i++){
url.searchParams.set(keys[i], query[keys[i]]);
}
searchParams = url.searchParams;
[link] = link.split('?');
} else {
searchParams = new URLSearchParams(query);
}
return `${link}?${searchParams.toString()}`;
};
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: props.href
} : {},
...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();
}
};
const vNodeProps = {
class: {
active: props.active,
disabled: props.disabled
},
...computedAttrs.value,
...computedProps.value,
onClick
};
return vNodeProps;
};
let component;
switch(computedTag.value){
case 'router-link':
component = routerLink;
break;
case 'nuxt-link':
component = nuxtLink;
break;
default:
component = 'a';
}
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() : []
});
}
});
function install(instance, options) {
instance.component('VCLink', VCLink);
}
var index = {
install
};
export { VCLink, index as default, install };
//# sourceMappingURL=index.mjs.map