@jasonshimmy/custom-elements-runtime 2.2.2 → 2.2.4
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/custom-elements-runtime.cjs.js +10 -10
- package/dist/custom-elements-runtime.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.es.js +1888 -1780
- package/dist/custom-elements-runtime.es.js.map +1 -1
- package/dist/custom-elements-runtime.router.cjs.js +3 -3
- package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.router.es.js +1 -1
- package/dist/custom-elements-runtime.ssr.cjs.js +1 -1
- package/dist/custom-elements-runtime.ssr.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.ssr.es.js +12 -10
- package/dist/custom-elements-runtime.ssr.es.js.map +1 -1
- package/dist/{helpers-D3UjNfYY.cjs → namespace-helpers-DwMMXN9Q.cjs} +3 -3
- package/dist/namespace-helpers-DwMMXN9Q.cjs.map +1 -0
- package/dist/{helpers-CDfJhmMS.js → namespace-helpers-Vwt2Fzds.js} +97 -55
- package/dist/namespace-helpers-Vwt2Fzds.js.map +1 -0
- package/dist/runtime/event-manager.d.ts +6 -6
- package/dist/runtime/namespace-helpers.d.ts +17 -0
- package/dist/runtime/node-metadata.d.ts +2 -2
- package/dist/runtime/types.d.ts +2 -2
- package/dist/runtime/vdom-model-helpers.d.ts +2 -2
- package/dist/runtime/vdom-ssr.d.ts +7 -1
- package/dist/runtime/vdom.d.ts +5 -5
- package/dist/ssr.d.ts +21 -0
- package/package.json +1 -1
- package/dist/helpers-CDfJhmMS.js.map +0 -1
- package/dist/helpers-D3UjNfYY.cjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./custom-elements-runtime.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("./custom-elements-runtime.cjs.js"),m=require("./namespace-helpers-DwMMXN9Q.cjs"),W=require("./custom-elements-runtime.store.cjs.js"),h=require("./logger-CqdBMdui.cjs"),B=require("./custom-elements-runtime.directives.cjs.js"),P=s=>s?typeof URLSearchParams>"u"?{}:Object.fromEntries(new URLSearchParams(s)):{},E=(s,o)=>{for(const e of s){const f=[],u=e.path.replace(/:[^/]+/g,l=>(f.push(l.slice(1)),"([^/]+)")),i=new RegExp(`^${u}$`),c=o.match(i);if(c){const l={};return f.forEach((d,v)=>{l[d]=c[v+1]}),{route:e,params:l}}}return{route:null,params:{}}};function x(s,o){for(const e of s)if(E([e],o).route!==null)return e;return null}const O={};async function N(s){if(s.component)return s.component;if(s.load){if(O[s.path])return O[s.path];try{const o=await s.load();return O[s.path]=o.default,o.default}catch{throw new Error(`Failed to load component for route: ${s.path}`)}}throw new Error(`No component or loader defined for route: ${s.path}`)}function A(s){const{routes:o,base:e="",initialUrl:f}=s;let u,i,c,l,d,v,y;const C=async(n,a)=>{const t=x(o,n.path);if(!t||!t.beforeEnter)return!0;try{const r=await t.beforeEnter(n,a);return typeof r=="string"?(await w(r,!0),!1):r!==!1}catch(r){return h.devError("beforeEnter error",r),!1}},R=async(n,a)=>{const t=x(o,n.path);if(!t||!t.onEnter)return!0;try{const r=await t.onEnter(n,a);return typeof r=="string"?(await w(r,!0),!1):r!==!1}catch(r){return h.devError("onEnter error",r),!1}},k=(n,a)=>{const t=x(o,n.path);if(!(!t||!t.afterEnter))try{t.afterEnter(n,a)}catch(r){h.devError("afterEnter error",r)}},w=async(n,a=!1)=>{try{const t={path:n.replace(e,"")||"/",query:{}},r=E(o,t.path);if(!r.route)throw new Error(`No route found for ${t.path}`);const b=c.getState(),g={path:t.path,params:r.params,query:t.query};if(!await C(g,b)||!await R(g,b))return;typeof window<"u"&&typeof document<"u"&&(a?window.history.replaceState({},"",e+n):window.history.pushState({},"",e+n)),c.setState(g),k(g,b)}catch(t){h.devError("Navigation error:",t)}};if(typeof window<"u"&&typeof document<"u"&&typeof f>"u"){u=()=>{const a=new URL(window.location.href),t=a.pathname.replace(e,"")||"/",r=P(a.search);return{path:t,query:r}},i=u();const n=E(o,i.path);c=W.createStore({path:i.path,params:n.params,query:i.query}),l=async(a=!1)=>{const t=u();await w(t.path,a)},window.addEventListener("popstate",()=>l(!0)),d=a=>w(a,!1),v=a=>w(a,!0),y=()=>window.history.back()}else{u=()=>{const t=new URL(f||"/","http://localhost"),r=t.pathname.replace(e,"")||"/",b=P(t.search);return{path:r,query:b}},i=u();const n=E(o,i.path);c=W.createStore({path:i.path,params:n.params,query:i.query}),l=async()=>{const t=u();await a(t.path)};const a=async t=>{try{const r={path:t.replace(e,"")||"/",query:{}},b=E(o,r.path);if(!b.route)throw new Error(`No route found for ${r.path}`);const g=c.getState(),q={path:r.path,params:b.params,query:r.query},S=x(o,q.path);if(S?.beforeEnter){const $=await S.beforeEnter(q,g);if(typeof $=="string"){await a($);return}if($===!1)return}if(S?.onEnter){const $=await S.onEnter(q,g);if(typeof $=="string"){await a($);return}if($===!1)return}c.setState(q),S?.afterEnter&&S.afterEnter(q,g)}catch(r){throw h.devError("SSR navigation error:",r),r}};d=async t=>a(t),v=async t=>a(t),y=()=>{}}return{store:c,push:d,replace:v,back:y,subscribe:c.subscribe,matchRoute:n=>E(o,n),getCurrent:()=>c.getState(),resolveRouteComponent:N}}function D(s,o){return E(s,o)}let L=null;function U(s){const o=A(s);return L=o,p.component("router-view",async()=>{const e=L||o;if(!e)return p.html`<div>Router not initialized.</div>`;const f=m.ref(e.getCurrent());let u;p.useOnConnected(()=>{try{e&&typeof e.subscribe=="function"&&(u=e.subscribe(c=>{try{f.value=c}catch(l){h.devWarn("router-view subscription update failed",l)}}))}catch(c){h.devWarn("router-view subscribe failed",c)}}),p.useOnDisconnected(()=>{if(typeof u=="function")try{u()}catch(c){h.devWarn("router-view unsubscribe failed",c)}});const i=e.matchRoute(f.value.path);if(!i||!i.route)return p.html`<div>Not found</div>`;try{const l=await e.resolveRouteComponent(i.route);if(typeof l=="string")return{tag:l,props:{},children:[]};if(typeof l=="function"){const d=l();return(d instanceof Promise?d:Promise.resolve(d)).then(y=>typeof y=="string"?{tag:y,props:{},children:[]}:y)}return p.html`<div>Invalid route component</div>`}catch{return p.html`<div>Invalid route component</div>`}}),p.component("router-link",()=>{const e=p.useProps({to:"",tag:"a",replace:!1,exact:!1,activeClass:"active",exactActiveClass:"exact-active",ariaCurrentValue:"page",disabled:!1,external:!1,linkClass:"",linkStyle:""}),f=L||o,u=m.ref(f.getCurrent());let i;p.useStyle(()=>"a,button{display:inline-block;}"+e.linkStyle),p.useOnConnected(()=>{try{f&&typeof f.subscribe=="function"&&(i=f.subscribe(n=>{try{u.value=n}catch(a){h.devWarn("router-link subscription update failed",a)}}))}catch(n){h.devWarn("router-link subscribe failed",n)}}),p.useOnDisconnected(()=>{if(typeof i=="function")try{i()}catch(n){h.devWarn("router-link unsubscribe failed",n)}});const c=m.computed(()=>u.value.path===e.to),l=m.computed(()=>e.exact?c.value:u.value&&typeof u.value.path=="string"?u.value.path.startsWith(e.to):!1),d=m.computed(()=>{const a=(e.linkClass||"").split(/\s+/).filter(Boolean),t={};for(const r of a)t[r]=!0;return t}),v=m.computed(()=>({...d.value,[e.activeClass||"active"]:l.value,[e.exactActiveClass||"exact-active"]:c.value})),y=m.computed(()=>e.tag==="button"),C=m.computed(()=>c.value?e.ariaCurrentValue:""),R=m.computed(()=>!!e.disabled),k=m.computed(()=>!!e.external&&(e.tag==="a"||!e.tag)),w=n=>{if(e.disabled){n.preventDefault();return}e.external&&(e.tag==="a"||!e.tag)||(n.preventDefault(),e.replace?f.replace(e.to):f.push(e.to))};return p.html`
|
|
2
2
|
${B.match().when(y.value,p.html`
|
|
3
3
|
<button
|
|
4
4
|
part="button"
|
|
5
|
-
:class="${
|
|
5
|
+
:class="${v.value}"
|
|
6
6
|
aria-current="${C.value}"
|
|
7
7
|
disabled="${R.value?"":null}"
|
|
8
8
|
aria-disabled="${R.value?"true":null}"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<a
|
|
16
16
|
part="link"
|
|
17
17
|
href="${e.to}"
|
|
18
|
-
:class="${
|
|
18
|
+
:class="${v.value}"
|
|
19
19
|
aria-current="${C.value}"
|
|
20
20
|
aria-disabled="${R.value?"true":null}"
|
|
21
21
|
tabindex="${R.value?"-1":null}"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-elements-runtime.router.cjs.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","s","e","devWarn","useOnDisconnected","comp","out","resolvedComp","props","useProps","unsubRouterLink","useStyle","isExactActive","computed","isActive","userClasses","list","map","c","classObject","isButton","ariaCurrentValue","isDisabled","isExternal"],"mappings":"wTAwFaA,EAAcC,GACpBA,EACD,OAAO,gBAAoB,IAAoB,CAAA,EAC5C,OAAO,YAAY,IAAI,gBAAgBA,CAAM,CAAC,EAFjC,CAAA,EAKTC,EAAa,CACxBC,EACAC,IAC4D,CAC5D,UAAWC,KAASF,EAAQ,CAC1B,MAAMG,EAAuB,CAAA,EACvBC,EAAYF,EAAM,KAAK,QAAQ,UAAYG,IAC/CF,EAAW,KAAKE,EAAE,MAAM,CAAC,CAAC,EACnB,UACR,EACKC,EAAQ,IAAI,OAAO,IAAIF,CAAS,GAAG,EACnCG,EAAQN,EAAK,MAAMK,CAAK,EAC9B,GAAIC,EAAO,CACT,MAAMC,EAAiC,CAAA,EACvC,OAAAL,EAAW,QAAQ,CAACM,EAAMC,IAAM,CAC9BF,EAAOC,CAAI,EAAIF,EAAMG,EAAI,CAAC,CAC5B,CAAC,EACM,CAAE,MAAAR,EAAO,OAAAM,CAAA,CAClB,CACF,CACA,MAAO,CAAE,MAAO,KAAM,OAAQ,CAAA,CAAC,CACjC,EAMA,SAASG,EAAiBX,EAAiBC,EAA4B,CACrE,UAAWW,KAAKZ,EACd,GAAID,EAAW,CAACa,CAAC,EAAGX,CAAI,EAAE,QAAU,KAAM,OAAOW,EAEnD,OAAO,IACT,CAGA,MAAMC,EAGF,CAAA,EAOJ,eAAsBC,EACpBZ,EACmE,CACnE,GAAIA,EAAM,UAAW,OAAOA,EAAM,UAClC,GAAIA,EAAM,KAAM,CACd,GAAIW,EAAeX,EAAM,IAAI,EAAG,OAAOW,EAAeX,EAAM,IAAI,EAChE,GAAI,CACF,MAAMa,EAAM,MAAMb,EAAM,KAAA,EACxB,OAAAW,EAAeX,EAAM,IAAI,EAAIa,EAAI,QAC1BA,EAAI,OACb,MAAQ,CACN,MAAM,IAAI,MAAM,uCAAuCb,EAAM,IAAI,EAAE,CACrE,CACF,CACA,MAAM,IAAI,MAAM,6CAA6CA,EAAM,IAAI,EAAE,CAC3E,CAEO,SAASc,EAAUC,EAAsB,CAC9C,KAAM,CAAE,OAAAjB,EAAQ,KAAAkB,EAAO,GAAI,WAAAC,GAAeF,EAE1C,IAAIG,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EAGJ,MAAMC,EAAiB,MAAOC,EAAgBC,IAAqB,CACjE,MAAMC,EAAUnB,EAAiBX,EAAQ4B,EAAG,IAAI,EAChD,GAAI,CAACE,GAAW,CAACA,EAAQ,YAAa,MAAO,GAC7C,GAAI,CACF,MAAMC,EAAS,MAAMD,EAAQ,YAAYF,EAAIC,CAAI,EACjD,OAAI,OAAOE,GAAW,UAEpB,MAAMC,EAASD,EAAQ,EAAI,EACpB,IAEFA,IAAW,EACpB,OAASE,EAAK,CACZC,OAAAA,EAAAA,SAAS,oBAAqBD,CAAG,EAC1B,EACT,CACF,EAEME,EAAa,MAAOP,EAAgBC,IAAqB,CAC7D,MAAMC,EAAUnB,EAAiBX,EAAQ4B,EAAG,IAAI,EAChD,GAAI,CAACE,GAAW,CAACA,EAAQ,QAAS,MAAO,GACzC,GAAI,CACF,MAAMC,EAAS,MAAMD,EAAQ,QAAQF,EAAIC,CAAI,EAC7C,OAAI,OAAOE,GAAW,UACpB,MAAMC,EAASD,EAAQ,EAAI,EACpB,IAEFA,IAAW,EACpB,OAASE,EAAK,CACZC,OAAAA,EAAAA,SAAS,gBAAiBD,CAAG,EACtB,EACT,CACF,EAEMG,EAAgB,CAACR,EAAgBC,IAAqB,CAC1D,MAAMC,EAAUnB,EAAiBX,EAAQ4B,EAAG,IAAI,EAChD,GAAI,GAACE,GAAW,CAACA,EAAQ,YACzB,GAAI,CACFA,EAAQ,WAAWF,EAAIC,CAAI,CAC7B,OAASI,EAAK,CACZC,EAAAA,SAAS,mBAAoBD,CAAG,CAClC,CACF,EAEMD,EAAW,MAAO/B,EAAcoC,EAAU,KAAU,CACxD,GAAI,CACF,MAAMC,EAAM,CACV,KAAMrC,EAAK,QAAQiB,EAAM,EAAE,GAAK,IAChC,MAAO,CAAA,CAAC,EAEJX,EAAQR,EAAWC,EAAQsC,EAAI,IAAI,EACzC,GAAI,CAAC/B,EAAM,MAAO,MAAM,IAAI,MAAM,sBAAsB+B,EAAI,IAAI,EAAE,EAElE,MAAMT,EAAOP,EAAM,SAAA,EACbM,EAAiB,CACrB,KAAMU,EAAI,KACV,OAAQ/B,EAAM,OACd,MAAO+B,EAAI,KAAA,EASb,GAJI,CADkB,MAAMX,EAAeC,EAAIC,CAAI,GAK/C,CADc,MAAMM,EAAWP,EAAIC,CAAI,EAC3B,OAEZ,OAAO,OAAW,KAAe,OAAO,SAAa,MACnDQ,EACF,OAAO,QAAQ,aAAa,CAAA,EAAI,GAAInB,EAAOjB,CAAI,EAE/C,OAAO,QAAQ,UAAU,CAAA,EAAI,GAAIiB,EAAOjB,CAAI,GAIhDqB,EAAM,SAASM,CAAE,EAGjBQ,EAAcR,EAAIC,CAAI,CACxB,OAASI,EAAK,CACZC,EAAAA,SAAS,oBAAqBD,CAAG,CACnC,CACF,EAKA,GACE,OAAO,OAAW,KAClB,OAAO,SAAa,KACpB,OAAOd,EAAe,IACtB,CAEAC,EAAc,IAAM,CAClB,MAAMmB,EAAM,IAAI,IAAI,OAAO,SAAS,IAAI,EAClCtC,EAAOsC,EAAI,SAAS,QAAQrB,EAAM,EAAE,GAAK,IACzCsB,EAAQ3C,EAAW0C,EAAI,MAAM,EACnC,MAAO,CAAE,KAAAtC,EAAM,MAAAuC,CAAA,CACjB,EAEAnB,EAAUD,EAAA,EACV,MAAMb,EAAQR,EAAWC,EAAQqB,EAAQ,IAAI,EAC7CC,EAAQmB,EAAAA,YAAwB,CAC9B,KAAMpB,EAAQ,KACd,OAAQd,EAAM,OACd,MAAOc,EAAQ,KAAA,CAChB,EAEDE,EAAS,MAAOc,EAAU,KAAU,CAClC,MAAMC,EAAMlB,EAAA,EACZ,MAAMY,EAASM,EAAI,KAAMD,CAAO,CAClC,EAEA,OAAO,iBAAiB,WAAY,IAAMd,EAAO,EAAI,CAAC,EAEtDC,EAAQvB,GAAiB+B,EAAS/B,EAAM,EAAK,EAC7CwB,EAAaxB,GAAiB+B,EAAS/B,EAAM,EAAI,EACjDyB,EAAO,IAAM,OAAO,QAAQ,KAAA,CAC9B,KAAO,CAELN,EAAc,IAAM,CAClB,MAAMmB,EAAM,IAAI,IAAIpB,GAAc,IAAK,kBAAkB,EACnDlB,EAAOsC,EAAI,SAAS,QAAQrB,EAAM,EAAE,GAAK,IACzCsB,EAAQ3C,EAAW0C,EAAI,MAAM,EACnC,MAAO,CAAE,KAAAtC,EAAM,MAAAuC,CAAA,CACjB,EAEAnB,EAAUD,EAAA,EACV,MAAMb,EAAQR,EAAWC,EAAQqB,EAAQ,IAAI,EAC7CC,EAAQmB,EAAAA,YAAwB,CAC9B,KAAMpB,EAAQ,KACd,OAAQd,EAAM,OACd,MAAOc,EAAQ,KAAA,CAChB,EAEDE,EAAS,SAAY,CACnB,MAAMe,EAAMlB,EAAA,EACZ,MAAMsB,EAAYJ,EAAI,IAAI,CAC5B,EAYA,MAAMI,EAAc,MAAOzC,GAAiB,CAC1C,GAAI,CACF,MAAMqC,EAAM,CACV,KAAMrC,EAAK,QAAQiB,EAAM,EAAE,GAAK,IAChC,MAAO,CAAA,CAAC,EAEJX,EAAQR,EAAWC,EAAQsC,EAAI,IAAI,EAIzC,GAAI,CAAC/B,EAAM,MAAO,MAAM,IAAI,MAAM,sBAAsB+B,EAAI,IAAI,EAAE,EAElE,MAAMT,EAAOP,EAAM,SAAA,EACbM,EAAiB,CACrB,KAAMU,EAAI,KACV,OAAQ/B,EAAM,OACd,MAAO+B,EAAI,KAAA,EAIPR,EAAUnB,EAAiBX,EAAQ4B,EAAG,IAAI,EAChD,GAAIE,GAAS,YAAa,CACxB,MAAMC,EAAS,MAAMD,EAAQ,YAAYF,EAAIC,CAAI,EACjD,GAAI,OAAOE,GAAW,SAAU,CAE9B,MAAMW,EAAYX,CAAM,EACxB,MACF,CACA,GAAIA,IAAW,GAAO,MACxB,CAGA,GAAID,GAAS,QAAS,CACpB,MAAMC,EAAS,MAAMD,EAAQ,QAAQF,EAAIC,CAAI,EAC7C,GAAI,OAAOE,GAAW,SAAU,CAC9B,MAAMW,EAAYX,CAAM,EACxB,MACF,CACA,GAAIA,IAAW,GAAO,MACxB,CAEAT,EAAM,SAASM,CAAE,EAGbE,GAAS,YACXA,EAAQ,WAAWF,EAAIC,CAAI,CAE/B,OAASI,EAAK,CAGZC,MAAAA,EAAAA,SAAS,wBAAyBD,CAAG,EAC/BA,CACR,CACF,EAEAT,EAAO,MAAOvB,GAAiByC,EAAYzC,CAAI,EAC/CwB,EAAY,MAAOxB,GAAiByC,EAAYzC,CAAI,EACpDyB,EAAO,IAAM,CAAC,CAChB,CAEA,MAAO,CAAA,MACLJ,EACA,KAAAE,EACA,QAASC,EACT,KAAAC,EACA,UAAWJ,EAAM,UACjB,WAAarB,GAAiBF,EAAWC,EAAQC,CAAI,EACrD,WAAY,IAAkBqB,EAAM,SAAA,EACpC,sBAAAR,CAAA,CAEJ,CAGO,SAAS6B,EAAc3C,EAAiBC,EAAc,CAC3D,OAAOF,EAAWC,EAAQC,CAAI,CAChC,CAKA,IAAI2C,EAAoD,KASjD,SAASC,EAAW5B,EAAsB,CAC/C,MAAM6B,EAAS9B,EAAUC,CAAM,EAK/B,OAAA2B,EAAeE,EAEfC,EAAAA,UAAU,cAAe,SAAY,CAGnC,MAAMnC,EAAIgC,GAAgBE,EAE1B,GAAI,CAAClC,EAAG,OAAOoC,EAAAA,yCAEf,MAAMC,EAAUC,EAAAA,IAAItC,EAAE,WAAA,CAAY,EAKlC,IAAIuC,EAEJC,EAAAA,eAAe,IAAM,CACnB,GAAI,CACExC,GAAK,OAAOA,EAAE,WAAc,aAC9BuC,EAAkBvC,EAAE,UAAWyC,GAAM,CACnC,GAAI,CACFJ,EAAQ,MAAQI,CAClB,OAASC,EAAG,CACVC,EAAAA,QAAQ,yCAA0CD,CAAC,CACrD,CACF,CAAC,EAEL,OAASA,EAAG,CACVC,EAAAA,QAAQ,+BAAgCD,CAAC,CAC3C,CACF,CAAC,EAEDE,EAAAA,kBAAkB,IAAM,CACtB,GAAI,OAAOL,GAAoB,WAC7B,GAAI,CACFA,EAAA,CACF,OAASG,EAAG,CACVC,EAAAA,QAAQ,iCAAkCD,CAAC,CAC7C,CAEJ,CAAC,EAED,MAAM/C,EAAQK,EAAE,WAAWqC,EAAQ,MAAM,IAAI,EAC7C,GAAI,CAAC1C,GAAS,CAACA,EAAM,MAAO,OAAOyC,EAAAA,2BAGnC,GAAI,CAEF,MAAMS,EADU,MAAM7C,EAAE,sBAAsBL,EAAM,KAAK,EAOzD,GAAI,OAAOkD,GAAS,SAClB,MAAO,CAAE,IAAKA,EAAM,MAAO,CAAA,EAAI,SAAU,EAAC,EAI5C,GAAI,OAAOA,GAAS,WAAY,CAC9B,MAAMC,EAAMD,EAAA,EAEZ,OADiBC,aAAe,QAAUA,EAAM,QAAQ,QAAQA,CAAG,GACnD,KAAMC,GAChB,OAAOA,GAAiB,SACnB,CAAE,IAAKA,EAAc,MAAO,CAAA,EAAI,SAAU,EAAC,EAC7CA,CACR,CACH,CAEA,OAAOX,EAAAA,wCACT,MAAQ,CACN,OAAOA,EAAAA,wCACT,CACF,CAAC,EAEDD,EAAAA,UAAU,cAAe,IAAM,CAE7B,MAAMa,EAAQC,EAAAA,SAAmC,CAC/C,GAAI,GACJ,IAAK,IACL,QAAS,GACT,MAAO,GACP,YAAa,SACb,iBAAkB,eAClB,iBAAkB,OAClB,SAAU,GACV,SAAU,GACV,UAAW,GACX,UAAW,EAAA,CACZ,EAIKjD,EAAIgC,GAAgBE,EAEpBG,EAAUC,EAAAA,IAAItC,EAAE,WAAA,CAAY,EAGlC,IAAIkD,EAEJC,EAAAA,SACE,IAAO,kCAAoCH,EAAM,SAAA,EAGnDR,EAAAA,eAAe,IAAM,CACnB,GAAI,CACExC,GAAK,OAAOA,EAAE,WAAc,aAC9BkD,EAAkBlD,EAAE,UAAWyC,GAAM,CACnC,GAAI,CACFJ,EAAQ,MAAQI,CAClB,OAASC,EAAG,CACVC,EAAAA,QAAQ,yCAA0CD,CAAC,CACrD,CACF,CAAC,EAEL,OAASA,EAAG,CACVC,EAAAA,QAAQ,+BAAgCD,CAAC,CAC3C,CACF,CAAC,EAEDE,EAAAA,kBAAkB,IAAM,CACtB,GAAI,OAAOM,GAAoB,WAC7B,GAAI,CACFA,EAAA,CACF,OAASR,EAAG,CACVC,EAAAA,QAAQ,iCAAkCD,CAAC,CAC7C,CAEJ,CAAC,EAED,MAAMU,EAAgBC,EAAAA,SACpB,IAAMhB,EAAQ,MAAM,OAAUW,EAAM,EAAA,EAEhCM,EAAWD,EAAAA,SAAS,IACxBL,EAAM,MACFI,EAAc,MACdf,EAAQ,OAAS,OAAOA,EAAQ,MAAM,MAAS,SAC7CA,EAAQ,MAAM,KAAK,WAAWW,EAAM,EAAY,EAChD,EAAA,EAMFO,EAAcF,EAAAA,SAAS,IAAM,CAEjC,MAAMG,GADOR,EAAM,WAAwB,IAC1B,MAAM,KAAK,EAAE,OAAO,OAAO,EACtCS,EAA+B,CAAA,EACrC,UAAWC,KAAKF,EAAMC,EAAIC,CAAC,EAAI,GAC/B,OAAOD,CACT,CAAC,EAEKE,EAAcN,EAAAA,SAAS,KAAO,CAClC,GAAGE,EAAY,MACf,CAAEP,EAAM,aAA0B,QAAQ,EAAGM,EAAS,MACtD,CAAEN,EAAM,kBAA+B,cAAc,EACnDI,EAAc,KAAA,EAChB,EAEIQ,EAAWP,EAAAA,SAAS,IAAOL,EAAM,MAAmB,QAAQ,EAK5Da,EAAmBR,EAAAA,SAAS,IAChCD,EAAc,MAASJ,EAAM,iBAA8B,EAAA,EAEvDc,EAAaT,EAAAA,SAAS,IAAM,CAAC,CAACL,EAAM,QAAQ,EAC5Ce,EAAaV,EAAAA,SACjB,IACE,CAAC,CAACL,EAAM,WACNA,EAAM,MAAmB,KAAO,CAAEA,EAAM,IAAA,EAGxC5B,EAAYsB,GAAkB,CAClC,GAAIM,EAAM,SAAU,CAClBN,EAAE,eAAA,EACF,MACF,CAEEM,EAAM,WACJA,EAAM,MAAmB,KAAO,CAAEA,EAAM,OAI5CN,EAAE,eAAA,EACEM,EAAM,QACRhD,EAAE,QAAQgD,EAAM,EAAY,EAE5BhD,EAAE,KAAKgD,EAAM,EAAY,EAE7B,EAEA,OAAOZ,EAAAA;AAAAA,QACHzC,EAAAA,QACC,KACCiE,EAAS,MACTxB,EAAAA;AAAAA;AAAAA;AAAAA,wBAGcuB,EAAY,KAAK;AAAA,8BACXE,EAAiB,KAAK;AAAA,0BAC1BC,EAAW,MAAQ,GAAK,IAAI;AAAA,+BACvBA,EAAW,MAAQ,OAAS,IAAI;AAAA,0BACrCA,EAAW,MAAQ,KAAO,IAAI;AAAA,wBAChC1C,CAAQ;AAAA;AAAA;AAAA;AAAA,WAAA,EAMvB,UAAUgB,EAAAA;AAAAA;AAAAA;AAAAA,oBAGCY,EAAM,EAAE;AAAA,sBACNW,EAAY,KAAK;AAAA,4BACXE,EAAiB,KAAK;AAAA,6BACrBC,EAAW,MAAQ,OAAS,IAAI;AAAA,wBACrCA,EAAW,MAAQ,KAAO,IAAI;AAAA,sBAChCC,EAAW,MAAQ,SAAW,IAAI;AAAA,mBACrCA,EAAW,MAAQ,sBAAwB,IAAI;AAAA,sBAC5C3C,CAAQ;AAAA;AAAA;AAAA,SAGrB,EACA,MAAM;AAAA,KAEb,CAAC,EAEMc,CACT"}
|
|
1
|
+
{"version":3,"file":"custom-elements-runtime.router.cjs.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","s","e","devWarn","useOnDisconnected","comp","out","resolvedComp","props","useProps","unsubRouterLink","useStyle","isExactActive","computed","isActive","userClasses","list","map","c","classObject","isButton","ariaCurrentValue","isDisabled","isExternal"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { component as P, html as R, useOnConnected as A, useOnDisconnected as B, useProps as j, useStyle as F } from "./custom-elements-runtime.es.js";
|
|
2
|
-
import { r as U, c as w } from "./helpers-
|
|
2
|
+
import { r as U, c as w } from "./namespace-helpers-Vwt2Fzds.js";
|
|
3
3
|
import { createStore as D } from "./custom-elements-runtime.store.es.js";
|
|
4
4
|
import { d as k, a as x } from "./logger-BpibrmKL.js";
|
|
5
5
|
import { match as I } from "./custom-elements-runtime.directives.es.js";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./namespace-helpers-DwMMXN9Q.cjs");function s(r,c){if(typeof r=="string")return i.escapeHTML(r);if(r.tag==="#text")return typeof r.children=="string"?i.escapeHTML(r.children):"";if(r.tag==="#anchor")return(Array.isArray(r.children)?r.children.filter(n=>n!=null):[]).map(n=>s(n,c)).join("");if(r.tag==="#raw")return typeof r.children=="string"?r.children:"";let e={};r.props&&r.props.attrs&&(e={...r.props.attrs});const a=c?.injectSvgNamespace??!0,l=c?.injectKnownNamespaces??a;a&&r.tag==="svg"&&!("xmlns"in e)?e.xmlns=i.SVG_NS:l&&r.tag in i.TAG_NAMESPACE_MAP&&!("xmlns"in e)&&(e.xmlns=i.TAG_NAMESPACE_MAP[r.tag]);const g=Object.entries(e).map(([t,n])=>` ${t}="${i.escapeHTML(String(n))}"`).join(""),p=Array.isArray(r.children)?r.children.filter(t=>t!=null).map(t=>s(t,c)).join(""):typeof r.children=="string"?i.escapeHTML(r.children):r.children?s(r.children):"";return`<${r.tag}${g}>${p}</${r.tag}>`}exports.renderToString=s;
|
|
2
2
|
//# sourceMappingURL=custom-elements-runtime.ssr.cjs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-elements-runtime.ssr.cjs.js","sources":["../src/lib/runtime/vdom-ssr.ts"],"sourcesContent":["import type { VNode } from './types';\nimport { escapeHTML } from './helpers';\n\n/**\n * Render a VNode to a string (SSR).\n * Kept intentionally minimal: only serializes attributes under `props.attrs`\n * to avoid leaking runtime-only values (functions, reactive state, directives).\n * @param vnode The virtual node to render.\n * @returns The rendered HTML string.\n */\nexport function renderToString(vnode: VNode): string {\n if (typeof vnode === 'string') return escapeHTML(vnode) as string;\n\n if (vnode.tag === '#text') {\n return typeof vnode.children === 'string'\n ? (escapeHTML(vnode.children) as string)\n : '';\n }\n\n if (vnode.tag === '#anchor') {\n // Preserve meaningful falsy children (0, false, '') while filtering out\n // only null and undefined. Anchor blocks are normalized by the compiler\n // to exclude null/undefined; SSR should follow the same rule to avoid\n // hydration mismatches where falsy values are significant.\n const children = Array.isArray(vnode.children)\n ? vnode.children.filter((c) => c !== null && c !== undefined)\n : [];\n return children.map(renderToString).join('');\n }\n\n if (vnode.tag === '#raw') {\n return typeof vnode.children === 'string' ? vnode.children : '';\n }\n\n // Collect attributes from props.attrs\n let
|
|
1
|
+
{"version":3,"file":"custom-elements-runtime.ssr.cjs.js","sources":["../src/lib/runtime/vdom-ssr.ts"],"sourcesContent":["import type { VNode } from './types';\nimport { escapeHTML } from './helpers';\nimport { TAG_NAMESPACE_MAP, SVG_NS } from './namespace-helpers';\n\n/**\n * Render a VNode to a string (SSR).\n * Kept intentionally minimal: only serializes attributes under `props.attrs`\n * to avoid leaking runtime-only values (functions, reactive state, directives).\n * @param vnode The virtual node to render.\n * @returns The rendered HTML string.\n */\nexport type RenderOptions = {\n /** Backwards-compatible: whether to inject the SVG namespace on <svg> nodes (default true) */\n injectSvgNamespace?: boolean;\n /** Inject known well-known namespaces for tags like <math> when missing (default follows injectSvgNamespace) */\n injectKnownNamespaces?: boolean;\n};\n\nexport function renderToString(vnode: VNode, opts?: RenderOptions): string {\n if (typeof vnode === 'string') return escapeHTML(vnode) as string;\n\n if (vnode.tag === '#text') {\n return typeof vnode.children === 'string'\n ? (escapeHTML(vnode.children) as string)\n : '';\n }\n\n if (vnode.tag === '#anchor') {\n // Preserve meaningful falsy children (0, false, '') while filtering out\n // only null and undefined. Anchor blocks are normalized by the compiler\n // to exclude null/undefined; SSR should follow the same rule to avoid\n // hydration mismatches where falsy values are significant.\n const children = Array.isArray(vnode.children)\n ? vnode.children.filter((c) => c !== null && c !== undefined)\n : [];\n return children.map((c) => renderToString(c, opts)).join('');\n }\n\n if (vnode.tag === '#raw') {\n return typeof vnode.children === 'string' ? vnode.children : '';\n }\n\n // Collect attributes from props.attrs. For SSR we mirror vnode.attrs\n // but ensure SVG nodes behave like client-side: if this is an <svg>\n // and no xmlns was provided, inject the standard SVG namespace so\n // server markup matches client-created DOM namespace.\n let attrsObj: Record<string, unknown> = {};\n if (vnode.props && vnode.props.attrs) {\n attrsObj = { ...vnode.props.attrs };\n }\n\n const inject = opts?.injectSvgNamespace ?? true;\n const injectKnown = opts?.injectKnownNamespaces ?? inject;\n\n // Inject namespace for well-known tags when missing. By default we\n // preserve previous behavior (SVG injected) and also allow injecting\n // other known namespaces (MathML) when injectKnownNamespaces is true.\n if (inject && vnode.tag === 'svg' && !('xmlns' in attrsObj)) {\n attrsObj.xmlns = SVG_NS;\n } else if (\n injectKnown &&\n vnode.tag in TAG_NAMESPACE_MAP &&\n !('xmlns' in attrsObj)\n ) {\n attrsObj.xmlns = TAG_NAMESPACE_MAP[vnode.tag];\n }\n\n const attrsString = Object.entries(attrsObj)\n .map(([k, v]) => ` ${k}=\"${escapeHTML(String(v))}\"`)\n .join('');\n\n const children = Array.isArray(vnode.children)\n ? vnode.children\n .filter((c) => c !== null && c !== undefined)\n .map((c) => renderToString(c, opts))\n .join('')\n : typeof vnode.children === 'string'\n ? escapeHTML(vnode.children)\n : vnode.children\n ? renderToString(vnode.children)\n : '';\n\n return `<${vnode.tag}${attrsString}>${children}</${vnode.tag}>`;\n}\n"],"names":["renderToString","vnode","opts","escapeHTML","c","attrsObj","inject","injectKnown","SVG_NS","TAG_NAMESPACE_MAP","attrsString","k","v","children"],"mappings":"oIAkBO,SAASA,EAAeC,EAAcC,EAA8B,CACzE,GAAI,OAAOD,GAAU,SAAU,OAAOE,EAAAA,WAAWF,CAAK,EAEtD,GAAIA,EAAM,MAAQ,QAChB,OAAO,OAAOA,EAAM,UAAa,SAC5BE,EAAAA,WAAWF,EAAM,QAAQ,EAC1B,GAGN,GAAIA,EAAM,MAAQ,UAQhB,OAHiB,MAAM,QAAQA,EAAM,QAAQ,EACzCA,EAAM,SAAS,OAAQG,GAAMA,GAAM,IAAuB,EAC1D,CAAA,GACY,IAAKA,GAAMJ,EAAeI,EAAGF,CAAI,CAAC,EAAE,KAAK,EAAE,EAG7D,GAAID,EAAM,MAAQ,OAChB,OAAO,OAAOA,EAAM,UAAa,SAAWA,EAAM,SAAW,GAO/D,IAAII,EAAoC,CAAA,EACpCJ,EAAM,OAASA,EAAM,MAAM,QAC7BI,EAAW,CAAE,GAAGJ,EAAM,MAAM,KAAA,GAG9B,MAAMK,EAASJ,GAAM,oBAAsB,GACrCK,EAAcL,GAAM,uBAAyBI,EAK/CA,GAAUL,EAAM,MAAQ,OAAS,EAAE,UAAWI,GAChDA,EAAS,MAAQG,EAAAA,OAEjBD,GACAN,EAAM,OAAOQ,EAAAA,mBACb,EAAE,UAAWJ,KAEbA,EAAS,MAAQI,oBAAkBR,EAAM,GAAG,GAG9C,MAAMS,EAAc,OAAO,QAAQL,CAAQ,EACxC,IAAI,CAAC,CAACM,EAAGC,CAAC,IAAM,IAAID,CAAC,KAAKR,EAAAA,WAAW,OAAOS,CAAC,CAAC,CAAC,GAAG,EAClD,KAAK,EAAE,EAEJC,EAAW,MAAM,QAAQZ,EAAM,QAAQ,EACzCA,EAAM,SACH,OAAQG,GAAMA,GAAM,IAAuB,EAC3C,IAAKA,GAAMJ,EAAeI,EAAGF,CAAI,CAAC,EAClC,KAAK,EAAE,EACV,OAAOD,EAAM,UAAa,SACxBE,EAAAA,WAAWF,EAAM,QAAQ,EACzBA,EAAM,SACJD,EAAeC,EAAM,QAAQ,EAC7B,GAER,MAAO,IAAIA,EAAM,GAAG,GAAGS,CAAW,IAAIG,CAAQ,KAAKZ,EAAM,GAAG,GAC9D"}
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import { e as
|
|
2
|
-
function
|
|
3
|
-
if (typeof r == "string") return
|
|
1
|
+
import { e as s, S as p, T as e } from "./namespace-helpers-Vwt2Fzds.js";
|
|
2
|
+
function c(r, a) {
|
|
3
|
+
if (typeof r == "string") return s(r);
|
|
4
4
|
if (r.tag === "#text")
|
|
5
|
-
return typeof r.children == "string" ?
|
|
5
|
+
return typeof r.children == "string" ? s(r.children) : "";
|
|
6
6
|
if (r.tag === "#anchor")
|
|
7
|
-
return (Array.isArray(r.children) ? r.children.filter((
|
|
7
|
+
return (Array.isArray(r.children) ? r.children.filter((n) => n != null) : []).map((n) => c(n, a)).join("");
|
|
8
8
|
if (r.tag === "#raw")
|
|
9
9
|
return typeof r.children == "string" ? r.children : "";
|
|
10
|
-
let
|
|
11
|
-
r.props && r.props.attrs && (
|
|
12
|
-
const
|
|
13
|
-
|
|
10
|
+
let i = {};
|
|
11
|
+
r.props && r.props.attrs && (i = { ...r.props.attrs });
|
|
12
|
+
const l = a?.injectSvgNamespace ?? !0, g = a?.injectKnownNamespaces ?? l;
|
|
13
|
+
l && r.tag === "svg" && !("xmlns" in i) ? i.xmlns = p : g && r.tag in e && !("xmlns" in i) && (i.xmlns = e[r.tag]);
|
|
14
|
+
const h = Object.entries(i).map(([t, n]) => ` ${t}="${s(String(n))}"`).join(""), f = Array.isArray(r.children) ? r.children.filter((t) => t != null).map((t) => c(t, a)).join("") : typeof r.children == "string" ? s(r.children) : r.children ? c(r.children) : "";
|
|
15
|
+
return `<${r.tag}${h}>${f}</${r.tag}>`;
|
|
14
16
|
}
|
|
15
17
|
export {
|
|
16
|
-
|
|
18
|
+
c as renderToString
|
|
17
19
|
};
|
|
18
20
|
//# sourceMappingURL=custom-elements-runtime.ssr.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-elements-runtime.ssr.es.js","sources":["../src/lib/runtime/vdom-ssr.ts"],"sourcesContent":["import type { VNode } from './types';\nimport { escapeHTML } from './helpers';\n\n/**\n * Render a VNode to a string (SSR).\n * Kept intentionally minimal: only serializes attributes under `props.attrs`\n * to avoid leaking runtime-only values (functions, reactive state, directives).\n * @param vnode The virtual node to render.\n * @returns The rendered HTML string.\n */\nexport function renderToString(vnode: VNode): string {\n if (typeof vnode === 'string') return escapeHTML(vnode) as string;\n\n if (vnode.tag === '#text') {\n return typeof vnode.children === 'string'\n ? (escapeHTML(vnode.children) as string)\n : '';\n }\n\n if (vnode.tag === '#anchor') {\n // Preserve meaningful falsy children (0, false, '') while filtering out\n // only null and undefined. Anchor blocks are normalized by the compiler\n // to exclude null/undefined; SSR should follow the same rule to avoid\n // hydration mismatches where falsy values are significant.\n const children = Array.isArray(vnode.children)\n ? vnode.children.filter((c) => c !== null && c !== undefined)\n : [];\n return children.map(renderToString).join('');\n }\n\n if (vnode.tag === '#raw') {\n return typeof vnode.children === 'string' ? vnode.children : '';\n }\n\n // Collect attributes from props.attrs\n let
|
|
1
|
+
{"version":3,"file":"custom-elements-runtime.ssr.es.js","sources":["../src/lib/runtime/vdom-ssr.ts"],"sourcesContent":["import type { VNode } from './types';\nimport { escapeHTML } from './helpers';\nimport { TAG_NAMESPACE_MAP, SVG_NS } from './namespace-helpers';\n\n/**\n * Render a VNode to a string (SSR).\n * Kept intentionally minimal: only serializes attributes under `props.attrs`\n * to avoid leaking runtime-only values (functions, reactive state, directives).\n * @param vnode The virtual node to render.\n * @returns The rendered HTML string.\n */\nexport type RenderOptions = {\n /** Backwards-compatible: whether to inject the SVG namespace on <svg> nodes (default true) */\n injectSvgNamespace?: boolean;\n /** Inject known well-known namespaces for tags like <math> when missing (default follows injectSvgNamespace) */\n injectKnownNamespaces?: boolean;\n};\n\nexport function renderToString(vnode: VNode, opts?: RenderOptions): string {\n if (typeof vnode === 'string') return escapeHTML(vnode) as string;\n\n if (vnode.tag === '#text') {\n return typeof vnode.children === 'string'\n ? (escapeHTML(vnode.children) as string)\n : '';\n }\n\n if (vnode.tag === '#anchor') {\n // Preserve meaningful falsy children (0, false, '') while filtering out\n // only null and undefined. Anchor blocks are normalized by the compiler\n // to exclude null/undefined; SSR should follow the same rule to avoid\n // hydration mismatches where falsy values are significant.\n const children = Array.isArray(vnode.children)\n ? vnode.children.filter((c) => c !== null && c !== undefined)\n : [];\n return children.map((c) => renderToString(c, opts)).join('');\n }\n\n if (vnode.tag === '#raw') {\n return typeof vnode.children === 'string' ? vnode.children : '';\n }\n\n // Collect attributes from props.attrs. For SSR we mirror vnode.attrs\n // but ensure SVG nodes behave like client-side: if this is an <svg>\n // and no xmlns was provided, inject the standard SVG namespace so\n // server markup matches client-created DOM namespace.\n let attrsObj: Record<string, unknown> = {};\n if (vnode.props && vnode.props.attrs) {\n attrsObj = { ...vnode.props.attrs };\n }\n\n const inject = opts?.injectSvgNamespace ?? true;\n const injectKnown = opts?.injectKnownNamespaces ?? inject;\n\n // Inject namespace for well-known tags when missing. By default we\n // preserve previous behavior (SVG injected) and also allow injecting\n // other known namespaces (MathML) when injectKnownNamespaces is true.\n if (inject && vnode.tag === 'svg' && !('xmlns' in attrsObj)) {\n attrsObj.xmlns = SVG_NS;\n } else if (\n injectKnown &&\n vnode.tag in TAG_NAMESPACE_MAP &&\n !('xmlns' in attrsObj)\n ) {\n attrsObj.xmlns = TAG_NAMESPACE_MAP[vnode.tag];\n }\n\n const attrsString = Object.entries(attrsObj)\n .map(([k, v]) => ` ${k}=\"${escapeHTML(String(v))}\"`)\n .join('');\n\n const children = Array.isArray(vnode.children)\n ? vnode.children\n .filter((c) => c !== null && c !== undefined)\n .map((c) => renderToString(c, opts))\n .join('')\n : typeof vnode.children === 'string'\n ? escapeHTML(vnode.children)\n : vnode.children\n ? renderToString(vnode.children)\n : '';\n\n return `<${vnode.tag}${attrsString}>${children}</${vnode.tag}>`;\n}\n"],"names":["renderToString","vnode","opts","escapeHTML","c","attrsObj","inject","injectKnown","SVG_NS","TAG_NAMESPACE_MAP","attrsString","k","v","children"],"mappings":";AAkBO,SAASA,EAAeC,GAAcC,GAA8B;AACzE,MAAI,OAAOD,KAAU,SAAU,QAAOE,EAAWF,CAAK;AAEtD,MAAIA,EAAM,QAAQ;AAChB,WAAO,OAAOA,EAAM,YAAa,WAC5BE,EAAWF,EAAM,QAAQ,IAC1B;AAGN,MAAIA,EAAM,QAAQ;AAQhB,YAHiB,MAAM,QAAQA,EAAM,QAAQ,IACzCA,EAAM,SAAS,OAAO,CAACG,MAAMA,KAAM,IAAuB,IAC1D,CAAA,GACY,IAAI,CAACA,MAAMJ,EAAeI,GAAGF,CAAI,CAAC,EAAE,KAAK,EAAE;AAG7D,MAAID,EAAM,QAAQ;AAChB,WAAO,OAAOA,EAAM,YAAa,WAAWA,EAAM,WAAW;AAO/D,MAAII,IAAoC,CAAA;AACxC,EAAIJ,EAAM,SAASA,EAAM,MAAM,UAC7BI,IAAW,EAAE,GAAGJ,EAAM,MAAM,MAAA;AAG9B,QAAMK,IAASJ,GAAM,sBAAsB,IACrCK,IAAcL,GAAM,yBAAyBI;AAKnD,EAAIA,KAAUL,EAAM,QAAQ,SAAS,EAAE,WAAWI,KAChDA,EAAS,QAAQG,IAEjBD,KACAN,EAAM,OAAOQ,KACb,EAAE,WAAWJ,OAEbA,EAAS,QAAQI,EAAkBR,EAAM,GAAG;AAG9C,QAAMS,IAAc,OAAO,QAAQL,CAAQ,EACxC,IAAI,CAAC,CAACM,GAAGC,CAAC,MAAM,IAAID,CAAC,KAAKR,EAAW,OAAOS,CAAC,CAAC,CAAC,GAAG,EAClD,KAAK,EAAE,GAEJC,IAAW,MAAM,QAAQZ,EAAM,QAAQ,IACzCA,EAAM,SACH,OAAO,CAACG,MAAMA,KAAM,IAAuB,EAC3C,IAAI,CAACA,MAAMJ,EAAeI,GAAGF,CAAI,CAAC,EAClC,KAAK,EAAE,IACV,OAAOD,EAAM,YAAa,WACxBE,EAAWF,EAAM,QAAQ,IACzBA,EAAM,WACJD,EAAeC,EAAM,QAAQ,IAC7B;AAER,SAAO,IAAIA,EAAM,GAAG,GAAGS,CAAW,IAAIG,CAAQ,KAAKZ,EAAM,GAAG;AAC9D;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";const y=require("./logger-CqdBMdui.cjs");class
|
|
1
|
+
"use strict";const y=require("./logger-CqdBMdui.cjs");class H{pendingUpdates=new Map;isFlushScheduled=!1;schedule(e,r){const n=r||e;if(this.pendingUpdates.set(n,e),!this.isFlushScheduled){this.isFlushScheduled=!0;const s=globalThis.process;typeof s<"u"&&s.env?.NODE_ENV==="test"||typeof window<"u"&&(window.__vitest__||window.Cypress)?this.flush():queueMicrotask(()=>this.flush())}}flush(){const e=this.pendingUpdates;this.pendingUpdates=new Map,this.isFlushScheduled=!1;for(const r of e.values())try{r()}catch(n){y.devError("Error in batched update:",n)}}get pendingCount(){return this.pendingUpdates.size}}const L=new H;function S(t,e){L.schedule(t,e)}const w=new WeakSet;class D{static cache=new WeakMap;static arrayHandlerCache=new WeakMap;static objectHandlerCache=new WeakMap;static getOrCreateProxy(e,r,n=!1){const s=this.cache.get(e);if(s)return s;const i=n?this.getOrCreateArrayHandler(r):this.getOrCreateObjectHandler(r),a=new Proxy(e,i);try{A.markAsProxy(a)}catch{}return this.cache.set(e,a),a}static getOrCreateArrayHandler(e){if(!this.arrayHandlerCache.has(e)){const r={get:(n,s,i)=>{const a=Reflect.get(n,s,i);return typeof a=="function"&&typeof s=="string"&&["push","pop","shift","unshift","splice","sort","reverse","fill","copyWithin"].includes(s)?function(...u){const l=a.apply(n,u);return e.triggerUpdate(),l}:a},set:(n,s,i)=>(n[s]=e.makeReactiveValue(i),e.triggerUpdate(),!0),deleteProperty:(n,s)=>(delete n[s],e.triggerUpdate(),!0)};this.arrayHandlerCache.set(e,r)}return this.arrayHandlerCache.get(e)}static getOrCreateObjectHandler(e){if(!this.objectHandlerCache.has(e)){const r={get:(n,s,i)=>Reflect.get(n,s,i),set:(n,s,i)=>(n[s]=e.makeReactiveValue(i),e.triggerUpdate(),!0),deleteProperty:(n,s)=>(delete n[s],e.triggerUpdate(),!0)};this.objectHandlerCache.set(e,r)}return this.objectHandlerCache.get(e)}static hasProxy(e){return this.cache.has(e)}static clear(){this.cache=new WeakMap,this.arrayHandlerCache=new WeakMap,this.objectHandlerCache=new WeakMap}static getStats(){return{hasCachedProxies:this.cache instanceof WeakMap}}}class A{static contextCache=new WeakMap;static createReactiveProxy(e,r,n){try{if(w.has(e))return e}catch{}const s=Array.isArray(e);let i=this.contextCache.get(r);i||(i=new WeakMap,this.contextCache.set(r,i));let a=i.get(n);return a||(a={triggerUpdate:r,makeReactiveValue:n},i.set(n,a)),D.getOrCreateProxy(e,a,s)}static markAsProxy(e){if(e)try{w.add(e)}catch{}}}class N{currentComponent=null;componentData=new Map;stateStorage=new Map;trackingDisabled=!1;setCurrentComponent(e,r){if(this.currentComponent=e,!this.componentData.has(e))this.componentData.set(e,{dependencies:new Set,renderFn:r,stateIndex:0,lastWarnTime:0});else{const n=this.componentData.get(e);n.renderFn=r,n.stateIndex=0}}clearCurrentComponent(){this.currentComponent=null}disableTracking(){this.trackingDisabled=!0}enableTracking(){this.trackingDisabled=!1}isRenderingComponent(){return this.currentComponent!==null}shouldEmitRenderWarning(){if(!this.currentComponent)return!0;const e=this.componentData.get(this.currentComponent);if(!e)return!0;const r=Date.now();return r-e.lastWarnTime<1e3?!1:(e.lastWarnTime=r,!0)}withoutTracking(e){const r=this.trackingDisabled;this.trackingDisabled=!0;try{return e()}finally{this.trackingDisabled=r}}getOrCreateState(e){if(!this.currentComponent)return new g(e);const r=this.componentData.get(this.currentComponent);if(!r)return new g(e);const n=`${this.currentComponent}:${r.stateIndex++}`;let s=this.stateStorage.get(n);return s||(s=new g(e),this.stateStorage.set(n,s)),s}trackDependency(e){if(this.trackingDisabled||!this.currentComponent)return;const r=this.componentData.get(this.currentComponent);r&&(r.dependencies.add(e),e.addDependent(this.currentComponent))}triggerUpdate(e){const r=e.getDependents();for(const n of r){const s=this.componentData.get(n);s&&S(s.renderFn,n)}}cleanup(e){const r=this.componentData.get(e);if(r){for(const s of r.dependencies)s.removeDependent(e);this.componentData.delete(e)}const n=e+":";for(const s of this.stateStorage.keys())s.startsWith(n)&&this.stateStorage.delete(s)}}const c=new N;class g{_value;dependents=new Set;constructor(e){this._value=this.makeReactive(e);try{const r=Symbol.for("@cer/ReactiveState");Object.defineProperty(this,r,{value:!0,enumerable:!1,configurable:!1})}catch{}}get value(){return c.trackDependency(this),this._value}set value(e){c.isRenderingComponent()&&c.shouldEmitRenderWarning()&&y.devWarn(`🚨 State modification detected during render! This can cause infinite loops.
|
|
2
2
|
• Move state updates to event handlers
|
|
3
3
|
• Use useEffect/watch for side effects
|
|
4
|
-
• Ensure computed properties don't modify state`),this._value=this.makeReactive(e),c.triggerUpdate(this)}addDependent(e){this.dependents.add(e)}removeDependent(e){this.dependents.delete(e)}getDependents(){return this.dependents}makeReactive(e){return e===null||typeof e!="object"||e instanceof Node||e instanceof Element||e instanceof HTMLElement?e:
|
|
5
|
-
//# sourceMappingURL=helpers-
|
|
4
|
+
• Ensure computed properties don't modify state`),this._value=this.makeReactive(e),c.triggerUpdate(this)}addDependent(e){this.dependents.add(e)}removeDependent(e){this.dependents.delete(e)}getDependents(){return this.dependents}makeReactive(e){return e===null||typeof e!="object"||e instanceof Node||e instanceof Element||e instanceof HTMLElement?e:A.createReactiveProxy(e,()=>c.triggerUpdate(this),r=>this.makeReactive(r))}}function R(t){return c.getOrCreateState(t===void 0?null:t)}function m(t){if(!t||typeof t!="object")return!1;try{const e=Symbol.for("@cer/ReactiveState");return Object.prototype.hasOwnProperty.call(t,e)}catch{return!1}}function P(t){const e=new g(t());return{get value(){return c.trackDependency(e),t()}}}function O(t,e,r={}){let n=t();r.immediate&&e(n,n);const s=`watch-${Math.random().toString(36).substr(2,9)}`,i=()=>{c.setCurrentComponent(s,i);const a=t();c.clearCurrentComponent(),a!==n&&(e(a,n),n=a)};return c.setCurrentComponent(s,i),t(),c.clearCurrentComponent(),()=>{c.cleanup(s)}}const W=t=>{try{t()}catch{}},f=new Map,p=new Map,h=new Map,C=500;let M,T,b=!1,_=!1,E;const U=!!globalThis.process?.versions?.node;function j(t){if(f.has(t))return f.get(t);const e=t.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();return f.size<C&&f.set(t,e),e}function F(t){if(p.has(t))return p.get(t);const e=t.replace(/-([a-z])/g,(r,n)=>n.toUpperCase());return p.size<C&&p.set(t,e),e}function z(t){if(typeof t=="string"){if(h.has(t))return h.get(t);const e=t.replace(/[&<>"']/g,r=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[r]);return e!==t&&h.size<C&&h.set(t,e),e}return t}function d(t){if(!t)return"";const e=String(t);if(typeof document<"u"&&typeof document.createElement=="function"){const o=e.replace(/</g,"").replace(/>/g,""),u=E||(E=document.createElement("div"));try{d._el=u}catch{}return u.innerHTML=o,(u.textContent||"").replace(new RegExp("","g"),"<").replace(new RegExp("","g"),">")}const r={lt:"<",gt:">",amp:"&",quot:'"',apos:"'",nbsp:" "},n=M??d._namedMap;let s=n;if(!s&&U)try{const i=globalThis.require;if(typeof i=="function"){const a=["@jasonshimmy/custom-elements-runtime/entities.json","../../entities.json","../../../entities.json","../entities.json","./entities.json"];for(const o of a)try{const u=i(o);if(u&&typeof u=="object"){s=u;break}}catch{}}}catch{}if(!s){s=r,b=!0;try{d._usedFallback=!0}catch{}const i=d._namedMapLoader??T;i&&i().then(a=>{M=a;try{d._namedMap=a}catch{}}).catch(()=>{})}if((b||d._usedFallback)&&!(_||d._warnedFallback)){_=!0;try{d._warnedFallback=!0}catch{}try{y.devWarn("decodeEntities: using small SSR fallback entity map. Register the full entities.json via registerEntityMap(entities) on the server to enable full HTML5 named-entity decoding.")}catch{}}return e.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g,(i,a)=>{if(a.charCodeAt(0)===35){const l=(a.charAt(1)||"").toLowerCase()==="x"?parseInt(a.slice(2),16):parseInt(a.slice(1),10);return Number.isNaN(l)?`&${a};`:String.fromCodePoint(l)}const o=s[a]??(n&&n[a]);return o!==void 0?o:`&${a};`})}async function x(){const t=["@jasonshimmy","custom-elements-runtime","entities.json"].join("/");try{const e=await import(t);return e&&(e.default||e)}catch{try{const e=[t,"./entities.json","../../entities.json","../../../entities.json"];for(const r of e)try{const n=await import(r);if(n)return n&&(n.default||n)}catch{}return{lt:"<",gt:">",amp:"&",quot:'"',apos:"'",nbsp:" "}}catch{return{lt:"<",gt:">",amp:"&",quot:'"',apos:"'",nbsp:" "}}}}T=x;d._namedMapLoader=x;function I(t){const e=String(t);return{__unsafeHTML:e,__rawHTML:e}}function V(t){return!!t&&(typeof t.__unsafeHTML=="string"||typeof t.__rawHTML=="string")}function q(t,e){if(typeof e=="string"){if(e==="")return;const r=e.split(".");let n=t;for(const s of r){if(n==null||typeof n!="object"){n=void 0;break}n=n[s]}return m(n)?n.value:n}return e}function G(t,e,r){const n=String(e).split("."),s=n.pop();if(!s)return;const i=n.reduce((a,o)=>(a[o]==null&&(a[o]={}),a[o]),t);m(i[s])?i[s].value=r:i[s]=r}function $(t){try{if(t&&typeof t=="object"){if(m(t))return t.value;if("value"in t){const e=t.value;return e==null||typeof e=="string"||typeof e=="number"||typeof e=="boolean"?e:t}}}catch{}return t}function K(t){const e=$(t);if(e==null)return null;const r=typeof e;return r==="string"||r==="number"||r==="boolean"?String(e):null}function Z(t){if(!t||typeof t!="string")return!1;if(t==="class"||t.endsWith("Class"))return!0;if(t.includes("-"))try{if(t.split("-").some(r=>r==="class"))return!0}catch{}return!1}const k={xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace"};function B(t,e,r){try{if(!e||!e.includes(":")){t.setAttribute(e,r);return}const n=e.indexOf(":"),s=e.substring(0,n),i=e.substring(n+1),a=k[s];a?t.setAttributeNS(a,i,r):t.setAttribute(e,r)}catch{try{t.setAttribute(e,r)}catch{}}}function X(t,e){try{if(!e||!e.includes(":")){t.removeAttribute(e);return}const r=e.indexOf(":"),n=e.substring(0,r),s=e.substring(r+1),i=k[n];i?t.removeAttributeNS(i,s):t.removeAttribute(e)}catch{try{t.removeAttribute(e)}catch{}}}const v="http://www.w3.org/2000/svg",J="http://www.w3.org/1998/Math/MathML",Q={svg:v,math:J};exports.SVG_NS=v;exports.TAG_NAMESPACE_MAP=Q;exports.computed=P;exports.decodeEntities=d;exports.escapeHTML=z;exports.getNestedValue=q;exports.isClassLikeAttr=Z;exports.isReactiveState=m;exports.isUnsafeHTML=V;exports.reactiveSystem=c;exports.ref=R;exports.removeAttributeSmart=X;exports.safe=W;exports.safeSerializeAttr=K;exports.scheduleDOMUpdate=S;exports.setAttributeSmart=B;exports.setNestedValue=G;exports.toCamel=F;exports.toKebab=j;exports.unsafeHTML=I;exports.watch=O;
|
|
5
|
+
//# sourceMappingURL=namespace-helpers-DwMMXN9Q.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namespace-helpers-DwMMXN9Q.cjs","sources":["../src/lib/runtime/scheduler.ts","../src/lib/runtime/reactive-proxy-cache.ts","../src/lib/runtime/reactive.ts","../src/lib/runtime/helpers.ts","../src/lib/runtime/namespace-helpers.ts"],"sourcesContent":["/**\n * Update Scheduler for batching DOM updates\n * Prevents excessive re-renders and improves performance\n */\nimport { devError } from './logger';\n\nclass UpdateScheduler {\n private pendingUpdates = new Map<string | (() => void), () => void>();\n private isFlushScheduled = false;\n\n /**\n * Schedule an update to be executed in the next microtask\n * Uses component identity to deduplicate multiple render requests for the same component\n */\n schedule(update: () => void, componentId?: string): void {\n // IMPORTANT: Never use update.toString() as it breaks with minification!\n // Use the componentId if provided, otherwise use the function reference directly as the key\n // since Map supports using function references as keys (identity-based comparison)\n const key = componentId || update;\n this.pendingUpdates.set(key, update);\n\n if (!this.isFlushScheduled) {\n this.isFlushScheduled = true;\n\n // Check if we're in a test environment\n const maybeProcess = (\n globalThis as { process?: { env?: { NODE_ENV?: string } } }\n ).process;\n const isTestEnv =\n (typeof maybeProcess !== 'undefined' &&\n maybeProcess.env?.NODE_ENV === 'test') ||\n (typeof window !== 'undefined' &&\n ((window as { __vitest__?: unknown; Cypress?: unknown }).__vitest__ ||\n (window as { __vitest__?: unknown; Cypress?: unknown }).Cypress));\n\n if (isTestEnv) {\n // Execute synchronously in test environments to avoid timing issues\n this.flush();\n } else {\n queueMicrotask(() => this.flush());\n }\n }\n }\n\n /**\n * Execute all pending updates\n */\n private flush(): void {\n const updates = this.pendingUpdates;\n this.pendingUpdates = new Map();\n this.isFlushScheduled = false;\n\n // Execute all updates in batch\n for (const update of updates.values()) {\n try {\n update();\n } catch (error) {\n // Continue with other updates even if one fails\n devError('Error in batched update:', error);\n }\n }\n }\n\n /**\n * Get the number of pending updates\n */\n get pendingCount(): number {\n return this.pendingUpdates.size;\n }\n}\n\n// Global scheduler instance\nexport const updateScheduler = new UpdateScheduler();\n\n/**\n * Schedule a DOM update to be batched with optional component identity\n */\nexport function scheduleDOMUpdate(\n update: () => void,\n componentId?: string,\n): void {\n updateScheduler.schedule(update, componentId);\n}\n","/**\n * Reactive proxy cache to optimize proxy creation and reuse\n * Uses WeakMap for automatic garbage collection when objects are no longer referenced\n */\n\n/**\n * Cache for reactive proxies to avoid creating multiple proxies for the same object\n */\n// legacy symbol marker removed — use WeakSet and non-enumerable flag instead\n// Track actual proxy instances with a WeakSet for robust detection\nconst proxiedObjects = new WeakSet<object>();\n// No legacy flag: rely solely on WeakSet and WeakMap for proxy detection\n\nclass ReactiveProxyCache {\n private static cache = new WeakMap<object, object>();\n private static arrayHandlerCache = new WeakMap<\n object,\n ProxyHandler<object>\n >();\n private static objectHandlerCache = new WeakMap<\n object,\n ProxyHandler<object>\n >();\n\n /**\n * Get or create a reactive proxy for an object\n */\n static getOrCreateProxy<T extends object>(\n obj: T,\n reactiveState: {\n triggerUpdate: () => void;\n makeReactiveValue: (value: unknown) => unknown;\n },\n isArray: boolean = false,\n ): T {\n // Check if we already have a cached proxy\n const cached = this.cache.get(obj);\n if (cached) {\n return cached as T;\n }\n\n // Create appropriate handler\n const handler = isArray\n ? this.getOrCreateArrayHandler(reactiveState)\n : this.getOrCreateObjectHandler(reactiveState);\n\n // Create proxy\n const proxy = new Proxy(obj, handler);\n\n // Mark and track the proxy instance (do this via the optimizer helper)\n try {\n ProxyOptimizer.markAsProxy(proxy as Record<string | symbol, unknown>);\n } catch {\n void 0;\n }\n\n // Cache the proxy by the original target object\n this.cache.set(obj, proxy);\n\n return proxy as T;\n }\n\n /**\n * Get or create a cached array handler\n */\n private static getOrCreateArrayHandler(reactiveState: {\n triggerUpdate: () => void;\n makeReactiveValue: (value: unknown) => unknown;\n }): ProxyHandler<object> {\n // Create a unique handler for this reactive state\n if (!this.arrayHandlerCache.has(reactiveState)) {\n const handler: ProxyHandler<unknown[]> = {\n get: (target, prop, receiver) => {\n const value = Reflect.get(target, prop, receiver);\n\n // Intercept array mutating methods\n if (typeof value === 'function' && typeof prop === 'string') {\n const mutatingMethods = [\n 'push',\n 'pop',\n 'shift',\n 'unshift',\n 'splice',\n 'sort',\n 'reverse',\n 'fill',\n 'copyWithin',\n ];\n if (mutatingMethods.includes(prop)) {\n return function (...args: unknown[]) {\n const result = value.apply(target, args);\n // Trigger update after mutation\n reactiveState.triggerUpdate();\n return result;\n };\n }\n }\n\n return value;\n },\n set: (target, prop, value) => {\n (target as unknown as Record<string | symbol, unknown>)[prop] =\n reactiveState.makeReactiveValue(value);\n reactiveState.triggerUpdate();\n return true;\n },\n deleteProperty: (target, prop) => {\n delete (target as unknown as Record<string | symbol, unknown>)[prop];\n reactiveState.triggerUpdate();\n return true;\n },\n };\n\n this.arrayHandlerCache.set(reactiveState, handler);\n }\n\n return this.arrayHandlerCache.get(reactiveState)!;\n }\n\n /**\n * Get or create a cached object handler\n */\n private static getOrCreateObjectHandler(reactiveState: {\n triggerUpdate: () => void;\n makeReactiveValue: (value: unknown) => unknown;\n }): ProxyHandler<object> {\n // Create a unique handler for this reactive state\n if (!this.objectHandlerCache.has(reactiveState)) {\n const handler: ProxyHandler<Record<string | symbol, unknown>> = {\n get: (target, prop, receiver) => {\n return Reflect.get(target, prop, receiver);\n },\n set: (target, prop, value) => {\n (target as Record<string | symbol, unknown>)[prop] =\n reactiveState.makeReactiveValue(value);\n reactiveState.triggerUpdate();\n return true;\n },\n deleteProperty: (target, prop) => {\n delete (target as Record<string | symbol, unknown>)[prop];\n reactiveState.triggerUpdate();\n return true;\n },\n };\n\n this.objectHandlerCache.set(reactiveState, handler);\n }\n\n return this.objectHandlerCache.get(reactiveState)!;\n }\n\n /**\n * Check if an object already has a cached proxy\n */\n static hasProxy(obj: object): boolean {\n return this.cache.has(obj);\n }\n\n /**\n * Clear all cached proxies (useful for testing)\n */\n static clear(): void {\n this.cache = new WeakMap();\n this.arrayHandlerCache = new WeakMap();\n this.objectHandlerCache = new WeakMap();\n }\n\n /**\n * Get cache statistics (for debugging)\n * Note: WeakMap doesn't provide size, so this is limited\n */\n static getStats(): { hasCachedProxies: boolean } {\n // WeakMap doesn't expose size, but we can check if we have any handlers cached\n return {\n hasCachedProxies: this.cache instanceof WeakMap,\n };\n }\n}\n\n/**\n * Optimized proxy creation utilities\n */\nclass ProxyOptimizer {\n // Cache a stable reactiveContext object keyed by onUpdate -> makeReactive\n // This allows handler caches in ReactiveProxyCache to reuse handlers\n // for identical reactive contexts instead of creating a new context object\n // on each createReactiveProxy call.\n private static contextCache = new WeakMap<\n (...args: unknown[]) => unknown,\n WeakMap<\n (...args: unknown[]) => unknown,\n {\n triggerUpdate: () => void;\n makeReactiveValue: (value: unknown) => unknown;\n }\n >\n >();\n /**\n * Create an optimized reactive proxy with minimal overhead\n */\n static createReactiveProxy<T extends object>(\n obj: T,\n onUpdate: () => void,\n makeReactive: (value: unknown) => unknown,\n ): T {\n // If the argument is already a proxy instance, return it directly.\n try {\n if (proxiedObjects.has(obj)) return obj;\n } catch {\n // ignore\n }\n\n const isArray = Array.isArray(obj);\n\n // Reuse a stable reactiveContext object per (onUpdate, makeReactive) pair.\n let inner = this.contextCache.get(onUpdate);\n if (!inner) {\n inner = new WeakMap();\n this.contextCache.set(onUpdate, inner);\n }\n let reactiveContext = inner.get(makeReactive);\n if (!reactiveContext) {\n reactiveContext = {\n triggerUpdate: onUpdate,\n makeReactiveValue: makeReactive,\n };\n inner.set(makeReactive, reactiveContext);\n }\n\n // Delegate to the cache which will return an existing proxy for the target\n // or create one if it doesn't exist yet.\n return ReactiveProxyCache.getOrCreateProxy(obj, reactiveContext, isArray);\n }\n\n /**\n * Mark an object as a proxy (for optimization)\n */\n static markAsProxy(obj: object): void {\n if (!obj) return;\n\n // Prefer adding the actual proxy instance to the WeakSet which does not trigger proxy traps\n try {\n proxiedObjects.add(obj);\n } catch {\n // ignore\n }\n }\n}\n\nexport { ReactiveProxyCache, ProxyOptimizer };\n","import { scheduleDOMUpdate } from './scheduler';\nimport { ProxyOptimizer } from './reactive-proxy-cache';\nimport { devWarn } from './logger';\n\n/**\n * Global reactive system for tracking dependencies and triggering updates\n */\nclass ReactiveSystem {\n private currentComponent: string | null = null;\n // Consolidated component data: stores dependencies, render function, state index, and last warning time\n private componentData = new Map<\n string,\n {\n dependencies: Set<ReactiveState<unknown>>;\n renderFn: () => void;\n stateIndex: number;\n lastWarnTime: number;\n }\n >();\n // Flat storage: compound key `${componentId}:${stateIndex}` -> ReactiveState\n private stateStorage = new Map<string, ReactiveState<unknown>>();\n private trackingDisabled = false;\n\n /**\n * Set the current component being rendered for dependency tracking\n */\n setCurrentComponent(componentId: string, renderFn: () => void): void {\n this.currentComponent = componentId;\n if (!this.componentData.has(componentId)) {\n this.componentData.set(componentId, {\n dependencies: new Set(),\n renderFn,\n stateIndex: 0,\n lastWarnTime: 0,\n });\n } else {\n const data = this.componentData.get(componentId)!;\n data.renderFn = renderFn;\n data.stateIndex = 0; // Reset state index for this render\n }\n }\n\n /**\n * Clear the current component after rendering\n */\n clearCurrentComponent(): void {\n this.currentComponent = null;\n }\n\n /**\n * Temporarily disable dependency tracking\n */\n disableTracking(): void {\n this.trackingDisabled = true;\n }\n\n /**\n * Re-enable dependency tracking\n */\n enableTracking(): void {\n this.trackingDisabled = false;\n }\n\n /**\n * Check if a component is currently rendering\n */\n isRenderingComponent(): boolean {\n return this.currentComponent !== null;\n }\n\n /**\n * Return whether we should emit a render-time warning for the current component.\n * This throttles warnings to avoid spamming the console for legitimate rapid updates.\n */\n shouldEmitRenderWarning(): boolean {\n if (!this.currentComponent) return true;\n const data = this.componentData.get(this.currentComponent);\n if (!data) return true;\n\n const now = Date.now();\n const THROTTLE_MS = 1000; // 1 second per component\n if (now - data.lastWarnTime < THROTTLE_MS) return false;\n\n data.lastWarnTime = now;\n return true;\n }\n\n /**\n * Execute a function with tracking disabled\n */\n withoutTracking<T>(fn: () => T): T {\n const wasDisabled = this.trackingDisabled;\n this.trackingDisabled = true;\n try {\n return fn();\n } finally {\n this.trackingDisabled = wasDisabled;\n }\n }\n\n /**\n * Get or create a state instance for the current component\n */\n getOrCreateState<T>(initialValue: T): ReactiveState<T> {\n if (!this.currentComponent) {\n return new ReactiveState(initialValue);\n }\n\n const data = this.componentData.get(this.currentComponent);\n if (!data) {\n return new ReactiveState(initialValue);\n }\n\n const stateKey = `${this.currentComponent}:${data.stateIndex++}`;\n let state = this.stateStorage.get(stateKey) as ReactiveState<T> | undefined;\n\n if (!state) {\n state = new ReactiveState(initialValue);\n this.stateStorage.set(stateKey, state);\n }\n\n return state;\n }\n\n /**\n * Track a dependency for the current component\n */\n trackDependency(state: ReactiveState<unknown>): void {\n if (this.trackingDisabled || !this.currentComponent) return;\n\n const data = this.componentData.get(this.currentComponent);\n if (data) {\n data.dependencies.add(state);\n state.addDependent(this.currentComponent);\n }\n }\n\n /**\n * Trigger updates for all components that depend on a state\n */\n triggerUpdate(state: ReactiveState<unknown>): void {\n const deps = state.getDependents();\n for (const componentId of deps) {\n const data = this.componentData.get(componentId);\n if (data) {\n scheduleDOMUpdate(data.renderFn, componentId);\n }\n }\n }\n\n /**\n * Clean up component dependencies when component is destroyed\n */\n cleanup(componentId: string): void {\n const data = this.componentData.get(componentId);\n if (data) {\n for (const state of data.dependencies) {\n state.removeDependent(componentId);\n }\n this.componentData.delete(componentId);\n }\n // Remove any flat-stored state keys for this component\n const prefix = componentId + ':';\n for (const key of this.stateStorage.keys()) {\n if (key.startsWith(prefix)) {\n this.stateStorage.delete(key);\n }\n }\n }\n}\n\nconst reactiveSystem = new ReactiveSystem();\n\n// Export for internal use\nexport { reactiveSystem };\n\n/**\n * Internal reactive state class\n */\nexport class ReactiveState<T> {\n private _value: T;\n private dependents = new Set<string>();\n\n constructor(initialValue: T) {\n this._value = this.makeReactive(initialValue);\n // Mark instances with a stable cross-bundle symbol so other modules\n // can reliably detect ReactiveState objects even when classes are\n // renamed/minified or when multiple copies of the package exist.\n try {\n // Use a global symbol key to make it resilient across realms/bundles\n const key = Symbol.for('@cer/ReactiveState');\n Object.defineProperty(this, key, {\n value: true,\n enumerable: false,\n configurable: false,\n });\n } catch {\n // ignore if Symbol.for or defineProperty fails in exotic runtimes\n }\n }\n\n get value(): T {\n // Track this state as a dependency when accessed during render\n reactiveSystem.trackDependency(this);\n return this._value;\n }\n\n set value(newValue: T) {\n // Check for state modifications during render (potential infinite loop)\n if (reactiveSystem.isRenderingComponent()) {\n if (reactiveSystem.shouldEmitRenderWarning()) {\n devWarn(\n '🚨 State modification detected during render! This can cause infinite loops.\\n' +\n ' • Move state updates to event handlers\\n' +\n ' • Use useEffect/watch for side effects\\n' +\n \" • Ensure computed properties don't modify state\",\n );\n }\n }\n\n this._value = this.makeReactive(newValue);\n // Trigger updates for all dependent components\n reactiveSystem.triggerUpdate(this);\n }\n\n addDependent(componentId: string): void {\n this.dependents.add(componentId);\n }\n\n removeDependent(componentId: string): void {\n this.dependents.delete(componentId);\n }\n\n getDependents(): Set<string> {\n return this.dependents;\n }\n\n private makeReactive<U>(obj: U): U {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n // Skip reactivity for DOM nodes - they should not be made reactive\n if (\n (obj as unknown) instanceof Node ||\n (obj as unknown) instanceof Element ||\n (obj as unknown) instanceof HTMLElement\n ) {\n return obj;\n }\n\n // Use optimized proxy creation\n return ProxyOptimizer.createReactiveProxy(\n obj as unknown as object,\n () => reactiveSystem.triggerUpdate(this),\n (value: unknown) => this.makeReactive(value),\n ) as U;\n }\n}\n\n/**\n * Create reactive state that automatically triggers component re-renders\n * when accessed during render and modified afterwards.\n * Defaults to null if no initial value is provided (Vue-style ref).\n *\n * @example\n * ```ts\n * const counter = ref(0);\n * const user = ref({ name: 'John', age: 30 });\n * const emptyRef = ref(); // defaults to null\n *\n * // Usage in component\n * counter.value++; // triggers re-render\n * user.value.name = 'Jane'; // triggers re-render\n * console.log(emptyRef.value); // null\n * ```\n */\nexport function ref(): ReactiveState<null>;\nexport function ref<T>(initialValue: T): ReactiveState<T>;\nexport function ref<T>(initialValue?: T): ReactiveState<T | null> {\n // Ensure the created state has the union type T | null and explicitly\n // tell getOrCreateState the correct generic to avoid conditional-type recursion.\n return reactiveSystem.getOrCreateState<T | null>(\n (initialValue === undefined ? null : (initialValue as T)) as T | null,\n );\n}\n\n/**\n * Type guard to detect ReactiveState instances in a robust way that works\n * across bundlers, minifiers, and multiple package copies.\n */\nexport function isReactiveState(v: unknown): v is ReactiveState<unknown> {\n if (!v || typeof v !== 'object') return false;\n try {\n const key = Symbol.for('@cer/ReactiveState');\n // Safely check for the presence of the symbol-keyed property without indexing with a unique symbol\n return Object.prototype.hasOwnProperty.call(v, key);\n } catch {\n return false;\n }\n}\n\n/**\n * Create computed state that derives from other reactive state\n *\n * @example\n * ```ts\n * const firstName = ref('John');\n * const lastName = ref('Doe');\n * const fullName = computed(() => `${firstName.value} ${lastName.value}`);\n * ```\n */\nexport function computed<T>(fn: () => T): { readonly value: T } {\n const computedState = new ReactiveState(fn());\n\n // We need to track dependencies when the computed function runs\n // For now, we'll re-evaluate on every access (can be optimized later)\n return {\n get value(): T {\n reactiveSystem.trackDependency(computedState as ReactiveState<unknown>);\n return fn();\n },\n };\n}\n\n/**\n * Create a watcher that runs when dependencies change\n *\n * @example\n * ```ts\n * const count = ref(0);\n * watch(() => count.value, (newVal, oldVal) => {\n * console.log(`Count changed from ${oldVal} to ${newVal}`);\n * });\n * ```\n */\nexport function watch<T>(\n source: () => T,\n callback: (newValue: T, oldValue: T) => void,\n options: { immediate?: boolean } = {},\n): () => void {\n let oldValue = source();\n\n if (options.immediate) {\n callback(oldValue, oldValue);\n }\n\n // Create a dummy component to track dependencies\n const watcherId = `watch-${Math.random().toString(36).substr(2, 9)}`;\n\n const updateWatcher = () => {\n reactiveSystem.setCurrentComponent(watcherId, updateWatcher);\n const newValue = source();\n reactiveSystem.clearCurrentComponent();\n\n if (newValue !== oldValue) {\n callback(newValue, oldValue);\n oldValue = newValue;\n }\n };\n\n // Initial run to establish dependencies\n reactiveSystem.setCurrentComponent(watcherId, updateWatcher);\n source();\n reactiveSystem.clearCurrentComponent();\n\n // Return cleanup function\n return () => {\n reactiveSystem.cleanup(watcherId);\n };\n}\n","/**\n * Safe execution helper - silently ignores errors\n */\nexport const safe = (fn: () => void): void => {\n try {\n fn();\n } catch {\n void 0;\n }\n};\n\nimport { isReactiveState } from './reactive';\nimport { devWarn } from './logger';\n\n// Caches for string transformations to improve performance\nconst KEBAB_CASE_CACHE = new Map<string, string>();\nconst CAMEL_CASE_CACHE = new Map<string, string>();\nconst HTML_ESCAPE_CACHE = new Map<string, string>();\n\n// Cache size limits to prevent memory bloat\nconst MAX_CACHE_SIZE = 500;\n\n// Module-level state for entity map and loader. Using module-level vars avoids\n// reliance on attaching properties to functions which can be brittle when\n// minifiers are configured to mangle properties.\nlet _namedEntityMap: Record<string, string> | undefined;\n// eslint-disable-next-line prefer-const\nlet _namedEntityMapLoader: (() => Promise<Record<string, string>>) | undefined;\nlet _usedEntityFallback = false;\nlet _warnedEntityFallback = false;\n// Module-level decode element used in browser environments to avoid attaching\n// an element to the function object (function properties can be mangled by\n// aggressive minifiers). Keep a function-attached reference only for backward\n// compatibility but prefer `_decodeEl` at runtime.\nlet _decodeEl: HTMLDivElement | undefined;\n// NOTE (internal): The runtime prefers module-level state for the entity map\n// and decode element to ensure minifier-safe behavior in production builds.\n// We intentionally retain assignments to function-attached properties in a\n// few places solely for backward compatibility with older tests and code\n// paths. New code should rely on `registerEntityMap`, `loadEntityMap`, and\n// the exported `decodeEntities` function rather than inspecting internal\n// function properties.\n// Use globalThis to avoid TypeScript requiring Node typings for `process`.\nconst _isNode = !!(globalThis as { process?: { versions?: { node?: string } } })\n .process?.versions?.node;\n\n/**\n * Convert camelCase to kebab-case with caching\n */\nexport function toKebab(str: string): string {\n if (KEBAB_CASE_CACHE.has(str)) {\n return KEBAB_CASE_CACHE.get(str)!;\n }\n\n const result = str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n\n // Prevent memory bloat with size limit\n if (KEBAB_CASE_CACHE.size < MAX_CACHE_SIZE) {\n KEBAB_CASE_CACHE.set(str, result);\n }\n\n return result;\n}\n\n/**\n * Convert kebab-case to camelCase with caching\n */\nexport function toCamel(str: string): string {\n if (CAMEL_CASE_CACHE.has(str)) {\n return CAMEL_CASE_CACHE.get(str)!;\n }\n\n const result = str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());\n\n if (CAMEL_CASE_CACHE.size < MAX_CACHE_SIZE) {\n CAMEL_CASE_CACHE.set(str, result);\n }\n\n return result;\n}\n\n/**\n * Clear string transformation caches (useful for testing)\n */\nexport function clearStringCaches(): void {\n KEBAB_CASE_CACHE.clear();\n CAMEL_CASE_CACHE.clear();\n HTML_ESCAPE_CACHE.clear();\n}\n\n/**\n * Get cache statistics for debugging\n */\nexport function getStringCacheStats(): {\n kebabCacheSize: number;\n camelCacheSize: number;\n htmlEscapeCacheSize: number;\n} {\n return {\n kebabCacheSize: KEBAB_CASE_CACHE.size,\n camelCacheSize: CAMEL_CASE_CACHE.size,\n htmlEscapeCacheSize: HTML_ESCAPE_CACHE.size,\n };\n}\n\nexport function escapeHTML(\n str: string | number | boolean,\n): string | number | boolean {\n if (typeof str === 'string') {\n // Check cache first for frequently escaped strings\n if (HTML_ESCAPE_CACHE.has(str)) {\n return HTML_ESCAPE_CACHE.get(str)!;\n }\n\n const result = str.replace(\n /[&<>\"']/g,\n (c) =>\n ({\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n })[c]!,\n );\n\n // Only cache strings that contain entities to escape\n if (result !== str && HTML_ESCAPE_CACHE.size < MAX_CACHE_SIZE) {\n HTML_ESCAPE_CACHE.set(str, result);\n }\n\n return result;\n }\n return str;\n}\n\n/**\n * Decode HTML entities (named and numeric) into their character equivalents.\n * - In browser: uses a DOM-based technique to decode entities while preserving\n * existing raw tags.\n * - In non-DOM (SSR) environments: handles numeric references and a conservative\n * named-entity map for common entities.\n *\n * @param str - string containing HTML entities\n * @returns decoded string\n */\nexport function decodeEntities(str: string): string {\n if (!str) return '';\n const s = String(str);\n\n // Browser environment: use a DOM element to decode the full set of named entities.\n if (\n typeof document !== 'undefined' &&\n typeof document.createElement === 'function'\n ) {\n const SENTINEL_L = '\\uF000';\n const SENTINEL_G = '\\uF001';\n // Protect existing literal tags so they won't be parsed as HTML by innerHTML\n const protectedStr = s.replace(/</g, SENTINEL_L).replace(/>/g, SENTINEL_G);\n\n // Prefer module-level el to avoid relying on function-attached properties\n // which can be renamed/mangled by some minifiers. Keep function-attached\n // `_el` for backward compatibility but do not depend on it.\n const el = _decodeEl || (_decodeEl = document.createElement('div'));\n try {\n (decodeEntities as { _el?: HTMLElement })._el = el;\n } catch {\n void 0;\n }\n\n el.innerHTML = protectedStr;\n const decoded = el.textContent || '';\n return decoded\n .replace(new RegExp(SENTINEL_L, 'g'), '<')\n .replace(new RegExp(SENTINEL_G, 'g'), '>');\n }\n\n // SSR / non-DOM fallback: handle numeric refs and named entities via an external JSON map.\n // Keep a tiny inline map for the most common entities so decodeEntities remains sync.\n const tinyMap: Record<string, string> = {\n lt: '<',\n gt: '>',\n amp: '&',\n quot: '\"',\n apos: \"'\",\n nbsp: '\\u00A0',\n };\n\n // Prefer module-level registered map first (minifier-safe). Keep function\n // attached map as a fallback for backward compatibility only.\n const registered =\n _namedEntityMap ??\n (decodeEntities as { _namedMap?: Record<string, string> })._namedMap;\n\n // Select map: module-level registered > function-attached registered > sync require (Node-only) > tinyMap.\n let namedMap: Record<string, string> | undefined = registered;\n\n if (!namedMap && _isNode) {\n // Try to synchronously require the JSON in Node-like environments without importing `require`.\n try {\n // Use globalThis to avoid referencing `require` directly (prevents TS needing node types)\n const maybeRequire = (globalThis as { require?: (id: string) => unknown })\n .require;\n if (typeof maybeRequire === 'function') {\n // Try several common require paths (installed package, dist layout, src layout)\n const candidates = [\n '@jasonshimmy/custom-elements-runtime/entities.json', // installed package export\n '../../entities.json', // dist/runtime -> ../../entities.json\n '../../../entities.json', // src/lib/runtime -> ../../../entities.json\n '../entities.json',\n './entities.json',\n ];\n for (const p of candidates) {\n try {\n const m = maybeRequire(p);\n // Ensure the required value is an object before assigning and cast it to the expected type\n if (m && typeof m === 'object') {\n namedMap = m as Record<string, string>;\n break;\n }\n } catch {\n void 0;\n }\n }\n }\n } catch {\n void 0;\n }\n }\n\n // If we still don't have a map, fall back to tinyMap and trigger background loader if present.\n if (!namedMap) {\n namedMap = tinyMap;\n // Keep both module and function-level flags in sync for backward compatibility.\n // Mark fallback usage primarily on module-level flags (minifier-safe).\n _usedEntityFallback = true;\n try {\n (decodeEntities as { _usedFallback?: boolean })._usedFallback = true;\n } catch {\n void 0;\n }\n const loader =\n (\n decodeEntities as {\n _namedMapLoader?: () => Promise<Record<string, string>>;\n }\n )._namedMapLoader ?? _namedEntityMapLoader;\n if (loader) {\n // Load asynchronously; when ready, cache it for future sync calls and sync to function props.\n loader()\n .then((m: Record<string, string>) => {\n _namedEntityMap = m;\n try {\n (\n decodeEntities as { _namedMap?: Record<string, string> }\n )._namedMap = m;\n } catch {\n void 0;\n }\n })\n .catch(() => {});\n }\n }\n\n // Emit a one-time dev warning if we used the tiny fallback.\n // Prefer module-level flags first, then function-attached fallbacks for\n // backward compatibility. This avoids depending on function property names\n // which some minifiers may mangle.\n if (\n (_usedEntityFallback ||\n (decodeEntities as { _usedFallback?: boolean })._usedFallback) &&\n !(\n _warnedEntityFallback ||\n (decodeEntities as { _warnedFallback?: boolean })._warnedFallback\n )\n ) {\n _warnedEntityFallback = true;\n try {\n (decodeEntities as { _warnedFallback?: boolean })._warnedFallback = true;\n } catch {\n void 0;\n }\n try {\n devWarn(\n 'decodeEntities: using small SSR fallback entity map. Register the full entities.json via registerEntityMap(entities) on the server to enable full HTML5 named-entity decoding.',\n );\n } catch {\n void 0;\n }\n }\n\n // Replace entities: numeric (hex/dec) or named.\n return s.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, (_, entity) => {\n if (entity.charCodeAt(0) === 35) {\n // '#'\n const isHex = (entity.charAt(1) || '').toLowerCase() === 'x';\n const num = isHex\n ? parseInt(entity.slice(2), 16)\n : parseInt(entity.slice(1), 10);\n return Number.isNaN(num) ? `&${entity};` : String.fromCodePoint(num);\n }\n const mapped =\n (namedMap as Record<string, string>)[entity] ??\n (registered && registered[entity]);\n return mapped !== undefined ? mapped : `&${entity};`;\n });\n}\n\n/**\n * Dynamically load the full named-entity map (used in SSR). Exported for testing and\n * to allow bundlers to exclude the JSON from client bundles when dynamic import\n * is used behind a DOM check.\n */\nexport async function loadEntityMap(): Promise<Record<string, string>> {\n // Prefer dynamic import so bundlers can code-split or ignore this file for browser bundles.\n // Try the published package export first; in installed packages this is usually the most\n // reliable path. Make the specifier a runtime string to discourage bundlers from inlining.\n const pkgExport = [\n '@jasonshimmy',\n 'custom-elements-runtime',\n 'entities.json',\n ].join('/');\n try {\n // @vite-ignore: dynamic import specifier constructed at runtime\n const mPkg = await import(/* @vite-ignore */ pkgExport as string);\n return (mPkg && (mPkg.default || mPkg)) as Record<string, string>;\n } catch {\n // Next try relative local JSON (useful during development or mono-repo installs)\n try {\n // Try several reasonable local import paths (development vs built layouts)\n const localCandidates = [\n pkgExport, // try package export via dynamic import too (best for installed packages)\n './entities.json',\n '../../entities.json',\n '../../../entities.json',\n ];\n for (const p of localCandidates) {\n try {\n // @vite-ignore: intentionally dynamic path candidates for dev/local resolution\n const mLocal = await import(/* @vite-ignore */ p as string);\n if (mLocal)\n return (mLocal && (mLocal.default || mLocal)) as Record<\n string,\n string\n >;\n } catch {\n void 0;\n }\n }\n // If none of the dynamic imports succeeded, fall back to the small map.\n return {\n lt: '<',\n gt: '>',\n amp: '&',\n quot: '\"',\n apos: \"'\",\n nbsp: '\\u00A0',\n };\n } catch {\n // Final small fallback\n return {\n lt: '<',\n gt: '>',\n amp: '&',\n quot: '\"',\n apos: \"'\",\n nbsp: '\\u00A0',\n };\n }\n }\n}\n\n// Attach loader to module state and (for backward compatibility) to the function\n// as well. Using module-level state avoids property-mangling risks in minified\n// builds; attaching to the function keeps tests that reference the property\n// working until they can be updated.\n_namedEntityMapLoader = loadEntityMap;\n(\n decodeEntities as typeof decodeEntities & {\n _namedMapLoader?: typeof loadEntityMap;\n }\n)._namedMapLoader = loadEntityMap;\n\n/**\n * Register a full named-entity map for SSR. Intended for server startup code to\n * provide the authoritative HTML5 entity mapping. This keeps the client bundle\n * small because the map is only injected on the server side.\n *\n * registerEntityMap should be called once at server startup prior to rendering.\n */\nexport function registerEntityMap(\n map: Record<string, string>,\n options?: { overwrite?: boolean },\n): void {\n if (!map || typeof map !== 'object') return;\n const existing = _namedEntityMap;\n if (existing && !options?.overwrite) return; // first registration wins by default\n _namedEntityMap = map;\n}\n\n/**\n * Clear any registered entity map. Useful for tests or restarting state.\n */\nexport function clearRegisteredEntityMap(): void {\n _namedEntityMap = undefined;\n}\n\n/**\n * Wrap a string as raw HTML. This is intentionally unsafe — callers must\n * sanitize untrusted input before using this. The returned object provides\n * two property names to be compatible with different parts of the runtime.\n */\nexport function unsafeHTML(html: string): {\n __unsafeHTML: string;\n __rawHTML: string;\n} {\n const s = String(html);\n // Provide both property names to be compatible with compiler/renderer expectations\n return { __unsafeHTML: s, __rawHTML: s };\n}\n\n/** Type-guard for unsafeHTML wrapper */\nexport function isUnsafeHTML(\n value: unknown,\n): value is { __unsafeHTML?: string; __rawHTML?: string } {\n return (\n !!value &&\n (typeof (value as { __unsafeHTML?: unknown }).__unsafeHTML === 'string' ||\n typeof (value as { __rawHTML?: unknown }).__rawHTML === 'string')\n );\n}\n\n/**\n * Get nested property value from object using dot notation\n */\nexport function getNestedValue(\n obj: Record<string, unknown>,\n path: string,\n): unknown {\n if (typeof path === 'string') {\n // Handle empty path explicitly: return undefined to indicate no lookup\n if (path === '') return undefined;\n const keys = path.split('.');\n let current: unknown = obj;\n\n for (const key of keys) {\n if (current == null || typeof current !== 'object') {\n current = undefined;\n break;\n }\n current = (current as Record<string, unknown>)[key];\n }\n\n // If the result is a ReactiveState object, return its value\n if (isReactiveState(current)) {\n return (current as { value: unknown }).value;\n }\n return current;\n }\n return path;\n}\n\n/**\n * Set nested property value in object using dot notation\n */\nexport function setNestedValue(\n obj: Record<string, unknown>,\n path: string,\n value: unknown,\n): void {\n const keys = String(path).split('.');\n const lastKey = keys.pop();\n if (!lastKey) return;\n const target = keys.reduce(\n (current: Record<string, unknown>, key: string) => {\n if (current[key] == null) current[key] = {};\n return current[key] as Record<string, unknown>;\n },\n obj,\n ) as Record<string, unknown>;\n\n // If target[lastKey] is a ReactiveState object, set its value property\n if (isReactiveState(target[lastKey])) {\n target[lastKey].value = value;\n } else {\n target[lastKey] = value;\n }\n}\n\n/**\n * Safely unwrap reactive-like wrappers to their inner primitive when safe.\n * Returns the original value when it's not safe to coerce to a primitive.\n */\nexport function unwrapIfPrimitive(val: unknown): unknown {\n try {\n if (val && typeof val === 'object') {\n if (isReactiveState(val)) return (val as { value: unknown }).value;\n if ('value' in val) {\n const maybe = (val as { value: unknown }).value;\n // Only return primitive inner values; otherwise return original\n if (\n maybe === null ||\n maybe === undefined ||\n typeof maybe === 'string' ||\n typeof maybe === 'number' ||\n typeof maybe === 'boolean'\n ) {\n return maybe;\n }\n return val;\n }\n }\n } catch {\n // ignore\n }\n return val;\n}\n\n/**\n * Return a serialized string for an attribute value when safe to write to DOM.\n * Returns `null` when the value should not be written as an attribute.\n */\nexport function safeSerializeAttr(val: unknown): string | null {\n const v = unwrapIfPrimitive(val);\n if (v === null || v === undefined) return null;\n const t = typeof v;\n if (t === 'string' || t === 'number' || t === 'boolean') return String(v);\n return null; // complex objects, nodes, functions -> do not serialize\n}\n\n/**\n * Determine if an attribute name is class-like and should be preserved on hosts.\n * Class-like: exactly 'class', camelCase ending with 'Class', or kebab-case ending with '-class'.\n */\nexport function isClassLikeAttr(name: string): boolean {\n if (!name || typeof name !== 'string') return false;\n if (name === 'class') return true;\n if (name.endsWith('Class')) return true;\n // Kebab-case: consider attributes where one of the hyphen-separated tokens is 'class'\n if (name.includes('-')) {\n try {\n const parts = name.split('-');\n if (parts.some((p) => p === 'class')) return true;\n } catch {\n // fallthrough\n }\n }\n return false;\n}\n","/**\n * Namespace-aware attribute helpers.\n * Provides small, fast utilities to set/remove attributes using the\n * appropriate namespace when an attribute uses a known prefix (e.g. xlink:href).\n */\n\nconst ATTR_NAMESPACE_MAP: Record<string, string> = {\n xlink: 'http://www.w3.org/1999/xlink',\n xml: 'http://www.w3.org/XML/1998/namespace',\n};\n\n/**\n * Set attribute using namespace when the key contains a known prefix.\n */\nexport function setAttributeSmart(\n el: Element,\n key: string,\n value: string,\n): void {\n try {\n if (!key || !key.includes(':')) {\n el.setAttribute(key, value);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.setAttributeNS(ns, local, value);\n else el.setAttribute(key, value);\n } catch {\n try {\n // Fallback to un-namespaced setAttribute on error\n el.setAttribute(key, value);\n } catch {\n /* swallow */\n }\n }\n}\n\n/**\n * Remove attribute using namespace when the key contains a known prefix.\n */\nexport function removeAttributeSmart(el: Element, key: string): void {\n try {\n if (!key || !key.includes(':')) {\n el.removeAttribute(key);\n return;\n }\n const idx = key.indexOf(':');\n const prefix = key.substring(0, idx);\n const local = key.substring(idx + 1);\n const ns = ATTR_NAMESPACE_MAP[prefix];\n if (ns) el.removeAttributeNS(ns, local);\n else el.removeAttribute(key);\n } catch {\n try {\n el.removeAttribute(key);\n } catch {\n /* swallow */\n }\n }\n}\n\nexport const __TEST_ONLY_ATTR_NS_MAP = ATTR_NAMESPACE_MAP;\n\n// Common element namespace URIs and a small tag->namespace map used by\n// both the client renderer and the SSR serializer. Exporting these from\n// this module keeps namespace knowledge centralized and prevents\n// accidental duplication between runtime and SSR code.\nexport const SVG_NS = 'http://www.w3.org/2000/svg';\nexport const MATHML_NS = 'http://www.w3.org/1998/Math/MathML';\n\nexport const TAG_NAMESPACE_MAP: Record<string, string> = {\n svg: SVG_NS,\n math: MATHML_NS,\n};\n"],"names":["UpdateScheduler","update","componentId","key","maybeProcess","updates","error","devError","updateScheduler","scheduleDOMUpdate","proxiedObjects","ReactiveProxyCache","obj","reactiveState","isArray","cached","handler","proxy","ProxyOptimizer","target","prop","receiver","value","args","result","onUpdate","makeReactive","inner","reactiveContext","ReactiveSystem","renderFn","data","now","fn","wasDisabled","initialValue","ReactiveState","stateKey","state","deps","prefix","reactiveSystem","newValue","devWarn","ref","isReactiveState","v","computed","computedState","watch","source","callback","options","oldValue","watcherId","updateWatcher","safe","KEBAB_CASE_CACHE","CAMEL_CASE_CACHE","HTML_ESCAPE_CACHE","MAX_CACHE_SIZE","_namedEntityMap","_namedEntityMapLoader","_usedEntityFallback","_warnedEntityFallback","_decodeEl","_isNode","toKebab","str","toCamel","_","letter","escapeHTML","c","decodeEntities","s","protectedStr","el","tinyMap","registered","namedMap","maybeRequire","candidates","p","m","loader","entity","num","mapped","loadEntityMap","pkgExport","mPkg","localCandidates","mLocal","unsafeHTML","html","isUnsafeHTML","getNestedValue","path","keys","current","setNestedValue","lastKey","unwrapIfPrimitive","val","maybe","safeSerializeAttr","t","isClassLikeAttr","name","ATTR_NAMESPACE_MAP","setAttributeSmart","idx","local","ns","removeAttributeSmart","SVG_NS","MATHML_NS","TAG_NAMESPACE_MAP"],"mappings":"sDAMA,MAAMA,CAAgB,CACZ,mBAAqB,IACrB,iBAAmB,GAM3B,SAASC,EAAoBC,EAA4B,CAIvD,MAAMC,EAAMD,GAAeD,EAG3B,GAFA,KAAK,eAAe,IAAIE,EAAKF,CAAM,EAE/B,CAAC,KAAK,iBAAkB,CAC1B,KAAK,iBAAmB,GAGxB,MAAMG,EACJ,WACA,QAEC,OAAOA,EAAiB,KACvBA,EAAa,KAAK,WAAa,QAChC,OAAO,OAAW,MACf,OAAuD,YACtD,OAAuD,SAI5D,KAAK,MAAA,EAEL,eAAe,IAAM,KAAK,OAAO,CAErC,CACF,CAKQ,OAAc,CACpB,MAAMC,EAAU,KAAK,eACrB,KAAK,mBAAqB,IAC1B,KAAK,iBAAmB,GAGxB,UAAWJ,KAAUI,EAAQ,SAC3B,GAAI,CACFJ,EAAA,CACF,OAASK,EAAO,CAEdC,EAAAA,SAAS,2BAA4BD,CAAK,CAC5C,CAEJ,CAKA,IAAI,cAAuB,CACzB,OAAO,KAAK,eAAe,IAC7B,CACF,CAGO,MAAME,EAAkB,IAAIR,EAK5B,SAASS,EACdR,EACAC,EACM,CACNM,EAAgB,SAASP,EAAQC,CAAW,CAC9C,CCxEA,MAAMQ,MAAqB,QAG3B,MAAMC,CAAmB,CACvB,OAAe,MAAQ,IAAI,QAC3B,OAAe,kBAAoB,IAAI,QAIvC,OAAe,mBAAqB,IAAI,QAQxC,OAAO,iBACLC,EACAC,EAIAC,EAAmB,GAChB,CAEH,MAAMC,EAAS,KAAK,MAAM,IAAIH,CAAG,EACjC,GAAIG,EACF,OAAOA,EAIT,MAAMC,EAAUF,EACZ,KAAK,wBAAwBD,CAAa,EAC1C,KAAK,yBAAyBA,CAAa,EAGzCI,EAAQ,IAAI,MAAML,EAAKI,CAAO,EAGpC,GAAI,CACFE,EAAe,YAAYD,CAAyC,CACtE,MAAQ,CAER,CAGA,YAAK,MAAM,IAAIL,EAAKK,CAAK,EAElBA,CACT,CAKA,OAAe,wBAAwBJ,EAGd,CAEvB,GAAI,CAAC,KAAK,kBAAkB,IAAIA,CAAa,EAAG,CAC9C,MAAMG,EAAmC,CACvC,IAAK,CAACG,EAAQC,EAAMC,IAAa,CAC/B,MAAMC,EAAQ,QAAQ,IAAIH,EAAQC,EAAMC,CAAQ,EAGhD,OAAI,OAAOC,GAAU,YAAc,OAAOF,GAAS,UACzB,CACtB,OACA,MACA,QACA,UACA,SACA,OACA,UACA,OACA,YAAA,EAEkB,SAASA,CAAI,EACxB,YAAaG,EAAiB,CACnC,MAAMC,EAASF,EAAM,MAAMH,EAAQI,CAAI,EAEvC,OAAAV,EAAc,cAAA,EACPW,CACT,EAIGF,CACT,EACA,IAAK,CAACH,EAAQC,EAAME,KACjBH,EAAuDC,CAAI,EAC1DP,EAAc,kBAAkBS,CAAK,EACvCT,EAAc,cAAA,EACP,IAET,eAAgB,CAACM,EAAQC,KACvB,OAAQD,EAAuDC,CAAI,EACnEP,EAAc,cAAA,EACP,GACT,EAGF,KAAK,kBAAkB,IAAIA,EAAeG,CAAO,CACnD,CAEA,OAAO,KAAK,kBAAkB,IAAIH,CAAa,CACjD,CAKA,OAAe,yBAAyBA,EAGf,CAEvB,GAAI,CAAC,KAAK,mBAAmB,IAAIA,CAAa,EAAG,CAC/C,MAAMG,EAA0D,CAC9D,IAAK,CAACG,EAAQC,EAAMC,IACX,QAAQ,IAAIF,EAAQC,EAAMC,CAAQ,EAE3C,IAAK,CAACF,EAAQC,EAAME,KACjBH,EAA4CC,CAAI,EAC/CP,EAAc,kBAAkBS,CAAK,EACvCT,EAAc,cAAA,EACP,IAET,eAAgB,CAACM,EAAQC,KACvB,OAAQD,EAA4CC,CAAI,EACxDP,EAAc,cAAA,EACP,GACT,EAGF,KAAK,mBAAmB,IAAIA,EAAeG,CAAO,CACpD,CAEA,OAAO,KAAK,mBAAmB,IAAIH,CAAa,CAClD,CAKA,OAAO,SAASD,EAAsB,CACpC,OAAO,KAAK,MAAM,IAAIA,CAAG,CAC3B,CAKA,OAAO,OAAc,CACnB,KAAK,UAAY,QACjB,KAAK,sBAAwB,QAC7B,KAAK,uBAAyB,OAChC,CAMA,OAAO,UAA0C,CAE/C,MAAO,CACL,iBAAkB,KAAK,iBAAiB,OAAA,CAE5C,CACF,CAKA,MAAMM,CAAe,CAKnB,OAAe,aAAe,IAAI,QAalC,OAAO,oBACLN,EACAa,EACAC,EACG,CAEH,GAAI,CACF,GAAIhB,EAAe,IAAIE,CAAG,EAAG,OAAOA,CACtC,MAAQ,CAER,CAEA,MAAME,EAAU,MAAM,QAAQF,CAAG,EAGjC,IAAIe,EAAQ,KAAK,aAAa,IAAIF,CAAQ,EACrCE,IACHA,MAAY,QACZ,KAAK,aAAa,IAAIF,EAAUE,CAAK,GAEvC,IAAIC,EAAkBD,EAAM,IAAID,CAAY,EAC5C,OAAKE,IACHA,EAAkB,CAChB,cAAeH,EACf,kBAAmBC,CAAA,EAErBC,EAAM,IAAID,EAAcE,CAAe,GAKlCjB,EAAmB,iBAAiBC,EAAKgB,EAAiBd,CAAO,CAC1E,CAKA,OAAO,YAAYF,EAAmB,CACpC,GAAKA,EAGL,GAAI,CACFF,EAAe,IAAIE,CAAG,CACxB,MAAQ,CAER,CACF,CACF,CChPA,MAAMiB,CAAe,CACX,iBAAkC,KAElC,kBAAoB,IAUpB,iBAAmB,IACnB,iBAAmB,GAK3B,oBAAoB3B,EAAqB4B,EAA4B,CAEnE,GADA,KAAK,iBAAmB5B,EACpB,CAAC,KAAK,cAAc,IAAIA,CAAW,EACrC,KAAK,cAAc,IAAIA,EAAa,CAClC,iBAAkB,IAClB,SAAA4B,EACA,WAAY,EACZ,aAAc,CAAA,CACf,MACI,CACL,MAAMC,EAAO,KAAK,cAAc,IAAI7B,CAAW,EAC/C6B,EAAK,SAAWD,EAChBC,EAAK,WAAa,CACpB,CACF,CAKA,uBAA8B,CAC5B,KAAK,iBAAmB,IAC1B,CAKA,iBAAwB,CACtB,KAAK,iBAAmB,EAC1B,CAKA,gBAAuB,CACrB,KAAK,iBAAmB,EAC1B,CAKA,sBAAgC,CAC9B,OAAO,KAAK,mBAAqB,IACnC,CAMA,yBAAmC,CACjC,GAAI,CAAC,KAAK,iBAAkB,MAAO,GACnC,MAAMA,EAAO,KAAK,cAAc,IAAI,KAAK,gBAAgB,EACzD,GAAI,CAACA,EAAM,MAAO,GAElB,MAAMC,EAAM,KAAK,IAAA,EAEjB,OAAIA,EAAMD,EAAK,aADK,IAC8B,IAElDA,EAAK,aAAeC,EACb,GACT,CAKA,gBAAmBC,EAAgB,CACjC,MAAMC,EAAc,KAAK,iBACzB,KAAK,iBAAmB,GACxB,GAAI,CACF,OAAOD,EAAA,CACT,QAAA,CACE,KAAK,iBAAmBC,CAC1B,CACF,CAKA,iBAAoBC,EAAmC,CACrD,GAAI,CAAC,KAAK,iBACR,OAAO,IAAIC,EAAcD,CAAY,EAGvC,MAAMJ,EAAO,KAAK,cAAc,IAAI,KAAK,gBAAgB,EACzD,GAAI,CAACA,EACH,OAAO,IAAIK,EAAcD,CAAY,EAGvC,MAAME,EAAW,GAAG,KAAK,gBAAgB,IAAIN,EAAK,YAAY,GAC9D,IAAIO,EAAQ,KAAK,aAAa,IAAID,CAAQ,EAE1C,OAAKC,IACHA,EAAQ,IAAIF,EAAcD,CAAY,EACtC,KAAK,aAAa,IAAIE,EAAUC,CAAK,GAGhCA,CACT,CAKA,gBAAgBA,EAAqC,CACnD,GAAI,KAAK,kBAAoB,CAAC,KAAK,iBAAkB,OAErD,MAAMP,EAAO,KAAK,cAAc,IAAI,KAAK,gBAAgB,EACrDA,IACFA,EAAK,aAAa,IAAIO,CAAK,EAC3BA,EAAM,aAAa,KAAK,gBAAgB,EAE5C,CAKA,cAAcA,EAAqC,CACjD,MAAMC,EAAOD,EAAM,cAAA,EACnB,UAAWpC,KAAeqC,EAAM,CAC9B,MAAMR,EAAO,KAAK,cAAc,IAAI7B,CAAW,EAC3C6B,GACFtB,EAAkBsB,EAAK,SAAU7B,CAAW,CAEhD,CACF,CAKA,QAAQA,EAA2B,CACjC,MAAM6B,EAAO,KAAK,cAAc,IAAI7B,CAAW,EAC/C,GAAI6B,EAAM,CACR,UAAWO,KAASP,EAAK,aACvBO,EAAM,gBAAgBpC,CAAW,EAEnC,KAAK,cAAc,OAAOA,CAAW,CACvC,CAEA,MAAMsC,EAAStC,EAAc,IAC7B,UAAWC,KAAO,KAAK,aAAa,KAAA,EAC9BA,EAAI,WAAWqC,CAAM,GACvB,KAAK,aAAa,OAAOrC,CAAG,CAGlC,CACF,CAEA,MAAMsC,EAAiB,IAAIZ,EAQpB,MAAMO,CAAiB,CACpB,OACA,eAAiB,IAEzB,YAAYD,EAAiB,CAC3B,KAAK,OAAS,KAAK,aAAaA,CAAY,EAI5C,GAAI,CAEF,MAAMhC,EAAM,OAAO,IAAI,oBAAoB,EAC3C,OAAO,eAAe,KAAMA,EAAK,CAC/B,MAAO,GACP,WAAY,GACZ,aAAc,EAAA,CACf,CACH,MAAQ,CAER,CACF,CAEA,IAAI,OAAW,CAEb,OAAAsC,EAAe,gBAAgB,IAAI,EAC5B,KAAK,MACd,CAEA,IAAI,MAAMC,EAAa,CAEjBD,EAAe,wBACbA,EAAe,2BACjBE,EAAAA,QACE;AAAA;AAAA;AAAA,kDAAA,EAQN,KAAK,OAAS,KAAK,aAAaD,CAAQ,EAExCD,EAAe,cAAc,IAAI,CACnC,CAEA,aAAavC,EAA2B,CACtC,KAAK,WAAW,IAAIA,CAAW,CACjC,CAEA,gBAAgBA,EAA2B,CACzC,KAAK,WAAW,OAAOA,CAAW,CACpC,CAEA,eAA6B,CAC3B,OAAO,KAAK,UACd,CAEQ,aAAgBU,EAAW,CAMjC,OALIA,IAAQ,MAAQ,OAAOA,GAAQ,UAMhCA,aAA2B,MAC3BA,aAA2B,SAC3BA,aAA2B,YAErBA,EAIFM,EAAe,oBACpBN,EACA,IAAM6B,EAAe,cAAc,IAAI,EACtCnB,GAAmB,KAAK,aAAaA,CAAK,CAAA,CAE/C,CACF,CAqBO,SAASsB,EAAOT,EAA2C,CAGhE,OAAOM,EAAe,iBACnBN,IAAiB,OAAY,KAAQA,CAAA,CAE1C,CAMO,SAASU,EAAgBC,EAAyC,CACvE,GAAI,CAACA,GAAK,OAAOA,GAAM,SAAU,MAAO,GACxC,GAAI,CACF,MAAM3C,EAAM,OAAO,IAAI,oBAAoB,EAE3C,OAAO,OAAO,UAAU,eAAe,KAAK2C,EAAG3C,CAAG,CACpD,MAAQ,CACN,MAAO,EACT,CACF,CAYO,SAAS4C,EAAYd,EAAoC,CAC9D,MAAMe,EAAgB,IAAIZ,EAAcH,GAAI,EAI5C,MAAO,CACL,IAAI,OAAW,CACb,OAAAQ,EAAe,gBAAgBO,CAAuC,EAC/Df,EAAA,CACT,CAAA,CAEJ,CAaO,SAASgB,EACdC,EACAC,EACAC,EAAmC,CAAA,EACvB,CACZ,IAAIC,EAAWH,EAAA,EAEXE,EAAQ,WACVD,EAASE,EAAUA,CAAQ,EAI7B,MAAMC,EAAY,SAAS,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,OAAO,EAAG,CAAC,CAAC,GAE5DC,EAAgB,IAAM,CAC1Bd,EAAe,oBAAoBa,EAAWC,CAAa,EAC3D,MAAMb,EAAWQ,EAAA,EACjBT,EAAe,sBAAA,EAEXC,IAAaW,IACfF,EAAST,EAAUW,CAAQ,EAC3BA,EAAWX,EAEf,EAGA,OAAAD,EAAe,oBAAoBa,EAAWC,CAAa,EAC3DL,EAAA,EACAT,EAAe,sBAAA,EAGR,IAAM,CACXA,EAAe,QAAQa,CAAS,CAClC,CACF,CC/WO,MAAME,EAAQvB,GAAyB,CAC5C,GAAI,CACFA,EAAA,CACF,MAAQ,CAER,CACF,EAMMwB,MAAuB,IACvBC,MAAuB,IACvBC,MAAwB,IAGxBC,EAAiB,IAKvB,IAAIC,EAEAC,EACAC,EAAsB,GACtBC,EAAwB,GAKxBC,EASJ,MAAMC,EAAU,CAAC,CAAE,WAChB,SAAS,UAAU,KAKf,SAASC,EAAQC,EAAqB,CAC3C,GAAIX,EAAiB,IAAIW,CAAG,EAC1B,OAAOX,EAAiB,IAAIW,CAAG,EAGjC,MAAM5C,EAAS4C,EAAI,QAAQ,kBAAmB,OAAO,EAAE,YAAA,EAGvD,OAAIX,EAAiB,KAAOG,GAC1BH,EAAiB,IAAIW,EAAK5C,CAAM,EAG3BA,CACT,CAKO,SAAS6C,EAAQD,EAAqB,CAC3C,GAAIV,EAAiB,IAAIU,CAAG,EAC1B,OAAOV,EAAiB,IAAIU,CAAG,EAGjC,MAAM5C,EAAS4C,EAAI,QAAQ,YAAa,CAACE,EAAGC,IAAWA,EAAO,aAAa,EAE3E,OAAIb,EAAiB,KAAOE,GAC1BF,EAAiB,IAAIU,EAAK5C,CAAM,EAG3BA,CACT,CA0BO,SAASgD,EACdJ,EAC2B,CAC3B,GAAI,OAAOA,GAAQ,SAAU,CAE3B,GAAIT,EAAkB,IAAIS,CAAG,EAC3B,OAAOT,EAAkB,IAAIS,CAAG,EAGlC,MAAM5C,EAAS4C,EAAI,QACjB,WACCK,IACE,CACC,IAAK,QACL,IAAK,OACL,IAAK,OACL,IAAK,SACL,IAAK,OAAA,GACJA,CAAC,CAAA,EAIR,OAAIjD,IAAW4C,GAAOT,EAAkB,KAAOC,GAC7CD,EAAkB,IAAIS,EAAK5C,CAAM,EAG5BA,CACT,CACA,OAAO4C,CACT,CAYO,SAASM,EAAeN,EAAqB,CAClD,GAAI,CAACA,EAAK,MAAO,GACjB,MAAMO,EAAI,OAAOP,CAAG,EAGpB,GACE,OAAO,SAAa,KACpB,OAAO,SAAS,eAAkB,WAClC,CAIA,MAAMQ,EAAeD,EAAE,QAAQ,KAAM,GAAU,EAAE,QAAQ,KAAM,GAAU,EAKnEE,EAAKZ,IAAcA,EAAY,SAAS,cAAc,KAAK,GACjE,GAAI,CACDS,EAAyC,IAAMG,CAClD,MAAQ,CAER,CAEA,OAAAA,EAAG,UAAYD,GACCC,EAAG,aAAe,IAE/B,QAAQ,IAAI,OAAO,IAAY,GAAG,EAAG,GAAG,EACxC,QAAQ,IAAI,OAAO,IAAY,GAAG,EAAG,GAAG,CAC7C,CAIA,MAAMC,EAAkC,CACtC,GAAI,IACJ,GAAI,IACJ,IAAK,IACL,KAAM,IACN,KAAM,IACN,KAAM,GAAA,EAKFC,EACJlB,GACCa,EAA0D,UAG7D,IAAIM,EAA+CD,EAEnD,GAAI,CAACC,GAAYd,EAEf,GAAI,CAEF,MAAMe,EAAgB,WACnB,QACH,GAAI,OAAOA,GAAiB,WAAY,CAEtC,MAAMC,EAAa,CACjB,qDACA,sBACA,yBACA,mBACA,iBAAA,EAEF,UAAWC,KAAKD,EACd,GAAI,CACF,MAAME,EAAIH,EAAaE,CAAC,EAExB,GAAIC,GAAK,OAAOA,GAAM,SAAU,CAC9BJ,EAAWI,EACX,KACF,CACF,MAAQ,CAER,CAEJ,CACF,MAAQ,CAER,CAIF,GAAI,CAACJ,EAAU,CACbA,EAAWF,EAGXf,EAAsB,GACtB,GAAI,CACDW,EAA+C,cAAgB,EAClE,MAAQ,CAER,CACA,MAAMW,EAEFX,EAGA,iBAAmBZ,EACnBuB,GAEFA,EAAA,EACG,KAAMD,GAA8B,CACnCvB,EAAkBuB,EAClB,GAAI,CAEAV,EACA,UAAYU,CAChB,MAAQ,CAER,CACF,CAAC,EACA,MAAM,IAAM,CAAC,CAAC,CAErB,CAMA,IACGrB,GACEW,EAA+C,gBAClD,EACEV,GACCU,EAAiD,iBAEpD,CACAV,EAAwB,GACxB,GAAI,CACDU,EAAiD,gBAAkB,EACtE,MAAQ,CAER,CACA,GAAI,CACF/B,EAAAA,QACE,gLAAA,CAEJ,MAAQ,CAER,CACF,CAGA,OAAOgC,EAAE,QAAQ,iCAAkC,CAACL,EAAGgB,IAAW,CAChE,GAAIA,EAAO,WAAW,CAAC,IAAM,GAAI,CAG/B,MAAMC,GADSD,EAAO,OAAO,CAAC,GAAK,IAAI,gBAAkB,IAErD,SAASA,EAAO,MAAM,CAAC,EAAG,EAAE,EAC5B,SAASA,EAAO,MAAM,CAAC,EAAG,EAAE,EAChC,OAAO,OAAO,MAAMC,CAAG,EAAI,IAAID,CAAM,IAAM,OAAO,cAAcC,CAAG,CACrE,CACA,MAAMC,EACHR,EAAoCM,CAAM,IAC1CP,GAAcA,EAAWO,CAAM,GAClC,OAAOE,IAAW,OAAYA,EAAS,IAAIF,CAAM,GACnD,CAAC,CACH,CAOA,eAAsBG,GAAiD,CAIrE,MAAMC,EAAY,CAChB,eACA,0BACA,eAAA,EACA,KAAK,GAAG,EACV,GAAI,CAEF,MAAMC,EAAO,MAAM,OAA0BD,GAC7C,OAAQC,IAASA,EAAK,SAAWA,EACnC,MAAQ,CAEN,GAAI,CAEF,MAAMC,EAAkB,CACtBF,EACA,kBACA,sBACA,wBAAA,EAEF,UAAWP,KAAKS,EACd,GAAI,CAEF,MAAMC,EAAS,MAAM,OAA0BV,GAC/C,GAAIU,EACF,OAAQA,IAAWA,EAAO,SAAWA,EAIzC,MAAQ,CAER,CAGF,MAAO,CACL,GAAI,IACJ,GAAI,IACJ,IAAK,IACL,KAAM,IACN,KAAM,IACN,KAAM,GAAA,CAEV,MAAQ,CAEN,MAAO,CACL,GAAI,IACJ,GAAI,IACJ,IAAK,IACL,KAAM,IACN,KAAM,IACN,KAAM,GAAA,CAEV,CACF,CACF,CAMA/B,EAAwB2B,EAEtBf,EAGA,gBAAkBe,EA+Bb,SAASK,EAAWC,EAGzB,CACA,MAAMpB,EAAI,OAAOoB,CAAI,EAErB,MAAO,CAAE,aAAcpB,EAAG,UAAWA,CAAA,CACvC,CAGO,SAASqB,EACd1E,EACwD,CACxD,MACE,CAAC,CAACA,IACD,OAAQA,EAAqC,cAAiB,UAC7D,OAAQA,EAAkC,WAAc,SAE9D,CAKO,SAAS2E,EACdrF,EACAsF,EACS,CACT,GAAI,OAAOA,GAAS,SAAU,CAE5B,GAAIA,IAAS,GAAI,OACjB,MAAMC,EAAOD,EAAK,MAAM,GAAG,EAC3B,IAAIE,EAAmBxF,EAEvB,UAAWT,KAAOgG,EAAM,CACtB,GAAIC,GAAW,MAAQ,OAAOA,GAAY,SAAU,CAClDA,EAAU,OACV,KACF,CACAA,EAAWA,EAAoCjG,CAAG,CACpD,CAGA,OAAI0C,EAAgBuD,CAAO,EACjBA,EAA+B,MAElCA,CACT,CACA,OAAOF,CACT,CAKO,SAASG,EACdzF,EACAsF,EACA5E,EACM,CACN,MAAM6E,EAAO,OAAOD,CAAI,EAAE,MAAM,GAAG,EAC7BI,EAAUH,EAAK,IAAA,EACrB,GAAI,CAACG,EAAS,OACd,MAAMnF,EAASgF,EAAK,OAClB,CAACC,EAAkCjG,KAC7BiG,EAAQjG,CAAG,GAAK,OAAMiG,EAAQjG,CAAG,EAAI,CAAA,GAClCiG,EAAQjG,CAAG,GAEpBS,CAAA,EAIEiC,EAAgB1B,EAAOmF,CAAO,CAAC,EACjCnF,EAAOmF,CAAO,EAAE,MAAQhF,EAExBH,EAAOmF,CAAO,EAAIhF,CAEtB,CAMO,SAASiF,EAAkBC,EAAuB,CACvD,GAAI,CACF,GAAIA,GAAO,OAAOA,GAAQ,SAAU,CAClC,GAAI3D,EAAgB2D,CAAG,EAAG,OAAQA,EAA2B,MAC7D,GAAI,UAAWA,EAAK,CAClB,MAAMC,EAASD,EAA2B,MAE1C,OACEC,GAAU,MAEV,OAAOA,GAAU,UACjB,OAAOA,GAAU,UACjB,OAAOA,GAAU,UAEVA,EAEFD,CACT,CACF,CACF,MAAQ,CAER,CACA,OAAOA,CACT,CAMO,SAASE,EAAkBF,EAA6B,CAC7D,MAAM1D,EAAIyD,EAAkBC,CAAG,EAC/B,GAAI1D,GAAM,KAAyB,OAAO,KAC1C,MAAM6D,EAAI,OAAO7D,EACjB,OAAI6D,IAAM,UAAYA,IAAM,UAAYA,IAAM,UAAkB,OAAO7D,CAAC,EACjE,IACT,CAMO,SAAS8D,EAAgBC,EAAuB,CACrD,GAAI,CAACA,GAAQ,OAAOA,GAAS,SAAU,MAAO,GAE9C,GADIA,IAAS,SACTA,EAAK,SAAS,OAAO,EAAG,MAAO,GAEnC,GAAIA,EAAK,SAAS,GAAG,EACnB,GAAI,CAEF,GADcA,EAAK,MAAM,GAAG,EAClB,KAAM1B,GAAMA,IAAM,OAAO,EAAG,MAAO,EAC/C,MAAQ,CAER,CAEF,MAAO,EACT,CC9hBA,MAAM2B,EAA6C,CACjD,MAAO,+BACP,IAAK,sCACP,EAKO,SAASC,EACdlC,EACA1E,EACAmB,EACM,CACN,GAAI,CACF,GAAI,CAACnB,GAAO,CAACA,EAAI,SAAS,GAAG,EAAG,CAC9B0E,EAAG,aAAa1E,EAAKmB,CAAK,EAC1B,MACF,CACA,MAAM0F,EAAM7G,EAAI,QAAQ,GAAG,EACrBqC,EAASrC,EAAI,UAAU,EAAG6G,CAAG,EAC7BC,EAAQ9G,EAAI,UAAU6G,EAAM,CAAC,EAC7BE,EAAKJ,EAAmBtE,CAAM,EAChC0E,EAAIrC,EAAG,eAAeqC,EAAID,EAAO3F,CAAK,EACrCuD,EAAG,aAAa1E,EAAKmB,CAAK,CACjC,MAAQ,CACN,GAAI,CAEFuD,EAAG,aAAa1E,EAAKmB,CAAK,CAC5B,MAAQ,CAER,CACF,CACF,CAKO,SAAS6F,EAAqBtC,EAAa1E,EAAmB,CACnE,GAAI,CACF,GAAI,CAACA,GAAO,CAACA,EAAI,SAAS,GAAG,EAAG,CAC9B0E,EAAG,gBAAgB1E,CAAG,EACtB,MACF,CACA,MAAM6G,EAAM7G,EAAI,QAAQ,GAAG,EACrBqC,EAASrC,EAAI,UAAU,EAAG6G,CAAG,EAC7BC,EAAQ9G,EAAI,UAAU6G,EAAM,CAAC,EAC7BE,EAAKJ,EAAmBtE,CAAM,EAChC0E,EAAIrC,EAAG,kBAAkBqC,EAAID,CAAK,EACjCpC,EAAG,gBAAgB1E,CAAG,CAC7B,MAAQ,CACN,GAAI,CACF0E,EAAG,gBAAgB1E,CAAG,CACxB,MAAQ,CAER,CACF,CACF,CAQO,MAAMiH,EAAS,6BACTC,EAAY,qCAEZC,EAA4C,CACvD,IAAKF,EACL,KAAMC,CACR"}
|