storybook-vue3-router
Version:
A Storybook decorator that allows you to build stories for your routing-aware components.
180 lines (170 loc) • 5.52 kB
JavaScript
;
var vue = require('vue');
var vueRouter = require('vue-router');
var actions = require('storybook/actions');
const Home = {
template: `
<div>
<h2>Home</h2>
<div style="display: flex; gap: 1em">
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</div>
</div>
`
};
const About = {
template: `
<div>
<h2>About</h2>
<div style="display: flex; gap: 1em">
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
</div>
</div>
`
};
const defaultRoutes = [
{
path: "/",
name: "home",
component: Home,
beforeEnter: (to, from) => actions.action("beforeEnter")({ to: to.fullPath, from: from.fullPath })
},
{
path: "/about",
name: "about",
component: About,
beforeEnter: (to, from) => actions.action("beforeEnter")({ to: to.fullPath, from: from.fullPath })
}
];
function globalRouterGuardFn(router, beforeEach, forceReload = false) {
if (typeof beforeEach === "function") {
if (forceReload) {
router.go(0);
return;
}
router.beforeEach((to, from, next) => beforeEach(to, from, next));
}
}
function initialRoute(router, initialRoute2) {
router.replace(initialRoute2 || "/");
}
function resetRoutes(router, newRoutes) {
const oldRoutes = router.getRoutes();
oldRoutes.forEach((route) => {
router.removeRoute(route.name);
});
newRoutes.forEach((route) => {
router.addRoute(route);
});
}
function getFromArgs(args, options) {
let filtered = {};
options.forEach((option) => {
filtered = { ...filtered, [option]: args[option] };
});
return filtered;
}
function withVueRouter(routes = defaultRoutes, options) {
return () => ({
setup() {
const { app } = vue.getCurrentInstance().appContext;
let router;
const existingRouter = app.config.globalProperties.$router;
const existingRoute = app.config.globalProperties.$route;
if ((!existingRouter || existingRouter.isMocked === true) && (!existingRoute || existingRoute.isMocked === true)) {
router = vueRouter.createRouter({
history: vueRouter.createWebHashHistory(),
routes,
...options?.vueRouterOptions
});
globalRouterGuardFn(router, options?.beforeEach);
app.use(router);
} else {
router = existingRouter;
resetRoutes(router, routes);
globalRouterGuardFn(existingRouter, options?.beforeEach, true);
}
initialRoute(router, options?.initialRoute);
},
template: "<story/>"
});
}
function withAsyncVueRouter(routes = defaultRoutes, options) {
return () => ({
async setup() {
const { app } = vue.getCurrentInstance().appContext;
let router;
const existingRouter = app.config.globalProperties.$router;
const existingRoute = app.config.globalProperties.$route;
if ((!existingRouter || existingRouter.isMocked === true) && (!existingRoute || existingRoute.isMocked === true)) {
router = vueRouter.createRouter({
history: vueRouter.createWebHashHistory(),
routes,
...options?.vueRouterOptions
});
globalRouterGuardFn(router, options?.beforeEach);
app.use(router);
} else {
router = existingRouter;
resetRoutes(router, routes);
globalRouterGuardFn(existingRouter, options?.beforeEach, true);
}
initialRoute(router, options?.initialRoute);
await router.isReady();
},
template: `
<story/>
`
});
}
function withMockRouter(options) {
return (_, ctx) => ({
setup() {
const { app } = vue.getCurrentInstance().appContext;
const existingRouter = app.config.globalProperties.$router;
const existingRoute = app.config.globalProperties.$route;
const forceReload = existingRouter && existingRouter.isMocked !== true && (existingRoute && existingRoute.isMocked !== true);
if (forceReload) {
existingRouter.go(0);
return;
} else {
app.config.globalProperties.$router = {
isMocked: true,
// !IMPORTANT this line is required to ensure the full vue-router implementation can initialize
push: async (location) => {
actions.action("$router.push()")(location);
},
replace: async (location) => {
actions.action("$router.replace()")(location);
},
go: (n) => {
actions.action("$router.go()")(n);
},
back: () => {
actions.action("$router.back()")("back");
},
forward: () => {
actions.action("$router.forward()")("forward");
}
};
app.config.globalProperties.$route = {
isMocked: true,
// !IMPORTANT this line is required to ensure the full vue-router implementation can initialize
path: ctx.args?.path || "/",
fullPath: `/#${ctx.args?.path}`,
name: ctx.args?.name || "home",
meta: options.meta ? getFromArgs(ctx.args, options.meta) : {},
params: options.params ? getFromArgs(ctx.args, options.params) : {},
query: options.query ? getFromArgs(ctx.args, options.query) : {}
};
}
},
template: "<story/>"
});
}
exports.asyncVueRouter = withAsyncVueRouter;
exports.mockRouter = withMockRouter;
exports.vueRouter = withVueRouter;
//# sourceMappingURL=index.cjs.map