transone 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/README.zh-CN.md +6 -0
- package/dist/core/app.d.ts +3 -1
- package/dist/core/cleanup.d.ts +7 -0
- package/dist/core/component/base.d.ts +16 -0
- package/dist/index-8qh91wft.js +12 -0
- package/dist/index-8qh91wft.js.map +27 -0
- package/dist/index-sg4er0f8.js +5 -0
- package/dist/{index-jq6fv0br.js.map → index-sg4er0f8.js.map} +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +2 -2
- package/dist/request/index.js +1 -1
- package/dist/router/index.js +1 -1
- package/package.json +1 -1
- package/dist/index-5dxcnfw6.js +0 -12
- package/dist/index-5dxcnfw6.js.map +0 -26
- package/dist/index-jq6fv0br.js +0 -5
package/README.md
CHANGED
|
@@ -255,3 +255,9 @@ bun run lint
|
|
|
255
255
|
## License
|
|
256
256
|
|
|
257
257
|
MIT
|
|
258
|
+
|
|
259
|
+
## Resource cleanup
|
|
260
|
+
|
|
261
|
+
Web runtime components can register owned resources with `this.onDispose(cleanup)`, in registration order, and unregister using its return value. Teardown continues after throwing hooks, children or disposers; repeated unmounts do not repeat cleanup. Single errors retain their identity; multiple errors retain their `errors` collection.
|
|
262
|
+
Request completion releases external abort listeners and timers, including Mini Program hosts whose abort does not invoke a callback.
|
|
263
|
+
See the [cleanup guide and static compilation boundaries](../../docs/reliability.md).
|
package/README.zh-CN.md
CHANGED
|
@@ -27,3 +27,9 @@ TransOne 核心框架包:一份 TypeScript 源码,跨端框架的核心运
|
|
|
27
27
|
bun test # 测试
|
|
28
28
|
bun run build # 构建 dist(ESM + .d.ts)
|
|
29
29
|
```
|
|
30
|
+
|
|
31
|
+
## 资源清理
|
|
32
|
+
|
|
33
|
+
Web 组件可通过 `this.onDispose(cleanup)` 按注册顺序登记资源释放,返回的函数可撤销登记。卸载期间即使钩子、子组件或某个清理函数抛错,也会继续处理其余资源;重复卸载不会重复执行清理。单个异常保留原对象,多个异常汇总并保留 `errors`。
|
|
34
|
+
请求结束后自动释放外部取消监听与定时器;小程序宿主取消不回调时仍能正常结算。
|
|
35
|
+
使用示例和静态编译边界见[诊断与清理](../../docs/reliability.md)。
|
package/dist/core/app.d.ts
CHANGED
|
@@ -36,6 +36,7 @@ export declare class OneApp<TState extends object = Record<string, unknown>, TCo
|
|
|
36
36
|
private container;
|
|
37
37
|
private rootInstance;
|
|
38
38
|
private mounted;
|
|
39
|
+
private unmounting;
|
|
39
40
|
private templateEngine;
|
|
40
41
|
private readonly appContext;
|
|
41
42
|
private readonly providers;
|
|
@@ -60,6 +61,8 @@ export declare class OneApp<TState extends object = Record<string, unknown>, TCo
|
|
|
60
61
|
* 卸载应用
|
|
61
62
|
*/
|
|
62
63
|
unmount(): void;
|
|
64
|
+
private teardown;
|
|
65
|
+
private releaseResources;
|
|
63
66
|
/**
|
|
64
67
|
* 应用是否正在运行
|
|
65
68
|
*/
|
|
@@ -106,7 +109,6 @@ export declare class OneApp<TState extends object = Record<string, unknown>, TCo
|
|
|
106
109
|
private mergeDocumentScripts;
|
|
107
110
|
private onMounted;
|
|
108
111
|
private onUpdated;
|
|
109
|
-
private onBeforeUnmount;
|
|
110
112
|
}
|
|
111
113
|
/**
|
|
112
114
|
* 创建应用实例
|
|
@@ -27,6 +27,9 @@ export declare abstract class Component<TProps extends ComponentProps = Componen
|
|
|
27
27
|
private readonly providers;
|
|
28
28
|
private readonly updateEffect;
|
|
29
29
|
private appContext;
|
|
30
|
+
private disposed;
|
|
31
|
+
private unmounting;
|
|
32
|
+
private readonly disposers;
|
|
30
33
|
private parentComponent;
|
|
31
34
|
private elementChangeListener;
|
|
32
35
|
protected styleManager: StyleManager;
|
|
@@ -39,7 +42,20 @@ export declare abstract class Component<TProps extends ComponentProps = Componen
|
|
|
39
42
|
mount(container: HTMLElement): void;
|
|
40
43
|
mountToNode(): Node;
|
|
41
44
|
update(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Teardown order: beforeUnmount, descendants, FIFO disposers, framework
|
|
47
|
+
* bindings/styles/effect, DOM and references, then onUnmounted. Every stage
|
|
48
|
+
* runs even after failures; repeated/reentrant calls do nothing.
|
|
49
|
+
*/
|
|
42
50
|
unmount(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Register instance-owned resources (timers, subscriptions, cancellation).
|
|
53
|
+
* Callbacks run once, in registration order, after descendants. The returned
|
|
54
|
+
* function unregisters without running the callback. Registrations during or
|
|
55
|
+
* after teardown run immediately; a later mount starts a fresh resource scope.
|
|
56
|
+
* An immediate callback's error is thrown to its caller.
|
|
57
|
+
*/
|
|
58
|
+
protected onDispose(cleanup: () => void): () => void;
|
|
43
59
|
setProps(props: Partial<TProps>): void;
|
|
44
60
|
setState(state: Partial<TState>): void;
|
|
45
61
|
setAppContext(context: unknown): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import{Da as re,Ea as fe,Fa as q}from"./index-ryj080w6.js";import{gb as j}from"./index-dse0chhf.js";class l{errors=[];attempt(e){try{e()}catch(t){this.errors.push(t)}}add(e){this.errors.push(e)}throwIfAny(e){if(this.errors.length===1)throw this.errors[0];if(this.errors.length>1){let t=globalThis.AggregateError;if(t)throw new t(this.errors,e);let n=Error(e);throw n.name="AggregateError",n.errors=this.errors,n}}}var E=Symbol("is_reactive"),h=Symbol("is_readonly"),B=Symbol("is_ref"),Y=["push","pop","shift","unshift","splice","sort","reverse"];function f(e,t){return Boolean(Reflect.get(e,t))}function m(e){return e!==null&&typeof e==="object"}class D{pending=new Set;flushing=!1;flushPromise=null;flushResolve=null;enqueue(e){if(this.pending.has(e))return;if(this.pending.add(e),!this.flushing)queueMicrotask(()=>this.flush())}flush(){if(this.flushing)return;this.flushing=!0;try{while(this.pending.size>0){let e=Array.from(this.pending);this.pending.clear();for(let t of e)if(t.active)t()}}finally{this.flushing=!1;let e=this.flushResolve;this.flushResolve=null,this.flushPromise=null,e?.()}}nextTick(){if(!this.flushing&&this.pending.size===0)return Promise.resolve();if(this.flushPromise)return this.flushPromise;return this.flushPromise=new Promise((e)=>{this.flushResolve=e}),this.flushPromise}}var be=0,w=new D;function Qe(){return w.nextTick()}function Ze(){w.flush()}class g{static instance;activeEffect=null;effectStack=[];targetMap=new WeakMap;reactiveMap=new WeakMap;readonlyMap=new WeakMap;proxyMap=new WeakMap;constructor(){}static getInstance(){if(!g.instance)g.instance=new g;return g.instance}reactive(e){if(!m(e))return console.warn("reactive: target must be an object"),e;if(Ee(e))return e;if(this.reactiveMap.has(e))return this.reactiveMap.get(e);if(Array.isArray(e))return this.createReactiveArray(e);let t=new Proxy(e,{get:(n,r)=>{if(r===E)return!0;if(r===h)return!1;this.track(n,r);let o=Reflect.get(n,r);if(m(o)&&!f(o,h))return this.reactive(o);return o},set:(n,r,o)=>{if(f(n,h))return console.warn(`Cannot set property ${String(r)} on readonly object`),!1;let i=Reflect.get(n,r);if(m(o)&&!f(o,E)&&!f(o,h))o=this.reactive(o);let s=Reflect.set(n,r,o);if(i!==o)this.trigger(n,r);return s},deleteProperty:(n,r)=>{if(f(n,h))return console.warn(`Cannot delete property ${String(r)} on readonly object`),!1;let o=r in n,i=Reflect.deleteProperty(n,r);if(o)this.trigger(n,r);return i}});return this.reactiveMap.set(e,t),this.proxyMap.set(t,e),t}toRawValue(e){if(m(e)&&this.proxyMap.has(e))return this.proxyMap.get(e);return e}createReactiveArray(e){if(this.reactiveMap.has(e))return this.reactiveMap.get(e);let t=new Proxy(e,{get:(n,r)=>{if(r===E)return!0;if(r===h)return!1;this.track(n,r);let o=Reflect.get(n,r);if(typeof r==="string"&&(r==="includes"||r==="indexOf"||r==="lastIndexOf")){this.track(n,"length");for(let s=0;s<n.length;s++)this.track(n,String(s));let i=o;return(...s)=>{let a=i.apply(n,s);if(a===!1||a===-1){let p=n.map((d)=>this.toRawValue(d));return p[r].apply(p,s.map((d)=>this.toRawValue(d)))}return a}}if(typeof r==="string"&&Y.includes(r))return(...i)=>{let a=o.apply(n,i);return this.trigger(n,"length"),this.trigger(n,r),a};if(m(o)&&!f(o,h))return this.reactive(o);return o},set:(n,r,o)=>{if(f(n,h))return console.warn(`Cannot set property ${String(r)} on readonly object`),!1;let i=Reflect.get(n,r);if(m(o)&&!f(o,E)&&!f(o,h))o=this.reactive(o);let s=Reflect.set(n,r,o);if(i!==o){if(this.trigger(n,r),typeof r==="string"&&!isNaN(Number(r)))this.trigger(n,"length")}return s},deleteProperty:(n,r)=>{if(f(n,h))return console.warn(`Cannot delete property ${String(r)} on readonly object`),!1;let o=r in n,i=Reflect.deleteProperty(n,r);if(o)this.trigger(n,r),this.trigger(n,"length");return i}});return this.reactiveMap.set(e,t),this.proxyMap.set(t,e),t}readonly(e){if(!m(e))return console.warn("readonly: target must be an object"),e;if(f(e,h))return e;if(this.readonlyMap.has(e))return this.readonlyMap.get(e);let t=new Proxy(e,{get:(n,r)=>{if(r===E)return!1;if(r===h)return!0;let o=Reflect.get(n,r);if(m(o))return this.readonly(o);return o},set:()=>(console.warn("Cannot set property on readonly object"),!1),deleteProperty:()=>(console.warn("Cannot delete property on readonly object"),!1)});return this.readonlyMap.set(e,t),t}effect(e,t){let{lazy:n=!1,scheduler:r,throwOnError:o=!1}=t||{},i=()=>{if(!i.active)return e();try{return this.cleanup(i),this.effectStack.push(i),this.activeEffect=i,e()}catch(s){if(o)throw s;console.error("Effect error:",s);return}finally{this.effectStack.pop(),this.activeEffect=this.effectStack[this.effectStack.length-1]??null}};if(i.id=be++,i.deps=[],i.active=!0,i.scheduler=r,!n)i();return i}runWithEffect(e,t){this.effectStack.push(e),this.activeEffect=e;try{return t()}finally{this.effectStack.pop(),this.activeEffect=this.effectStack[this.effectStack.length-1]??null}}computed(e){let t=!0,n,r={},o=()=>{this.track(r,"value")},i=this.effect(()=>{n=e(),t=!1},{lazy:!0,scheduler:()=>{if(!t)t=!0,this.trigger(r,"value")}});return{get value(){if(t)i();return o(),n}}}cleanup(e){e.deps.forEach((t)=>{t.delete(e)}),e.deps.length=0}track(e,t){if(!this.activeEffect||!this.activeEffect.active)return;let n=this.targetMap.get(e);if(!n)n=new Map,this.targetMap.set(e,n);let r=n.get(t);if(!r)r=new Set,n.set(t,r);if(!r.has(this.activeEffect))r.add(this.activeEffect),this.activeEffect.deps.push(r)}trigger(e,t){let n=this.targetMap.get(e);if(!n)return;let r=n.get(t);if(!r)return;new Set(r).forEach((i)=>{if(i.active)if(i.scheduler)i.scheduler(i);else i()})}stop(e){if(e.active)this.cleanup(e),e.active=!1}}function K(e){return g.getInstance().reactive(e)}function Je(e){return g.getInstance().readonly(e)}function y(e,t){return g.getInstance().effect(e,t)}function Xe(e){return g.getInstance().computed(e)}function et(e){let t={value:e};return Object.defineProperty(t,B,{configurable:!1,enumerable:!1,value:!0}),K(t)}function Q(e){return m(e)&&Boolean(Reflect.get(e,B))}function tt(e){return Q(e)?e.value:e}function C(e){g.getInstance().stop(e)}function U(e,t){if(!m(e)||t.has(e))return;if(t.add(e),Array.isArray(e)){e.forEach((n)=>U(n,t));return}Object.keys(e).forEach((n)=>{U(e[n],t)})}function nt(e,t,n={}){let r=g.getInstance(),o=Q(e)?()=>e.value:e,i,s=null,a=()=>{if(!u.active)return;s?.(),s=null;let d=p();t(d,i,(v)=>{s=v}),i=d},p=y(()=>{let d=o();if(n.deep&&m(d))U(d,new Set);return d},{lazy:!0,scheduler:()=>{if(n.sync)a();else w.enqueue(u)}}),u=y(()=>{a()},{lazy:!0});if(n.immediate)a();else i=p();return()=>{r.stop(p),r.stop(u)}}function Ee(e){return m(e)&&f(e,E)}function rt(e){return m(e)&&f(e,h)}function R(e){if(e===void 0||e===null)return[];return Array.isArray(e)?e:[e]}function Z(e){return typeof e==="object"&&e!==null&&"component"in e}function J(e){return typeof e==="object"&&e!==null&&"tag"in e&&e.tag!=="slot"}function X(e){return typeof e==="object"&&e!==null&&"tag"in e&&e.tag==="slot"}function it(e,t,n,r,o,i){return{tag:e,props:t,children:n,listeners:r,key:o,directions:i}}function xe(e,t={}){return{tag:e,...t}}function c(e){return(t={})=>xe(e,t)}var A=c("div"),st=c("span"),at=c("p"),pt=c("button"),ct=c("input"),ut=c("section"),lt=c("main"),dt=c("header"),ht=c("footer"),ft=c("nav"),mt=c("article"),gt=c("aside"),vt=c("h1"),yt=c("h2"),Rt=c("h3"),Ct=c("h4"),bt=c("h5"),Et=c("h6"),xt=c("strong"),Tt=c("em"),wt=c("small"),St=c("pre"),Pt=c("code"),At=c("blockquote"),Lt=c("ul"),Mt=c("ol"),Nt=c("li"),It=c("a"),kt=c("img"),Ht=c("form"),jt=c("label"),Ot=c("textarea"),_t=c("select"),Vt=c("option"),Bt=c("table"),Dt=c("thead"),$t=c("tbody"),Ut=c("tr"),Kt=c("th"),Wt=c("td");function Ft(e,t,n,r,o){if(typeof e==="function")return{component:e,props:t,children:n,key:r,directions:o};return{component:e.component,props:e.props,children:e.children,key:e.key,directions:e.directions,emitters:e.emitters}}function zt(e,t,n){return{tag:"slot",props:{name:e},key:t,directions:n}}function Gt(e,t,n){return e.map((r,o)=>{let i=t(r,o);if(typeof i==="string")throw Error("each render callback must return a VNode");if(!n)return i;return{...i,key:n(r,o)}})}function te(e){let t=e.split(".");if(e.length===0||t.some((n)=>n.length===0||n==="__proto__"||n==="prototype"||n==="constructor"))throw Error(`Invalid model path "${e}"`);return t}function F(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function ne(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function Te(e){return typeof e==="string"?e:e.path}function ee(e,t){let n=e;for(let r of te(t)){if(!F(n))throw Error(`Invalid model path "${t}"`);if(!ne(n,r)){if(r in n)throw Error(`Invalid model path "${t}"`);return}n=n[r]}return n}function we(e,t,n){let r=te(t),o=e;for(let s of r.slice(0,-1)){if(!ne(o,s)){if(s in o)throw Error(`Invalid model path "${t}"`);o[s]={}}else if(!F(o[s]))throw Error(`Invalid model path "${t}"`);let a=o[s];if(!F(a))throw Error(`Invalid model path "${t}"`);o=a}let i=r[r.length-1];o[i]=n}function W(e,t){if(typeof e!=="string"&&e.format)return e.format(t);return t===void 0||t===null?"":String(t)}function Se(e,t){if(typeof e!=="string"&&e.parse)return e.parse(t);return t}function Pe(e,t,n){if(e instanceof HTMLInputElement){if(e.type==="checkbox"){e.checked=Array.isArray(n)?n.some((r)=>String(r)===e.value):Boolean(n);return}if(e.type==="radio"){e.checked=n===e.value;return}e.value=W(t,n);return}if(e instanceof HTMLTextAreaElement){e.value=W(t,n);return}if(e instanceof HTMLSelectElement){if(e.multiple){let r=Array.isArray(n)?new Set(n.map(String)):new Set;for(let o=0;o<e.options.length;o+=1){let i=e.options.item(o);if(!i)continue;i.selected=r.has(i.value)}return}e.value=W(t,n)}}function Ae(e,t){if(e instanceof HTMLInputElement){if(e.type==="checkbox"){if(Array.isArray(t)){let n=t.filter((r)=>String(r)!==e.value);return e.checked?[...n,e.value]:n}return e.checked}if(e.type==="radio")return e.checked?e.value:t;return e.value}if(e instanceof HTMLTextAreaElement)return e.value;if(e instanceof HTMLSelectElement){if(!e.multiple)return e.value;let n=[];for(let r=0;r<e.selectedOptions.length;r+=1){let o=e.selectedOptions.item(r);if(o)n.push(o.value)}return n}return}class z{bindings=new WeakMap;bind(e,t,n){if(!this.isSupportedControl(e))return;let r=this.bindings.get(e);if(r&&this.sameBinding(r,t))return;this.cleanup(e);let o=Te(t),i=()=>Pe(e,t,ee(n,o)),s=e instanceof HTMLTextAreaElement||e instanceof HTMLInputElement&&!["checkbox","radio"].includes(e.type)?"input":"change",a=()=>{let u=ee(n,o);we(n,o,Se(t,Ae(e,u)))};e.addEventListener(s,a);let p=y(i);this.bindings.set(e,{binding:t,path:o,parse:typeof t==="string"?void 0:t.parse,format:typeof t==="string"?void 0:t.format,eventName:s,listener:a,effect:p})}cleanup(e){let t=this.bindings.get(e);if(!t)return;e.removeEventListener(t.eventName,t.listener),C(t.effect),this.bindings.delete(e)}isSupportedControl(e){return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement}sameBinding(e,t){if(typeof e.binding==="string"||typeof t==="string")return e.binding===t;return e.path===t.path&&e.parse===t.parse&&e.format===t.format}}function M(e){return/^on[A-Z]/.test(e)||/^on[a-z]/.test(e)}function oe(e){return e.slice(2).toLowerCase()}function ie(e){let[t,...n]=e.split(".");return{eventName:t,modifiers:new Set(n)}}function se(e,t){let n=(r)=>{if(t.has("stop"))r.stopPropagation();if(t.has("prevent"))r.preventDefault();if(t.has("self")&&r.currentTarget!==r.target)return;if(t.has("once"))r.currentTarget.removeEventListener(r.type,n);e(r)};return n}function ae(e,t,n){let r=t.includes("-")?t:t.replace(/[A-Z]/g,(o)=>`-${o.toLowerCase()}`);e.setProperty(r,re(n))}var N=null;function pe(e){if(!e||!(e instanceof I))throw Error("Invalid router instance");N=e}function Le(){if(!N)throw Error("Router is not initialized. Please make sure you have installed the router plugin.");return N}function ce(){return N}var ue="http://www.w3.org/2000/svg",Me=new Set(["svg","g","defs","rect","circle","ellipse","line","polyline","polygon","path","text","tspan","textPath","use","symbol","marker","linearGradient","radialGradient","stop","pattern","mask","clipPath","foreignObject"]);class H{listeners=new WeakMap;effects=new WeakMap;modelBindings=new z;matches(e){return typeof e==="object"&&e!==null&&J(e)}mount(e,t){if(e.directions?.if===!1)return document.createComment("if");let n=e.tag==="navigator",r=n?document.createElement("a"):Me.has(e.tag)?document.createElementNS(ue,e.tag):document.createElement(e.tag);try{let o=e.props??{};if(n){let{url:i,openType:s,...a}=o,p=typeof i==="string"?i:"#";r.setAttribute("href",p);let u=(d)=>{let v=ce();if(v)d.preventDefault(),v.push(r.getAttribute("href")??"#")};r.addEventListener("click",u),this.listeners.set(r,new Map([["navigator",{eventName:"click",listener:u}]])),this.applyProps(r,{},a,t)}else this.applyProps(r,{},o,t);return this.updateListeners(r,{},this.collectListeners(e)),this.mountChildren(r,e,t),this.applyDirections(r,void 0,e.directions,t),r}catch(o){let i=new l;throw i.add(o),i.attempt(()=>this.unmount(e,r,t)),i.throwIfAny("Element initialization and cleanup failed"),o}}patch(e,t,n,r){if(e.tag!==t.tag||n.nodeType===Node.COMMENT_NODE){let i=this.mount(t,r);return n.parentNode?.replaceChild(i,n),this.unmount(e,n,r),i}if(!(n instanceof Element))return n;if(t.directions?.if===!1){let i=document.createComment("if");return n.parentNode?.replaceChild(i,n),this.unmount(e,n,r),i}if(t.tag==="navigator"||e.tag==="navigator"){let i=e.props??{},s=t.props??{},a=typeof i.url==="string"?i.url:"",p=typeof s.url==="string"?s.url:"";if(a!==p)n.setAttribute("href",p);let u={...s};delete u.url,delete u.openType,this.applyProps(n,i,u,r)}else this.applyProps(n,e.props??{},t.props??{},r);return this.updateListeners(n,this.collectListeners(e),this.collectListeners(t)),this.updateChildren(n,e,t,r),this.applyDirections(n,e.directions,t.directions,r),n}unmount(e,t,n){if(!(t instanceof Element))return;let r=new l;this.effects.get(t)?.forEach((o)=>r.attempt(()=>C(o))),this.effects.delete(t),this.listeners.get(t)?.forEach(({eventName:o,listener:i})=>{r.attempt(()=>t.removeEventListener(o,i))}),this.listeners.delete(t),r.attempt(()=>this.modelBindings.cleanup(t)),r.attempt(()=>this.unmountChildren(t,e,n)),r.throwIfAny("Element teardown failed")}mountChildren(e,t,n){R(t.children).forEach((r)=>{e.appendChild(n.renderer.mount(r,n))})}updateChildren(e,t,n,r){this.updateOrdinaryChildren(e,R(t.children),R(n.children),r)}unmountChildren(e,t,n){let r=Array.from(e.childNodes),o=new l;R(t.children).forEach((i,s)=>{let a=r[s];if(a)o.attempt(()=>n.renderer.unmount(i,a,n))}),o.throwIfAny("Element children teardown failed")}applyProps(e,t,n,r){Object.keys(t).forEach((o)=>{if(M(o)||o in n)return;if(o==="className"||o==="class")e.removeAttribute("class");else if(o==="style")e.removeAttribute("style");else if(o==="value"&&typeof e==="object"&&e!==null&&"value"in e)e.value="";else e.removeAttribute(k(o))}),Object.entries(n).forEach(([o,i])=>{if(M(o))return;if(t[o]===i)return;if(o==="className"||o==="class"){if(e.namespaceURI===ue)e.setAttribute("class",String(i??""));else e.className=String(i??"");return}if(o==="value"&&typeof e==="object"&&e!==null&&"value"in e){e.value=String(i??"");return}if(o==="style"&&typeof i==="object"&&i!==null){e.removeAttribute("style");let s=e.style;Object.entries(i).forEach(([a,p])=>{ae(s,a,p)});return}if(i===!1||i===void 0||i===null){e.removeAttribute(k(o));return}if(i===!0){e.setAttribute(k(o),"");return}if(typeof i==="string"&&r.templateEngine.hasExpressions(i)){this.setupReactiveAttribute(e,o,i,r);return}e.setAttribute(k(o),String(i))})}applyDirections(e,t,n,r){if(n&&"show"in n)e.style.display=n.show?"":"none";else if(t&&"show"in t)e.style.display="";if(!n?.model){this.modelBindings.cleanup(e);return}this.modelBindings.bind(e,n.model,r.templateEngine.state)}updateOrdinaryChildren(e,t,n,r){if(this.assertNoDuplicateKeys(t),this.assertNoDuplicateKeys(n),this.hasOnlyKeyedChildren(t,n)){this.updateKeyedChildren(e,t,n,r);return}let o=Math.min(t.length,n.length);for(let s=0;s<o;s+=1){let a=e.childNodes[s];if(!a){e.appendChild(r.renderer.mount(n[s],r));continue}r.renderer.patch(t[s],n[s],a,r)}for(let s=o;s<n.length;s+=1)e.appendChild(r.renderer.mount(n[s],r));let i=new l;for(let s=t.length-1;s>=n.length;s-=1){let a=e.childNodes[s];if(a)i.attempt(()=>r.renderer.unmount(t[s],a,r)),i.attempt(()=>{if(a.parentNode===e)e.removeChild(a)})}i.throwIfAny("Removed element children teardown failed")}updateKeyedChildren(e,t,n,r){let o=t.map((p,u)=>({vnode:p,node:e.childNodes[u],index:u})),i=new Map,s=new Set;o.forEach((p)=>{let u=this.getVNodeKey(p.vnode);if(u!==void 0&&p.node)i.set(u,{vnode:p.vnode,node:p.node,index:p.index})}),n.forEach((p,u)=>{let d=this.getVNodeKey(p),v=d===void 0?void 0:i.get(d),b;if(v)b=r.renderer.patch(v.vnode,p,v.node,r),s.add(v.index);else b=r.renderer.mount(p,r);let V=e.childNodes[u]??null;if(b!==V)e.insertBefore(b,V)});let a=new l;o.forEach((p)=>{if(!p.node||s.has(p.index))return;let u=p.node;a.attempt(()=>r.renderer.unmount(p.vnode,u,r)),a.attempt(()=>{if(u.parentNode===e)e.removeChild(u)})}),a.throwIfAny("Removed keyed children teardown failed")}hasOnlyKeyedChildren(e,t){return[...e,...t].every((n)=>this.getVNodeKey(n)!==void 0)}assertNoDuplicateKeys(e){let t=new Set;e.forEach((n)=>{let r=this.getVNodeKey(n);if(r===void 0)return;if(t.has(r))throw Error(`Duplicate key "${r}"`);t.add(r)})}getVNodeKey(e){if(typeof e==="string")return;return e.key}collectListeners(e){let t={};return Object.entries(e.props??{}).forEach(([n,r])=>{if(M(n)&&typeof r==="function")t[oe(n)]=r}),{...t,...e.listeners??{}}}updateListeners(e,t,n){let r=this.listeners.get(e)??new Map,o=new Set(Object.keys(t)),i=new Set(Object.keys(n));o.forEach((s)=>{if(!i.has(s)||t[s]!==n[s]){let a=r.get(s);if(a)e.removeEventListener(a.eventName,a.listener),r.delete(s)}}),i.forEach((s)=>{if(!o.has(s)||t[s]!==n[s]){let{eventName:a,modifiers:p}=ie(s),u=typeof e.tagName==="string"&&e.tagName.toLowerCase()==="textarea",d=a==="confirm"&&!u?"keydown":a,v=se((b)=>{if(d==="keydown"){if(b.key!=="Enter")return}n[s](b)},p);e.addEventListener(d,v),r.set(s,{eventName:d,listener:v})}}),this.listeners.set(e,r)}setupReactiveAttribute(e,t,n,r){let o=y(()=>{e.setAttribute(t,r.templateEngine.evaluateTemplateValue(n))});this.trackEffect(e,o)}trackEffect(e,t){let n=this.effects.get(e)??new Set;n.add(t),this.effects.set(e,n)}}function k(e){if(e.startsWith("data")&&e.length>4)return`data${e.slice(4).replace(/[A-Z]/g,(t)=>`-${t.toLowerCase()}`)}`;if(e==="tabIndex"||e==="colSpan"||e==="htmlFor")return e.toLowerCase();return e}class L{strategies;constructor(){this.strategies=[new le,new de,new he,new H]}mount(e,t){return this.findStrategy(e).mount(e,t)}patch(e,t,n,r){let o=this.findStrategy(e),i=this.findStrategy(t);if(o!==i){let s=i.mount(t,r);return n.parentNode?.replaceChild(s,n),o.unmount(e,n,r),s}return o.patch(e,t,n,r)}unmount(e,t,n){this.findStrategy(e).unmount(e,t,n)}findStrategy(e){let t=this.strategies.find((n)=>n.matches(e));if(!t)throw Error("No render strategy found for vnode");return t}}class le{matches(e){return typeof e==="string"}mount(e,t){return t.templateEngine.parseTemplate(e)}patch(e,t,n,r){if(e===t)return n;let o=this.mount(t,r);return n.parentNode?.replaceChild(o,n),o}unmount(){}}class de{instances=new WeakMap;instanceNodes=new Map;emitterUnsubscribers=new WeakMap;matches(e){return typeof e==="object"&&e!==null&&Z(e)}mount(e,t){if(e.directions?.if===!1)return document.createComment("if");let n=j(e.component,this.createProps(e));try{if(t.appContext&&n.setAppContext)n.setAppContext(t.appContext);this.syncEmitters(n,e.emitters??{}),t.registerChild(n);let r=n.mountToNode();return this.trackInstanceNode(n,r),n.setElementChangeListener?.((o,i)=>{this.trackInstanceNode(n,o),this.trackInstanceNode(n,i)}),r}catch(r){let o=new l;throw o.add(r),o.attempt(()=>this.clearEmitters(n)),o.attempt(()=>n.unmount()),this.clearInstanceNodes(n),o.attempt(()=>t.unregisterChild(n)),o.throwIfAny("Child initialization and cleanup failed"),r}}patch(e,t,n,r){if(n.nodeType===Node.COMMENT_NODE){let s=this.mount(t,r);return n.parentNode?.replaceChild(s,n),this.unmount(e,n,r),s}if(t.directions?.if===!1){let s=document.createComment("if");return n.parentNode?.replaceChild(s,n),this.unmount(e,n,r),s}let o=this.instances.get(n);if(o&&e.component===t.component){this.syncEmitters(o,t.emitters??{}),o.setProps(this.createProps(t));let s=o.getElement()??n;return this.trackInstanceNode(o,s),s}let i=this.mount(t,r);return n.parentNode?.replaceChild(i,n),this.unmount(e,n,r),i}unmount(e,t,n){let r=this.instances.get(t);if(r){let o=new l;o.attempt(()=>this.clearEmitters(r)),o.attempt(()=>r.unmount()),this.clearInstanceNodes(r),o.attempt(()=>n.unregisterChild(r)),o.throwIfAny("Child teardown failed")}}createProps(e){return{...e.props??{},children:R(e.children)}}syncEmitters(e,t){let n=this.emitterUnsubscribers.get(e)??new Map;n.forEach(({listener:r,unsubscribe:o},i)=>{let s=t[i];if(!s||s!==r)o(),n.delete(i)}),Object.entries(t).forEach(([r,o])=>{if(n.get(r)?.listener===o)return;n.set(r,{listener:o,unsubscribe:e.on(r,o)})}),this.emitterUnsubscribers.set(e,n)}clearEmitters(e){let t=new l;this.emitterUnsubscribers.get(e)?.forEach(({unsubscribe:n})=>{t.attempt(n)}),this.emitterUnsubscribers.delete(e),t.throwIfAny("Component emitter cleanup failed")}trackInstanceNode(e,t){this.instances.set(t,e);let n=this.instanceNodes.get(e)??new Set;n.add(t),this.instanceNodes.set(e,n)}clearInstanceNodes(e){this.instanceNodes.get(e)?.forEach((t)=>{this.instances.delete(t)}),this.instanceNodes.delete(e)}}class he{renderedChildren=new WeakMap;matches(e){return typeof e==="object"&&e!==null&&X(e)}mount(e,t){if(e.directions?.if===!1)return document.createComment("if");let n=document.createElement("div");n.setAttribute("data-slot",e.props.name);try{return this.mountSlotChildren(n,this.resolveChildren(e,t),t),n}catch(r){let o=new l;throw o.add(r),o.attempt(()=>this.unmount(e,n,t)),o.throwIfAny("Slot initialization and cleanup failed"),r}}patch(e,t,n,r){if(n.nodeType===Node.COMMENT_NODE){let o=this.mount(t,r);return n.parentNode?.replaceChild(o,n),o}if(t.directions?.if===!1){let o=document.createComment("if");return n.parentNode?.replaceChild(o,n),this.unmount(e,n,r),o}if(n instanceof HTMLElement)n.setAttribute("data-slot",t.props.name),this.replaceSlotChildren(n,e,t,r);return n}unmount(e,t,n){if(!(t instanceof HTMLElement))return;let r=new l;r.attempt(()=>this.unmountSlotChildren(t,n)),this.renderedChildren.delete(t),r.throwIfAny("Slot teardown failed")}resolveChildren(e,t){return t.slots[e.props.name]??R(e.children)}replaceSlotChildren(e,t,n,r){let o=this.renderedChildren.get(e)??[],i=this.resolveChildren(n,r),s=Math.min(o.length,i.length);for(let p=0;p<s;p+=1){let u=e.childNodes[p];if(!u){e.appendChild(r.renderer.mount(i[p],r));continue}r.renderer.patch(o[p],i[p],u,r)}for(let p=s;p<i.length;p+=1)e.appendChild(r.renderer.mount(i[p],r));let a=new l;for(let p=o.length-1;p>=i.length;p-=1){let u=e.childNodes[p];if(u)a.attempt(()=>r.renderer.unmount(o[p],u,r)),a.attempt(()=>{if(u.parentNode===e)e.removeChild(u)})}this.renderedChildren.set(e,i),a.throwIfAny("Removed slot children teardown failed")}mountSlotChildren(e,t,n){let r=[];this.renderedChildren.set(e,r),t.forEach((o)=>{e.appendChild(n.renderer.mount(o,n)),r.push(o)})}unmountSlotChildren(e,t){let n=this.renderedChildren.get(e)??[],r=Array.from(e.childNodes),o=new l;n.forEach((i,s)=>{let a=r[s];if(a)o.attempt(()=>t.renderer.unmount(i,a,t))}),o.throwIfAny("Slot children teardown failed")}}class x{state;bindings=[];templateRegex=/{{(.*?)}}/g;constructor(e){this.state=e;if(!e||typeof e!=="object")throw Error("TemplateEngine requires a valid state object")}parseTemplate(e){if(typeof e!=="string")e=String(e);let t=document.createTextNode("");this.templateRegex.lastIndex=0;let n=Array.from(e.matchAll(this.templateRegex));if(n&&n.length>0)this.setupReactiveBindings(t,e,n);else t.textContent=e;return t}setupReactiveBindings(e,t,n){let r=new Set,o=this.evaluateTemplate(t,n,r);e.textContent=o;let i=y(()=>{try{let s=this.evaluateTemplate(t,n,r);if(e.textContent!==s)e.textContent=s}catch(s){console.error("Template update error:",s),e.textContent=`Error: ${s instanceof Error?s.message:"Unknown error"}`}});this.bindings.push({node:e,originalText:t,effect:i})}evaluateTemplate(e,t,n){let r=e;return t.forEach((o)=>{let i=o[1]?.trim();if(i){n.add(i);let s=this.getValueFromState(i),a=s===void 0||s===null?"":String(s);r=r.replace(o[0],a)}}),r}getValueFromState(e){if(!e)return;let t=e.split("."),n=this.state;for(let r of t){if(!n||typeof n!=="object")return;n=n[r]}return n}clearBindings(){this.bindings.forEach((e)=>{C(e.effect)}),this.bindings=[]}getBindingCount(){return this.bindings.length}hasExpressions(e){return this.templateRegex.lastIndex=0,this.templateRegex.test(e)}extractKeys(e){let t=[],n,r=new RegExp(this.templateRegex,"g");while((n=r.exec(e))!==null){let o=n[1]?.trim();if(o)t.push(o)}return t}evaluateTemplateValue(e){this.templateRegex.lastIndex=0;let t=Array.from(e.matchAll(this.templateRegex));if(!t||t.length===0)return e;let n=new Set;return this.evaluateTemplate(e,t,n)}}class T{props;vnode=null;el=null;renderer=new L;templateEngine;childComponents=new Set;eventListeners={};providers=new Map;updateEffect;appContext=null;disposed=!1;unmounting=!1;disposers=new Set;parentComponent=null;elementChangeListener=null;styleManager;state;mounted=!1;constructor(e={}){this.props=e;this.styleManager=new fe,this.state=K(this.initState()??{}),this.templateEngine=new x(this.state),this.initStyles(),this.updateEffect=y(()=>{if(this.mounted)try{this.update()}catch(t){if(!this.dispatchError(t))throw t}},{throwOnError:!0,scheduler:(t)=>{w.enqueue(t)}})}mount(e){if(!e||!(e instanceof HTMLElement))throw Error("Invalid container element");try{e.appendChild(this.mountToNode())}catch(t){let n=new l;n.add(t),n.attempt(()=>this.unmount()),console.error("组件渲染错误:",t),n.throwIfAny("Component mount and cleanup failed")}}mountToNode(){if(this.mounted&&this.el)return this.el;if(this.unmounting)throw Error("Cannot mount a component during teardown");try{if(this.disposed)this.disposed=!1,this.updateEffect.active=!0,this.initStyles();return this.beforeMount(),this.el=g.getInstance().runWithEffect(this.updateEffect,()=>(this.vnode=this.render(),this.renderer.mount(this.vnode,this.createRenderContext()))),this.mounted=!0,this.onMounted(),this.el}catch(e){let t=new l,n=!1;if(t.attempt(()=>{n=this.dispatchError(e)}),!n)t.add(e);return t.attempt(()=>this.unmount()),t.throwIfAny("Component mount and cleanup failed"),document.createComment("error-boundary")}}update(){if(this.unmounting||this.disposed||!this.el||!this.vnode)return;this.beforeUpdate();let e=this.vnode,t=this.el;if(this.el=g.getInstance().runWithEffect(this.updateEffect,()=>{let n=this.render(),r=this.renderer.patch(e,n,t,this.createRenderContext());return this.vnode=n,r}),t!==this.el)this.elementChangeListener?.(t,this.el);this.onUpdated(),this.onPropsChange()}unmount(){if(this.disposed||this.unmounting)return;this.unmounting=!0,this.disposed=!0;let e=this.mounted,t=new l;if(e)t.attempt(()=>this.beforeUnmount());if(this.vnode&&this.el)t.attempt(()=>this.renderer.unmount(this.vnode,this.el,this.createRenderContext()));for(let n of Array.from(this.childComponents))t.attempt(()=>n.unmount()),t.attempt(()=>n.setParentComponent?.(null));this.childComponents.clear();for(let n of Array.from(this.disposers))if(this.disposers.delete(n))t.attempt(n);for(let n of Object.keys(this.eventListeners))this.eventListeners[n].clear(),delete this.eventListeners[n];if(this.providers.clear(),this.parentComponent=null,this.elementChangeListener=null,this.appContext=null,t.attempt(()=>this.templateEngine.clearBindings()),t.attempt(()=>this.styleManager.destroy()),t.attempt(()=>C(this.updateEffect)),t.attempt(()=>this.el?.parentNode?.removeChild(this.el)),this.el=null,this.vnode=null,this.mounted=!1,e)t.attempt(()=>this.onUnmounted());this.unmounting=!1,t.throwIfAny("Component teardown failed")}onDispose(e){if(this.disposed||this.unmounting)return e(),()=>{};let t=()=>e();return this.disposers.add(t),()=>{this.disposers.delete(t)}}setProps(e){if(this.props={...this.props,...e},this.mounted)w.enqueue(this.updateEffect)}setState(e){Object.assign(this.state,e)}setAppContext(e){this.appContext=e,this.childComponents.forEach((t)=>{t.setAppContext?.(e)})}setParentComponent(e){this.parentComponent=e}getParentComponent(){return this.parentComponent}setElementChangeListener(e){this.elementChangeListener=e}provide(e,t){this.providers.set(e,t)}inject(e,t){let n=this.resolveInjection(e);return n.found?n.value:t}resolveInjection(e){if(this.providers.has(e))return{found:!0,value:this.providers.get(e)};if(this.parentComponent?.resolveInjection)return this.parentComponent.resolveInjection(e);return this.resolveAppInjection(e)}getElement(){return this.el}beforeMount(){}onMounted(){}beforeUpdate(){}onUpdated(){}onPropsChange(){}beforeUnmount(){}onUnmounted(){}dispatchError(e){let t=this.getParentComponent();while(t){let n=t;if(typeof n.onErrorCaptured==="function"){if(n.onErrorCaptured(e,this)===!1)return!0}t=t.getParentComponent?.()??null}return!1}getContext(){return this.appContext}get router(){return this.getRouterFrom(this.appContext)??this.getRouterFromGlobalApp()}emit(e,...t){this.eventListeners[e]?.forEach((n)=>{n(...t)})}on(e,t){if(!this.eventListeners[e])this.eventListeners[e]=new Set;return this.eventListeners[e].add(t),()=>this.off(e,t)}off(e,t){this.eventListeners[e]?.delete(t)}createRenderContext(){return{appContext:this.appContext,templateEngine:this.templateEngine,renderer:this.renderer,slots:this.collectSlots(),registerChild:(e)=>{this.childComponents.add(e),e.setParentComponent?.(this),e.setAppContext?.(this.appContext)},unregisterChild:(e)=>{this.childComponents.delete(e),e.setParentComponent?.(null)}}}collectSlots(){let e={default:[]};return R(this.props.children).forEach((n)=>{let r=this.getSlotName(n);if(!e[r])e[r]=[];e[r].push(this.normalizeSlotChild(n))}),e}getSlotName(e){if(typeof e==="string")return"default";return"slot"in e&&typeof e.slot==="string"?e.slot:"default"}normalizeSlotChild(e){if(typeof e==="string"||!("slot"in e))return e;let t={...e};return delete t.slot,t}getRouterFrom(e){if(!e||typeof e!=="object"||!("router"in e))return;return e.router}getRouterFromGlobalApp(){let e=globalThis.__APP__;return this.getRouterFrom(e)}resolveAppInjection(e){if(!this.appContext||typeof this.appContext!=="object")return{found:!1,value:void 0};return this.appContext.app?.resolveInjection?.(e)??{found:!1,value:void 0}}}class me extends T{}function S(e){if(!e.startsWith("/"))return`/${e}`;return e||"/"}function O(e,t){let n=S(t.split("?")[0]);for(let i of e){if(i.path==="*")continue;let s=Ne(i.path,n);if(s)return{route:i,params:s}}let r=e.find((i)=>i.path==="*");if(r)return{route:r,params:{pathMatch:n}};let o=e.find((i)=>i.path==="/");return o?{route:o,params:{}}:null}function Ne(e,t){let n=ge(e),r=ge(t);if(n.length!==r.length)return null;let o={};for(let i=0;i<n.length;i+=1){let s=n[i],a=r[i];if(s.startsWith(":")){let p=s.slice(1);if(!p)return null;o[decodeURIComponent(p)]=decodeURIComponent(a);continue}if(s!==a)return null}return o}function ge(e){let t=S(e);if(t==="/")return[];return t.split("/").filter(Boolean)}function ve(e,t,n){let r=S(e),o=n==="/"?r:n+r;return t==="hash"?`#${o}`:o}function ye(e,t){let n,r,o;if(e==="history")r=window.location.pathname+window.location.search,n=window.location.pathname,o=window.location.search;else{r=window.location.hash||"#/",n=r.startsWith("#")?r.slice(1):r;let s=n.indexOf("?");o=s>=0?n.slice(s+1):"",n=s>=0?n.slice(0,s):n}if(n.startsWith(t)&&t!=="/"&&n!=="/")n=n.slice(t.length);return n=S(n),{path:n,fullPath:r,query:Ie(o),params:{}}}function G(e,t,n,r){let o=S(e),i=r==="/"?o:r+o;if(n==="history"){if(t)window.history.replaceState({},"",i);else window.history.pushState({},"",i);return}if(t){let s=window.location.href.split("#")[0];window.location.replace(`${s}#${i}`);return}window.location.hash=i}function Ie(e){let t={},n=e.startsWith("?")?e.slice(1):e;if(!n)return t;return n.split("&").forEach((r)=>{let[o,i]=r.split("=");if(o)t[decodeURIComponent(o)]=i?decodeURIComponent(i):""}),t}function ke(e){let t=e.indexOf("?");if(t<0)return{};let n=e.slice(t+1),r={};if(!n)return r;return n.split("&").forEach((o)=>{let[i,s]=o.split("=");if(i)r[decodeURIComponent(i)]=s?decodeURIComponent(s):""}),r}class I{currentRoute=null;currentLocation=null;routes=[];app=null;mode;base;routeChangeListeners=[];beforeGuards=[];afterHooks=[];removeWindowListener;constructor(e){let t=Array.isArray(e)?{routes:e}:e;this.routes=t.routes||[],this.mode=t.mode||"history",this.base=t.base||"/",this.validateRoutes(),this.initEvents(),this.resolveCurrentRoute()}install(e){this.app=e,e.router=this,pe(this);let t=e.getContext();t.router=this,this.resolveCurrentRoute()}push(e){this.navigate(e,!1)}replace(e){this.navigate(e,!0)}forward(){window.history.forward()}back(){window.history.back()}go(e){window.history.go(e)}getCurrentRoute(){if(!this.currentLocation)this.resolveCurrentRoute();return this.currentLocation}getCurrentRouteRecord(){if(!this.currentRoute)this.resolveCurrentRoute();return this.currentRoute}onRouteChange(e){return this.routeChangeListeners.push(e),()=>{let t=this.routeChangeListeners.indexOf(e);if(t>-1)this.routeChangeListeners.splice(t,1)}}beforeEach(e){return this.beforeGuards.push(e),()=>{let t=this.beforeGuards.indexOf(e);if(t>-1)this.beforeGuards.splice(t,1)}}afterEach(e){return this.afterHooks.push(e),()=>{let t=this.afterHooks.indexOf(e);if(t>-1)this.afterHooks.splice(t,1)}}getRoutes(){return[...this.routes]}addRoute(e){if(this.routes.some((n)=>n.path===e.path))throw Error(`Route already exists: ${e.path}`);if(this.routes.push(e),this.getCurrentLocation().path===e.path)this.handleRouteChange()}createHref(e){return ve(e,this.mode,this.base)}destroy(){if(this.removeWindowListener?.(),this.removeWindowListener=void 0,this.app?.router===this)this.app.router=void 0;this.app=null}navigate(e,t){if(!e||typeof e!=="string")throw Error("Path must be a non-empty string");let n=this.currentLocation,r=this.resolveTarget(e);if(!r)return;let o=r.location;for(let i of this.beforeGuards){let s=i(o,n);if(s===!1)return;if(typeof s==="string"&&s!==e){this.navigate(s,t);return}}if(n&&this.isSameLocation(n,o))return;G(r.path,t,this.mode,this.base),this.currentRoute=r.route,this.currentLocation=o,this.triggerRouteChangeListeners(o,n),this.afterHooks.forEach((i)=>{try{i(o,n)}catch(s){console.error("Route afterEach error:",s)}})}resolveTarget(e){let t=O(this.routes,e.split("?")[0]);if(!t)return null;let n=this.applyRedirect(t),r=n?.path??e,o=n?.route??t.route;return{path:r,route:o,location:{path:r.split("?")[0],query:ke(r),params:n?.params??t.params,fullPath:r,name:o?.name,meta:o?.meta}}}applyRedirect(e){let t=new Set,n=e,r="";while(n.route.redirect){if(t.has(n.route.path))throw Error(`Redirect loop detected for route: ${n.route.path}`);t.add(n.route.path),r=n.route.redirect;let o=O(this.routes,r.split("?")[0]);if(!o)return null;n=o}return r?{route:n.route,params:n.params,path:r}:null}validateRoutes(){if(!Array.isArray(this.routes))throw Error("Router routes must be an array");let e=new Set;this.routes.forEach((t)=>{if(!t.component&&!t.redirect)throw Error(`Route ${t.path} must define a component or redirect`);if(e.has(t.path))throw Error(`Duplicate route path: ${t.path}`);e.add(t.path)})}initEvents(){if(typeof window>"u")return;let e=this.mode==="history"?"popstate":"hashchange",t=()=>{this.handleRouteChange()};window.addEventListener(e,t),this.removeWindowListener=()=>{window.removeEventListener(e,t)}}handleRouteChange(){let e=this.currentLocation,t=this.resolveCurrentRoute();if(!this.isSameLocation(e,t))this.triggerRouteChangeListeners(t,e)}resolveCurrentRoute(){let e=this.getCurrentLocation(),t=O(this.routes,e.path),n=t?this.applyRedirect(t):null,r=n?.route??t?.route??null;if(n&&n.path!==e.path)G(n.path,!0,this.mode,this.base);if(this.currentRoute=r,this.currentLocation={...e,params:n?.params??t?.params??{},name:r?.name,meta:r?.meta},this.afterHooks.length>0){let o=this.currentLocation;this.afterHooks.forEach((i)=>{try{i(o,null)}catch(s){console.error("Route afterEach error:",s)}})}return this.currentLocation}getCurrentLocation(){return ye(this.mode,this.base)}isSameLocation(e,t){return e?.fullPath===t?.fullPath&&e?.name===t?.name}triggerRouteChangeListeners(e,t){this.routeChangeListeners.forEach((n)=>{try{n(e,t)}catch(r){console.error("Route change listener error:",r)}})}}class He extends T{unsubscribe;initState(){return{currentPath:this.router?.getCurrentRoute()?.path??window.location.pathname}}initStyles(){}onMounted(){let e=this.router;this.unsubscribe=e?.onRouteChange((t)=>{this.state.currentPath=t.path})}onUnmounted(){this.unsubscribe?.()}render(){let e=this.router,t=this.props.activeClass??"active",n=this.state.currentPath===this.props.to,r=[this.props.className,n?t:void 0].filter(Boolean).join(" ");return{tag:"a",props:{href:e?.createHref(this.props.to)??this.props.to,className:r},listeners:{click:(o)=>{if(o.preventDefault(),this.props.replace)e?.replace(this.props.to);else e?.push(this.props.to)}},children:this.props.children&&this.props.children.length>0?this.props.children:[this.props.to]}}}class je extends T{unsubscribe;initState(){let e=this.router;return{route:e?.getCurrentRoute()??null,record:e?.getCurrentRouteRecord()??null}}initStyles(){}onMounted(){let e=this.router;this.unsubscribe=e?.onRouteChange((t)=>{this.state.route=t,this.state.record=e.getCurrentRouteRecord()})}onUnmounted(){this.unsubscribe?.()}render(){let e=this.state.record??this.router?.getCurrentRouteRecord();return{tag:"div",props:{"data-router-view":""},children:e?.component?[{component:e.component}]:[]}}}function Jn(e){return new I(e)}var Oe=new Set(["base","link","meta"]);function Re(e){let t=e.lang??"en",n=e.charset??"utf-8",r=e.viewport??"width=device-width, initial-scale=1",o=_({lang:t,...e.htmlAttributes??{}}),i=_(e.bodyAttributes),s=_e(e.body);return["<!doctype html>",`<html${o}>`,"<head>",` <meta charset="${P(n)}">`,` <meta name="viewport" content="${P(r)}">`,` <title>${P(e.title)}</title>`,e.description?` <meta name="description" content="${P(e.description)}">`:"",...(e.head??[]).map((a)=>` ${Ve(a)}`),e.styles&&e.styles.length>0?` <style>${q(e.styles)}</style>`:"","</head>",`<body${i}>`,s,...(e.scripts??[]).map((a)=>` ${Be(a)}`),"</body>","</html>"].filter((a)=>a!=="").join(`
|
|
2
|
+
`)}function _e(e){if(typeof document>"u")throw Error("renderHtmlDocument requires a DOM-like document");let t=document.createElement("div"),n=new L,r=new Set,o=Array.isArray(e)?e:[e],i={templateEngine:new x({}),renderer:n,slots:{default:[]},registerChild:(a)=>{r.add(a)},unregisterChild:(a)=>{r.delete(a)}};o.forEach((a)=>{t.appendChild(n.mount(a,i))});let s=t.innerHTML;return r.forEach((a)=>{a.unmount()}),s}function Ve(e){let t=_(e.attributes);if(Oe.has(e.tag)&&!e.text)return`<${e.tag}${t}>`;return`<${e.tag}${t}>${P(e.text??"")}</${e.tag}>`}function Be(e){return`<script${_({type:e.type,src:e.src,async:e.async,defer:e.defer,...e.attributes??{}})}></script>`}function _(e={}){let t=Object.entries(e).flatMap(([n,r])=>{if(r===!1||r===null||r===void 0)return[];return r===!0?[n]:[`${n}="${P(String(r))}"`]}).join(" ");return t?` ${t}`:""}function P(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}var Ce="#app";class De{options;container=null;rootInstance=null;mounted=!1;unmounting=!1;templateEngine=null;appContext;providers=new Map;plugins=[];unmountedCallback;router;constructor(e={}){this.options=e;this.appContext={app:this,version:"0.9.0",config:e.config||{}}}handleError(e){console.error("应用错误:",e),this.renderErrorUI(e)}renderErrorUI(e){if(!this.container)return;this.container.innerHTML=`
|
|
3
|
+
<div style="padding: 20px; background-color: #ffebee; color: #c62828; font-family: Arial, sans-serif;">
|
|
4
|
+
<h3>应用错误</h3>
|
|
5
|
+
<p>${e.message}</p>
|
|
6
|
+
<pre style="background-color: #fff; padding: 10px; border-radius: 4px; overflow: auto;">${e.stack}</pre>
|
|
7
|
+
</div>
|
|
8
|
+
`}use(e,...t){if(typeof e.install!=="function")throw Error("插件必须提供 install 方法");return e.install(this,...t),this.plugins.push({plugin:e,args:t}),this}mount(){if(this.unmounting||this.mounted){console.warn("应用已经处于运行状态");return}let e=this.resolveMountContainer();if(!e)return;try{if(this.container=e,globalThis.__APP__=this,this.options.root){if(this.rootInstance=j(this.options.root,this.options.rootProps),"setAppContext"in this.rootInstance)this.rootInstance.setAppContext(this.appContext);if(this.options.state&&"setState"in this.rootInstance)this.rootInstance.setState(this.options.state);this.rootInstance.mount(this.container),this.templateEngine=new x(this.options.state||{})}this.mounted=!0,this.onMounted()}catch(t){let n=new l;n.add(t),this.unmounting=!0,this.teardown(n),this.unmounting=!1;try{n.throwIfAny("App mount and cleanup failed")}catch(r){this.container=e;try{this.handleError(r)}finally{this.container=null}}}}unmount(){if(this.unmounting)return;if(!this.mounted&&!this.rootInstance&&!this.container&&!this.templateEngine){console.warn("应用未处于运行状态");return}this.unmounting=!0;let e=new l;this.teardown(e),this.unmounting=!1;try{e.throwIfAny("App teardown failed")}catch(t){console.error("Failed to unmount app:",t)}}teardown(e){for(let{plugin:t}of this.plugins)e.attempt(()=>t.onBeforeUnmount?.(this));if(this.releaseResources(e),this.unmountedCallback)e.attempt(this.unmountedCallback)}releaseResources(e){if(e.attempt(()=>this.rootInstance?.unmount()),this.rootInstance=null,e.attempt(()=>this.templateEngine?.clearBindings()),this.templateEngine=null,e.attempt(()=>{if(this.container)this.container.innerHTML=""}),this.container=null,this.mounted=!1,globalThis.__APP__===this)delete globalThis.__APP__}isRunning(){return this.mounted}updateRootComponent(e){if(this.mounted)this.unmount();this.options.root=e,this.mount()}update(e){if(!this.mounted)return console.warn("Cannot update unmounted app"),this;try{if(e&&this.options.state){if(this.options.state={...this.options.state,...e},this.rootInstance&&"setState"in this.rootInstance)this.rootInstance.setState(e);if(this.templateEngine)this.templateEngine.state=this.options.state}this.onUpdated()}catch(t){console.error("Failed to update app:",t)}return this}getContext(){return this.appContext}provide(e,t){return this.providers.set(e,t),this}inject(e,t){let n=this.resolveInjection(e);return n.found?n.value:t}resolveInjection(e){if(!this.providers.has(e))return{found:!1,value:void 0};return{found:!0,value:this.providers.get(e)}}getState(){return this.options.state}setState(e){if(this.options.state=e,this.mounted)this.update();return this}onUnmounted(e){return this.unmountedCallback=e,this}renderHtmlDocument(e={}){let t=this.options.document??{},n=this.mergeDocumentScripts(t.scripts,e.scripts);return Re({...t,...e,title:e.title??t.title??"TransOne App",body:e.body??t.body??this.createMountDocumentBody(),scripts:n})}resolveRootElement(e){if(!e)return null;if(typeof e==="string"){if(typeof document>"u")return null;return document.querySelector(e)}return typeof Element<"u"&&e instanceof Element?e:null}resolveMountContainer(){if(typeof document>"u")return null;let e=this.resolveRootElement(this.options.rootElement??Ce);return e instanceof HTMLElement?e:null}createMountDocumentBody(){let e=this.options.rootElement??Ce;if(typeof e==="string")return this.createMountElementFromSelector(e);if(typeof Element<"u"&&e instanceof Element){let t={};if(e.id)t.id=e.id;if(e.className)t.className=e.className;return{tag:e.tagName.toLowerCase(),props:t}}return A({props:{id:"app"}})}createMountElementFromSelector(e){if(e.startsWith("#")&&e.length>1)return A({props:{id:e.slice(1)}});if(e.startsWith(".")&&e.length>1)return A({props:{className:e.slice(1)}});return A({props:{"data-transone-root":e}})}mergeDocumentScripts(e,t){if(!e&&!t)return;return[...e??[],...t??[]]}onMounted(){this.plugins.forEach(({plugin:e})=>{if(e&&typeof e.onMounted==="function")e.onMounted(this)})}onUpdated(){this.plugins.forEach(({plugin:e})=>{if(e&&typeof e.onUpdated==="function")e.onUpdated(this)})}}
|
|
9
|
+
export{w as a,Qe as b,Ze as c,g as d,K as e,Je as f,y as g,Xe as h,et as i,Q as j,tt as k,C as l,nt as m,Ee as n,rt as o,R as p,Z as q,J as r,X as s,it as t,xe as u,A as v,st as w,at as x,pt as y,ct as z,ut as A,lt as B,dt as C,ht as D,ft as E,mt as F,gt as G,vt as H,yt as I,Rt as J,Ct as K,bt as L,Et as M,xt as N,Tt as O,wt as P,St as Q,Pt as R,At as S,Lt as T,Mt as U,Nt as V,It as W,kt as X,Ht as Y,jt as Z,Ot as _,_t as $,Vt as aa,Bt as ba,Dt as ca,$t as da,Ut as ea,Kt as fa,Wt as ga,Ft as ha,zt as ia,Gt as ja,Te as ka,ee as la,we as ma,z as na,I as oa,He as pa,je as qa,Jn as ra,Le as sa,H as ta,L as ua,le as va,de as wa,he as xa,x as ya,T as za,me as Aa,Re as Ba,De as Ca};
|
|
10
|
+
|
|
11
|
+
//# debugId=6A7DF95ED95FE4AF64756E2164756E21
|
|
12
|
+
//# sourceMappingURL=index-8qh91wft.js.map
|