@tanstack/vue-router
Version:
Modern and scalable routing for Vue applications
122 lines • 4.33 kB
JSX
import * as Vue from 'vue';
const VueErrorBoundary = Vue.defineComponent({
name: 'VueErrorBoundary',
props: {
onError: Function,
resetKey: [String, Number],
},
emits: ['catch'],
setup(props, { slots }) {
const error = Vue.ref(null);
const resetFn = Vue.ref(null);
const reset = () => {
error.value = null;
};
Vue.watch(() => props.resetKey, (newKey, oldKey) => {
if (newKey !== oldKey && error.value) {
reset();
}
});
Vue.onErrorCaptured((err) => {
if (err instanceof Promise ||
(err && typeof err.then === 'function')) {
return false;
}
error.value = err;
resetFn.value = reset;
if (props.onError) {
props.onError(err);
}
return false;
});
return () => {
if (error.value && slots.fallback) {
const fallbackContent = slots.fallback({
error: error.value,
reset,
});
return Array.isArray(fallbackContent) && fallbackContent.length === 1
? fallbackContent[0]
: fallbackContent;
}
const defaultContent = slots.default && slots.default();
return Array.isArray(defaultContent) && defaultContent.length === 1
? defaultContent[0]
: defaultContent;
};
},
});
const CatchBoundaryWrapper = Vue.defineComponent({
name: 'CatchBoundary',
inheritAttrs: false,
props: ['getResetKey', 'children', 'errorComponent', 'onCatch'],
setup(props) {
const resetKey = Vue.computed(() => props.getResetKey());
return () => {
return Vue.h(VueErrorBoundary, {
resetKey: resetKey.value,
onError: props.onCatch,
}, {
default: () => props.children,
fallback: ({ error, reset }) => {
if (props.errorComponent) {
return Vue.h(props.errorComponent, { error, reset });
}
return Vue.h(ErrorComponent, { error, reset });
},
});
};
},
});
export function CatchBoundary(props) {
return Vue.h(CatchBoundaryWrapper, props);
}
export const ErrorComponent = Vue.defineComponent({
name: 'ErrorComponent',
props: {
error: Object,
reset: Function,
},
setup(props) {
const show = Vue.ref(process.env.NODE_ENV !== 'production');
const toggleShow = () => {
show.value = !show.value;
};
return () => Vue.h('div', { style: { padding: '.5rem', maxWidth: '100%' } }, [
Vue.h('div', { style: { display: 'flex', alignItems: 'center', gap: '.5rem' } }, [
Vue.h('strong', { style: { fontSize: '1rem' } }, 'Something went wrong!'),
Vue.h('button', {
style: {
appearance: 'none',
fontSize: '.6em',
border: '1px solid currentColor',
padding: '.1rem .2rem',
fontWeight: 'bold',
borderRadius: '.25rem',
},
onClick: toggleShow,
}, show.value ? 'Hide Error' : 'Show Error'),
]),
Vue.h('div', { style: { height: '.25rem' } }),
show.value
? Vue.h('div', {}, [
Vue.h('pre', {
style: {
fontSize: '.7em',
border: '1px solid red',
borderRadius: '.25rem',
padding: '.3rem',
color: 'red',
overflow: 'auto',
},
}, [
props.error?.message
? Vue.h('code', {}, props.error.message)
: null,
]),
])
: null,
]);
},
});
//# sourceMappingURL=CatchBoundary.jsx.map