@jasonshimmy/custom-elements-runtime 2.2.4 → 2.2.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"custom-elements-runtime.router.es.js","sources":["../src/lib/router.ts"],"sourcesContent":["import { html } from './runtime/template-compiler';\nimport { component } from './runtime/component';\nimport {\n useProps,\n useOnConnected,\n useOnDisconnected,\n useStyle,\n} from './runtime/hooks';\nimport { ref, computed } from './runtime/reactive';\nimport { createStore, type Store } from './store';\nimport { devError, devWarn } from './runtime/logger';\nimport { match } from './directives';\n\nexport type RouteComponent =\n | { new (...args: unknown[]): unknown } // class components\n | ((...args: unknown[]) => unknown); // functional components\n\nexport interface RouteState {\n path: string;\n params: Record<string, string>;\n query: Record<string, string>;\n}\n\nexport type GuardResult = boolean | string | Promise<boolean | string>;\n\nexport interface Route {\n path: string;\n\n /**\n * Statically available component (already imported)\n */\n component?: string | (() => unknown);\n\n /**\n * Lazy loader that resolves to something renderable\n */\n load?: () => Promise<{\n default: string | HTMLElement | ((...args: unknown[]) => unknown);\n }>;\n\n /**\n * Runs before matching — return false to cancel,\n * or a string to redirect\n */\n beforeEnter?: (to: RouteState, from: RouteState) => GuardResult;\n\n /**\n * Runs right before navigation commits — can cancel or redirect\n */\n onEnter?: (to: RouteState, from: RouteState) => GuardResult;\n\n /**\n * Runs after navigation completes — cannot cancel\n */\n afterEnter?: (to: RouteState, from: RouteState) => void;\n}\n\nexport interface RouterLinkProps {\n to: string;\n tag: string;\n replace: boolean;\n exact: boolean;\n activeClass: string;\n exactActiveClass: string;\n ariaCurrentValue: string;\n disabled: boolean;\n external: boolean;\n linkClass?: string;\n linkStyle?: string;\n}\n\nexport interface RouterLinkComputed {\n current: RouteState;\n isExactActive: boolean;\n isActive: boolean;\n className: string;\n ariaCurrent: string;\n isButton: boolean;\n disabledAttr: string;\n externalAttr: string;\n}\n\nexport interface RouterConfig {\n routes: Route[];\n base?: string;\n initialUrl?: string; // For SSR: explicitly pass the URL\n}\n\nexport const parseQuery = (search: string): Record<string, string> => {\n if (!search) return {};\n if (typeof URLSearchParams === 'undefined') return {};\n return Object.fromEntries(new URLSearchParams(search));\n};\n\nexport const matchRoute = (\n routes: Route[],\n path: string,\n): { route: Route | null; params: Record<string, string> } => {\n for (const route of routes) {\n const paramNames: string[] = [];\n const regexPath = route.path.replace(/:[^/]+/g, (m) => {\n paramNames.push(m.slice(1));\n return '([^/]+)';\n });\n const regex = new RegExp(`^${regexPath}$`);\n const match = path.match(regex);\n if (match) {\n const params: Record<string, string> = {};\n paramNames.forEach((name, i) => {\n params[name] = match[i + 1];\n });\n return { route, params };\n }\n }\n return { route: null, params: {} };\n};\n\n/**\n * Find the first route that matches the given path.\n * Consolidates repeated inline checks like `routes.find(r => matchRoute([r], path).route !== null)`\n */\nfunction findMatchedRoute(routes: Route[], path: string): Route | null {\n for (const r of routes) {\n if (matchRoute([r], path).route !== null) return r;\n }\n return null;\n}\n\n// Async component loader cache\nconst componentCache: Record<\n string,\n string | HTMLElement | ((...args: unknown[]) => unknown)\n> = {};\n\n/**\n * Loads a route's component, supporting both static and async.\n * @param route Route object\n * @returns Promise resolving to the component\n */\nexport async function resolveRouteComponent(\n route: Route,\n): Promise<string | HTMLElement | ((...args: unknown[]) => unknown)> {\n if (route.component) return route.component;\n if (route.load) {\n if (componentCache[route.path]) return componentCache[route.path];\n try {\n const mod = await route.load();\n componentCache[route.path] = mod.default;\n return mod.default;\n } catch {\n throw new Error(`Failed to load component for route: ${route.path}`);\n }\n }\n throw new Error(`No component or loader defined for route: ${route.path}`);\n}\n\nexport function useRouter(config: RouterConfig) {\n const { routes, base = '', initialUrl } = config;\n\n let getLocation: () => { path: string; query: Record<string, string> };\n let initial: { path: string; query: Record<string, string> };\n let store: Store<RouteState>;\n let update: (replace?: boolean) => Promise<void>;\n let push: (path: string) => Promise<void>;\n let replaceFn: (path: string) => Promise<void>;\n let back: () => void;\n\n // Run matching route guards/hooks\n const runBeforeEnter = async (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.beforeEnter) return true;\n try {\n const result = await matched.beforeEnter(to, from);\n if (typeof result === 'string') {\n // Redirect\n await navigate(result, true);\n return false;\n }\n return result !== false;\n } catch (err) {\n devError('beforeEnter error', err);\n return false;\n }\n };\n\n const runOnEnter = async (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.onEnter) return true;\n try {\n const result = await matched.onEnter(to, from);\n if (typeof result === 'string') {\n await navigate(result, true);\n return false;\n }\n return result !== false;\n } catch (err) {\n devError('onEnter error', err);\n return false;\n }\n };\n\n const runAfterEnter = (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.afterEnter) return;\n try {\n matched.afterEnter(to, from);\n } catch (err) {\n devError('afterEnter error', err);\n }\n };\n\n const navigate = async (path: string, replace = false) => {\n try {\n const loc = {\n path: path.replace(base, '') || '/',\n query: {},\n };\n const match = matchRoute(routes, loc.path);\n if (!match.route) throw new Error(`No route found for ${loc.path}`);\n\n const from = store.getState();\n const to: RouteState = {\n path: loc.path,\n params: match.params,\n query: loc.query,\n };\n\n // beforeEnter guard\n const allowedBefore = await runBeforeEnter(to, from);\n if (!allowedBefore) return;\n\n // onEnter guard (right before commit)\n const allowedOn = await runOnEnter(to, from);\n if (!allowedOn) return;\n\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n if (replace) {\n window.history.replaceState({}, '', base + path);\n } else {\n window.history.pushState({}, '', base + path);\n }\n }\n\n store.setState(to);\n\n // afterEnter hook (post commit)\n runAfterEnter(to, from);\n } catch (err) {\n devError('Navigation error:', err);\n }\n };\n\n // If an explicit `initialUrl` is provided we treat this as SSR/static rendering\n // even if a `window` exists (useful for hydration tests). Browser mode only\n // applies when `initialUrl` is undefined.\n if (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined' &&\n typeof initialUrl === 'undefined'\n ) {\n // Browser mode\n getLocation = () => {\n const url = new URL(window.location.href);\n const path = url.pathname.replace(base, '') || '/';\n const query = parseQuery(url.search);\n return { path, query };\n };\n\n initial = getLocation();\n const match = matchRoute(routes, initial.path);\n store = createStore<RouteState>({\n path: initial.path,\n params: match.params,\n query: initial.query,\n });\n\n update = async (replace = false) => {\n const loc = getLocation();\n await navigate(loc.path, replace);\n };\n\n window.addEventListener('popstate', () => update(true));\n\n push = (path: string) => navigate(path, false);\n replaceFn = (path: string) => navigate(path, true);\n back = () => window.history.back();\n } else {\n // SSR mode\n getLocation = () => {\n const url = new URL(initialUrl || '/', 'http://localhost');\n const path = url.pathname.replace(base, '') || '/';\n const query = parseQuery(url.search);\n return { path, query };\n };\n\n initial = getLocation();\n const match = matchRoute(routes, initial.path);\n store = createStore<RouteState>({\n path: initial.path,\n params: match.params,\n query: initial.query,\n });\n\n update = async () => {\n const loc = getLocation();\n await navigateSSR(loc.path);\n };\n\n // SSR navigation contract:\n // - `push` / `replace` call into `navigateSSR` and return a Promise.\n // - On the server we intentionally surface navigation failures so\n // server-side logic (or tests) can react: missing routes or thrown\n // errors from `beforeEnter`/`onEnter` will cause the Promise to\n // reject. This lets the server render 404s or abort builds.\n // - For valid routes the server-side navigation resolves and updates\n // the internal store state so rendered output matches the target\n // path. The `back()` operation is client-only and is a synchronous\n // no-op in SSR mode.\n const navigateSSR = async (path: string) => {\n try {\n const loc = {\n path: path.replace(base, '') || '/',\n query: {},\n };\n const match = matchRoute(routes, loc.path);\n // In SSR mode we intentionally surface navigation errors (missing\n // route) to the caller so server-side logic may handle them. If no\n // route matches, throw and let the caller observe the rejection.\n if (!match.route) throw new Error(`No route found for ${loc.path}`);\n\n const from = store.getState();\n const to: RouteState = {\n path: loc.path,\n params: match.params,\n query: loc.query,\n };\n\n // beforeEnter guard\n const matched = findMatchedRoute(routes, to.path);\n if (matched?.beforeEnter) {\n const result = await matched.beforeEnter(to, from);\n if (typeof result === 'string') {\n // Redirect\n await navigateSSR(result);\n return;\n }\n if (result === false) return;\n }\n\n // onEnter guard\n if (matched?.onEnter) {\n const result = await matched.onEnter(to, from);\n if (typeof result === 'string') {\n await navigateSSR(result);\n return;\n }\n if (result === false) return;\n }\n\n store.setState(to);\n\n // afterEnter hook\n if (matched?.afterEnter) {\n matched.afterEnter(to, from);\n }\n } catch (err) {\n // Surface SSR navigation errors so callers (and tests) can observe\n // failures during server-side resolution.\n devError('SSR navigation error:', err);\n throw err;\n }\n };\n\n push = async (path: string) => navigateSSR(path);\n replaceFn = async (path: string) => navigateSSR(path);\n back = () => {};\n }\n\n return {\n store,\n push,\n replace: replaceFn,\n back,\n subscribe: store.subscribe,\n matchRoute: (path: string) => matchRoute(routes, path),\n getCurrent: (): RouteState => store.getState(),\n resolveRouteComponent,\n };\n}\n\n// SSR/static site support: match route for a given path\nexport function matchRouteSSR(routes: Route[], path: string) {\n return matchRoute(routes, path);\n}\n\n// Module-level reference to the latest initialized router. Tests and\n// components may rely on re-initializing the router during their setup,\n// so exposing this lets components pick up the most recent instance.\nlet activeRouter: ReturnType<typeof useRouter> | null = null;\n\n/**\n * Singleton router instance for global access.\n *\n * Define here to prevent circular dependency\n * issue with component.\n */\n\nexport function initRouter(config: RouterConfig) {\n const router = useRouter(config);\n // Expose the most recently initialized router to components defined\n // earlier in the process (tests may call initRouter multiple times).\n // Components reference `activeRouter` so re-calling initRouter updates\n // the router instance they use.\n activeRouter = router;\n\n component('router-view', async () => {\n // Prefer the latest initialized router (tests may re-init). Fallback\n // to the router captured at init time.\n const r = activeRouter || router;\n // Reactive current route so the component re-renders when router updates\n if (!r) return html`<div>Router not initialized.</div>`;\n\n const current = ref(r.getCurrent());\n\n // We'll capture the unsubscribe function when the component connects\n // and register a disconnect cleanup during render-time (useOnDisconnected\n // must be called during the component render/execution).\n let unsubRouterView: (() => void) | undefined;\n\n useOnConnected(() => {\n try {\n if (r && typeof r.subscribe === 'function') {\n unsubRouterView = r.subscribe((s) => {\n try {\n current.value = s;\n } catch (e) {\n devWarn('router-view subscription update failed', e);\n }\n });\n }\n } catch (e) {\n devWarn('router-view subscribe failed', e);\n }\n });\n\n useOnDisconnected(() => {\n if (typeof unsubRouterView === 'function') {\n try {\n unsubRouterView();\n } catch (e) {\n devWarn('router-view unsubscribe failed', e);\n }\n }\n });\n\n const match = r.matchRoute(current.value.path);\n if (!match || !match.route) return html`<div>Not found</div>`;\n\n // Resolve the component (supports cached async loaders)\n try {\n const compRaw = await r.resolveRouteComponent(match.route);\n const comp = compRaw as\n | string\n | HTMLElement\n | ((...args: unknown[]) => unknown)\n | undefined;\n // String tag (custom element) -> render as VNode\n if (typeof comp === 'string') {\n return { tag: comp, props: {}, children: [] };\n }\n\n // Function component (sync or async) -> call and return its VNode(s)\n if (typeof comp === 'function') {\n const out = comp();\n const resolved = out instanceof Promise ? out : Promise.resolve(out);\n return resolved.then((resolvedComp) => {\n if (typeof resolvedComp === 'string')\n return { tag: resolvedComp, props: {}, children: [] };\n return resolvedComp;\n });\n }\n\n return html`<div>Invalid route component</div>`;\n } catch {\n return html`<div>Invalid route component</div>`;\n }\n });\n\n component('router-link', () => {\n // Declare props via useProps so observedAttributes are correct\n const props = useProps<Partial<RouterLinkProps>>({\n to: '',\n tag: 'a',\n replace: false,\n exact: false,\n activeClass: 'active',\n exactActiveClass: 'exact-active',\n ariaCurrentValue: 'page',\n disabled: false,\n external: false,\n linkClass: '',\n linkStyle: '',\n });\n\n // Prefer the latest initialized router (tests may re-init). Fallback\n // to the router captured at init time.\n const r = activeRouter || router;\n // Reactive current state so link updates when route changes\n const current = ref(r.getCurrent());\n // Capture unsubscribe for link subscriptions and register disconnect\n // cleanup during render time.\n let unsubRouterLink: (() => void) | undefined;\n\n useStyle(\n () => (`a,button{display:inline-block;}` + props.linkStyle) as string,\n );\n\n useOnConnected(() => {\n try {\n if (r && typeof r.subscribe === 'function') {\n unsubRouterLink = r.subscribe((s) => {\n try {\n current.value = s;\n } catch (e) {\n devWarn('router-link subscription update failed', e);\n }\n });\n }\n } catch (e) {\n devWarn('router-link subscribe failed', e);\n }\n });\n\n useOnDisconnected(() => {\n if (typeof unsubRouterLink === 'function') {\n try {\n unsubRouterLink();\n } catch (e) {\n devWarn('router-link unsubscribe failed', e);\n }\n }\n });\n\n const isExactActive = computed(\n () => current.value.path === (props.to as string),\n );\n const isActive = computed(() =>\n props.exact\n ? isExactActive.value\n : current.value && typeof current.value.path === 'string'\n ? current.value.path.startsWith(props.to as string)\n : false,\n );\n\n // Build user classes reactively from the `linkClass` prop.\n // We intentionally do NOT read the host `class` attribute to avoid\n // duplicate styling applied to both host and inner element.\n const userClasses = computed(() => {\n const raw = (props.linkClass as string) || '';\n const list = raw.split(/\\s+/).filter(Boolean);\n const map: Record<string, boolean> = {};\n for (const c of list) map[c] = true;\n return map;\n });\n\n const classObject = computed(() => ({\n ...userClasses.value,\n [(props.activeClass as string) || 'active']: isActive.value,\n [(props.exactActiveClass as string) || 'exact-active']:\n isExactActive.value,\n }));\n\n const isButton = computed(() => (props.tag as string) === 'button');\n // Instead of pre-building attribute fragments as strings (which can\n // accidentally inject invalid attribute names into the template and\n // cause DOMExceptions), compute simple booleans/values and apply\n // attributes explicitly in the template below.\n const ariaCurrentValue = computed(() =>\n isExactActive.value ? (props.ariaCurrentValue as string) : '',\n );\n const isDisabled = computed(() => !!props.disabled);\n const isExternal = computed(\n () =>\n !!props.external &&\n ((props.tag as string) === 'a' || !(props.tag as string)),\n );\n\n const navigate = (e: MouseEvent) => {\n if (props.disabled) {\n e.preventDefault();\n return;\n }\n if (\n props.external &&\n ((props.tag as string) === 'a' || !(props.tag as string))\n ) {\n return;\n }\n e.preventDefault();\n if (props.replace) {\n r.replace(props.to as string);\n } else {\n r.push(props.to as string);\n }\n };\n\n return html`\n ${match()\n .when(\n isButton.value,\n html`\n <button\n part=\"button\"\n :class=\"${classObject.value}\"\n aria-current=\"${ariaCurrentValue.value}\"\n disabled=\"${isDisabled.value ? '' : null}\"\n aria-disabled=\"${isDisabled.value ? 'true' : null}\"\n tabindex=\"${isDisabled.value ? '-1' : null}\"\n @click=\"${navigate}\"\n >\n <slot></slot>\n </button>\n `,\n )\n .otherwise(html`\n <a\n part=\"link\"\n href=\"${props.to}\"\n :class=\"${classObject.value}\"\n aria-current=\"${ariaCurrentValue.value}\"\n aria-disabled=\"${isDisabled.value ? 'true' : null}\"\n tabindex=\"${isDisabled.value ? '-1' : null}\"\n target=\"${isExternal.value ? '_blank' : null}\"\n rel=\"${isExternal.value ? 'noopener noreferrer' : null}\"\n @click=\"${navigate}\"\n ><slot></slot\n ></a>\n `)\n .done()}\n `;\n });\n\n return router;\n}\n"],"names":["parseQuery","search","matchRoute","routes","path","route","paramNames","regexPath","m","regex","match","params","name","i","findMatchedRoute","r","componentCache","resolveRouteComponent","mod","useRouter","config","base","initialUrl","getLocation","initial","store","update","push","replaceFn","back","runBeforeEnter","to","from","matched","result","navigate","err","devError","runOnEnter","runAfterEnter","replace","loc","url","query","createStore","navigateSSR","matchRouteSSR","activeRouter","initRouter","router","component","html","current","ref","unsubRouterView","useOnConnected","e","devWarn","useOnDisconnected","comp","out","resolvedComp","props","useProps","unsubRouterLink","useStyle","s","isExactActive","computed","isActive","userClasses","list","map","c","classObject","isButton","ariaCurrentValue","isDisabled","isExternal"],"mappings":"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"}
1
+ {"version":3,"file":"custom-elements-runtime.router.es.js","sources":["../src/lib/router.ts"],"sourcesContent":["import { html } from './runtime/template-compiler';\nimport { component } from './runtime/component';\nimport {\n useProps,\n useOnConnected,\n useOnDisconnected,\n useStyle,\n} from './runtime/hooks';\nimport { ref, computed } from './runtime/reactive';\nimport { createStore, type Store } from './store';\nimport { devError, devWarn } from './runtime/logger';\nimport { match } from './directives';\n\nexport type RouteComponent =\n | { new (...args: unknown[]): unknown } // class components\n | ((...args: unknown[]) => unknown); // functional components\n\nexport interface RouteState {\n path: string;\n params: Record<string, string>;\n query: Record<string, string>;\n}\n\nexport type GuardResult = boolean | string | Promise<boolean | string>;\n\nexport interface Route {\n path: string;\n\n /**\n * Statically available component (already imported)\n */\n component?: string | (() => unknown);\n\n /**\n * Lazy loader that resolves to something renderable\n */\n load?: () => Promise<{\n default: string | HTMLElement | ((...args: unknown[]) => unknown);\n }>;\n\n /**\n * Runs before matching — return false to cancel,\n * or a string to redirect\n */\n beforeEnter?: (to: RouteState, from: RouteState) => GuardResult;\n\n /**\n * Runs right before navigation commits — can cancel or redirect\n */\n onEnter?: (to: RouteState, from: RouteState) => GuardResult;\n\n /**\n * Runs after navigation completes — cannot cancel\n */\n afterEnter?: (to: RouteState, from: RouteState) => void;\n}\n\nexport interface RouterLinkProps {\n to: string;\n tag: string;\n replace: boolean;\n exact: boolean;\n activeClass: string;\n exactActiveClass: string;\n ariaCurrentValue: string;\n disabled: boolean;\n external: boolean;\n class?: string;\n style?: string;\n}\n\nexport interface RouterLinkComputed {\n current: RouteState;\n isExactActive: boolean;\n isActive: boolean;\n className: string;\n ariaCurrent: string;\n isButton: boolean;\n disabledAttr: string;\n externalAttr: string;\n}\n\nexport interface RouterConfig {\n routes: Route[];\n base?: string;\n initialUrl?: string; // For SSR: explicitly pass the URL\n}\n\nexport const parseQuery = (search: string): Record<string, string> => {\n if (!search) return {};\n if (typeof URLSearchParams === 'undefined') return {};\n return Object.fromEntries(new URLSearchParams(search));\n};\n\nexport const matchRoute = (\n routes: Route[],\n path: string,\n): { route: Route | null; params: Record<string, string> } => {\n for (const route of routes) {\n const paramNames: string[] = [];\n const regexPath = route.path.replace(/:[^/]+/g, (m) => {\n paramNames.push(m.slice(1));\n return '([^/]+)';\n });\n const regex = new RegExp(`^${regexPath}$`);\n const match = path.match(regex);\n if (match) {\n const params: Record<string, string> = {};\n paramNames.forEach((name, i) => {\n params[name] = match[i + 1];\n });\n return { route, params };\n }\n }\n return { route: null, params: {} };\n};\n\n/**\n * Find the first route that matches the given path.\n * Consolidates repeated inline checks like `routes.find(r => matchRoute([r], path).route !== null)`\n */\nfunction findMatchedRoute(routes: Route[], path: string): Route | null {\n for (const r of routes) {\n if (matchRoute([r], path).route !== null) return r;\n }\n return null;\n}\n\n// Async component loader cache\nconst componentCache: Record<\n string,\n string | HTMLElement | ((...args: unknown[]) => unknown)\n> = {};\n\n/**\n * Loads a route's component, supporting both static and async.\n * @param route Route object\n * @returns Promise resolving to the component\n */\nexport async function resolveRouteComponent(\n route: Route,\n): Promise<string | HTMLElement | ((...args: unknown[]) => unknown)> {\n if (route.component) return route.component;\n if (route.load) {\n if (componentCache[route.path]) return componentCache[route.path];\n try {\n const mod = await route.load();\n componentCache[route.path] = mod.default;\n return mod.default;\n } catch {\n throw new Error(`Failed to load component for route: ${route.path}`);\n }\n }\n throw new Error(`No component or loader defined for route: ${route.path}`);\n}\n\nexport function useRouter(config: RouterConfig) {\n const { routes, base = '', initialUrl } = config;\n\n let getLocation: () => { path: string; query: Record<string, string> };\n let initial: { path: string; query: Record<string, string> };\n let store: Store<RouteState>;\n let update: (replace?: boolean) => Promise<void>;\n let push: (path: string) => Promise<void>;\n let replaceFn: (path: string) => Promise<void>;\n let back: () => void;\n\n // Run matching route guards/hooks\n const runBeforeEnter = async (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.beforeEnter) return true;\n try {\n const result = await matched.beforeEnter(to, from);\n if (typeof result === 'string') {\n // Redirect\n await navigate(result, true);\n return false;\n }\n return result !== false;\n } catch (err) {\n devError('beforeEnter error', err);\n return false;\n }\n };\n\n const runOnEnter = async (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.onEnter) return true;\n try {\n const result = await matched.onEnter(to, from);\n if (typeof result === 'string') {\n await navigate(result, true);\n return false;\n }\n return result !== false;\n } catch (err) {\n devError('onEnter error', err);\n return false;\n }\n };\n\n const runAfterEnter = (to: RouteState, from: RouteState) => {\n const matched = findMatchedRoute(routes, to.path);\n if (!matched || !matched.afterEnter) return;\n try {\n matched.afterEnter(to, from);\n } catch (err) {\n devError('afterEnter error', err);\n }\n };\n\n const navigate = async (path: string, replace = false) => {\n try {\n const loc = {\n path: path.replace(base, '') || '/',\n query: {},\n };\n const match = matchRoute(routes, loc.path);\n if (!match.route) throw new Error(`No route found for ${loc.path}`);\n\n const from = store.getState();\n const to: RouteState = {\n path: loc.path,\n params: match.params,\n query: loc.query,\n };\n\n // beforeEnter guard\n const allowedBefore = await runBeforeEnter(to, from);\n if (!allowedBefore) return;\n\n // onEnter guard (right before commit)\n const allowedOn = await runOnEnter(to, from);\n if (!allowedOn) return;\n\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n if (replace) {\n window.history.replaceState({}, '', base + path);\n } else {\n window.history.pushState({}, '', base + path);\n }\n }\n\n store.setState(to);\n\n // afterEnter hook (post commit)\n runAfterEnter(to, from);\n } catch (err) {\n devError('Navigation error:', err);\n }\n };\n\n // If an explicit `initialUrl` is provided we treat this as SSR/static rendering\n // even if a `window` exists (useful for hydration tests). Browser mode only\n // applies when `initialUrl` is undefined.\n if (\n typeof window !== 'undefined' &&\n typeof document !== 'undefined' &&\n typeof initialUrl === 'undefined'\n ) {\n // Browser mode\n getLocation = () => {\n const url = new URL(window.location.href);\n const path = url.pathname.replace(base, '') || '/';\n const query = parseQuery(url.search);\n return { path, query };\n };\n\n initial = getLocation();\n const match = matchRoute(routes, initial.path);\n store = createStore<RouteState>({\n path: initial.path,\n params: match.params,\n query: initial.query,\n });\n\n update = async (replace = false) => {\n const loc = getLocation();\n await navigate(loc.path, replace);\n };\n\n window.addEventListener('popstate', () => update(true));\n\n push = (path: string) => navigate(path, false);\n replaceFn = (path: string) => navigate(path, true);\n back = () => window.history.back();\n } else {\n // SSR mode\n getLocation = () => {\n const url = new URL(initialUrl || '/', 'http://localhost');\n const path = url.pathname.replace(base, '') || '/';\n const query = parseQuery(url.search);\n return { path, query };\n };\n\n initial = getLocation();\n const match = matchRoute(routes, initial.path);\n store = createStore<RouteState>({\n path: initial.path,\n params: match.params,\n query: initial.query,\n });\n\n update = async () => {\n const loc = getLocation();\n await navigateSSR(loc.path);\n };\n\n // SSR navigation contract:\n // - `push` / `replace` call into `navigateSSR` and return a Promise.\n // - On the server we intentionally surface navigation failures so\n // server-side logic (or tests) can react: missing routes or thrown\n // errors from `beforeEnter`/`onEnter` will cause the Promise to\n // reject. This lets the server render 404s or abort builds.\n // - For valid routes the server-side navigation resolves and updates\n // the internal store state so rendered output matches the target\n // path. The `back()` operation is client-only and is a synchronous\n // no-op in SSR mode.\n const navigateSSR = async (path: string) => {\n try {\n const loc = {\n path: path.replace(base, '') || '/',\n query: {},\n };\n const match = matchRoute(routes, loc.path);\n // In SSR mode we intentionally surface navigation errors (missing\n // route) to the caller so server-side logic may handle them. If no\n // route matches, throw and let the caller observe the rejection.\n if (!match.route) throw new Error(`No route found for ${loc.path}`);\n\n const from = store.getState();\n const to: RouteState = {\n path: loc.path,\n params: match.params,\n query: loc.query,\n };\n\n // beforeEnter guard\n const matched = findMatchedRoute(routes, to.path);\n if (matched?.beforeEnter) {\n const result = await matched.beforeEnter(to, from);\n if (typeof result === 'string') {\n // Redirect\n await navigateSSR(result);\n return;\n }\n if (result === false) return;\n }\n\n // onEnter guard\n if (matched?.onEnter) {\n const result = await matched.onEnter(to, from);\n if (typeof result === 'string') {\n await navigateSSR(result);\n return;\n }\n if (result === false) return;\n }\n\n store.setState(to);\n\n // afterEnter hook\n if (matched?.afterEnter) {\n matched.afterEnter(to, from);\n }\n } catch (err) {\n // Surface SSR navigation errors so callers (and tests) can observe\n // failures during server-side resolution.\n devError('SSR navigation error:', err);\n throw err;\n }\n };\n\n push = async (path: string) => navigateSSR(path);\n replaceFn = async (path: string) => navigateSSR(path);\n back = () => {};\n }\n\n return {\n store,\n push,\n replace: replaceFn,\n back,\n subscribe: store.subscribe,\n matchRoute: (path: string) => matchRoute(routes, path),\n getCurrent: (): RouteState => store.getState(),\n resolveRouteComponent,\n };\n}\n\n// SSR/static site support: match route for a given path\nexport function matchRouteSSR(routes: Route[], path: string) {\n return matchRoute(routes, path);\n}\n\n// Module-level reference to the latest initialized router. Tests and\n// components may rely on re-initializing the router during their setup,\n// so exposing this lets components pick up the most recent instance.\nlet activeRouter: ReturnType<typeof useRouter> | null = null;\n\n/**\n * Singleton router instance for global access.\n *\n * Define here to prevent circular dependency\n * issue with component.\n */\n\nexport function initRouter(config: RouterConfig) {\n const router = useRouter(config);\n // Expose the most recently initialized router to components defined\n // earlier in the process (tests may call initRouter multiple times).\n // Components reference `activeRouter` so re-calling initRouter updates\n // the router instance they use.\n activeRouter = router;\n\n component('router-view', async () => {\n // Prefer the latest initialized router (tests may re-init). Fallback\n // to the router captured at init time.\n const r = activeRouter || router;\n // Reactive current route so the component re-renders when router updates\n if (!r) return html`<div>Router not initialized.</div>`;\n\n const current = ref(r.getCurrent());\n\n // We'll capture the unsubscribe function when the component connects\n // and register a disconnect cleanup during render-time (useOnDisconnected\n // must be called during the component render/execution).\n let unsubRouterView: (() => void) | undefined;\n\n useOnConnected(() => {\n try {\n if (r && typeof r.subscribe === 'function') {\n unsubRouterView = r.subscribe((s) => {\n try {\n current.value = s;\n } catch (e) {\n devWarn('router-view subscription update failed', e);\n }\n });\n }\n } catch (e) {\n devWarn('router-view subscribe failed', e);\n }\n });\n\n useOnDisconnected(() => {\n if (typeof unsubRouterView === 'function') {\n try {\n unsubRouterView();\n } catch (e) {\n devWarn('router-view unsubscribe failed', e);\n }\n }\n });\n\n const match = r.matchRoute(current.value.path);\n if (!match || !match.route) return html`<div>Not found</div>`;\n\n // Resolve the component (supports cached async loaders)\n try {\n const compRaw = await r.resolveRouteComponent(match.route);\n const comp = compRaw as\n | string\n | HTMLElement\n | ((...args: unknown[]) => unknown)\n | undefined;\n // String tag (custom element) -> render as VNode\n if (typeof comp === 'string') {\n return { tag: comp, props: {}, children: [] };\n }\n\n // Function component (sync or async) -> call and return its VNode(s)\n if (typeof comp === 'function') {\n const out = comp();\n const resolved = out instanceof Promise ? out : Promise.resolve(out);\n return resolved.then((resolvedComp) => {\n if (typeof resolvedComp === 'string')\n return { tag: resolvedComp, props: {}, children: [] };\n return resolvedComp;\n });\n }\n\n return html`<div>Invalid route component</div>`;\n } catch {\n return html`<div>Invalid route component</div>`;\n }\n });\n\n component('router-link', () => {\n // Declare props via useProps so observedAttributes are correct\n const props = useProps<Partial<RouterLinkProps>>({\n to: '',\n tag: 'a',\n replace: false,\n exact: false,\n activeClass: 'active',\n exactActiveClass: 'exact-active',\n ariaCurrentValue: 'page',\n disabled: false,\n external: false,\n // allow host `class` and `style` attributes to be read via useProps\n class: '',\n style: '',\n });\n\n // Prefer the latest initialized router (tests may re-init). Fallback\n // to the router captured at init time.\n const r = activeRouter || router;\n // Reactive current state so link updates when route changes\n const current = ref(r.getCurrent());\n // Capture unsubscribe for link subscriptions and register disconnect\n // cleanup during render time.\n let unsubRouterLink: (() => void) | undefined;\n\n // Keep a minimal internal host-scoped style for element display.\n // Host `style` will be applied to the inner anchor/button element.\n useStyle(() => `a,button{display:inline-block;}`);\n\n // We capture host attributes at connection time and migrate them to\n // internal refs so we can remove them from the host. This prevents\n // global/author CSS targeting the host from styling the host element\n // itself while still allowing authors to use `class`/`style` on the\n // router-link to style the inner anchor/button.\n const hostClassRef = ref((props.class as string) || '');\n const hostStyleRef = ref((props.style as string) || '');\n\n useOnConnected((ctx?: unknown) => {\n try {\n if (r && typeof r.subscribe === 'function') {\n unsubRouterLink = r.subscribe((s) => {\n try {\n current.value = s;\n } catch (e) {\n devWarn('router-link subscription update failed', e);\n }\n });\n }\n } catch (e) {\n devWarn('router-link subscribe failed', e);\n }\n\n // Migrate host `class`/`style` into internal refs and remove them\n // from the host so only the inner element is styled.\n try {\n const host = (ctx as { _host?: HTMLElement } | undefined)?._host;\n if (host instanceof HTMLElement) {\n const hc = host.getAttribute('class');\n const hs = host.getAttribute('style');\n if (hc) hostClassRef.value = hc;\n if (hs) hostStyleRef.value = hs;\n // Remove attributes from host to avoid styling the host\n if (hc !== null) host.removeAttribute('class');\n if (hs !== null) host.removeAttribute('style');\n }\n } catch (e) {\n devWarn('router-link host migration failed', e);\n }\n });\n\n useOnDisconnected(() => {\n if (typeof unsubRouterLink === 'function') {\n try {\n unsubRouterLink();\n } catch (e) {\n devWarn('router-link unsubscribe failed', e);\n }\n }\n });\n\n const isExactActive = computed(\n () => current.value.path === (props.to as string),\n );\n const isActive = computed(() =>\n props.exact\n ? isExactActive.value\n : current.value && typeof current.value.path === 'string'\n ? current.value.path.startsWith(props.to as string)\n : false,\n );\n\n // Build user classes reactively from the host `class` attribute prop.\n // We intentionally apply classes to the inner element so the consumer\n // can style the link via `class=\"...\"`.\n const userClasses = computed(() => {\n const rawHost =\n (hostClassRef && hostClassRef.value) || (props.class as string) || '';\n const list = rawHost.split(/\\s+/).filter(Boolean);\n const map: Record<string, boolean> = {};\n for (const c of list) map[c] = true;\n return map;\n });\n\n const classObject = computed(() => ({\n ...userClasses.value,\n [(props.activeClass as string) || 'active']: isActive.value,\n [(props.exactActiveClass as string) || 'exact-active']:\n isExactActive.value,\n }));\n\n // Compute a final class string (template accepts object or string; we\n // convert to string to safely include host classes and conditionals).\n const classString = computed(() =>\n Object.keys(classObject.value)\n .filter((k) => classObject.value[k])\n .join(' '),\n );\n\n const isButton = computed(() => (props.tag as string) === 'button');\n // Instead of pre-building attribute fragments as strings (which can\n // accidentally inject invalid attribute names into the template and\n // cause DOMExceptions), compute simple booleans/values and apply\n // attributes explicitly in the template below.\n const ariaCurrentValue = computed(() =>\n isExactActive.value ? (props.ariaCurrentValue as string) : '',\n );\n const isDisabled = computed(() => !!props.disabled);\n const isExternal = computed(\n () =>\n !!props.external &&\n ((props.tag as string) === 'a' || !(props.tag as string)),\n );\n\n // Inline style from host `style` attribute.\n const inlineStyle = computed(\n () =>\n (hostStyleRef && hostStyleRef.value) || (props.style as string) || '',\n );\n\n const navigate = (e: MouseEvent) => {\n if (props.disabled) {\n e.preventDefault();\n return;\n }\n if (\n props.external &&\n ((props.tag as string) === 'a' || !(props.tag as string))\n ) {\n return;\n }\n e.preventDefault();\n if (props.replace) {\n r.replace(props.to as string);\n } else {\n r.push(props.to as string);\n }\n };\n\n return html`\n ${match()\n .when(\n isButton.value,\n html`\n <button\n part=\"button\"\n class=\"${classString.value}\"\n style=\"${inlineStyle.value || null}\"\n aria-current=\"${ariaCurrentValue.value}\"\n disabled=\"${isDisabled.value ? '' : null}\"\n aria-disabled=\"${isDisabled.value ? 'true' : null}\"\n tabindex=\"${isDisabled.value ? '-1' : null}\"\n @click=\"${navigate}\"\n >\n <slot></slot>\n </button>\n `,\n )\n .otherwise(html`\n <a\n part=\"link\"\n href=\"${props.to}\"\n class=\"${classString.value}\"\n style=\"${inlineStyle.value || null}\"\n aria-current=\"${ariaCurrentValue.value}\"\n aria-disabled=\"${isDisabled.value ? 'true' : null}\"\n tabindex=\"${isDisabled.value ? '-1' : null}\"\n target=\"${isExternal.value ? '_blank' : null}\"\n rel=\"${isExternal.value ? 'noopener noreferrer' : null}\"\n @click=\"${navigate}\"\n ><slot></slot\n ></a>\n `)\n .done()}\n `;\n });\n\n return router;\n}\n"],"names":["parseQuery","search","matchRoute","routes","path","route","paramNames","regexPath","m","regex","match","params","name","i","findMatchedRoute","r","componentCache","resolveRouteComponent","mod","useRouter","config","base","initialUrl","getLocation","initial","store","update","push","replaceFn","back","runBeforeEnter","to","from","matched","result","navigate","err","devError","runOnEnter","runAfterEnter","replace","loc","url","query","createStore","navigateSSR","matchRouteSSR","activeRouter","initRouter","router","component","html","current","ref","unsubRouterView","useOnConnected","e","devWarn","useOnDisconnected","comp","out","resolvedComp","props","useProps","unsubRouterLink","useStyle","hostClassRef","hostStyleRef","ctx","s","host","hc","hs","isExactActive","computed","isActive","userClasses","list","map","c","classObject","classString","k","isButton","ariaCurrentValue","isDisabled","isExternal","inlineStyle"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("./custom-elements-runtime.directives.cjs.js");const t=require("./transitions-Bv8lUAOe.cjs");exports.Transition=t.Transition;exports.TransitionGroup=t.TransitionGroup;exports.createTransitionPreset=t.createTransitionPreset;exports.getTransitionStyleSheet=t.getTransitionStyleSheet;exports.transitionPresets=t.transitionPresets;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("./custom-elements-runtime.directives.cjs.js");const t=require("./transitions-DHQuI3AY.cjs");exports.Transition=t.Transition;exports.TransitionGroup=t.TransitionGroup;exports.createTransitionPreset=t.createTransitionPreset;exports.getTransitionStyleSheet=t.getTransitionStyleSheet;exports.transitionPresets=t.transitionPresets;
2
2
  //# sourceMappingURL=custom-elements-runtime.transitions.cjs.js.map
@@ -1,5 +1,5 @@
1
1
  import "./custom-elements-runtime.directives.es.js";
2
- import { T as e, d as r, e as i, a as n, t as o } from "./transitions-m6FraTTL.js";
2
+ import { T as e, d as r, e as i, a as n, t as o } from "./transitions-DCIjMqzG.js";
3
3
  export {
4
4
  e as Transition,
5
5
  r as TransitionGroup,
package/dist/router.d.ts CHANGED
@@ -44,8 +44,8 @@ export interface RouterLinkProps {
44
44
  ariaCurrentValue: string;
45
45
  disabled: boolean;
46
46
  external: boolean;
47
- linkClass?: string;
48
- linkStyle?: string;
47
+ class?: string;
48
+ style?: string;
49
49
  }
50
50
  export interface RouterLinkComputed {
51
51
  current: RouteState;
@@ -1,5 +1,5 @@
1
- import { anchorBlock as ye } from "./custom-elements-runtime.directives.es.js";
2
- const $e = `/*
1
+ import { anchorBlock as $e } from "./custom-elements-runtime.directives.es.js";
2
+ const ye = `/*
3
3
  * Custom Elements Variables CSS
4
4
  * CSS variables for colors and fonts
5
5
  */
@@ -139,7 +139,7 @@ function De(e) {
139
139
  return e.replace(/url\s*\(\s*['"]?javascript:[^)]*\)/gi, "").replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, "").replace(/expression\s*\([^)]*\)/gi, "");
140
140
  }
141
141
  const pe = ke`
142
- ${$e}
142
+ ${ye}
143
143
  :host,
144
144
  *,
145
145
  ::before,
@@ -833,7 +833,8 @@ const Ce = {
833
833
  "peer-hover": (e, r) => `.peer:hover ~ ${e}{${r}}`,
834
834
  "peer-focus": (e, r) => `.peer:focus ~ ${e}{${r}}`,
835
835
  "peer-checked": (e, r) => `.peer:checked ~ ${e}{${r}}`,
836
- "peer-disabled": (e, r) => `.peer:disabled ~ ${e}{${r}}`
836
+ "peer-disabled": (e, r) => `.peer:disabled ~ ${e}{${r}}`,
837
+ "dark-class": (e, r) => `:host(.dark) ${e}{${r}}`
837
838
  }, oe = {
838
839
  sm: "(min-width:640px)",
839
840
  md: "(min-width:768px)",
@@ -872,11 +873,11 @@ function ae(e) {
872
873
  const c = o.slice(0, n), s = o.slice(n + 1);
873
874
  if (!te[c]) return null;
874
875
  if (s.includes("/")) {
875
- const [t, a] = s.split("/").map(($) => parseFloat($));
876
+ const [t, a] = s.split("/").map((y) => parseFloat(y));
876
877
  if (Number.isNaN(t) || Number.isNaN(a) || a === 0)
877
878
  return null;
878
879
  const d = t / a * 100;
879
- return te[c].map(($) => `${$}:${d}%;`).join("");
880
+ return te[c].map((y) => `${y}:${d}%;`).join("");
880
881
  }
881
882
  const u = parseFloat(s);
882
883
  if (Number.isNaN(u)) return null;
@@ -890,10 +891,10 @@ function ce(e) {
890
891
  if (s === "reverse")
891
892
  return u ? "--cer-space-x-reverse:1;" : "--cer-space-y-reverse:1;";
892
893
  if (s.includes("/")) {
893
- const [d, $] = s.split("/").map((A) => parseFloat(A));
894
- if (Number.isNaN(d) || Number.isNaN($) || $ === 0)
894
+ const [d, y] = s.split("/").map((A) => parseFloat(A));
895
+ if (Number.isNaN(d) || Number.isNaN(y) || y === 0)
895
896
  return null;
896
- const v = d / $ * 100, C = r ? "-" : "";
897
+ const v = d / y * 100, C = r ? "-" : "";
897
898
  return u ? `--cer-space-x-reverse:0;& > :not([hidden]) ~ :not([hidden]){margin-inline-start:calc(${C}${v}% * calc(1 - var(--cer-space-x-reverse)));margin-inline-end:calc(${C}${v}% * var(--cer-space-x-reverse));}` : `--cer-space-y-reverse:0;& > :not([hidden]) ~ :not([hidden]){margin-top:calc(${C}${v}% * calc(1 - var(--cer-space-y-reverse)));margin-bottom:calc(${C}${v}% * var(--cer-space-y-reverse));}`;
898
899
  }
899
900
  const m = parseFloat(s);
@@ -940,7 +941,7 @@ function se(e) {
940
941
  if (n.includes("var(")) {
941
942
  const u = /var\([^)]*\)/.exec(n);
942
943
  if (u) {
943
- const m = u[0], t = o * 100, a = `color-mix(in srgb, ${m} ${t}%, rgba(0 0 0 / 0) ${100 - t}%)`, d = /#([0-9a-f]{6}|[0-9a-f]{3})/i.exec(m), $ = /^([a-z-]+):/.exec(n), v = $ ? $[1] : "background-color";
944
+ const m = u[0], t = o * 100, a = `color-mix(in srgb, ${m} ${t}%, rgba(0 0 0 / 0) ${100 - t}%)`, d = /#([0-9a-f]{6}|[0-9a-f]{3})/i.exec(m), y = /^([a-z-]+):/.exec(n), v = y ? y[1] : "background-color";
944
945
  if (d) {
945
946
  const A = `rgb(${J(d[0])} / ${o})`, f = m.replace(
946
947
  /#([0-9a-f]{6}|[0-9a-f]{3})/i,
@@ -967,7 +968,7 @@ function se(e) {
967
968
  if (c.includes("var(")) {
968
969
  const u = /var\([^)]*\)/.exec(c);
969
970
  if (u) {
970
- const m = u[0], t = o * 100, a = `color-mix(in srgb, ${m} ${t}%, rgba(0 0 0 / 0) ${100 - t}%)`, d = /#([0-9a-f]{6}|[0-9a-f]{3})/i.exec(m), $ = /^([a-z-]+):/.exec(c), v = $ ? $[1] : null;
971
+ const m = u[0], t = o * 100, a = `color-mix(in srgb, ${m} ${t}%, rgba(0 0 0 / 0) ${100 - t}%)`, d = /#([0-9a-f]{6}|[0-9a-f]{3})/i.exec(m), y = /^([a-z-]+):/.exec(c), v = y ? y[1] : null;
971
972
  if (d && v) {
972
973
  const A = `rgb(${J(d[0])} / ${o})`, f = m.replace(
973
974
  /#([0-9a-f]{6}|[0-9a-f]{3})/i,
@@ -1104,7 +1105,7 @@ function Le(e) {
1104
1105
  const c = new Set(n), s = [[], [], [], []], u = {}, m = (f, p = !1) => {
1105
1106
  const g = p ? `dark|${f}` : f;
1106
1107
  if (g in u) return u[g];
1107
- const b = $(f, p);
1108
+ const b = y(f, p);
1108
1109
  return u[g] = b, b;
1109
1110
  }, t = (f) => {
1110
1111
  const p = f.some((k) => ne.includes(k)), g = f.some(
@@ -1132,12 +1133,12 @@ function Le(e) {
1132
1133
  even: ":nth-child(even)",
1133
1134
  "focus-within": ":focus-within",
1134
1135
  "focus-visible": ":focus-visible"
1135
- }, $ = (f, p = !1) => {
1136
+ }, y = (f, p = !1) => {
1136
1137
  const g = a(f);
1137
1138
  let b = "", k = !1;
1138
1139
  for (const i of g) {
1139
- let y = i;
1140
- if (y.startsWith("!") && (k = !0, y = y.slice(1)), re[y] || ae(y) || ce(y) || de(y) || se(y) || le(y) || Z(y)) {
1140
+ let $ = i;
1141
+ if ($.startsWith("!") && (k = !0, $ = $.slice(1)), re[$] || ae($) || ce($) || de($) || se($) || le($) || Z($)) {
1141
1142
  b = i;
1142
1143
  break;
1143
1144
  }
@@ -1162,9 +1163,9 @@ function Le(e) {
1162
1163
  for (const i of h) {
1163
1164
  if (i === "dark" || ne.includes(i) || i.startsWith("@") && (ie.includes(i.slice(1)) || i.match(/^@\[.+\]$/)))
1164
1165
  continue;
1165
- const y = _e(i);
1166
- if (y) {
1167
- S = y;
1166
+ const $ = _e(i);
1167
+ if ($) {
1168
+ S = $;
1168
1169
  continue;
1169
1170
  }
1170
1171
  const F = d[i];
@@ -1176,8 +1177,8 @@ function Le(e) {
1176
1177
  typeof E == "function" && (l = E(l, _).split("{")[0]);
1177
1178
  }
1178
1179
  const D = W.join(""), L = V.join("");
1179
- function Q(i, y) {
1180
- if (!y) return i;
1180
+ function Q(i, $) {
1181
+ if (!$) return i;
1181
1182
  let F = 0, E = 0;
1182
1183
  if (i.length && (i[0] === ">" || i[0] === "+" || i[0] === "~" || i[0] === " ")) {
1183
1184
  let j = 1;
@@ -1185,30 +1186,30 @@ function Le(e) {
1185
1186
  for (; j < i.length; j++) {
1186
1187
  const z = i[j];
1187
1188
  if (z === "[" ? F++ : z === "]" && F > 0 ? F-- : z === "(" ? E++ : z === ")" && E > 0 && E--, F === 0 && E === 0 && (i[j] === ">" || i[j] === "+" || i[j] === "~" || i[j] === " "))
1188
- return i.slice(0, j) + y + i.slice(j);
1189
+ return i.slice(0, j) + $ + i.slice(j);
1189
1190
  }
1190
- return i + y;
1191
+ return i + $;
1191
1192
  }
1192
1193
  for (let j = 0; j < i.length; j++) {
1193
1194
  const z = i[j];
1194
1195
  if (z === "[" ? F++ : z === "]" && F > 0 ? F-- : z === "(" ? E++ : z === ")" && E > 0 && E--, F === 0 && E === 0 && (z === ">" || z === "+" || z === "~" || z === " "))
1195
- return i.slice(0, j) + y + i.slice(j);
1196
+ return i.slice(0, j) + $ + i.slice(j);
1196
1197
  }
1197
- return i + y;
1198
+ return i + $;
1198
1199
  }
1199
1200
  if (S)
1200
1201
  if (S.includes("&")) {
1201
- const i = S.indexOf("&"), y = S.slice(0, i), F = S.slice(i + 1), E = w + D;
1202
+ const i = S.indexOf("&"), $ = S.slice(0, i), F = S.slice(i + 1), E = w + D;
1202
1203
  if (W.length === 0)
1203
1204
  l = l.replace(
1204
1205
  w,
1205
- y + E + L + F
1206
+ $ + E + L + F
1206
1207
  );
1207
1208
  else {
1208
1209
  const j = Q(F, L);
1209
1210
  l = l.replace(
1210
1211
  w,
1211
- y + E + j
1212
+ $ + E + j
1212
1213
  );
1213
1214
  }
1214
1215
  } else
@@ -1416,7 +1417,7 @@ function Ne(e, r) {
1416
1417
  name: t,
1417
1418
  enterFrom: a,
1418
1419
  enterActive: d,
1419
- enterTo: $,
1420
+ enterTo: y,
1420
1421
  leaveFrom: v,
1421
1422
  leaveActive: C,
1422
1423
  leaveTo: A,
@@ -1430,15 +1431,15 @@ function Ne(e, r) {
1430
1431
  onLeaveCancelled: T
1431
1432
  } = e;
1432
1433
  let h;
1433
- o && X[o] ? (h = { ...X[o] }, a && (h.enterFrom = a), d && (h.enterActive = d), $ && (h.enterTo = $), v && (h.leaveFrom = v), C && (h.leaveActive = C), A && (h.leaveTo = A)) : h = {
1434
+ o && X[o] ? (h = { ...X[o] }, a && (h.enterFrom = a), d && (h.enterActive = d), y && (h.enterTo = y), v && (h.leaveFrom = v), C && (h.leaveActive = C), A && (h.leaveTo = A)) : h = {
1434
1435
  enterFrom: a,
1435
1436
  enterActive: d,
1436
- enterTo: $,
1437
+ enterTo: y,
1437
1438
  leaveFrom: v,
1438
1439
  leaveActive: C,
1439
1440
  leaveTo: A
1440
1441
  };
1441
- const R = t || (o ? `transition-${o}` : "transition"), _ = ye(n ? r : [], R);
1442
+ const R = t || (o ? `transition-${o}` : "transition"), _ = $e(n ? r : [], R);
1442
1443
  return _._transition = {
1443
1444
  name: R,
1444
1445
  classes: h,
@@ -1470,7 +1471,7 @@ function Be(e, r) {
1470
1471
  appear: t = !1,
1471
1472
  css: a = !0,
1472
1473
  name: d,
1473
- class: $,
1474
+ class: y,
1474
1475
  style: v,
1475
1476
  enterFrom: C,
1476
1477
  enterActive: A,
@@ -1526,7 +1527,7 @@ function Be(e, r) {
1526
1527
  key: P,
1527
1528
  props: {
1528
1529
  attrs: {
1529
- ...$ ? { class: $ } : {},
1530
+ ...y ? { class: y } : {},
1530
1531
  ...V ? { style: V } : {}
1531
1532
  },
1532
1533
  _transitionGroup: {
@@ -1603,4 +1604,4 @@ export {
1603
1604
  De as s,
1604
1605
  X as t
1605
1606
  };
1606
- //# sourceMappingURL=transitions-m6FraTTL.js.map
1607
+ //# sourceMappingURL=transitions-DCIjMqzG.js.map