UNPKG

@tanstack/vue-router

Version:

Modern and scalable routing for Vue applications

105 lines 3.72 kB
import * as Vue from 'vue'; import { renderInNonRouteComponentContext } from './nonRouteComponentContext'; const VueErrorBoundary = Vue.defineComponent({ name: 'VueErrorBoundary', props: { onError: Function, resetKey: [String, Number, Object], children: null, errorComponent: null, }, setup(props) { const error = 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; if (props.onError) { props.onError(err); } return false; }); return () => { if (!error.value) { return props.children; } const errorComponent = props.errorComponent ?? ErrorComponent; const errorProps = { error: error.value, reset, }; return process.env.NODE_ENV !== 'production' ? renderInNonRouteComponentContext(errorComponent, errorProps, 'errorComponent') : Vue.h(errorComponent, errorProps); }; }, }); export function CatchBoundary(props) { return Vue.h(VueErrorBoundary, { resetKey: props.getResetKey(), onError: props.onCatch, children: props.children, errorComponent: props.errorComponent, }); } CatchBoundary.inheritAttrs = false; CatchBoundary.props = ['getResetKey', 'children', 'errorComponent', 'onCatch']; 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