UNPKG

storybook-vue3-router

Version:

A Storybook decorator that allows you to build stories for your routing-aware components.

1 lines 17.6 kB
{"version":3,"file":"index.cjs","sources":["../src/defaultRoutes.ts","../src/utils.ts","../src/withVueRouter.ts","../src/withAsyncVueRouter.ts","../src/withMockRouter.ts"],"sourcesContent":["import type { RouteRecordRaw } from \"vue-router\";\r\nimport { action } from 'storybook/actions';\r\n\r\nconst Home = {\r\n template: `\r\n <div>\r\n <h2>Home</h2>\r\n \r\n <div style=\"display: flex; gap: 1em\">\r\n <router-link to=\"/\">Home</router-link>\r\n <router-link to=\"/about\">About</router-link>\r\n </div>\r\n </div>\r\n `\r\n};\r\n\r\nconst About = {\r\n template: `\r\n <div>\r\n <h2>About</h2>\r\n\r\n <div style=\"display: flex; gap: 1em\">\r\n <router-link to=\"/\">Home</router-link>\r\n <router-link to=\"/about\">About</router-link>\r\n </div>\r\n </div>\r\n `\r\n};\r\n\r\nexport const defaultRoutes: RouteRecordRaw[] = [\r\n {\r\n path: '/',\r\n name: 'home',\r\n component: Home,\r\n beforeEnter: (to, from) => action('beforeEnter')({ to: to.fullPath, from: from.fullPath })\r\n },\r\n {\r\n path: '/about',\r\n name: 'about',\r\n component: About,\r\n beforeEnter: (to, from) => action('beforeEnter')({ to: to.fullPath, from: from.fullPath })\r\n }\r\n]","import type {\r\n Router,\r\n RouteRecordRaw,\r\n NavigationGuard,\r\n RouteLocationRaw,\r\n RouteRecordNormalized\r\n} from 'vue-router'\r\n\r\nexport function globalRouterGuardFn(\r\n router: Router,\r\n beforeEach?: NavigationGuard,\r\n forceReload = false\r\n): void {\r\n if (typeof beforeEach === 'function') {\r\n /**\r\n * force reload in order to reset router and apply global beforeEach()\r\n * this is only required if the router has been initialized previously\r\n * TODO: can this be made less hacky?\r\n */\r\n if (forceReload) {\r\n router.go(0)\r\n return\r\n }\r\n // add `beforeEach` param on `router.beforeEach` and pass `to`, `from` and `next()` params to the function\r\n router.beforeEach((to, from, next) => beforeEach(to, from, next))\r\n }\r\n}\r\n\r\nexport function initialRoute(router: Router, initialRoute: RouteLocationRaw): void {\r\n router.replace(initialRoute || '/')\r\n}\r\n\r\nexport function resetRoutes(router: Router, newRoutes: RouteRecordRaw[]): void {\r\n const oldRoutes: Array<RouteRecordNormalized> = router.getRoutes()\r\n /* remove previously generated routes */\r\n oldRoutes.forEach((route) => {\r\n router.removeRoute(route.name)\r\n })\r\n /* add new story routes */\r\n newRoutes.forEach((route) => {\r\n router.addRoute(route)\r\n })\r\n}\r\n\r\ntype argObjectKeys = Record<string, unknown>\r\nexport function getFromArgs(args: argObjectKeys, options: Array<string>) {\r\n let filtered: argObjectKeys = {}\r\n options.forEach((option) => {\r\n filtered = { ...filtered, [option]: args[option] }\r\n })\r\n\r\n return filtered\r\n}","import { Decorator } from '@storybook/vue3'\r\nimport { getCurrentInstance } from 'vue';\r\n\r\nimport {\r\n createRouter,\r\n createWebHashHistory,\r\n /* types */\r\n type Router,\r\n type NavigationGuard,\r\n type RouteLocationNormalizedLoaded,\r\n type RouterOptions,\r\n} from 'vue-router'\r\n\r\nimport { defaultRoutes } from './defaultRoutes'\r\nimport { globalRouterGuardFn, initialRoute, resetRoutes } from './utils'\r\n\r\ntype MockRouter = Router & { isMocked?: boolean }\r\ntype MockRoute = RouteLocationNormalizedLoaded & { isMocked?: boolean }\r\n\r\n/**\r\n * Add a vue router instance to Storybook stories\r\n * @param routes (optional) custom routes for story\r\n * @param options (optional) custom options\r\n *\r\n * @remarks\r\n *\r\n * If there is a previously initialized story using vue-router and you wish to use `beforeEach` to apply global router guards via `options` param,\r\n * we must reload the story in order to apply the global route guards, this can have a minor performance impact.\r\n */\r\nexport function withVueRouter (\r\n /* optional: routes param - uses `defaultRoutes` if not provided */\r\n routes = defaultRoutes,\r\n /* optional: router options - used to pass `initialRoute` value, `beforeEach()` navigation guard methods and vue-router `createRouter` options */\r\n options?: {\r\n initialRoute?: string;\r\n beforeEach?: NavigationGuard;\r\n vueRouterOptions?: RouterOptions;\r\n }\r\n): Decorator {\r\n return () => ({\r\n setup () {\r\n const { app } = getCurrentInstance()!.appContext\r\n\r\n /* setup router var */\r\n let router\r\n\r\n /* check if there is an existing router */\r\n const existingRouter = app.config.globalProperties.$router as MockRouter\r\n const existingRoute = app.config.globalProperties.$route as MockRoute\r\n if (\r\n (!existingRouter || existingRouter.isMocked === true) &&\r\n (!existingRoute || existingRoute.isMocked === true)\r\n ) {\r\n /* create vue router */\r\n router = createRouter({\r\n history: createWebHashHistory(),\r\n routes,\r\n ...options?.vueRouterOptions,\r\n })\r\n\r\n /* setup optional global router guards */\r\n globalRouterGuardFn(router, options?.beforeEach)\r\n\r\n /* tell storybook to use vue router */\r\n app.use(router)\r\n } else {\r\n /* set router to value of existing router */\r\n router = existingRouter\r\n\r\n /* reset routes (remove old / add new) */\r\n resetRoutes(router, routes)\r\n /* setup optional global router guards (if provided and there is an existing router this will force a page reload) */\r\n globalRouterGuardFn(existingRouter, options?.beforeEach, true)\r\n }\r\n\r\n /* go to initial route */\r\n initialRoute(router, options?.initialRoute)\r\n },\r\n template: '<story/>'\r\n })\r\n}\r\nexport default withVueRouter\r\n","import { Decorator } from '@storybook/vue3'\r\nimport { getCurrentInstance } from 'vue';\r\n\r\nimport {\r\n createRouter,\r\n createWebHashHistory,\r\n /* types */\r\n type Router,\r\n type NavigationGuard,\r\n type RouteLocationNormalizedLoaded,\r\n type RouterOptions,\r\n} from 'vue-router'\r\n\r\nimport { defaultRoutes } from './defaultRoutes'\r\nimport { globalRouterGuardFn, initialRoute, resetRoutes } from './utils'\r\n\r\ntype MockRouter = Router & { isMocked?: boolean }\r\ntype MockRoute = RouteLocationNormalizedLoaded & { isMocked?: boolean }\r\n\r\n/**\r\n * Add a vue router instance to Storybook stories\r\n * @param routes (optional) custom routes for story\r\n * @param options (optional) custom options\r\n *\r\n * @remarks\r\n *\r\n * If there is a previously initialized story using vue-router and you wish to use `beforeEach` to apply global router guards via `options` param,\r\n * we must reload the story in order to apply the global route guards, this can have a minor performance impact.\r\n */\r\nexport function withAsyncVueRouter (\r\n /* optional: routes param - uses `defaultRoutes` if not provided */\r\n routes = defaultRoutes,\r\n /* optional: router options - used to pass `initialRoute` value, `beforeEach()` navigation guard methods and vue-router `createRouter` options */\r\n options?: {\r\n initialRoute?: string;\r\n beforeEach?: NavigationGuard;\r\n vueRouterOptions?: RouterOptions;\r\n }\r\n): Decorator {\r\n return () => ({\r\n async setup () {\r\n const { app } = getCurrentInstance()!.appContext\r\n\r\n /* setup router var */\r\n let router\r\n\r\n /* check if there is an existing router */\r\n const existingRouter = app.config.globalProperties.$router as MockRouter\r\n const existingRoute = app.config.globalProperties.$route as MockRoute\r\n if (\r\n (!existingRouter || existingRouter.isMocked === true) &&\r\n (!existingRoute || existingRoute.isMocked === true)\r\n ) {\r\n /* create vue router */\r\n router = createRouter({\r\n history: createWebHashHistory(),\r\n routes,\r\n ...options?.vueRouterOptions,\r\n })\r\n\r\n /* setup optional global router guards */\r\n globalRouterGuardFn(router, options?.beforeEach)\r\n\r\n /* tell storybook to use vue router */\r\n app.use(router)\r\n } else {\r\n /* set router to value of existing router */\r\n router = existingRouter\r\n\r\n /* reset routes (remove old / add new) */\r\n resetRoutes(router, routes)\r\n /* setup optional global router guards (if provided and there is an existing router this will force a page reload) */\r\n globalRouterGuardFn(existingRouter, options?.beforeEach, true)\r\n }\r\n\r\n /* go to initial route */\r\n initialRoute(router, options?.initialRoute)\r\n\r\n await router.isReady()\r\n },\r\n template: `\r\n <story/>\r\n `\r\n })\r\n}\r\nexport default withAsyncVueRouter\r\n","\r\nimport { Decorator } from '@storybook/vue3'\r\nimport { getCurrentInstance } from 'vue';\r\nimport { action } from 'storybook/actions'\r\n\r\nimport type {\r\n Router,\r\n RouteLocationRaw,\r\n RouteLocationNormalizedLoaded\r\n} from 'vue-router'\r\n\r\nimport { getFromArgs } from './utils'\r\n\r\ntype MockRouter = Router & { isMocked?: boolean }\r\ntype MockRoute = RouteLocationNormalizedLoaded & { isMocked?: boolean }\r\n\r\n/**\r\n * Add a vue router instance to Storybook stories\r\n * @param routes (optional) custom routes for story\r\n * @param options (optional) custom options\r\n *\r\n * @remarks\r\n *\r\n * If there is a previously initialized story using vue-router and you wish to use `beforeEach` to apply global router guards via `options` param,\r\n * we must reload the story in order to apply the global route guards, this can have a minor performance impact.\r\n */\r\nexport function withMockRouter (\r\n /* optional: router options - used to pass `initialRoute` value, `beforeEach()` navigation guard methods and vue-router `createRouter` options */\r\n options: { meta?: Array<string>, params?: Array<string>, query?: Array<string> }\r\n): Decorator {\r\n return (_, ctx) => ({\r\n setup () {\r\n const { app } = getCurrentInstance()!.appContext\r\n const existingRouter = app.config.globalProperties.$router as MockRouter\r\n const existingRoute = app.config.globalProperties.$route as MockRoute\r\n \r\n /* if vue-router is already initialized we refresh the page to ensure full (non-mocked) vue-router can be initialized */\r\n const forceReload = (existingRouter && existingRouter.isMocked !== true) && (existingRoute && existingRoute.isMocked !== true)\r\n if (forceReload) {\r\n existingRouter.go(0)\r\n return\r\n } else {\r\n app.config.globalProperties.$router = {\r\n isMocked: true, // !IMPORTANT this line is required to ensure the full vue-router implementation can initialize\r\n push: async (location: RouteLocationRaw) => { action('$router.push()')(location) },\r\n replace: async (location: RouteLocationRaw) => { action('$router.replace()')(location) },\r\n go: (n: number) => { action('$router.go()')(n) },\r\n back: () => { action('$router.back()')('back') },\r\n forward: () => { action('$router.forward()')('forward') },\r\n } as MockRouter\r\n app.config.globalProperties.$route = {\r\n isMocked: true, // !IMPORTANT this line is required to ensure the full vue-router implementation can initialize\r\n path: ctx.args?.path || '/',\r\n fullPath: `/#${ctx.args?.path}`,\r\n name: ctx.args?.name || 'home',\r\n meta: options.meta ? getFromArgs(ctx.args, options.meta) : {},\r\n params: options.params ? getFromArgs(ctx.args, options.params) : {},\r\n query: options.query ? getFromArgs(ctx.args, options.query) : {},\r\n } as MockRoute\r\n }\r\n },\r\n template: '<story/>'\r\n })\r\n}\r\n \r\nexport default withMockRouter\r\n"],"names":["action","initialRoute","getCurrentInstance","createRouter","createWebHashHistory"],"mappings":"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"}