@basmilius/routing 3.30.0 → 3.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["createVueRouter","VueRouterView","FALSE_REF","VueRouterView","useVueRoute","useRoute","useRouteNames","useVueRoute","useRoute","useRoute","useRoute","useRoute"],"sources":["../src/internal/modalState.ts","../src/internal/modalContext.ts","../src/internal/patchRouter.ts","../src/symbol.ts","../src/createRouter.ts","../src/component/ModalRouterView.ts","../src/component/RouterLink.ts","../src/internal/RoutedView.ts","../src/internal/resolveModal.ts","../src/component/RouterView.ts","../src/composable/useRoute.ts","../src/composable/useRouteNames.ts","../src/composable/useIsView.ts","../src/composable/useModalRoute.ts","../src/composable/useNamedRoute.ts","../src/composable/useNavigate.ts","../src/composable/useRouteMeta.ts","../src/composable/useRouteParam.ts","../src/composable/useRouteView.ts"],"sourcesContent":["import type { HistoryState } from 'vue-router';\n\nexport type ModalState = {\n readonly backgroundPath: string;\n readonly depth: number;\n};\n\n// note: Modal fields on `history.state`:\n// { modal: true, modalBackgroundPath: '/users', modalDepth: 0 }\n// - `modal` flags the entry as a modal.\n// - `modalBackgroundPath` is the fullPath rendered behind the wrapper.\n// - `modalDepth` is the parent-record count above the deepest matched\n// record that renders inside the wrapper (0 = deepest only).\n\nexport function readModalState(): ModalState | null {\n if (typeof history === 'undefined' || !history.state) {\n return null;\n }\n\n const state = history.state as Record<string, unknown>;\n\n if (state.modal !== true) {\n return null;\n }\n\n if (typeof state.modalBackgroundPath !== 'string' || !state.modalBackgroundPath) {\n return null;\n }\n\n return {\n backgroundPath: state.modalBackgroundPath,\n depth: typeof state.modalDepth === 'number' ? Math.max(0, state.modalDepth) : 0\n };\n}\n\nexport function writeModalState(base: HistoryState | null, backgroundPath: string | null, depth: number = 0): HistoryState {\n const next: HistoryState = {...(base ?? {})};\n\n if (backgroundPath === null) {\n // note: `null` (not `delete`) so vue-router's state-merging\n // unambiguously wipes the previous value.\n next.modal = null;\n next.modalBackgroundPath = null;\n next.modalDepth = null;\n\n return next;\n }\n\n next.modal = true;\n next.modalBackgroundPath = backgroundPath;\n next.modalDepth = Math.max(0, depth);\n\n return next;\n}\n","import { computed, type ComputedRef, shallowRef, type ShallowRef, unref, watch } from 'vue';\nimport { loadRouteLocation, type RouteLocationNormalized, type Router } from 'vue-router';\nimport type { ModalConfig } from '../types';\nimport { readModalState, writeModalState } from './modalState';\nimport type { OriginalNav } from './patchRouter';\n\n// note: True when all matched-record components are already materialised\n// (not still `() => import(...)` functions). Decides whether to assign\n// the background route synchronously or await `loadRouteLocation` first.\nfunction isFullyLoaded(route: RouteLocationNormalized): boolean {\n for (const record of route.matched) {\n if (!record.components) {\n continue;\n }\n\n for (const name in record.components) {\n const component = record.components[name];\n\n if (typeof component === 'function' && !('displayName' in component)) {\n return false;\n }\n }\n }\n\n return true;\n}\n\nexport type ModalContext = {\n readonly isModal: ComputedRef<boolean>;\n readonly backgroundRoute: ShallowRef<RouteLocationNormalized | null>;\n readonly depth: ShallowRef<number>;\n readonly initiallyOpen: ShallowRef<boolean>;\n readonly defaultModal: ModalConfig | null;\n // note: Symbol of the `<RouterView modals>` instance that owns the\n // host role. `null` when no host is mounted — modals don't render.\n readonly host: ShallowRef<symbol | null>;\n\n promote(): Promise<void>;\n\n // note: Reserves the host role. Returns `true` when the role was free\n // and is now ours; `false` when another instance got there first.\n claimHost(id: symbol): boolean;\n\n // note: Releases the host role only if `id` matches the current\n // holder, so a late \"loser\" unmount can't reset the actual host.\n releaseHost(id: symbol): void;\n};\n\nexport default function createModalContext(\n router: Router,\n original: OriginalNav,\n defaultModal: ModalConfig | null\n): ModalContext {\n const initial = readModalState();\n\n // note: On hard refresh of a modal URL, the background route's lazy\n // chunks aren't loaded yet — `components` are still import functions\n // that Vue would render as promise vnodes inside `<Transition>`. We\n // keep `backgroundRoute` null until `loadRouteLocation` materialises\n // them, then assign once.\n const backgroundRoute = shallowRef<RouteLocationNormalized | null>(null);\n\n // note: Number of parent matched records (above the deepest) that\n // render inside the modal wrapper. `0` renders only the deepest;\n // higher values include ancestors as in-modal layout.\n const depth = shallowRef(initial?.depth ?? 0);\n\n // note: True between the first render (history.state already shows\n // an open modal) and the moment the background route's async load\n // settles. Wrappers can consume this to skip the opening transition.\n const initiallyOpen = shallowRef(initial !== null);\n\n const isModal = computed(() => unref(backgroundRoute) !== null);\n\n let loadToken = 0;\n\n // note: On refresh, await the background chunks before surfacing the\n // background route. Already-cached chunks assign synchronously so\n // the first render sees the open-modal state.\n if (initial !== null) {\n const token = ++loadToken;\n const snapshot = router.resolve(initial.backgroundPath) as RouteLocationNormalized;\n\n if (isFullyLoaded(snapshot)) {\n backgroundRoute.value = snapshot;\n initiallyOpen.value = false;\n } else {\n loadRouteLocation(snapshot)\n .then(() => {\n if (token !== loadToken) {\n return;\n }\n\n backgroundRoute.value = router.resolve(initial.backgroundPath) as RouteLocationNormalized;\n initiallyOpen.value = false;\n })\n .catch(() => {\n if (token !== loadToken) {\n return;\n }\n\n backgroundRoute.value = null;\n initiallyOpen.value = false;\n });\n }\n }\n\n // note: React to subsequent navigations. `flush: 'pre'` runs before\n // render so RouterView picks up the new background the same tick.\n watch(router.currentRoute, () => {\n if (typeof history === 'undefined') {\n backgroundRoute.value = null;\n depth.value = 0;\n\n return;\n }\n\n const state = readModalState();\n\n if (state === null) {\n loadToken++;\n backgroundRoute.value = null;\n depth.value = 0;\n initiallyOpen.value = false;\n\n return;\n }\n\n depth.value = state.depth;\n\n const token = ++loadToken;\n const backgroundPath = state.backgroundPath;\n const snapshot = router.resolve(backgroundPath) as RouteLocationNormalized;\n\n // note: Fast path — chunks already loaded (typical navigation),\n // assign synchronously to avoid a flash of modal-as-fullpage.\n // Slow path — hard refresh, await load to avoid promise vnodes.\n if (isFullyLoaded(snapshot)) {\n backgroundRoute.value = snapshot;\n\n return;\n }\n\n loadRouteLocation(snapshot)\n .then(() => {\n if (token !== loadToken) {\n return;\n }\n\n backgroundRoute.value = router.resolve(backgroundPath) as RouteLocationNormalized;\n })\n .catch(() => {\n if (token !== loadToken) {\n return;\n }\n\n backgroundRoute.value = null;\n });\n }, {flush: 'pre'});\n\n async function promote(): Promise<void> {\n const current = unref(router.currentRoute);\n\n // note: Turns the modal's URL into the \"real\" page. `replace`\n // avoids a duplicate history entry; `force: true` because\n // vue-router otherwise skips a same-URL replace.\n await original.replace({\n path: current.fullPath,\n force: true,\n state: writeModalState(null, null)\n });\n }\n\n const host = shallowRef<symbol | null>(null);\n\n function claimHost(id: symbol): boolean {\n if (host.value !== null) {\n return false;\n }\n\n host.value = id;\n\n return true;\n }\n\n function releaseHost(id: symbol): void {\n if (host.value !== id) {\n return;\n }\n\n host.value = null;\n }\n\n return {\n isModal,\n backgroundRoute,\n depth,\n initiallyOpen,\n defaultModal,\n host,\n promote,\n claimHost,\n releaseHost\n };\n}\n","import { unref } from 'vue';\nimport type { HistoryState, NavigationFailure, RouteLocationOptions, RouteLocationRaw, Router } from 'vue-router';\nimport { readModalState, writeModalState } from './modalState';\n\ntype Navigate = (to: RouteLocationRaw) => Promise<NavigationFailure | void | undefined>;\n\nexport type OriginalNav = {\n readonly push: Navigate;\n readonly replace: Navigate;\n};\n\nfunction withState(to: RouteLocationRaw, state: HistoryState): RouteLocationRaw {\n if (typeof to === 'string') {\n return {path: to, state};\n }\n\n return {...to, state};\n}\n\nfunction injectState(to: RouteLocationRaw, backgroundPath: string | null, depth: number = 0): RouteLocationRaw {\n const base = typeof to === 'string' ? null : (to.state ?? null);\n\n return withState(to, writeModalState(base, backgroundPath, depth));\n}\n\nfunction readModalFlag(flag: boolean | number | undefined): {open: boolean; depth: number; explicitClose: boolean} {\n if (flag === true) {\n return {open: true, depth: 0, explicitClose: false};\n }\n\n if (flag === false) {\n return {open: false, depth: 0, explicitClose: true};\n }\n\n if (typeof flag === 'number') {\n return {open: true, depth: Math.max(0, flag), explicitClose: false};\n }\n\n return {open: false, depth: 0, explicitClose: false};\n}\n\nexport default function patchRouter(router: Router): OriginalNav {\n const origPush: Navigate = router.push.bind(router);\n const origReplace: Navigate = router.replace.bind(router);\n\n function transform(to: RouteLocationRaw): RouteLocationRaw {\n const wantsModal = typeof to === 'string' ? undefined : (to as RouteLocationOptions).modal;\n const flag = readModalFlag(wantsModal);\n const current = readModalState();\n\n // note: Explicit `modal: true` / `<number>` opens on top of the\n // current route. Already-open modals reuse the existing background.\n if (flag.open) {\n const backgroundPath = current?.backgroundPath ?? unref(router.currentRoute).fullPath;\n\n return injectState(to, backgroundPath, flag.depth);\n }\n\n // note: Explicit `modal: false` exits the modal entirely.\n if (flag.explicitClose) {\n return injectState(to, null);\n }\n\n // note: Implicit navigation from within a modal. Keep the modal open\n // when the target shares the root-matched record (sibling within\n // the same modal tree), otherwise exit. Depth carries across.\n if (current !== null) {\n const resolved = router.resolve(to);\n const currentRoot = unref(router.currentRoute).matched[0]?.path;\n const nextRoot = resolved.matched[0]?.path;\n const sameRoot = !!currentRoot && currentRoot === nextRoot;\n\n return sameRoot ? injectState(to, current.backgroundPath, current.depth) : injectState(to, null);\n }\n\n return to;\n }\n\n router.push = async (to) => await origPush(transform(to));\n router.replace = async (to) => await origReplace(transform(to));\n\n return {\n push: origPush,\n replace: origReplace\n };\n}\n","import type { ComputedRef, InjectionKey, Ref, ShallowRef } from 'vue';\nimport type { RouteLocationNormalized } from 'vue-router';\nimport type { ModalContext } from './internal/modalContext';\n\nexport const modalContextKey: InjectionKey<ModalContext> = Symbol('basmilius:routing:modal-context');\nexport const routeOverrideKey: InjectionKey<ComputedRef<RouteLocationNormalized>> = Symbol('basmilius:routing:route-override');\nexport const isInModalKey: InjectionKey<Ref<boolean>> = Symbol('basmilius:routing:in-modal');\n\n// note: Gates the modal's inner `<VueRouterView>` for one tick on a\n// user-triggered open so the wrapper's `<Transition>` plays the enter\n// animation. See `RouterView.ts` for the full rationale.\nexport const innerReadyKey: InjectionKey<ShallowRef<boolean>> = Symbol('basmilius:routing:inner-ready');\n","import type { App } from 'vue';\nimport { createRouter as createVueRouter, type Router } from 'vue-router';\nimport createModalContext from './internal/modalContext';\nimport patchRouter from './internal/patchRouter';\nimport { modalContextKey } from './symbol';\nimport type { RouterOptions } from './types';\n\nexport default function createRouter(options: RouterOptions): Router {\n const {defaultModal, ...routerOptions} = options;\n\n const router = createVueRouter(routerOptions);\n const original = patchRouter(router);\n const ctx = createModalContext(router, original, defaultModal ?? null);\n\n const originalInstall = router.install.bind(router);\n\n router.install = (app: App): void => {\n originalInstall(app);\n app.provide(modalContextKey, ctx);\n };\n\n return router;\n}\n","import { type Component, defineComponent, h, inject, type VNodeChild } from 'vue';\nimport { RouterView as VueRouterView } from 'vue-router';\nimport { innerReadyKey } from '../symbol';\n\n// note: Thin wrapper around `VueRouterView` that honours the\n// `innerReadyKey` gate from our `RouterView`. Use this in wrapper\n// templates that need `v-slot` to animate push-navigations inside a\n// modal — vue-router's plain `RouterView` would mount in the same tick\n// as the wrapper and skip its enter animation. Outside a modal context\n// (no gate provided) it's a passthrough.\nconst ModalRouterView: Component = defineComponent({\n name: 'ModalRouterView',\n inheritAttrs: false,\n setup(_props, {attrs, slots}) {\n const innerReady = inject(innerReadyKey, null);\n\n return (): VNodeChild => {\n if (innerReady === null) {\n return h(VueRouterView, attrs, slots);\n }\n\n // note: Gate closed -> render nothing so the wrapper's\n // `<Transition>` observes an empty slot on mount, then\n // picks up the child once the gate flips.\n if (!innerReady.value) {\n return undefined;\n }\n\n return h(VueRouterView, attrs, slots);\n };\n }\n});\n\nexport default ModalRouterView;\n","import { type Component, computed, defineComponent, h, type PropType, type VNodeChild } from 'vue';\nimport { type RouteLocationRaw, useLink, useRouter } from 'vue-router';\n\ntype AriaCurrentValue = 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false';\n\nconst RouterLink: Component = defineComponent({\n name: 'RouterLink',\n props: {\n to: {\n type: [String, Object] as PropType<RouteLocationRaw>,\n required: true\n },\n replace: {\n type: Boolean,\n default: false\n },\n activeClass: {\n type: String,\n default: 'router-link-active'\n },\n exactActiveClass: {\n type: String,\n default: 'router-link-exact-active'\n },\n ariaCurrentValue: {\n type: String as PropType<AriaCurrentValue>,\n default: 'page'\n },\n custom: {\n type: Boolean,\n default: false\n },\n modal: {\n type: [Boolean, Number] as PropType<boolean | number>,\n default: false\n }\n },\n setup(props, {slots}) {\n const router = useRouter();\n\n // note: Pass per-field computeds (not a resolved object) so vue-\n // router's `useLink` tracks `props.to` / `props.replace` through\n // its internal `unref()` calls. Resolving via `.value` would hand\n // it a snapshot and `href` / `isActive` would never update on\n // prop changes.\n const link = useLink({\n to: computed(() => props.to),\n replace: computed(() => props.replace)\n });\n\n // note: `modal` is truthy for `true` and any number (including 0,\n // which means \"open as modal, deepest only\"). Normalises into\n // the shape patchRouter expects on `RouteLocationOptions.modal`.\n function modalFlag(): boolean | number {\n return typeof props.modal === 'number' ? props.modal : props.modal === true;\n }\n\n function isModalRequested(): boolean {\n return props.modal === true || typeof props.modal === 'number';\n }\n\n async function navigate(event?: MouseEvent): Promise<void> {\n if (isModalRequested()) {\n if (event) {\n // note: Let modifier clicks / non-primary buttons\n // fall through so middle-click / ctrl+click still\n // open the URL in a new tab. Modal routes must be\n // valid standalone pages.\n if (event.defaultPrevented) {\n return;\n }\n\n if (event.button !== undefined && event.button !== 0) {\n return;\n }\n\n if (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {\n return;\n }\n\n event.preventDefault();\n }\n\n const flag = modalFlag();\n const target: RouteLocationRaw = typeof props.to === 'string'\n ? {path: props.to, modal: flag}\n : {...props.to, modal: flag};\n\n if (props.replace) {\n await router.replace(target);\n } else {\n await router.push(target);\n }\n\n return;\n }\n\n await link.navigate(event);\n }\n\n return (): VNodeChild => {\n const slotProps = {\n href: link.href.value,\n route: link.route.value,\n navigate,\n isActive: link.isActive.value,\n isExactActive: link.isExactActive.value\n };\n\n const children = slots.default?.(slotProps);\n\n if (props.custom) {\n return children;\n }\n\n return h('a', {\n href: link.href.value,\n 'aria-current': link.isExactActive.value ? props.ariaCurrentValue : undefined,\n class: {\n [props.activeClass]: link.isActive.value,\n [props.exactActiveClass]: link.isExactActive.value\n },\n onClick: navigate\n }, children);\n };\n }\n});\n\nexport default RouterLink;\n","import { type Component, computed, defineComponent, type PropType, provide, type Ref, shallowRef, type VNodeChild } from 'vue';\nimport { type RouteLocationNormalized, routerViewLocationKey, viewDepthKey } from 'vue-router';\nimport { isInModalKey, routeOverrideKey } from '../symbol';\n\nconst TRUE_REF = shallowRef(true);\nconst FALSE_REF = shallowRef(false);\n\n// note: Both providers override `routerViewLocationKey` so descendant\n// `<RouterView>`s render the supplied `route` instead of the router's\n// live currentRoute. `viewDepthKey` is set to the index at which the\n// inner `VueRouterView` should resume in `matched[]` — for\n// `BackgroundProvider`, the host's own depth (so a nested host doesn't\n// re-render its ancestors); for `ModalProvider`, the absolute matched\n// index computed by RouterView from `ctx.depth`.\n\nexport const BackgroundProvider: Component = defineComponent({\n name: 'BackgroundProvider',\n props: {\n route: {\n type: Object as PropType<RouteLocationNormalized>,\n required: true\n },\n viewDepth: {\n type: Number,\n default: 0\n }\n },\n setup(props, {slots}) {\n const routeRef = computed(() => props.route);\n\n provide(routerViewLocationKey, routeRef);\n provide(viewDepthKey, props.viewDepth);\n provide(routeOverrideKey, routeRef);\n provide(isInModalKey, FALSE_REF);\n\n return (): VNodeChild => slots.default?.();\n }\n});\n\nexport const ModalProvider: Component = defineComponent({\n name: 'ModalProvider',\n props: {\n route: {\n type: Object as PropType<RouteLocationNormalized>,\n required: true\n },\n // note: Ref instead of a plain number — Vue's runtime `h()` prop\n // diffing can miss primitive updates when patching in a tight\n // cycle alongside reactive route changes. Ref identity stays\n // stable; `.value` propagates through normal reactivity.\n depthRef: {\n type: Object as PropType<Ref<number>>,\n required: true\n }\n },\n setup(props, {slots}) {\n const routeRef = computed(() => props.route);\n\n provide(routerViewLocationKey, routeRef);\n provide(viewDepthKey, props.depthRef);\n provide(routeOverrideKey, routeRef);\n provide(isInModalKey, TRUE_REF);\n\n return (): VNodeChild => slots.default?.();\n }\n});\n","import type { RouteLocationNormalized } from 'vue-router';\nimport type { ModalConfig } from '../types';\n\n// note: Walks matched records deepest-first so children override their\n// parent's `meta.modal`. Falls back to `defaultModal` from\n// `createRouter()` when no record declares one.\nexport default function resolveModal(\n route: RouteLocationNormalized,\n fallback: ModalConfig | null\n): ModalConfig | null {\n for (let i = route.matched.length - 1; i >= 0; --i) {\n const modal = route.matched[i]?.meta?.modal;\n\n if (modal) {\n return modal;\n }\n }\n\n return fallback;\n}\n","import { type Component, defineComponent, Fragment, h, inject, nextTick, onBeforeUnmount, provide, type Ref, shallowRef, unref, type VNodeChild, watch } from 'vue';\nimport { RouterView as VueRouterView, useRoute, useRouter, viewDepthKey } from 'vue-router';\nimport { BackgroundProvider, ModalProvider } from '../internal/RoutedView';\nimport resolveModal from '../internal/resolveModal';\nimport { innerReadyKey, modalContextKey, routeOverrideKey } from '../symbol';\nimport type { ModalConfig } from '../types';\n\nconst RouterView: Component = defineComponent({\n name: 'RouterView',\n inheritAttrs: false,\n props: {\n // note: Opts this instance in as the host that renders the modal\n // layer on top of the background route. Exactly one `<RouterView>`\n // in the tree should set this; if multiple do, the first to mount\n // wins (others render vanilla and emit a console warning).\n modals: {\n type: Boolean,\n default: false\n }\n },\n setup(props, {attrs, slots}) {\n const ctx = inject(modalContextKey, null);\n const override = inject(routeOverrideKey, null);\n const route = useRoute();\n const router = useRouter();\n\n // note: Vue-router injects `viewDepthKey` from the parent\n // `VueRouterView` (or 0 at the top). It can be a number or a\n // `Ref<number>`; `unref` collapses both. Passed to\n // `BackgroundProvider` so the background tree resumes at the\n // correct matched index when this RouterView is nested.\n const injectedViewDepth = inject(viewDepthKey, 0);\n\n // note: Identity used to claim/release the modal host role on the\n // shared `modalContext`. The matching unmount release targets\n // exactly our claim — never a successor's.\n const hostId = Symbol('basmilius:routing:router-view-host');\n\n let isModalHost = false;\n\n if (props.modals && override === null && ctx) {\n isModalHost = ctx.claimHost(hostId);\n\n if (!isModalHost) {\n // eslint-disable-next-line no-console\n console.warn(\n '[routing] Multiple <RouterView modals> instances detected. ' +\n 'The first mounted instance owns the modal host role; this ' +\n 'instance will render as a vanilla RouterView.'\n );\n } else {\n onBeforeUnmount(() => ctx.releaseHost(hostId));\n }\n }\n\n // note: Wrapper component (e.g. FluxOverlay) stays mounted across\n // modal close for its leave animation, and is reused when\n // consecutive modals share the same wrapper.\n const lastModal = shallowRef<ModalConfig | null>(null);\n\n // note: Held as a ref because Vue's runtime `h()` can miss\n // primitive prop updates on `ModalProvider` when route changes\n // patch in the same tick. Ref identity stays stable.\n const modalDepthRef: Ref<number> = shallowRef(0);\n\n // note: Gates whether the modal's inner `<RouterView>` is attached.\n // On a user-triggered open we hold it back one tick so the\n // wrapper's `<Transition>` observes \"no child -> child\" and plays\n // its enter animation. On hard refresh of a modal URL we skip the\n // gate so the page arrives already-open without animating.\n const innerReady = shallowRef(false);\n\n // note: Snapshot at setup — `modalContext` flips `initiallyOpen`\n // back to `false` once the background route resolves, which is\n // too early to read from the watcher below.\n const wasInitiallyOpen = ctx?.initiallyOpen.value ?? false;\n\n let hasSeenActiveModal = false;\n\n // note: Exposed so `ModalRouterView` inside consumer wrapper\n // templates honours the same one-tick delay as the fallback slot.\n provide(innerReadyKey, innerReady);\n\n if (ctx && isModalHost) {\n watch(() => ctx.backgroundRoute.value !== null, async (isOpen) => {\n if (!isOpen) {\n innerReady.value = false;\n\n return;\n }\n\n const isFirstActivation = !hasSeenActiveModal;\n hasSeenActiveModal = true;\n\n // note: Pageload of a modal URL — wrapper and inner mount\n // together without a transition.\n if (isFirstActivation && wasInitiallyOpen) {\n innerReady.value = true;\n\n return;\n }\n\n // note: User-triggered open — wrapper renders first with\n // an empty slot, inner attaches next tick to animate in.\n innerReady.value = false;\n await nextTick();\n innerReady.value = true;\n }, {immediate: true, flush: 'pre'});\n }\n\n return (): VNodeChild => {\n // note: Already inside a BackgroundProvider / ModalProvider\n // subtree — render vanilla so we don't recurse into another\n // background/modal split.\n if (override !== null) {\n return h(VueRouterView, attrs, slots);\n }\n\n if (!ctx) {\n return h(VueRouterView, attrs, slots);\n }\n\n // note: Only the instance that claimed the host role renders\n // modals. All others fall through to vanilla.\n if (!isModalHost) {\n return h(VueRouterView, attrs, slots);\n }\n\n const backgroundRoute = ctx.backgroundRoute.value;\n const modalActive = ctx.isModal.value && backgroundRoute !== null;\n\n // note: Resolve inline (not via watcher) — at setup the route\n // is `START_LOCATION` with empty `matched`, so a watcher with\n // `immediate: true` would miss the per-route `meta.modal`.\n if (modalActive) {\n const resolved = resolveModal(route, ctx.defaultModal);\n\n if (resolved !== null && resolved !== lastModal.value) {\n lastModal.value = resolved;\n }\n }\n\n const wrapperConfig = lastModal.value;\n\n // note: Never been a modal here -> plain RouterView.\n if (!modalActive && !wrapperConfig) {\n return h(VueRouterView, attrs, slots);\n }\n\n // note: Background renders the stored route while open; the\n // current route while closed (wrapper lingering for leave\n // animation). Keeps layout-level `useRoute()` stable.\n const bgRoute = modalActive ? backgroundRoute : route;\n\n // note: `ctx.depth` is the user-supplied parent count. Translate\n // to an absolute `matched[]` index:\n // depth 0 -> matched[length - 1] (deepest only)\n // depth N -> matched[length - 1 - N]\n const parentCount = ctx.depth.value;\n const viewDepth = Math.max(0, route.matched.length - 1 - parentCount);\n\n modalDepthRef.value = viewDepth;\n\n // note: ModalProvider wraps the wrapper component so the\n // wrapper's internal Teleport still inherits the provider\n // context. Inner is `undefined` while closed or gated, so\n // the wrapper's `<Transition>` observes an empty slot.\n const modalInner = modalActive && innerReady.value\n ? h(VueRouterView)\n : undefined;\n\n const wrappedModalInner = wrapperConfig\n ? h(wrapperConfig.component, {\n ...(wrapperConfig.props ?? {}),\n // note: Runtime props after the spread so consumers\n // can't shadow them via `meta.modal.props`. Use\n // `modalReady` (not `modalActive`) to v-if the\n // inner `<ModalRouterView>` — `modalActive` is true\n // at mount and would skip the enter animation.\n modalRoute: route,\n modalActive,\n modalReady: modalActive && innerReady.value,\n onClose: (): void => {\n router.back();\n }\n }, {\n default: (): VNodeChild => modalInner\n })\n : modalInner;\n\n const modalLayer = h(ModalProvider, {route, depthRef: modalDepthRef}, {\n default: (): VNodeChild => wrappedModalInner\n });\n\n const hostViewDepth = unref(injectedViewDepth);\n\n return h(Fragment, [\n h(BackgroundProvider, {route: bgRoute, viewDepth: hostViewDepth}, {\n default: (): VNodeChild => h(VueRouterView, attrs, slots)\n }),\n modalLayer\n ]);\n };\n }\n});\n\nexport default RouterView;\n","import { computed, inject, shallowRef, unref } from 'vue';\nimport { type RouteLocationNormalizedLoaded, useRoute as useVueRoute } from 'vue-router';\nimport { isInModalKey, modalContextKey, routeOverrideKey } from '../symbol';\n\nexport type UseRoute = RouteLocationNormalizedLoaded & {\n readonly isModal: boolean;\n\n promote(): Promise<void>;\n};\n\nconst FALSE_REF = shallowRef(false);\nconst NOOP = async (): Promise<void> => undefined;\n\nexport default function (): UseRoute {\n const override = inject(routeOverrideKey, null);\n const ctx = inject(modalContextKey, null);\n const isModalRef = inject(isInModalKey, FALSE_REF);\n const raw = useVueRoute();\n\n const routeRef = computed<RouteLocationNormalizedLoaded>(() => {\n // note: Inside a Background/ModalProvider subtree — use the\n // explicit override so background-tree components see the\n // background route and modal-wrapper components see the modal\n // route, independent of the router's live currentRoute.\n if (override !== null) {\n return unref(override) as RouteLocationNormalizedLoaded;\n }\n\n // note: Outside any provider (top-level layouts) — surface the\n // background route while a modal is open so layout-level\n // `:key`s stay stable across opens/closes.\n if (ctx !== null && unref(ctx.isModal)) {\n const bg = unref(ctx.backgroundRoute);\n\n if (bg !== null) {\n return bg as RouteLocationNormalizedLoaded;\n }\n }\n\n return raw;\n });\n\n const promote = ctx !== null ? ctx.promote : NOOP;\n\n // note: Proxy (not a Ref) so the object can be used directly in\n // templates without auto-unwrapping stripping our extras. All\n // route properties flow through `routeRef.value` to keep reactivity\n // tracking intact in templates, computeds, and watchers.\n return new Proxy({} as UseRoute, {\n get(_target, key) {\n if (key === 'isModal') {\n return isModalRef.value;\n }\n\n if (key === 'promote') {\n return promote;\n }\n\n return (routeRef.value as unknown as Record<PropertyKey, unknown>)[key];\n },\n has(_target, key) {\n if (key === 'isModal' || key === 'promote') {\n return true;\n }\n\n return key in routeRef.value;\n },\n ownKeys(_target) {\n return [...Reflect.ownKeys(routeRef.value), 'isModal', 'promote'];\n },\n getOwnPropertyDescriptor(_target, key) {\n if (key === 'isModal') {\n return {configurable: true, enumerable: true, value: isModalRef.value};\n }\n\n if (key === 'promote') {\n return {configurable: true, enumerable: true, value: promote};\n }\n\n return Object.getOwnPropertyDescriptor(routeRef.value, key);\n }\n });\n}\n","import { computed, type ComputedRef, unref } from 'vue';\nimport useRoute from './useRoute';\n\nexport default function (): ComputedRef<string[]> {\n const route = useRoute();\n\n return computed(() => {\n const names: string[] = [];\n\n unref(route).matched.forEach(m => m.name && names.push(m.name as string));\n\n return names;\n });\n}\n","import { computed, type ComputedRef, unref } from 'vue';\nimport useRouteNames from './useRouteNames';\n\nexport default function (name: string, loose: boolean = false): ComputedRef<boolean> {\n const names = useRouteNames();\n\n if (loose) {\n return computed(() => unref(names).some(n => n.startsWith(name)));\n }\n\n return computed(() => unref(names).some(n => n === name));\n}\n","import { computed, type ComputedRef, inject, unref } from 'vue';\nimport { type RouteLocationNormalized, useRoute as useVueRoute } from 'vue-router';\nimport { isInModalKey, modalContextKey, routeOverrideKey } from '../symbol';\n\n// note: Surfaces the route driving the currently active modal, or `null`\n// when no modal is active. Inside a ModalProvider subtree the override\n// IS the modal route; outside, the router's live currentRoute is the\n// modal route (background is stashed on the context).\n// `BackgroundProvider` also sets `routeOverrideKey`, so `isInModalKey`\n// is the discriminator between background and modal subtrees.\nexport default function (): ComputedRef<RouteLocationNormalized | null> {\n const override = inject(routeOverrideKey, null);\n const isInModal = inject(isInModalKey, null);\n const ctx = inject(modalContextKey, null);\n const rawRoute = useVueRoute();\n\n return computed(() => {\n if (isInModal !== null && unref(isInModal) && override !== null) {\n return unref(override);\n }\n\n if (ctx !== null && unref(ctx.isModal)) {\n return rawRoute;\n }\n\n return null;\n });\n}\n","import { computed, type ComputedRef, provide, type Ref, unref } from 'vue';\nimport { viewDepthKey } from 'vue-router';\nimport useRoute, { type UseRoute } from './useRoute';\n\nexport default function (nameRef: Ref<string> | string): UseNamedRoute {\n const route = useRoute();\n\n const depth = computed(() => unref(route).matched.findIndex(m => !!m.components && unref(nameRef) in m.components));\n const matched = computed(() => unref(route).matched[unref(depth)]);\n const viewKey = computed(() => unref(matched)?.path);\n\n provide(viewDepthKey, depth);\n\n return {\n route,\n viewKey\n };\n}\n\ntype UseNamedRoute = {\n readonly route: UseRoute;\n readonly viewKey: ComputedRef<string | undefined>;\n};\n","import { type NavigationFailure, type RouteLocationRaw, useRouter } from 'vue-router';\n\ntype Result = NavigationFailure | void | undefined;\ntype To = Omit<RouteLocationRaw, 'replace'>;\ntype Navigate = (to: To, replace?: boolean) => Promise<Result>;\ntype Wrap = (fn: Navigate) => Navigate;\n\nexport default function (...wrap: Wrap[]): UseNavigate {\n const router = useRouter();\n\n let navigate: Navigate = async (to: To, replace: boolean = false) => {\n if (replace) {\n return await router.replace(to);\n }\n\n return await router.push(to);\n };\n\n for (const wrapper of wrap) {\n navigate = wrapper(navigate);\n }\n\n return {\n navigate,\n\n push: (to: To) => navigate(to),\n replace: (to: To) => navigate(to, true)\n };\n}\n\ntype UseNavigate = {\n navigate(to: To, replace?: boolean): Promise<Result>;\n push(to: To): Promise<Result>;\n replace(to: To): Promise<Result>;\n};\n","import { merge } from 'lodash-es';\nimport { computed, type ComputedRef, unref } from 'vue';\nimport type { RouteMeta } from 'vue-router';\nimport useRoute from './useRoute';\n\nexport default function (): ComputedRef<RouteMeta> {\n const route = useRoute();\n\n return computed(() => {\n const matched = unref(route).matched;\n let meta: RouteMeta = {};\n\n for (let i = matched.length - 1; i >= 0; --i) {\n const record = matched[i];\n\n if (!record || typeof record.meta !== 'object') {\n continue;\n }\n\n let matchMeta = {...record.meta};\n\n if ('navigation' in meta) {\n const {navigation: _navigation, ...matchMetaWithoutNavigation} = matchMeta;\n matchMeta = matchMetaWithoutNavigation;\n }\n\n meta = merge(meta, matchMeta);\n }\n\n return meta;\n });\n}\n","import { type Ref, ref, unref, watch } from 'vue';\nimport useRoute from './useRoute';\n\nexport default function (name: string, defaultValue: string | null = null): Ref<string | null> {\n const route = useRoute();\n const param = ref<string | null>(null);\n\n // note: `defaultValue` applies on every read of a missing/empty\n // param, not just at mount. The `immediate: true` flush handles\n // the initial value so we don't duplicate the fallback logic.\n watch(() => unref(route).params[name] as string | undefined, (value) => {\n param.value = value || defaultValue;\n }, {immediate: true});\n\n return param;\n}\n","import { computed, type ComputedRef, type Ref, unref } from 'vue';\nimport type { RouteComponent } from 'vue-router';\nimport useRoute from './useRoute';\n\nexport default function (nameRef: Ref<string> | string): ComputedRef<RouteComponent | null> {\n const route = useRoute();\n\n return computed(() => {\n const name = unref(nameRef);\n\n for (const match of unref(route).matched) {\n if (!match.components) {\n continue;\n }\n\n if (name in match.components) {\n return match.components[name];\n }\n }\n\n return null;\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["createVueRouter","VueRouterView","FALSE_REF","VueRouterView","useVueRoute","useRoute","useRouteNames","useVueRoute","useRoute","useRoute","useRoute","useRoute"],"sources":["../src/internal/modalState.ts","../src/internal/modalContext.ts","../src/internal/patchRouter.ts","../src/symbol.ts","../src/createRouter.ts","../src/component/ModalRouterView.ts","../src/component/RouterLink.ts","../src/internal/RoutedView.ts","../src/internal/resolveModal.ts","../src/component/RouterView.ts","../src/composable/useRoute.ts","../src/composable/useRouteNames.ts","../src/composable/useIsView.ts","../src/composable/useModalRoute.ts","../src/composable/useNamedRoute.ts","../src/composable/useNavigate.ts","../src/composable/useRouteMeta.ts","../src/composable/useRouteParam.ts","../src/composable/useRouteView.ts"],"sourcesContent":["import type { HistoryState } from 'vue-router';\n\nexport type ModalState = {\n readonly backgroundPath: string;\n readonly depth: number;\n};\n\n// note: Modal fields on `history.state`:\n// { modal: true, modalBackgroundPath: '/users', modalDepth: 0 }\n// - `modal` flags the entry as a modal.\n// - `modalBackgroundPath` is the fullPath rendered behind the wrapper.\n// - `modalDepth` is the parent-record count above the deepest matched\n// record that renders inside the wrapper (0 = deepest only).\n\nexport function readModalState(): ModalState | null {\n if (typeof history === 'undefined' || !history.state) {\n return null;\n }\n\n const state = history.state as Record<string, unknown>;\n\n if (state.modal !== true) {\n return null;\n }\n\n if (typeof state.modalBackgroundPath !== 'string' || !state.modalBackgroundPath) {\n return null;\n }\n\n return {\n backgroundPath: state.modalBackgroundPath,\n depth: typeof state.modalDepth === 'number' ? Math.max(0, state.modalDepth) : 0\n };\n}\n\nexport function writeModalState(base: HistoryState | null, backgroundPath: string | null, depth: number = 0): HistoryState {\n const next: HistoryState = {...(base ?? {})};\n\n if (backgroundPath === null) {\n // note: `null` (not `delete`) so vue-router's state-merging\n // unambiguously wipes the previous value.\n next.modal = null;\n next.modalBackgroundPath = null;\n next.modalDepth = null;\n\n return next;\n }\n\n next.modal = true;\n next.modalBackgroundPath = backgroundPath;\n next.modalDepth = Math.max(0, depth);\n\n return next;\n}\n","import { computed, type ComputedRef, shallowRef, type ShallowRef, unref, watch } from 'vue';\nimport { loadRouteLocation, type RouteLocationNormalized, type Router } from 'vue-router';\nimport type { ModalConfig } from '../types';\nimport { readModalState, writeModalState } from './modalState';\nimport type { OriginalNav } from './patchRouter';\n\n// note: True when all matched-record components are already materialised\n// (not still `() => import(...)` functions). Decides whether to assign\n// the background route synchronously or await `loadRouteLocation` first.\nfunction isFullyLoaded(route: RouteLocationNormalized): boolean {\n for (const record of route.matched) {\n if (!record.components) {\n continue;\n }\n\n for (const name in record.components) {\n const component = record.components[name];\n\n if (typeof component === 'function' && !('displayName' in component)) {\n return false;\n }\n }\n }\n\n return true;\n}\n\nexport type ModalContext = {\n readonly isModal: ComputedRef<boolean>;\n readonly backgroundRoute: ShallowRef<RouteLocationNormalized | null>;\n readonly depth: ShallowRef<number>;\n readonly initiallyOpen: ShallowRef<boolean>;\n readonly defaultModal: ModalConfig | null;\n // note: Symbol of the `<RouterView modals>` instance that owns the\n // host role. `null` when no host is mounted — modals don't render.\n readonly host: ShallowRef<symbol | null>;\n\n promote(): Promise<void>;\n\n // note: Reserves the host role. Returns `true` when the role was free\n // and is now ours; `false` when another instance got there first.\n claimHost(id: symbol): boolean;\n\n // note: Releases the host role only if `id` matches the current\n // holder, so a late \"loser\" unmount can't reset the actual host.\n releaseHost(id: symbol): void;\n};\n\nexport default function createModalContext(\n router: Router,\n original: OriginalNav,\n defaultModal: ModalConfig | null\n): ModalContext {\n const initial = readModalState();\n\n // note: On hard refresh of a modal URL, the background route's lazy\n // chunks aren't loaded yet — `components` are still import functions\n // that Vue would render as promise vnodes inside `<Transition>`. We\n // keep `backgroundRoute` null until `loadRouteLocation` materialises\n // them, then assign once.\n const backgroundRoute = shallowRef<RouteLocationNormalized | null>(null);\n\n // note: Number of parent matched records (above the deepest) that\n // render inside the modal wrapper. `0` renders only the deepest;\n // higher values include ancestors as in-modal layout.\n const depth = shallowRef(initial?.depth ?? 0);\n\n // note: True between the first render (history.state already shows\n // an open modal) and the moment the background route's async load\n // settles. Wrappers can consume this to skip the opening transition.\n const initiallyOpen = shallowRef(initial !== null);\n\n const isModal = computed(() => unref(backgroundRoute) !== null);\n\n let loadToken = 0;\n\n // note: On refresh, await the background chunks before surfacing the\n // background route. Already-cached chunks assign synchronously so\n // the first render sees the open-modal state.\n if (initial !== null) {\n const token = ++loadToken;\n const snapshot = router.resolve(initial.backgroundPath) as RouteLocationNormalized;\n\n if (isFullyLoaded(snapshot)) {\n backgroundRoute.value = snapshot;\n initiallyOpen.value = false;\n } else {\n loadRouteLocation(snapshot)\n .then(() => {\n if (token !== loadToken) {\n return;\n }\n\n backgroundRoute.value = router.resolve(initial.backgroundPath) as RouteLocationNormalized;\n initiallyOpen.value = false;\n })\n .catch(() => {\n if (token !== loadToken) {\n return;\n }\n\n backgroundRoute.value = null;\n initiallyOpen.value = false;\n });\n }\n }\n\n // note: React to subsequent navigations. `flush: 'pre'` runs before\n // render so RouterView picks up the new background the same tick.\n watch(router.currentRoute, () => {\n if (typeof history === 'undefined') {\n backgroundRoute.value = null;\n depth.value = 0;\n\n return;\n }\n\n const state = readModalState();\n\n if (state === null) {\n loadToken++;\n backgroundRoute.value = null;\n depth.value = 0;\n initiallyOpen.value = false;\n\n return;\n }\n\n depth.value = state.depth;\n\n const token = ++loadToken;\n const backgroundPath = state.backgroundPath;\n const snapshot = router.resolve(backgroundPath) as RouteLocationNormalized;\n\n // note: Fast path — chunks already loaded (typical navigation),\n // assign synchronously to avoid a flash of modal-as-fullpage.\n // Slow path — hard refresh, await load to avoid promise vnodes.\n if (isFullyLoaded(snapshot)) {\n backgroundRoute.value = snapshot;\n\n return;\n }\n\n loadRouteLocation(snapshot)\n .then(() => {\n if (token !== loadToken) {\n return;\n }\n\n backgroundRoute.value = router.resolve(backgroundPath) as RouteLocationNormalized;\n })\n .catch(() => {\n if (token !== loadToken) {\n return;\n }\n\n backgroundRoute.value = null;\n });\n }, {flush: 'pre'});\n\n async function promote(): Promise<void> {\n const current = unref(router.currentRoute);\n\n // note: Turns the modal's URL into the \"real\" page. `replace`\n // avoids a duplicate history entry; `force: true` because\n // vue-router otherwise skips a same-URL replace.\n await original.replace({\n path: current.fullPath,\n force: true,\n state: writeModalState(null, null)\n });\n }\n\n const host = shallowRef<symbol | null>(null);\n\n function claimHost(id: symbol): boolean {\n if (host.value !== null) {\n return false;\n }\n\n host.value = id;\n\n return true;\n }\n\n function releaseHost(id: symbol): void {\n if (host.value !== id) {\n return;\n }\n\n host.value = null;\n }\n\n return {\n isModal,\n backgroundRoute,\n depth,\n initiallyOpen,\n defaultModal,\n host,\n promote,\n claimHost,\n releaseHost\n };\n}\n","import { unref } from 'vue';\nimport type { HistoryState, NavigationFailure, RouteLocationOptions, RouteLocationRaw, Router } from 'vue-router';\nimport { readModalState, writeModalState } from './modalState';\n\ntype Navigate = (to: RouteLocationRaw) => Promise<NavigationFailure | void | undefined>;\n\nexport type OriginalNav = {\n readonly push: Navigate;\n readonly replace: Navigate;\n};\n\nfunction withState(to: RouteLocationRaw, state: HistoryState): RouteLocationRaw {\n if (typeof to === 'string') {\n return {path: to, state};\n }\n\n return {...to, state};\n}\n\nfunction injectState(to: RouteLocationRaw, backgroundPath: string | null, depth: number = 0): RouteLocationRaw {\n const base = typeof to === 'string' ? null : (to.state ?? null);\n\n return withState(to, writeModalState(base, backgroundPath, depth));\n}\n\nfunction readModalFlag(flag: boolean | number | undefined): { open: boolean; depth: number; explicitClose: boolean } {\n if (flag === true) {\n return {open: true, depth: 0, explicitClose: false};\n }\n\n if (flag === false) {\n return {open: false, depth: 0, explicitClose: true};\n }\n\n if (typeof flag === 'number') {\n return {open: true, depth: Math.max(0, flag), explicitClose: false};\n }\n\n return {open: false, depth: 0, explicitClose: false};\n}\n\nexport default function patchRouter(router: Router): OriginalNav {\n const origPush: Navigate = router.push.bind(router);\n const origReplace: Navigate = router.replace.bind(router);\n\n function transform(to: RouteLocationRaw): RouteLocationRaw {\n const wantsModal = typeof to === 'string' ? undefined : (to as RouteLocationOptions).modal;\n const flag = readModalFlag(wantsModal);\n const current = readModalState();\n\n // note: Explicit `modal: true` / `<number>` opens on top of the\n // current route. Already-open modals reuse the existing background.\n if (flag.open) {\n const backgroundPath = current?.backgroundPath ?? unref(router.currentRoute).fullPath;\n\n return injectState(to, backgroundPath, flag.depth);\n }\n\n // note: Explicit `modal: false` exits the modal entirely.\n if (flag.explicitClose) {\n return injectState(to, null);\n }\n\n // note: Implicit navigation from within a modal. Keep the modal open\n // when the target shares the root-matched record (sibling within\n // the same modal tree), otherwise exit. Depth carries across.\n if (current !== null) {\n const resolved = router.resolve(to);\n const currentRoot = unref(router.currentRoute).matched[0]?.path;\n const nextRoot = resolved.matched[0]?.path;\n const sameRoot = !!currentRoot && currentRoot === nextRoot;\n\n return sameRoot ? injectState(to, current.backgroundPath, current.depth) : injectState(to, null);\n }\n\n return to;\n }\n\n router.push = async (to) => await origPush(transform(to));\n router.replace = async (to) => await origReplace(transform(to));\n\n return {\n push: origPush,\n replace: origReplace\n };\n}\n","import type { ComputedRef, InjectionKey, Ref, ShallowRef } from 'vue';\nimport type { RouteLocationNormalized } from 'vue-router';\nimport type { ModalContext } from './internal/modalContext';\n\nexport const modalContextKey: InjectionKey<ModalContext> = Symbol('basmilius:routing:modal-context');\nexport const routeOverrideKey: InjectionKey<ComputedRef<RouteLocationNormalized>> = Symbol('basmilius:routing:route-override');\nexport const isInModalKey: InjectionKey<Ref<boolean>> = Symbol('basmilius:routing:in-modal');\n\n// note: Gates the modal's inner `<VueRouterView>` for one tick on a\n// user-triggered open so the wrapper's `<Transition>` plays the enter\n// animation. See `RouterView.ts` for the full rationale.\nexport const innerReadyKey: InjectionKey<ShallowRef<boolean>> = Symbol('basmilius:routing:inner-ready');\n","import type { App } from 'vue';\nimport { createRouter as createVueRouter, type Router } from 'vue-router';\nimport createModalContext from './internal/modalContext';\nimport patchRouter from './internal/patchRouter';\nimport { modalContextKey } from './symbol';\nimport type { RouterOptions } from './types';\n\nexport default function createRouter(options: RouterOptions): Router {\n const {defaultModal, ...routerOptions} = options;\n\n const router = createVueRouter(routerOptions);\n const original = patchRouter(router);\n const ctx = createModalContext(router, original, defaultModal ?? null);\n\n const originalInstall = router.install.bind(router);\n\n router.install = (app: App): void => {\n originalInstall(app);\n app.provide(modalContextKey, ctx);\n };\n\n return router;\n}\n","import { type Component, defineComponent, h, inject, type VNodeChild } from 'vue';\nimport { RouterView as VueRouterView } from 'vue-router';\nimport { innerReadyKey } from '../symbol';\n\n// note: Thin wrapper around `VueRouterView` that honours the\n// `innerReadyKey` gate from our `RouterView`. Use this in wrapper\n// templates that need `v-slot` to animate push-navigations inside a\n// modal — vue-router's plain `RouterView` would mount in the same tick\n// as the wrapper and skip its enter animation. Outside a modal context\n// (no gate provided) it's a passthrough.\nconst ModalRouterView: Component = defineComponent({\n name: 'ModalRouterView',\n inheritAttrs: false,\n setup(_props, {attrs, slots}) {\n const innerReady = inject(innerReadyKey, null);\n\n return (): VNodeChild => {\n if (innerReady === null) {\n return h(VueRouterView, attrs, slots);\n }\n\n // note: Gate closed -> render nothing so the wrapper's\n // `<Transition>` observes an empty slot on mount, then\n // picks up the child once the gate flips.\n if (!innerReady.value) {\n return undefined;\n }\n\n return h(VueRouterView, attrs, slots);\n };\n }\n});\n\nexport default ModalRouterView;\n","import { type Component, computed, defineComponent, h, type PropType, type VNodeChild } from 'vue';\nimport { type RouteLocationRaw, useLink, useRouter } from 'vue-router';\n\ntype AriaCurrentValue = 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | 'false';\n\nconst RouterLink: Component = defineComponent({\n name: 'RouterLink',\n props: {\n to: {\n type: [String, Object] as PropType<RouteLocationRaw>,\n required: true\n },\n replace: {\n type: Boolean,\n default: false\n },\n activeClass: {\n type: String,\n default: 'router-link-active'\n },\n exactActiveClass: {\n type: String,\n default: 'router-link-exact-active'\n },\n ariaCurrentValue: {\n type: String as PropType<AriaCurrentValue>,\n default: 'page'\n },\n custom: {\n type: Boolean,\n default: false\n },\n modal: {\n type: [Boolean, Number] as PropType<boolean | number>,\n default: false\n }\n },\n setup(props, {slots}) {\n const router = useRouter();\n\n // note: Pass per-field computeds (not a resolved object) so vue-\n // router's `useLink` tracks `props.to` / `props.replace` through\n // its internal `unref()` calls. Resolving via `.value` would hand\n // it a snapshot and `href` / `isActive` would never update on\n // prop changes.\n const link = useLink({\n to: computed(() => props.to),\n replace: computed(() => props.replace)\n });\n\n // note: `modal` is truthy for `true` and any number (including 0,\n // which means \"open as modal, deepest only\"). Normalises into\n // the shape patchRouter expects on `RouteLocationOptions.modal`.\n function modalFlag(): boolean | number {\n return typeof props.modal === 'number' ? props.modal : props.modal === true;\n }\n\n function isModalRequested(): boolean {\n return props.modal === true || typeof props.modal === 'number';\n }\n\n async function navigate(event?: MouseEvent): Promise<void> {\n if (isModalRequested()) {\n if (event) {\n // note: Let modifier clicks / non-primary buttons\n // fall through so middle-click / ctrl+click still\n // open the URL in a new tab. Modal routes must be\n // valid standalone pages.\n if (event.defaultPrevented) {\n return;\n }\n\n if (event.button !== undefined && event.button !== 0) {\n return;\n }\n\n if (event.metaKey || event.altKey || event.ctrlKey || event.shiftKey) {\n return;\n }\n\n event.preventDefault();\n }\n\n const flag = modalFlag();\n const target: RouteLocationRaw = typeof props.to === 'string'\n ? {path: props.to, modal: flag}\n : {...props.to, modal: flag};\n\n if (props.replace) {\n await router.replace(target);\n } else {\n await router.push(target);\n }\n\n return;\n }\n\n await link.navigate(event);\n }\n\n return (): VNodeChild => {\n const slotProps = {\n href: link.href.value,\n route: link.route.value,\n navigate,\n isActive: link.isActive.value,\n isExactActive: link.isExactActive.value\n };\n\n const children = slots.default?.(slotProps);\n\n if (props.custom) {\n return children;\n }\n\n return h('a', {\n href: link.href.value,\n 'aria-current': link.isExactActive.value ? props.ariaCurrentValue : undefined,\n class: {\n [props.activeClass]: link.isActive.value,\n [props.exactActiveClass]: link.isExactActive.value\n },\n onClick: navigate\n }, children);\n };\n }\n});\n\nexport default RouterLink;\n","import { type Component, computed, defineComponent, type PropType, provide, type Ref, shallowRef, type VNodeChild } from 'vue';\nimport { type RouteLocationNormalized, routerViewLocationKey, viewDepthKey } from 'vue-router';\nimport { isInModalKey, routeOverrideKey } from '../symbol';\n\nconst TRUE_REF = shallowRef(true);\nconst FALSE_REF = shallowRef(false);\n\n// note: Both providers override `routerViewLocationKey` so descendant\n// `<RouterView>`s render the supplied `route` instead of the router's\n// live currentRoute. `viewDepthKey` is set to the index at which the\n// inner `VueRouterView` should resume in `matched[]` — for\n// `BackgroundProvider`, the host's own depth (so a nested host doesn't\n// re-render its ancestors); for `ModalProvider`, the absolute matched\n// index computed by RouterView from `ctx.depth`.\n\nexport const BackgroundProvider: Component = defineComponent({\n name: 'BackgroundProvider',\n props: {\n route: {\n type: Object as PropType<RouteLocationNormalized>,\n required: true\n },\n viewDepth: {\n type: Number,\n default: 0\n }\n },\n setup(props, {slots}) {\n const routeRef = computed(() => props.route);\n\n provide(routerViewLocationKey, routeRef);\n provide(viewDepthKey, props.viewDepth);\n provide(routeOverrideKey, routeRef);\n provide(isInModalKey, FALSE_REF);\n\n return (): VNodeChild => slots.default?.();\n }\n});\n\nexport const ModalProvider: Component = defineComponent({\n name: 'ModalProvider',\n props: {\n route: {\n type: Object as PropType<RouteLocationNormalized>,\n required: true\n },\n // note: Ref instead of a plain number — Vue's runtime `h()` prop\n // diffing can miss primitive updates when patching in a tight\n // cycle alongside reactive route changes. Ref identity stays\n // stable; `.value` propagates through normal reactivity.\n depthRef: {\n type: Object as PropType<Ref<number>>,\n required: true\n }\n },\n setup(props, {slots}) {\n const routeRef = computed(() => props.route);\n\n provide(routerViewLocationKey, routeRef);\n provide(viewDepthKey, props.depthRef);\n provide(routeOverrideKey, routeRef);\n provide(isInModalKey, TRUE_REF);\n\n return (): VNodeChild => slots.default?.();\n }\n});\n","import type { RouteLocationNormalized } from 'vue-router';\nimport type { ModalConfig } from '../types';\n\n// note: Walks matched records deepest-first so children override their\n// parent's `meta.modal`. Falls back to `defaultModal` from\n// `createRouter()` when no record declares one.\nexport default function resolveModal(\n route: RouteLocationNormalized,\n fallback: ModalConfig | null\n): ModalConfig | null {\n for (let i = route.matched.length - 1; i >= 0; --i) {\n const modal = route.matched[i]?.meta?.modal;\n\n if (modal) {\n return modal;\n }\n }\n\n return fallback;\n}\n","import { type Component, defineComponent, Fragment, h, inject, nextTick, onBeforeUnmount, provide, type Ref, shallowRef, unref, type VNodeChild, watch } from 'vue';\nimport { RouterView as VueRouterView, useRoute, useRouter, viewDepthKey } from 'vue-router';\nimport { BackgroundProvider, ModalProvider } from '../internal/RoutedView';\nimport resolveModal from '../internal/resolveModal';\nimport { innerReadyKey, modalContextKey, routeOverrideKey } from '../symbol';\nimport type { ModalConfig } from '../types';\n\nconst RouterView: Component = defineComponent({\n name: 'RouterView',\n inheritAttrs: false,\n props: {\n // note: Opts this instance in as the host that renders the modal\n // layer on top of the background route. Exactly one `<RouterView>`\n // in the tree should set this; if multiple do, the first to mount\n // wins (others render vanilla and emit a console warning).\n modals: {\n type: Boolean,\n default: false\n }\n },\n setup(props, {attrs, slots}) {\n const ctx = inject(modalContextKey, null);\n const override = inject(routeOverrideKey, null);\n const route = useRoute();\n const router = useRouter();\n\n // note: Vue-router injects `viewDepthKey` from the parent\n // `VueRouterView` (or 0 at the top). It can be a number or a\n // `Ref<number>`; `unref` collapses both. Passed to\n // `BackgroundProvider` so the background tree resumes at the\n // correct matched index when this RouterView is nested.\n const injectedViewDepth = inject(viewDepthKey, 0);\n\n // note: Identity used to claim/release the modal host role on the\n // shared `modalContext`. The matching unmount release targets\n // exactly our claim — never a successor's.\n const hostId = Symbol('basmilius:routing:router-view-host');\n\n let isModalHost = false;\n\n if (props.modals && override === null && ctx) {\n isModalHost = ctx.claimHost(hostId);\n\n if (!isModalHost) {\n // eslint-disable-next-line no-console\n console.warn(\n '[routing] Multiple <RouterView modals> instances detected. ' +\n 'The first mounted instance owns the modal host role; this ' +\n 'instance will render as a vanilla RouterView.'\n );\n } else {\n onBeforeUnmount(() => ctx.releaseHost(hostId));\n }\n }\n\n // note: Wrapper component (e.g. FluxOverlay) stays mounted across\n // modal close for its leave animation, and is reused when\n // consecutive modals share the same wrapper.\n const lastModal = shallowRef<ModalConfig | null>(null);\n\n // note: Held as a ref because Vue's runtime `h()` can miss\n // primitive prop updates on `ModalProvider` when route changes\n // patch in the same tick. Ref identity stays stable.\n const modalDepthRef: Ref<number> = shallowRef(0);\n\n // note: Gates whether the modal's inner `<RouterView>` is attached.\n // On a user-triggered open we hold it back one tick so the\n // wrapper's `<Transition>` observes \"no child -> child\" and plays\n // its enter animation. On hard refresh of a modal URL we skip the\n // gate so the page arrives already-open without animating.\n const innerReady = shallowRef(false);\n\n // note: Snapshot at setup — `modalContext` flips `initiallyOpen`\n // back to `false` once the background route resolves, which is\n // too early to read from the watcher below.\n const wasInitiallyOpen = ctx?.initiallyOpen.value ?? false;\n\n let hasSeenActiveModal = false;\n\n // note: Exposed so `ModalRouterView` inside consumer wrapper\n // templates honours the same one-tick delay as the fallback slot.\n provide(innerReadyKey, innerReady);\n\n if (ctx && isModalHost) {\n watch(() => ctx.backgroundRoute.value !== null, async (isOpen) => {\n if (!isOpen) {\n innerReady.value = false;\n\n return;\n }\n\n const isFirstActivation = !hasSeenActiveModal;\n hasSeenActiveModal = true;\n\n // note: Pageload of a modal URL — wrapper and inner mount\n // together without a transition.\n if (isFirstActivation && wasInitiallyOpen) {\n innerReady.value = true;\n\n return;\n }\n\n // note: User-triggered open — wrapper renders first with\n // an empty slot, inner attaches next tick to animate in.\n innerReady.value = false;\n await nextTick();\n innerReady.value = true;\n }, {immediate: true, flush: 'pre'});\n }\n\n return (): VNodeChild => {\n // note: Already inside a BackgroundProvider / ModalProvider\n // subtree — render vanilla so we don't recurse into another\n // background/modal split.\n if (override !== null) {\n return h(VueRouterView, attrs, slots);\n }\n\n if (!ctx) {\n return h(VueRouterView, attrs, slots);\n }\n\n // note: Only the instance that claimed the host role renders\n // modals. All others fall through to vanilla.\n if (!isModalHost) {\n return h(VueRouterView, attrs, slots);\n }\n\n const backgroundRoute = ctx.backgroundRoute.value;\n const modalActive = ctx.isModal.value && backgroundRoute !== null;\n\n // note: Resolve inline (not via watcher) — at setup the route\n // is `START_LOCATION` with empty `matched`, so a watcher with\n // `immediate: true` would miss the per-route `meta.modal`.\n if (modalActive) {\n const resolved = resolveModal(route, ctx.defaultModal);\n\n if (resolved !== null && resolved !== lastModal.value) {\n lastModal.value = resolved;\n }\n }\n\n const wrapperConfig = lastModal.value;\n\n // note: Never been a modal here -> plain RouterView.\n if (!modalActive && !wrapperConfig) {\n return h(VueRouterView, attrs, slots);\n }\n\n // note: Background renders the stored route while open; the\n // current route while closed (wrapper lingering for leave\n // animation). Keeps layout-level `useRoute()` stable.\n const bgRoute = modalActive ? backgroundRoute : route;\n\n // note: `ctx.depth` is the user-supplied parent count. Translate\n // to an absolute `matched[]` index:\n // depth 0 -> matched[length - 1] (deepest only)\n // depth N -> matched[length - 1 - N]\n const parentCount = ctx.depth.value;\n const viewDepth = Math.max(0, route.matched.length - 1 - parentCount);\n\n modalDepthRef.value = viewDepth;\n\n // note: ModalProvider wraps the wrapper component so the\n // wrapper's internal Teleport still inherits the provider\n // context. Inner is `undefined` while closed or gated, so\n // the wrapper's `<Transition>` observes an empty slot.\n const modalInner = modalActive && innerReady.value\n ? h(VueRouterView)\n : undefined;\n\n const wrappedModalInner = wrapperConfig\n ? h(wrapperConfig.component, {\n ...(wrapperConfig.props ?? {}),\n // note: Runtime props after the spread so consumers\n // can't shadow them via `meta.modal.props`. Use\n // `modalReady` (not `modalActive`) to v-if the\n // inner `<ModalRouterView>` — `modalActive` is true\n // at mount and would skip the enter animation.\n modalRoute: route,\n modalActive,\n modalReady: modalActive && innerReady.value,\n onClose: (): void => {\n router.back();\n }\n }, {\n default: (): VNodeChild => modalInner\n })\n : modalInner;\n\n const modalLayer = h(ModalProvider, {route, depthRef: modalDepthRef}, {\n default: (): VNodeChild => wrappedModalInner\n });\n\n const hostViewDepth = unref(injectedViewDepth);\n\n return h(Fragment, [\n h(BackgroundProvider, {route: bgRoute, viewDepth: hostViewDepth}, {\n default: (): VNodeChild => h(VueRouterView, attrs, slots)\n }),\n modalLayer\n ]);\n };\n }\n});\n\nexport default RouterView;\n","import { computed, inject, shallowRef, unref } from 'vue';\nimport { type RouteLocationNormalizedLoaded, useRoute as useVueRoute } from 'vue-router';\nimport { isInModalKey, modalContextKey, routeOverrideKey } from '../symbol';\n\nexport type UseRoute = RouteLocationNormalizedLoaded & {\n readonly isModal: boolean;\n\n promote(): Promise<void>;\n};\n\nconst FALSE_REF = shallowRef(false);\nconst NOOP = async (): Promise<void> => undefined;\n\nexport default function (): UseRoute {\n const override = inject(routeOverrideKey, null);\n const ctx = inject(modalContextKey, null);\n const isModalRef = inject(isInModalKey, FALSE_REF);\n const raw = useVueRoute();\n\n const routeRef = computed<RouteLocationNormalizedLoaded>(() => {\n // note: Inside a Background/ModalProvider subtree — use the\n // explicit override so background-tree components see the\n // background route and modal-wrapper components see the modal\n // route, independent of the router's live currentRoute.\n if (override !== null) {\n return unref(override) as RouteLocationNormalizedLoaded;\n }\n\n // note: Outside any provider (top-level layouts) — surface the\n // background route while a modal is open so layout-level\n // `:key`s stay stable across opens/closes.\n if (ctx !== null && unref(ctx.isModal)) {\n const bg = unref(ctx.backgroundRoute);\n\n if (bg !== null) {\n return bg as RouteLocationNormalizedLoaded;\n }\n }\n\n return raw;\n });\n\n const promote = ctx !== null ? ctx.promote : NOOP;\n\n // note: Proxy (not a Ref) so the object can be used directly in\n // templates without auto-unwrapping stripping our extras. All\n // route properties flow through `routeRef.value` to keep reactivity\n // tracking intact in templates, computeds, and watchers.\n return new Proxy({} as UseRoute, {\n get(_target, key) {\n if (key === 'isModal') {\n return isModalRef.value;\n }\n\n if (key === 'promote') {\n return promote;\n }\n\n return (routeRef.value as unknown as Record<PropertyKey, unknown>)[key];\n },\n has(_target, key) {\n if (key === 'isModal' || key === 'promote') {\n return true;\n }\n\n return key in routeRef.value;\n },\n ownKeys(_target) {\n return [...Reflect.ownKeys(routeRef.value), 'isModal', 'promote'];\n },\n getOwnPropertyDescriptor(_target, key) {\n if (key === 'isModal') {\n return {configurable: true, enumerable: true, value: isModalRef.value};\n }\n\n if (key === 'promote') {\n return {configurable: true, enumerable: true, value: promote};\n }\n\n return Object.getOwnPropertyDescriptor(routeRef.value, key);\n }\n });\n}\n","import { computed, type ComputedRef, unref } from 'vue';\nimport useRoute from './useRoute';\n\nexport default function (): ComputedRef<string[]> {\n const route = useRoute();\n\n return computed(() => {\n const names: string[] = [];\n\n unref(route).matched.forEach(m => m.name && names.push(m.name as string));\n\n return names;\n });\n}\n","import { computed, type ComputedRef, unref } from 'vue';\nimport useRouteNames from './useRouteNames';\n\nexport default function (name: string, loose: boolean = false): ComputedRef<boolean> {\n const names = useRouteNames();\n\n if (loose) {\n return computed(() => unref(names).some(n => n.startsWith(name)));\n }\n\n return computed(() => unref(names).some(n => n === name));\n}\n","import { computed, type ComputedRef, inject, unref } from 'vue';\nimport { type RouteLocationNormalized, useRoute as useVueRoute } from 'vue-router';\nimport { isInModalKey, modalContextKey, routeOverrideKey } from '../symbol';\n\n// note: Surfaces the route driving the currently active modal, or `null`\n// when no modal is active. Inside a ModalProvider subtree the override\n// IS the modal route; outside, the router's live currentRoute is the\n// modal route (background is stashed on the context).\n// `BackgroundProvider` also sets `routeOverrideKey`, so `isInModalKey`\n// is the discriminator between background and modal subtrees.\nexport default function (): ComputedRef<RouteLocationNormalized | null> {\n const override = inject(routeOverrideKey, null);\n const isInModal = inject(isInModalKey, null);\n const ctx = inject(modalContextKey, null);\n const rawRoute = useVueRoute();\n\n return computed(() => {\n if (isInModal !== null && unref(isInModal) && override !== null) {\n return unref(override);\n }\n\n if (ctx !== null && unref(ctx.isModal)) {\n return rawRoute;\n }\n\n return null;\n });\n}\n","import { computed, type ComputedRef, provide, type Ref, unref } from 'vue';\nimport { viewDepthKey } from 'vue-router';\nimport useRoute, { type UseRoute } from './useRoute';\n\nexport default function (nameRef: Ref<string> | string): UseNamedRoute {\n const route = useRoute();\n\n const depth = computed(() => unref(route).matched.findIndex(m => !!m.components && unref(nameRef) in m.components));\n const matched = computed(() => unref(route).matched[unref(depth)]);\n const viewKey = computed(() => unref(matched)?.path);\n\n provide(viewDepthKey, depth);\n\n return {\n route,\n viewKey\n };\n}\n\ntype UseNamedRoute = {\n readonly route: UseRoute;\n readonly viewKey: ComputedRef<string | undefined>;\n};\n","import { type NavigationFailure, type RouteLocationRaw, useRouter } from 'vue-router';\n\ntype Result = NavigationFailure | void | undefined;\ntype To = Omit<RouteLocationRaw, 'replace'>;\ntype Navigate = (to: To, replace?: boolean) => Promise<Result>;\ntype Wrap = (fn: Navigate) => Navigate;\n\nexport default function (...wrap: Wrap[]): UseNavigate {\n const router = useRouter();\n\n let navigate: Navigate = async (to: To, replace: boolean = false) => {\n if (replace) {\n return await router.replace(to);\n }\n\n return await router.push(to);\n };\n\n for (const wrapper of wrap) {\n navigate = wrapper(navigate);\n }\n\n return {\n navigate,\n\n push: (to: To) => navigate(to),\n replace: (to: To) => navigate(to, true)\n };\n}\n\ntype UseNavigate = {\n navigate(to: To, replace?: boolean): Promise<Result>;\n push(to: To): Promise<Result>;\n replace(to: To): Promise<Result>;\n};\n","import { merge } from 'lodash-es';\nimport { computed, type ComputedRef, unref } from 'vue';\nimport type { RouteMeta } from 'vue-router';\nimport useRoute from './useRoute';\n\nexport default function (): ComputedRef<RouteMeta> {\n const route = useRoute();\n\n return computed(() => {\n const matched = unref(route).matched;\n let meta: RouteMeta = {};\n\n for (let i = matched.length - 1; i >= 0; --i) {\n const record = matched[i];\n\n if (!record || typeof record.meta !== 'object') {\n continue;\n }\n\n let matchMeta = {...record.meta};\n\n if ('navigation' in meta) {\n const {navigation: _navigation, ...matchMetaWithoutNavigation} = matchMeta;\n matchMeta = matchMetaWithoutNavigation;\n }\n\n meta = merge(meta, matchMeta);\n }\n\n return meta;\n });\n}\n","import { type Ref, ref, unref, watch } from 'vue';\nimport useRoute from './useRoute';\n\nexport default function (name: string, defaultValue: string | null = null): Ref<string | null> {\n const route = useRoute();\n const param = ref<string | null>(null);\n\n // note: `defaultValue` applies on every read of a missing/empty\n // param, not just at mount. The `immediate: true` flush handles\n // the initial value so we don't duplicate the fallback logic.\n watch(() => unref(route).params[name] as string | undefined, (value) => {\n param.value = value || defaultValue;\n }, {immediate: true});\n\n return param;\n}\n","import { computed, type ComputedRef, type Ref, unref } from 'vue';\nimport type { RouteComponent } from 'vue-router';\nimport useRoute from './useRoute';\n\nexport default function (nameRef: Ref<string> | string): ComputedRef<RouteComponent | null> {\n const route = useRoute();\n\n return computed(() => {\n const name = unref(nameRef);\n\n for (const match of unref(route).matched) {\n if (!match.components) {\n continue;\n }\n\n if (name in match.components) {\n return match.components[name];\n }\n }\n\n return null;\n });\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basmilius/routing",
|
|
3
3
|
"description": "Vue Router wrapper with overlay, modal and slide-over routing.",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.33.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"funding": "https://github.com/sponsors/basmilius",
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
"lodash-es": "^4.18.1"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"vue": "^3.6.0-beta.
|
|
54
|
-
"vue-router": "^5.0.
|
|
53
|
+
"vue": "^3.6.0-beta.12",
|
|
54
|
+
"vue-router": "^5.0.7"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/lodash-es": "^4.17.12",
|
|
58
58
|
"tsdown": "^0.22.0",
|
|
59
|
-
"vue": "^3.6.0-beta.
|
|
60
|
-
"vue-router": "^5.0.
|
|
59
|
+
"vue": "^3.6.0-beta.12",
|
|
60
|
+
"vue-router": "^5.0.7"
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -23,7 +23,7 @@ function injectState(to: RouteLocationRaw, backgroundPath: string | null, depth:
|
|
|
23
23
|
return withState(to, writeModalState(base, backgroundPath, depth));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
function readModalFlag(flag: boolean | number | undefined): {open: boolean; depth: number; explicitClose: boolean} {
|
|
26
|
+
function readModalFlag(flag: boolean | number | undefined): { open: boolean; depth: number; explicitClose: boolean } {
|
|
27
27
|
if (flag === true) {
|
|
28
28
|
return {open: true, depth: 0, explicitClose: false};
|
|
29
29
|
}
|