@djvlc/runtime-core 1.1.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +39 -3
- package/dist/index.d.ts +39 -3
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var t=require("@djvlc/contracts-types"),e=class extends Error{constructor(e,s,i,n){super(s||t.ErrorMessages[e]||"Unknown error"),this.name="DjvlcRuntimeError",this.code=e,this.details=i,this.traceId=n,this.timestamp=Date.now()}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,traceId:this.traceId,timestamp:this.timestamp}}},s=class extends e{constructor(e,s,i){super(t.ErrorCode.RESOURCE_PAGE_NOT_FOUND,e,s,i),this.name="PageLoadError"}},i=class extends e{constructor(e,s,i,n=t.ErrorCode.COMPONENT_LOAD_FAILED,r){super(n,i,{...r,componentName:e,componentVersion:s}),this.name="ComponentLoadError",this.componentName=e,this.componentVersion=s}},n=class extends e{constructor(e,s,i,n){super(t.ErrorCode.COMPONENT_INTEGRITY_MISMATCH,`Integrity check failed for ${e}@${s}`,{expectedHash:i,actualHash:n}),this.name="IntegrityError",this.componentName=e,this.componentVersion=s,this.expectedHash=i,this.actualHash=n}},r=class extends e{constructor(e,s,i){super(t.ErrorCode.COMPONENT_BLOCKED,`Component ${e}@${s} is blocked`,{componentName:e,componentVersion:s,reason:i}),this.name="ComponentBlockedError",this.componentName=e,this.componentVersion=s,this.reason=i}},o=class extends e{constructor(e,s,i,n){super(t.ErrorCode.VALIDATION_EXPRESSION_ERROR,s,{...n,expression:e,position:i}),this.name="ExpressionError",this.expression=e,this.position=i}},a=class extends e{constructor(e,s,i=t.ErrorCode.SYSTEM_INTERNAL_ERROR,n,r){super(i,s,{...r,actionType:e,actionId:n}),this.name="ActionError",this.actionType=e,this.actionId=n}},c=class extends e{constructor(e,s,i=t.ErrorCode.SYSTEM_INTERNAL_ERROR,n){super(i,s,{...n,queryId:e}),this.name="QueryError",this.queryId=e}},h=class{constructor(t){this.cache=new Map,this.options={env:"prod",cache:{enabled:!0,maxAge:300},...t}}async resolve(t,e){const i=this.getCacheKey(t,e);if(this.options.cache?.enabled){const e=this.cache.get(i);if(e&&this.isCacheValid(e.timestamp))return this.log("debug",`Page ${t} loaded from cache`),e.data}const n=performance.now();try{const s=await this.callResolveViaAdapter(t,e),r=await this.loadFromCdn(s,t);this.options.cache?.enabled&&this.cache.set(i,{data:r,timestamp:Date.now()});const o=performance.now()-n;return this.log("info",`Page ${t} resolved in ${o.toFixed(2)}ms`),r}catch(e){if(e instanceof s)throw e;throw new s(`Failed to resolve page: ${e instanceof Error?e.message:"Unknown error"}`,{pageId:t})}}async callResolveViaAdapter(t,e){const i=await this.options.userApiAdapter.resolvePage({pageId:t,uid:e?.uid,deviceId:e?.deviceId,env:this.options.env,channel:this.options.channel,previewToken:this.options.previewToken});if(!this.isValidPageResolveResponse(i))throw new s("Invalid page resolve response",{pageId:t});return i}async loadFromCdn(t,e){try{const i=await fetch(t.snapshotUrl,{headers:this.buildHeaders()});if(!i.ok)throw new s(`Failed to load snapshot: ${i.status}`,{pageId:e});const n=await i.json();return this.convertSnapshotToResult(n,t,e)}catch(t){if(t instanceof s)throw t;throw new s(`Failed to load from CDN: ${t instanceof Error?t.message:"Unknown error"}`,{pageId:e})}}convertSnapshotToResult(t,e,s){const i=this.convertSnapshotPageToPageSchema(t.page),n=this.convertSnapshotManifestToPageManifest(t.manifest),r=t.definitionsDigest?.actions?.map(t=>t.versionId)||[],o=t.definitionsDigest?.queries?.map(t=>t.versionId)||[];return n.actionDefinitionVersionIds=r,n.dataQueryVersionIds=o,{pageId:e.pageId,pageVersionId:e.resolvedVersionId,pageJson:i,manifest:n,runtimeConfig:{blockedComponents:e.ops.blockedComponents.map(t=>({name:t.name,version:t.version||"",reason:t.reason})),killSwitches:e.ops.killSwitch.map(t=>({type:t.targetType,enabled:t.enabled})),features:e.ops.flags},isPreview:"preview"===this.options.env||!!this.options.previewToken}}convertSnapshotPageToPageSchema(t){const e={layout:{canvasType:t.config.canvasType,canvasSize:t.config.canvasSize},styles:t.config.background||t.config.cssVariables?{background:t.config.background,cssVariables:t.config.cssVariables}:void 0},s=Object.keys(t.initialState).length>0?{fields:Object.keys(t.initialState).reduce((e,s)=>{const i=t.initialState[s];let n="string";return"number"==typeof i?n="number":"boolean"==typeof i?n="boolean":Array.isArray(i)?n="array":null!==i&&"object"==typeof i&&(n="object"),e[s]={type:n,initialValue:i},e},{})}:void 0,i={title:t.title};return{schemaVersion:t.schemaVersion,pageId:t.pageId,pageVersion:t.pageVersion,runtime:{name:"djvlc-runtime",version:"1.0.0"},meta:i,config:e,seo:t.seo,state:s,dataBindings:t.bindings,root:t.root}}convertSnapshotManifestToPageManifest(t){return{id:"",pageVersionId:"",manifestVersion:"1.0.0",createdAt:(new Date).toISOString(),contentHash:"",components:t.components.map(t=>({componentId:"",name:t.name,version:t.version,entry:`${t.assetsUrl}/${t.entrypoints.js}`,styleEntry:t.entrypoints.css?`${t.assetsUrl}/${t.entrypoints.css}`:void 0,integrity:t.integrity,preload:t.preload,priority:t.priority})),actionDefinitionVersionIds:[],dataQueryVersionIds:[],runtimeVersion:{min:t.runtime.minVersion,recommended:t.runtime.version}}}isValidPageResolveResponse(t){if(!t||"object"!=typeof t)return!1;const e=t;return"string"==typeof e.pageId&&"string"==typeof e.resolvedVersionId&&"string"==typeof e.cdnBase&&"string"==typeof e.snapshotUrl&&"string"==typeof e.manifestUrl&&void 0!==e.ops&&"string"==typeof e.etag&&"number"==typeof e.cacheTtlSeconds}preconnect(){const t=document.createElement("link");t.rel="preconnect",t.href=this.options.apiBaseUrl,document.head.appendChild(t)}clearCache(t){if(t)for(const e of this.cache.keys())e.startsWith(t)&&this.cache.delete(e);else this.cache.clear()}buildHeaders(){return{"Content-Type":"application/json",...this.options.headers}}getCacheKey(t,e){const s=[t,this.options.env,this.options.channel];return e?.uid&&s.push(e.uid),e?.deviceId&&s.push(e.deviceId),s.filter(Boolean).join(":")}isCacheValid(t){const e=1e3*(this.options.cache?.maxAge??300);return Date.now()-t<e}log(t,e){this.options.logger&&this.options.logger[t](e)}},l={sha256:"SHA-256",sha384:"SHA-384",sha512:"SHA-512"},u=class{constructor(t){this.loadedComponents=new Map,this.loadingPromises=new Map,this.options={enableSRI:!0,concurrency:4,timeout:3e4,blockedComponents:[],...t},this.blockedSet=new Set(this.options.blockedComponents)}async load(t){const e=this.getComponentKey(t.name,t.version);if(this.isBlocked(t.name,t.version))throw new r(t.name,t.version,"Component is blocked");const s=this.loadedComponents.get(e);if(s)return s;const i=this.loadingPromises.get(e);if(i)return i;const n=this.loadComponent(t);this.loadingPromises.set(e,n);try{const t=await n;return this.loadedComponents.set(e,t),t}finally{this.loadingPromises.delete(e)}}async loadAll(t){const e=new Map,{concurrency:s=4}=this.options,i=t.components;for(let t=0;t<i.length;t+=s){const n=i.slice(t,t+s).map(async t=>{const s=this.getComponentKey(t.name,t.version),i=performance.now();try{const n=await this.load(t);e.set(s,{name:t.name,version:t.version,status:"loaded",component:n.Component,loadTime:performance.now()-i})}catch(n){const o=n instanceof r?"blocked":"failed";if(e.set(s,{name:t.name,version:t.version,status:o,error:n instanceof Error?n.message:"Unknown error",loadTime:performance.now()-i}),"critical"===t.priority)throw n}});await Promise.all(n)}return e}preload(t){t.forEach(t=>{const e=document.createElement("link");e.rel="preload",e.as="script",e.href=this.resolveUrl(t.entry),this.options.enableSRI&&t.integrity&&(e.integrity=t.integrity,e.crossOrigin="anonymous"),document.head.appendChild(e)})}isLoaded(t,e){return this.loadedComponents.has(this.getComponentKey(t,e))}get(t,e){return this.loadedComponents.get(this.getComponentKey(t,e))}isBlocked(t,e){return this.blockedSet.has(`${t}@${e}`)||this.blockedSet.has(t)}updateBlockedList(t){this.blockedSet=new Set(t)}async loadComponent(t){const e=performance.now(),s=this.resolveUrl(t.entry);this.log("debug",`Loading component ${t.name}@${t.version}`);try{const n=await this.fetchWithTimeout(s);if(!n.ok)throw new i(t.name,t.version,`Failed to fetch component: ${n.status} ${n.statusText}`);const r=await n.text();this.options.enableSRI&&t.integrity&&await this.validateIntegrity(t,r);const o=await this.executeScript(r,t),a=performance.now()-e;return this.log("info",`Component ${t.name}@${t.version} loaded in ${a.toFixed(2)}ms`),{name:t.name,version:t.version,Component:o,loadTime:a}}catch(e){if(e instanceof i||e instanceof n||e instanceof r)throw e;throw new i(t.name,t.version,`Failed to load component: ${e instanceof Error?e.message:"Unknown error"}`)}}async fetchWithTimeout(t){const e=new AbortController,s=setTimeout(()=>e.abort(),this.options.timeout),i={signal:e.signal,credentials:"omit",headers:this.options.headers?{...this.options.headers}:void 0},n=this.options.fetchComponentScript??fetch;try{return await n(t,i)}finally{clearTimeout(s)}}async validateIntegrity(t,e){if(!t.integrity)return;const[s,i]=t.integrity.split("-");if(!s||!i)throw new n(t.name,t.version,t.integrity,"Invalid format");const r=l[s.toLowerCase()];if(!r)throw new n(t.name,t.version,t.integrity,`Unsupported SRI algorithm: ${s}, expected sha256/sha384/sha512`);const o=await crypto.subtle.digest(r,(new TextEncoder).encode(e)),a=Array.from(new Uint8Array(o)),c=btoa(String.fromCharCode(...a));if(c!==i)throw new n(t.name,t.version,i,c)}async executeScript(t,e){const s=new Blob([t],{type:"application/javascript"}),n=URL.createObjectURL(s);try{const t=await import(n),s=t.default??t[e.name]??t[this.kebabToPascal(e.name)]??t.Component;if(!s)throw new i(e.name,e.version,"Component module does not export a valid component (expected default or Component)");return s}finally{URL.revokeObjectURL(n)}}kebabToPascal(t){return t.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}resolveUrl(t){return t.startsWith("http://")||t.startsWith("https://")?t:`${this.options.cdnBaseUrl}/${t.replace(/^\//,"")}`}getComponentKey(t,e){return`${t}@${e}`}log(t,e){this.options.logger&&this.options.logger[t](e)}},d=class{constructor(t){this.preconnectedHosts=new Set,this.preloadedAssets=new Set,this.options=t}preconnectAll(){[...this.options.cdnHosts,...this.options.apiHosts].forEach(t=>this.preconnect(t))}preconnect(t){if(this.preconnectedHosts.has(t))return;const e=document.createElement("link");e.rel="preconnect",e.href=t.startsWith("http")?t:`https://${t}`,e.crossOrigin="anonymous",document.head.appendChild(e),this.preconnectedHosts.add(t)}dnsPrefetch(t){const e=document.createElement("link");e.rel="dns-prefetch",e.href=t.startsWith("http")?t:`https://${t}`,document.head.appendChild(e)}preloadScript(t,e){if(this.preloadedAssets.has(t))return;const s=document.createElement("link");s.rel="preload",s.setAttribute("as","script"),s.href=t,e&&(s.setAttribute("integrity",e),s.setAttribute("crossorigin","anonymous")),document.head.appendChild(s),this.preloadedAssets.add(t)}preloadStyle(t,e){if(this.preloadedAssets.has(t))return;const s=document.createElement("link");s.rel="preload",s.setAttribute("as","style"),s.href=t,e&&(s.setAttribute("integrity",e),s.setAttribute("crossorigin","anonymous")),document.head.appendChild(s),this.preloadedAssets.add(t)}preloadImage(t){if(this.preloadedAssets.has(t))return;const e=document.createElement("link");e.rel="preload",e.setAttribute("as","image"),e.href=t,document.head.appendChild(e),this.preloadedAssets.add(t)}prefetch(t,e){const s=document.createElement("link");s.rel="prefetch",s.href=t,e&&s.setAttribute("as",e),document.head.appendChild(s)}loadStylesheet(t,e){return new Promise((s,i)=>{const n=document.createElement("link");n.rel="stylesheet",n.href=t,e&&(n.integrity=e,n.crossOrigin="anonymous"),n.onload=()=>s(),n.onerror=()=>i(new Error(`Failed to load stylesheet: ${t}`)),document.head.appendChild(n)})}loadScript(t,e){return new Promise((s,i)=>{const n=document.createElement("script");n.src=t,n.async=!0,e&&(n.integrity=e,n.crossOrigin="anonymous"),n.onload=()=>s(),n.onerror=()=>i(new Error(`Failed to load script: ${t}`)),document.body.appendChild(n)})}},p=class{constructor(){this.listeners=new Set,this.changeCallbacks=new Set,this.state=this.createInitialState()}getState(){return this.state}getPhase(){return this.state.phase}setPhase(t){this.setState({phase:t})}setPage(t){const e=t.pageJson,s=this.initializePageState(e);t.preloadedData&&Object.assign(s,t.preloadedData),this.setState({page:t,variables:s})}initializePageState(t){const e={};if(t.state&&t.state.fields)for(const[s,i]of Object.entries(t.state.fields))if(i&&"object"==typeof i){const t=i;e[s]=t.initialValue}return e}setError(t){this.setState({phase:"error",error:t})}clearError(){this.state.error&&this.setState({error:null})}getVariable(t){return t.includes(".")?this.getNestedValue(this.state.variables,t):this.state.variables[t]}setVariable(t,e){const s=this.getVariable(t);if(t.includes(".")){const s={...this.state.variables};this.setNestedValue(s,t,e),this.setState({variables:s})}else this.setState({variables:{...this.state.variables,[t]:e}});this.notifyChange({key:t,oldValue:s,newValue:e})}setVariables(t){const e=[];for(const[s,i]of Object.entries(t)){const t=this.getVariable(s);e.push({key:s,oldValue:t,newValue:i})}this.setState({variables:{...this.state.variables,...t}}),e.forEach(t=>this.notifyChange(t))}getQuery(t){return this.state.queries[t]}setQuery(t,e){this.setState({queries:{...this.state.queries,[t]:e}})}clearQuery(t){const{[t]:e,...s}=this.state.queries;this.setState({queries:s})}setComponentStatus(t,e){const s=new Map(this.state.components);s.set(t,e),this.setState({components:s})}getComponentStatus(t){return this.state.components.get(t)}setDestroyed(){this.setState({phase:"destroyed",destroyed:!0})}isDestroyed(){return this.state.destroyed}subscribe(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}onStateChange(t){return this.changeCallbacks.add(t),()=>{this.changeCallbacks.delete(t)}}reset(){this.state=this.createInitialState(),this.notifyListeners()}getExpressionContext(){return{state:this.state.variables,binding:this.state.queries,local:{},context:{pageVersionId:this.state.page?.pageVersionId,pageId:this.state.page?.pageId,phase:this.state.phase,$now:Date.now()}}}setState(t){this.state={...this.state,...t},this.notifyListeners()}notifyListeners(){this.listeners.forEach(t=>{try{t(this.state)}catch(t){}})}notifyChange(t){this.changeCallbacks.forEach(e=>{try{e(t)}catch(t){}})}getNestedValue(t,e){const s=e.split(".");let i=t;for(const t of s){if(null==i)return;i=i[t]}return i}setNestedValue(t,e,s){const i=e.split(".");let n=t;for(let t=0;t<i.length-1;t++){const e=i[t];void 0!==n[e]&&null!==n[e]||(n[e]={}),n=n[e]}n[i[i.length-1]]=s}createInitialState(){return{phase:"idle",page:null,variables:{},queries:{},components:new Map,error:null,destroyed:!1}}},f=class{constructor(t){this.bindings=new Map,this.dependencyGraph=new Map,this.bindingDependencies=new Map,this.options=t}registerBindings(t){for(const e of t)this.registerBinding(e)}registerBinding(t){if(this.bindings.set(t.id,{binding:t,loading:!1,retryCount:0}),t.dependencies)for(const e of t.dependencies)this.dependencyGraph.has(e)||this.dependencyGraph.set(e,new Set),this.dependencyGraph.get(e).add(t.id);this.updateBindingDependencies(t),this.log("debug",`Registered data binding: ${t.id}`)}updateBindingDependencies(t){for(const[e,s]of this.bindings){if(e===t.id)continue;const i=s.binding;i.dependencies?.includes(t.targetState)&&(this.bindingDependencies.has(t.id)||this.bindingDependencies.set(t.id,new Set),this.bindingDependencies.get(t.id).add(e))}if(t.dependencies)for(const e of t.dependencies)for(const[s,i]of this.bindings)s!==t.id&&i.binding.targetState===e&&(this.bindingDependencies.has(s)||this.bindingDependencies.set(s,new Set),this.bindingDependencies.get(s).add(t.id))}async initializeBindings(t){const e=[];for(const t of this.bindings.values())"eager"===t.binding.loadStrategy&&e.push(t.binding);const s=this.topologicalSort(e),i=this.createLoadBatches(s);for(const e of i){const s=await Promise.allSettled(e.map(e=>this.loadBinding(e.id,t))),i=new Map;s.forEach((t,s)=>{const n=e[s].id;"fulfilled"===t.status?i.set(n,{success:!0,data:t.value}):i.set(n,{success:!1,error:t.reason})}),this.options.onBatchComplete?.(i)}}topologicalSort(t){const e=new Map(t.map(t=>[t.id,t])),s=new Set,i=[],n=t=>{if(!s.has(t.id)){if(s.add(t.id),t.dependencies)for(const i of t.dependencies)for(const[t,r]of e)r.targetState!==i||s.has(t)||n(r);i.push(t)}};for(const e of t)n(e);return i}createLoadBatches(t){const e=[],s=new Set;for(;s.size<t.length;){const i=[];for(const e of t){if(s.has(e.id))continue;let n=!0;if(e.dependencies)for(const i of e.dependencies){for(const e of t)if(e.targetState===i&&!s.has(e.id)){n=!1;break}if(!n)break}n&&i.push(e)}if(0===i.length)for(const e of t)if(!s.has(e.id)){i.push(e),this.log("warn",`Possible circular dependency detected at binding: ${e.id}`);break}i.forEach(t=>s.add(t.id)),i.length>0&&e.push(i)}return e}async loadBinding(t,e,s=!1){const i=this.bindings.get(t);if(!i)throw new c(t,`Data binding not found: ${t}`);const{binding:n}=i;if(!n.condition||this.evaluateCondition(n.condition,e)){if(!s&&this.isCacheValid(i))return this.log("debug",`Binding ${t} returned from cache`),i.cachedData;if(i.loading)this.log("debug",`Binding ${t} is already loading`);else{i.loading=!0;try{const s=this.resolveParams(n.params||{},e),r=await this.executeWithRetry(n,s),o=n.transform?this.applyTransform(r,n.transform,e):r;return i.cachedData=o,i.lastLoadTime=Date.now(),n.cache?.ttl&&(i.cacheExpireTime=Date.now()+1e3*n.cache.ttl),i.retryCount=0,this.options.stateSetter.setVariable(n.targetState,o),this.setupAutoRefresh(i,e),this.options.onDataLoaded?.(t,o),this.log("info",`Binding ${t} loaded successfully`),o}catch(t){throw await this.handleLoadError(i,t,e),t}finally{i.loading=!1}}}else this.log("debug",`Binding ${t} skipped by condition`)}async refreshBinding(t,e){await this.loadBinding(t,e,!0)}async refreshAll(t){const e=Array.from(this.bindings.keys()).map(e=>this.loadBinding(e,t,!0));await Promise.allSettled(e)}async onStateChange(t,e){const s=this.dependencyGraph.get(t);if(!s||0===s.size)return;this.log("debug",`State ${t} changed, refreshing dependent bindings`);const i=Array.from(s).map(t=>this.loadBinding(t,e,!0));await Promise.allSettled(i)}async triggerManualLoad(t,e){const s=this.bindings.get(t);if(!s)throw new c(t,`Data binding not found: ${t}`);return"manual"!==s.binding.loadStrategy&&this.log("warn",`Binding ${t} is not manual strategy`),this.loadBinding(t,e,!0)}checkVisibility(t,e,s){const i=this.bindings.get(t);i&&"lazy"===i.binding.loadStrategy&&e&&!i.lastLoadTime&&this.loadBinding(t,s).catch(e=>{this.log("error",`Lazy binding ${t} failed to load`,e)})}destroy(){for(const t of this.bindings.values())t.refreshTimer&&clearInterval(t.refreshTimer);this.bindings.clear(),this.dependencyGraph.clear(),this.log("debug","DataBindingManager destroyed")}async executeWithRetry(t,e){const s=t.onError?.retry?.maxRetries??0,i=t.onError?.retry?.backoffMs??1e3,n=t.onError?.retry?.backoff??"fixed";let r;for(let o=0;o<=s;o++)try{const s=await this.options.requester.requestData(t.queryVersionId,e);if(!s.success)throw new c(t.queryVersionId,s.message||"Query failed",void 0,{params:e});return s.data}catch(t){if(r=t,this.log("warn",`Query attempt ${o+1}/${s+1} failed:`,t),o<s){const t="exponential"===n?i*Math.pow(2,o):i;await this.delay(t)}}throw r||new Error("Query failed after all retries")}async handleLoadError(t,e,s){const{binding:i}=t,n=i.onError;t.retryCount++,void 0!==n?.fallbackValue&&this.options.stateSetter.setVariable(i.targetState,n.fallbackValue),n?.showError&&this.options.onDataError?.(i.id,e),this.log("error",`Binding ${i.id} load failed:`,e)}setupAutoRefresh(t,e){t.refreshTimer&&(clearInterval(t.refreshTimer),t.refreshTimer=void 0);const s=t.binding.refreshInterval;!s||s<=0||(t.refreshTimer=setInterval(()=>{this.loadBinding(t.binding.id,e,!0).catch(e=>{this.log("error",`Auto refresh for ${t.binding.id} failed:`,e)})},1e3*s))}isCacheValid(t){return!(!t.cachedData||!t.lastLoadTime||t.cacheExpireTime&&Date.now()>t.cacheExpireTime)}resolveParams(t,e){const s={};for(const[i,n]of Object.entries(t))s[i]=this.resolveValue(n,e);return s}resolveValue(t,e){if(null==t)return t;if("object"==typeof t&&!Array.isArray(t)){const s=t;if("expression"===s.type||"binding"===s.type)return this.options.expressionEngine.evaluateWithFallback(s.expression,e,s.fallback);const i={};for(const[t,n]of Object.entries(s))i[t]=this.resolveValue(n,e);return i}return"string"==typeof t&&t.includes("${")?this.options.expressionEngine.evaluateTemplate(t,e):t}evaluateCondition(t,e){const s=void 0===t.fallback||t.fallback,i=this.options.expressionEngine.evaluateWithFallback(t.value,e,s);return Boolean(i)}applyTransform(t,e,s){const i={...s,local:{...s.local||{},$data:t,$response:t}},n=void 0!==e.fallback?e.fallback:t;return this.options.expressionEngine.evaluateWithFallback(e.value,i,n)}delay(t){return new Promise(e=>setTimeout(e,t))}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},m=class{constructor(t={}){this.handlers=new Map,this.options={debug:!1,maxListeners:100,...t}}emit(t){this.options.debug&&this.log("debug",`Event emitted: ${t.type}`,t);const e=this.handlers.get(t.type);e&&e.forEach(e=>{try{e(t)}catch(e){this.log("error",`Error in event handler for ${t.type}:`,e)}})}on(t,e){let s=this.handlers.get(t);return s||(s=new Set,this.handlers.set(t,s)),s.size>=(this.options.maxListeners??100)&&this.log("warn",`Max listeners (${this.options.maxListeners}) reached for event: ${t}`),s.add(e),()=>{s?.delete(e),0===s?.size&&this.handlers.delete(t)}}off(t,e){const s=this.handlers.get(t);s&&(s.delete(e),0===s.size&&this.handlers.delete(t))}once(t,e){const s=this.on(t,t=>{s(),e(t)});return s}clear(t){t?this.handlers.delete(t):this.handlers.clear()}listenerCount(t){return this.handlers.get(t)?.size??0}static createEvent(t,e,s){return{type:t,data:e,timestamp:Date.now(),traceId:s}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},g=class t{constructor(t){this.debounceTimers=new Map,this.throttleTimers=new Map,this.options=t}async handleEvent(t,e,s){if(t.condition&&!this.evaluateCondition(t.condition,s,e))return void this.log("debug",`Handler ${t.id} skipped by condition`);if(t.throttle&&t.throttle>0&&!this.throttle(t.id,t.throttle))return void this.log("debug",`Handler ${t.id} throttled`);t.debounce&&t.debounce>0&&await this.debounce(t.id,t.debounce);const i={$event:e,$prevResult:void 0,$results:{}};await this.executeActionChain(t.actions,s,i)}async executeActionChain(t,e,s){const i=[];for(let n=0;n<t.length;n++){const r=t[n];if(r.condition){const t=this.buildActionContext(e,s);if(!this.evaluateCondition(r.condition,t,s.$event)){this.log("debug",`Action ${r.id||n} skipped by condition`);continue}}const o=this.executeSingleAction(r,e,s);r.async?i.push(o):await o}i.length>0&&await Promise.allSettled(i)}async executeSingleAction(t,e,s){const i=t.id||t.alias||t.builtinAction||t.actionDefinitionVersionId||"unknown";t.silent||this.options.executor.showLoading();try{const n=this.buildActionContext(e,s),r=this.resolveParams(t.params||{},n);this.options.onActionStart?.(t,r);const o=await this.executeWithRetry(t,r);s.$prevResult=o,t.id&&(s.$results[t.id]=o),this.options.onActionComplete?.(t,{success:!0,data:o}),this.log("debug",`Action ${i} completed successfully`),t.onSuccess&&t.onSuccess.length>0&&await this.executeActionChain(t.onSuccess,e,s)}catch(n){this.log("error",`Action ${i} failed:`,n),this.options.onActionComplete?.(t,{success:!1,error:n}),t.onError&&t.onError.length>0&&await this.executeActionChain(t.onError,e,{...s,$prevResult:{error:n.message}})}finally{t.silent||this.options.executor.hideLoading(),t.onFinally&&t.onFinally.length>0&&await this.executeActionChain(t.onFinally,e,s)}}async executeWithRetry(t,e){const s=t.policy?.retry?.maxAttempts??1,i=t.policy?.retry?.backoffMs??1e3,n=t.policy?.timeoutMs;let r;for(let o=1;o<=s;o++)try{let s;if(t.builtinAction)s=this.executeBuiltinAction(t.builtinAction,e);else{if(!t.actionDefinitionVersionId)throw new a("unknown","Action must specify builtinAction or actionDefinitionVersionId");s=this.executeCustomAction(t.actionDefinitionVersionId,e)}return n&&(s=this.withTimeout(s,n)),await s}catch(t){r=t,this.log("warn",`Action attempt ${o}/${s} failed:`,t),o<s&&await this.delay(i*o)}throw r||new Error("Action failed after all retries")}async executeBuiltinAction(t,e){switch(t){case"setState":return this.options.executor.setState(e.key,e.value),{success:!0};case"navigate":return this.options.executor.navigate({to:e.to??e.url,type:e.replace?"replace":e.external?"external":"push",params:e.params,query:e.query,newWindow:e.newWindow??e.newTab}),{success:!0};case"openDialog":return await this.options.executor.openDialog({type:e.type,content:e.content,title:e.title});case"closeDialog":return this.options.executor.closeDialog(e.dialogId),{success:!0};case"showToast":return this.options.executor.showToast({message:e.message,type:e.type,duration:e.duration}),{success:!0};case"showLoading":return this.options.executor.showLoading(e.message),{success:!0};case"hideLoading":return this.options.executor.hideLoading(),{success:!0};case"refreshData":return await this.options.executor.refreshData(e.queryId),{success:!0};case"track":return this.options.executor.track({eventName:e.eventName,params:e.params}),{success:!0};default:throw new a(t,`Unknown builtin action: ${t}`)}}async executeCustomAction(t,e){const s=t.split("@")[0],i=await this.options.executor.executeAction(s,{...e,actionDefinitionVersionId:t});if(!i.success)throw new a(s,i.errorMessage||"Action execution failed",void 0,t,{errorCode:i.errorCode});return i.data}resolveParams(t,e){const s={};for(const[i,n]of Object.entries(t))s[i]=this.resolveValue(n,e);return s}resolveValue(e,s){if(null==e)return e;if("string"==typeof e){if(e.startsWith("${")&&e.endsWith("}")){const t=e.slice(2,-1);return this.options.expressionEngine.evaluateWithFallback(t,s,e)}return e.includes("${")?this.options.expressionEngine.evaluateTemplate(e,s):e}if("number"==typeof e||"boolean"==typeof e)return e;if(Array.isArray(e))return e.map(t=>this.resolveValue(t,s));if("object"==typeof e){const i=e;if("string"==typeof i.type&&t.EXPRESSION_TYPES.includes(i.type)&&"string"==typeof i.value){const t=i;return this.options.expressionEngine.evaluateWithFallback(t.value,s,t.fallback)}const n={};for(const[t,e]of Object.entries(i))n[t]=this.resolveValue(e,s);return n}return e}evaluateCondition(t,e,s){const i={...e,local:{...e.local||{},$event:s}},n=void 0===t.fallback||t.fallback,r=this.options.expressionEngine.evaluateWithFallback(t.value,i,n);return Boolean(r)}buildActionContext(t,e){return{...t,local:{...t.local||{},$event:e.$event,$prevResult:e.$prevResult,$results:e.$results}}}withTimeout(t,e){return new Promise((s,i)=>{const n=setTimeout(()=>{i(new Error(`Action timed out after ${e}ms`))},e);t.then(t=>{clearTimeout(n),s(t)}).catch(t=>{clearTimeout(n),i(t)})})}debounce(t,e){return new Promise(s=>{const i=this.debounceTimers.get(t);i&&clearTimeout(i);const n=setTimeout(()=>{this.debounceTimers.delete(t),s()},e);this.debounceTimers.set(t,n)})}throttle(t,e){const s=Date.now();return!(s-(this.throttleTimers.get(t)??0)<e||(this.throttleTimers.set(t,s),0))}delay(t){return new Promise(e=>setTimeout(e,t))}destroy(){this.debounceTimers.forEach(t=>clearTimeout(t)),this.debounceTimers.clear(),this.throttleTimers.clear()}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}};g.EXPRESSION_TYPES=["state","binding","local","template","computed"];var y=g,b=class{constructor(t){this.pos=0,this.tokens=[],this.input=t}tokenize(){for(this.pos=0,this.tokens=[];this.pos<this.input.length&&(this.skipWhitespace(),!(this.pos>=this.input.length));){const t=this.readToken();t&&this.tokens.push(t)}return this.tokens.push({type:"EOF",value:null,start:this.input.length,end:this.input.length}),this.tokens}readToken(){const t=this.input[this.pos],e=this.pos;if(this.isDigit(t)||"-"===t&&this.isDigit(this.peek(1)))return this.readNumber();if('"'===t||"'"===t)return this.readString(t);if(this.isIdentifierStart(t))return this.readIdentifier();const s=this.readOperator();if(s)return s;switch(t){case".":return this.pos++,{type:"DOT",value:".",start:e,end:this.pos};case"[":return this.pos++,{type:"LBRACKET",value:"[",start:e,end:this.pos};case"]":return this.pos++,{type:"RBRACKET",value:"]",start:e,end:this.pos};case"(":return this.pos++,{type:"LPAREN",value:"(",start:e,end:this.pos};case")":return this.pos++,{type:"RPAREN",value:")",start:e,end:this.pos};case",":return this.pos++,{type:"COMMA",value:",",start:e,end:this.pos};case"?":return this.pos++,{type:"QUESTION",value:"?",start:e,end:this.pos};case":":return this.pos++,{type:"COLON",value:":",start:e,end:this.pos}}throw new Error(`Unexpected character '${t}' at position ${this.pos}`)}readNumber(){const t=this.pos;let e="";for("-"===this.input[this.pos]&&(e+="-",this.pos++);this.isDigit(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;if("."===this.input[this.pos]&&this.isDigit(this.peek(1)))for(e+=".",this.pos++;this.isDigit(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;return{type:"NUMBER",value:parseFloat(e),start:t,end:this.pos}}readString(t){const e=this.pos;this.pos++;let s="";for(;this.pos<this.input.length&&this.input[this.pos]!==t;){if("\\"===this.input[this.pos]){this.pos++;const t=this.input[this.pos];switch(t){case"n":s+="\n";break;case"t":s+="\t";break;case"r":s+="\r";break;case"\\":s+="\\";break;case'"':s+='"';break;case"'":s+="'";break;default:s+=t}}else s+=this.input[this.pos];this.pos++}if(this.input[this.pos]!==t)throw new Error(`Unterminated string at position ${e}`);return this.pos++,{type:"STRING",value:s,start:e,end:this.pos}}readIdentifier(){const t=this.pos;let e="";for(;this.pos<this.input.length&&this.isIdentifierChar(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;return"true"===e?{type:"BOOLEAN",value:!0,start:t,end:this.pos}:"false"===e?{type:"BOOLEAN",value:!1,start:t,end:this.pos}:"null"===e?{type:"NULL",value:null,start:t,end:this.pos}:{type:"IDENTIFIER",value:e,start:t,end:this.pos}}readOperator(){const t=this.pos,e=this.input.slice(this.pos,this.pos+2),s=this.input[this.pos];return["==","!=",">=","<=","&&","||","??"].includes(e)?(this.pos+=2,{type:"OPERATOR",value:e,start:t,end:this.pos}):["+","-","*","/","%",">","<","!"].includes(s)?(this.pos++,{type:"OPERATOR",value:s,start:t,end:this.pos}):null}skipWhitespace(){for(;this.pos<this.input.length&&/\s/.test(this.input[this.pos]);)this.pos++}isDigit(t){return/[0-9]/.test(t)}isIdentifierStart(t){return/[a-zA-Z_$]/.test(t)}isIdentifierChar(t){return/[a-zA-Z0-9_$]/.test(t)}peek(t=1){return this.input[this.pos+t]||""}},w={len:t=>"string"==typeof t||Array.isArray(t)?t.length:0,trim:t=>String(t??"").trim(),upper:t=>String(t??"").toUpperCase(),lower:t=>String(t??"").toLowerCase(),substr:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=void 0!==s?Number(s):void 0;return i.substring(n,void 0!==r?n+r:void 0)},concat:(...t)=>t.map(t=>String(t??"")).join(""),replace:(t,e,s)=>String(t??"").split(String(e)).join(String(s)),split:(t,e)=>String(t??"").split(String(e)),join:(t,e)=>Array.isArray(t)?t.join(void 0!==e?String(e):","):"",startsWith:(t,e)=>String(t??"").startsWith(String(e)),endsWith:(t,e)=>String(t??"").endsWith(String(e)),contains:(t,e)=>String(t??"").includes(String(e)),toNumber:t=>{const e=Number(t);return isNaN(e)?0:e},toString:t=>String(t??""),toInt:t=>Math.trunc(Number(t)||0),toFloat:t=>parseFloat(String(t))||0,round:(t,e)=>{const s=Number(t)||0,i=Number(e)||0,n=Math.pow(10,i);return Math.round(s*n)/n},floor:t=>Math.floor(Number(t)||0),ceil:t=>Math.ceil(Number(t)||0),abs:t=>Math.abs(Number(t)||0),min:(...t)=>{const e=t.map(t=>Number(t)).filter(t=>!isNaN(t));return e.length>0?Math.min(...e):0},max:(...t)=>{const e=t.map(t=>Number(t)).filter(t=>!isNaN(t));return e.length>0?Math.max(...e):0},sum:t=>Array.isArray(t)?t.reduce((t,e)=>t+(Number(e)||0),0):0,avg:t=>Array.isArray(t)&&0!==t.length?t.reduce((t,e)=>t+(Number(e)||0),0)/t.length:0,random:()=>Math.random(),randomInt:(t,e)=>{const s=Math.ceil(Number(t)||0),i=Math.floor(Number(e)||100);return Math.floor(Math.random()*(i-s+1))+s},now:()=>Date.now(),today:()=>(new Date).toISOString().split("T")[0],dateFormat:(t,e)=>{const s=new Date(Number(t)||Date.now()),i=t=>t.toString().padStart(2,"0");return String(e||"YYYY-MM-DD").replace("YYYY",s.getFullYear().toString()).replace("MM",i(s.getMonth()+1)).replace("DD",i(s.getDate())).replace("HH",i(s.getHours())).replace("mm",i(s.getMinutes())).replace("ss",i(s.getSeconds()))},dateParse:t=>new Date(String(t)).getTime(),year:t=>new Date(Number(t)||Date.now()).getFullYear(),month:t=>new Date(Number(t)||Date.now()).getMonth()+1,day:t=>new Date(Number(t)||Date.now()).getDate(),addDays:(t,e)=>{const s=new Date(Number(t)||Date.now());return s.setDate(s.getDate()+(Number(e)||0)),s.getTime()},diffDays:(t,e)=>{const s=new Date(Number(t)||Date.now()),i=new Date(Number(e)||Date.now()),n=Math.abs(i.getTime()-s.getTime());return Math.floor(n/864e5)},isNull:t=>null==t,isUndefined:t=>void 0===t,isEmpty:t=>null==t||("string"==typeof t||Array.isArray(t)?0===t.length:"object"==typeof t&&0===Object.keys(t).length),isArray:t=>Array.isArray(t),isObject:t=>null!==t&&"object"==typeof t&&!Array.isArray(t),isString:t=>"string"==typeof t,isNumber:t=>"number"==typeof t&&!isNaN(t),isBoolean:t=>"boolean"==typeof t,typeOf:t=>null===t?"null":Array.isArray(t)?"array":typeof t,default:(t,e)=>t??e,coalesce:(...t)=>{for(const e of t)if(null!=e)return e;return null},ifElse:(t,e,s)=>t?e:s,first:t=>{if(Array.isArray(t))return t[0]},last:t=>{if(Array.isArray(t))return t[t.length-1]},at:(t,e)=>{if(Array.isArray(t))return t[Number(e)||0]},slice:(t,e,s)=>Array.isArray(t)?t.slice(Number(e)||0,void 0!==s?Number(s):void 0):[],includes:(t,e)=>!!Array.isArray(t)&&t.includes(e),indexOf:(t,e)=>Array.isArray(t)?t.indexOf(e):-1,reverse:t=>Array.isArray(t)?[...t].reverse():[],sort:t=>Array.isArray(t)?[...t].sort():[],unique:t=>Array.isArray(t)?[...new Set(t)]:[],flatten:t=>Array.isArray(t)?t.flat():[],count:t=>Array.isArray(t)?t.length:0,get:(t,e,s)=>{if(null==t)return s;const i=String(e).split(".");let n=t;for(const t of i){if(null==n)return s;n=n[t]}return n??s},keys:t=>"object"!=typeof t||null===t?[]:Object.keys(t),values:t=>"object"!=typeof t||null===t?[]:Object.values(t),entries:t=>"object"!=typeof t||null===t?[]:Object.entries(t),has:(t,e)=>"object"==typeof t&&null!==t&&String(e)in t,merge:(...t)=>{const e={};for(const s of t)"object"==typeof s&&null!==s&&Object.assign(e,s);return e},and:(...t)=>t.every(t=>Boolean(t)),or:(...t)=>t.some(t=>Boolean(t)),not:t=>!t,eq:(t,e)=>t===e,ne:(t,e)=>t!==e,gt:(t,e)=>Number(t)>Number(e),gte:(t,e)=>Number(t)>=Number(e),lt:(t,e)=>Number(t)<Number(e),lte:(t,e)=>Number(t)<=Number(e),between:(t,e,s)=>{const i=Number(t);return i>=Number(e)&&i<=Number(s)},formatNumber:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return s.toLocaleString(void 0,{minimumFractionDigits:i,maximumFractionDigits:i})},formatCurrency:(t,e)=>{const s=Number(t)||0,i=String(e||"CNY");return s.toLocaleString("zh-CN",{style:"currency",currency:i})},formatPercent:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return(100*s).toFixed(i)+"%"},currency:(t,e,s)=>{const i=Number(t)||0,n=String(e??"¥"),r=Number(s)??2;return`${n}${i.toLocaleString(void 0,{minimumFractionDigits:r,maximumFractionDigits:r})}`},percent:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return(100*s).toFixed(i)+"%"},number:(t,e)=>{const s=Number(t)||0,i=Number(e)??0;return s.toLocaleString(void 0,{minimumFractionDigits:i,maximumFractionDigits:i})},pluralize:(t,e,s)=>{const i=Number(t)||0;return`${i} ${String(1===i?e:s)}`},mask:(t,e,s,i)=>{const n=String(t??""),r=Number(e)||3,o=Number(s)||4,a=String(i??"*");if(n.length<=r+o)return n;const c=n.slice(0,r),h=n.slice(-o);return c+a.repeat(n.length-r-o)+h},jsonParse:t=>{try{return JSON.parse(String(t))}catch{return null}},jsonStringify:t=>JSON.stringify(t),toJSON:t=>JSON.stringify(t),fromJSON:t=>{try{return JSON.parse(String(t))}catch{return null}},clamp:(t,e,s)=>{const i=Number(t)||0,n=Number(e)||0,r=Number(s)||100;return Math.min(Math.max(i,n),r)},length:t=>Array.isArray(t)||"string"==typeof t?t.length:0,average:t=>Array.isArray(t)&&0!==t.length?t.reduce((t,e)=>t+(Number(e)||0),0)/t.length:0,dateAdd:(t,e,s)=>{const i=new Date(Number(t)||Date.now()),n=Number(e)||0;switch(String(s??"day").toLowerCase()){case"year":case"years":i.setFullYear(i.getFullYear()+n);break;case"month":case"months":i.setMonth(i.getMonth()+n);break;case"week":case"weeks":i.setDate(i.getDate()+7*n);break;case"day":case"days":default:i.setDate(i.getDate()+n);break;case"hour":case"hours":i.setHours(i.getHours()+n);break;case"minute":case"minutes":i.setMinutes(i.getMinutes()+n)}return i.getTime()},dateDiff:(t,e,s)=>{const i=new Date(Number(t)||Date.now()),n=new Date(Number(e)||Date.now()).getTime()-i.getTime();switch(String(s??"day").toLowerCase()){case"year":case"years":return Math.floor(n/31536e6);case"month":case"months":return Math.floor(n/2592e6);case"week":case"weeks":return Math.floor(n/6048e5);case"day":case"days":default:return Math.floor(n/864e5);case"hour":case"hours":return Math.floor(n/36e5);case"minute":case"minutes":return Math.floor(n/6e4)}},$if:(t,e,s)=>t?e:s,toBoolean:t=>"string"==typeof t?"false"!==t.toLowerCase()&&"0"!==t&&""!==t:Boolean(t),substring:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=void 0!==s?Number(s):void 0;return i.substring(n,r)},padStart:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=String(s??" ");return i.padStart(n,r)},padEnd:(t,e,s)=>{const i=String(t??""),n=Number(e)||0,r=String(s??" ");return i.padEnd(n,r)},repeat:(t,e)=>{const s=String(t??""),i=Math.max(0,Math.floor(Number(e)||0));return s.repeat(i)}},v={"||":1,"??":1,"&&":2,"==":3,"!=":3,"<":4,">":4,"<=":4,">=":4,"+":5,"-":5,"*":6,"/":6,"%":6},$=class{constructor(t){this.pos=0,this.tokens=t}parse(){const t=this.parseExpression();if("EOF"!==this.current().type)throw new Error(`Unexpected token '${this.current().value}' at position ${this.current().start}`);return t}parseExpression(){return this.parseTernary()}parseTernary(){const t=this.parseBinary(0);if("QUESTION"===this.current().type){this.advance();const e=this.parseExpression();return this.expect("COLON"),{type:"conditional",test:t,consequent:e,alternate:this.parseExpression(),raw:void 0}}return t}parseBinary(t){let e=this.parseUnary();for(;;){const s=this.current();if("OPERATOR"!==s.type)break;const i=v[s.value];if(void 0===i||i<t)break;this.advance();const n=this.parseBinary(i+1);e={type:"binary",operator:s.value,left:e,right:n,raw:void 0}}return e}parseUnary(){const t=this.current();if("OPERATOR"===t.type&&("!"===t.value||"-"===t.value)){this.advance();const e=this.parseUnary();return{type:"unary",operator:t.value,argument:e,raw:void 0}}return this.parsePostfix()}parsePostfix(){let t=this.parsePrimary();for(;;){const e=this.current();if("DOT"===e.type)this.advance(),t={type:"member",object:t,property:this.expect("IDENTIFIER").value,computed:!1,raw:void 0};else if("LBRACKET"===e.type){this.advance();const e=this.parseExpression();this.expect("RBRACKET"),t={type:"member",object:t,property:e,computed:!0,raw:void 0}}else{if("LPAREN"!==e.type||"identifier"!==t.type)break;{const s=t.name;if(!(s in w))throw new Error(`Unknown function '${s}' at position ${e.start}`);this.advance();const i=this.parseArguments();this.expect("RPAREN"),t={type:"call",callee:s,arguments:i,raw:void 0}}}}return t}parsePrimary(){const t=this.current();if("NUMBER"===t.type||"STRING"===t.type||"BOOLEAN"===t.type||"NULL"===t.type)return this.advance(),{type:"literal",value:t.value,start:t.start,end:t.end,raw:void 0};if("IDENTIFIER"===t.type)return this.advance(),{type:"identifier",name:t.value,start:t.start,end:t.end,raw:void 0};if("LBRACKET"===t.type)return this.parseArray();if("LPAREN"===t.type){this.advance();const t=this.parseExpression();return this.expect("RPAREN"),t}throw new Error(`Unexpected token '${t.value}' at position ${t.start}`)}parseArray(){const t=this.current().start;this.advance();const e=[];for(;"RBRACKET"!==this.current().type&&(e.push(this.parseExpression()),"COMMA"===this.current().type);)this.advance();const s=this.current().end;return this.expect("RBRACKET"),{type:"array",elements:e,start:t,end:s,raw:void 0}}parseArguments(){const t=[];if("RPAREN"!==this.current().type)for(t.push(this.parseExpression());"COMMA"===this.current().type;)this.advance(),t.push(this.parseExpression());return t}current(){return this.tokens[this.pos]}advance(){return this.tokens[this.pos++]}expect(t){const e=this.current();if(e.type!==t)throw new Error(`Expected '${t}' but got '${e.type}' at position ${e.start}`);return this.advance()}},x=class{constructor(t={}){this.depth=0,this.startTime=0,this.options={maxDepth:100,timeout:1e3,debug:!1,...t}}evaluate(t,e){this.depth=0,this.startTime=Date.now();try{return{value:this.evaluateNode(t,e)}}catch(t){return{value:void 0,error:t instanceof Error?t:new Error(String(t))}}}evaluateNode(t,e){switch(this.checkLimits(),t.type){case"literal":return this.evaluateLiteral(t);case"identifier":return this.evaluateIdentifier(t,e);case"member":return this.evaluateMember(t,e);case"call":return this.evaluateCall(t,e);case"binary":return this.evaluateBinary(t,e);case"unary":return this.evaluateUnary(t,e);case"conditional":return this.evaluateConditional(t,e);case"array":return this.evaluateArray(t,e);default:throw new o("",`Unknown node type: ${t.type}`)}}evaluateLiteral(t){return t.value}evaluateIdentifier(t,e){const s=t.name;switch(s){case"state":return e.state;case"binding":case"query":return e.binding;case"local":return e.local;case"props":return e.props;case"event":return e.event;case"item":return e.local?.item;case"index":return e.local?.index;default:if(e.local&&s in e.local)return e.local[s];throw new o("",`Unknown variable '${s}'. Available: state, binding, local, props, event`)}}evaluateMember(t,e){const s=this.evaluateNode(t.object,e);if(null==s)return;let i;return i=t.computed?this.evaluateNode(t.property,e):t.property,"object"==typeof s&&null!==s?s[i]:void 0}evaluateCall(t,e){const s=w[t.callee];if(!s)throw new o("",`Unknown function '${t.callee}'`);return s(...t.arguments.map(t=>this.evaluateNode(t,e)))}evaluateBinary(t,e){const s=t.operator;if("&&"===s){const s=this.evaluateNode(t.left,e);return s?this.evaluateNode(t.right,e):s}if("||"===s){return this.evaluateNode(t.left,e)||this.evaluateNode(t.right,e)}if("??"===s){const s=this.evaluateNode(t.left,e);return null!=s?s:this.evaluateNode(t.right,e)}const i=this.evaluateNode(t.left,e),n=this.evaluateNode(t.right,e);switch(s){case"+":return"string"==typeof i||"string"==typeof n?String(i)+String(n):i+n;case"-":return i-n;case"*":return i*n;case"/":return i/n;case"%":return i%n;case"==":return i===n;case"!=":return i!==n;case"<":return i<n;case">":return i>n;case"<=":return i<=n;case">=":return i>=n;default:throw new o("",`Unknown operator '${s}'`)}}evaluateUnary(t,e){const s=this.evaluateNode(t.argument,e);switch(t.operator){case"!":return!s;case"-":return-s;default:throw new o("",`Unknown unary operator '${t.operator}'`)}}evaluateConditional(t,e){return this.evaluateNode(t.test,e)?this.evaluateNode(t.consequent,e):this.evaluateNode(t.alternate,e)}evaluateArray(t,e){return t.elements.map(t=>this.evaluateNode(t,e))}checkLimits(){if(this.depth++,this.depth>(this.options.maxDepth??100))throw new o("","Maximum recursion depth exceeded");if(Date.now()-this.startTime>(this.options.timeout??1e3))throw new o("","Expression evaluation timeout")}},S=class{constructor(t={}){this.astCache=new Map,this.options={cacheAST:!0,maxCacheSize:1e3,...t},this.evaluator=new x(t)}evaluate(t,e){try{const s=this.parse(t);return this.evaluator.evaluate(s,e)}catch(t){return{value:void 0,error:t instanceof Error?t:new Error(String(t))}}}evaluateWithFallback(t,e,s){const i="string"==typeof t?t:t.value,n="object"==typeof t&&void 0!==t.fallback?t.fallback:s,r=this.evaluate(i,e);return r.error?(this.log("warn",`Expression evaluation failed: ${r.error.message}`,i),n):r.value}evaluateTemplate(t,e){return t.replace(/\$\{([^}]+)\}/g,(t,s)=>{const i=this.evaluate(s.trim(),e);return i.error?(this.log("warn",`Template expression failed: ${i.error.message}`,s),""):String(i.value??"")})}parse(t){if(this.options.cacheAST){const e=this.astCache.get(t);if(e)return e}try{const e=new b(t).tokenize(),s=new $(e).parse();return this.options.cacheAST&&(this.astCache.size>=(this.options.maxCacheSize??1e3)&&Array.from(this.astCache.keys()).slice(0,Math.floor(this.astCache.size/2)).forEach(t=>this.astCache.delete(t)),this.astCache.set(t,s)),s}catch(e){throw new o(t,e instanceof Error?e.message:"Parse error")}}validate(t){const e=[],s=[],i=[],n=[];try{const e=this.parse(t);return this.collectReferences(e,i,n),{valid:!0,errors:[],warnings:s,referencedPaths:i,usedFunctions:n}}catch(t){return e.push({type:"invalid_syntax",message:t instanceof Error?t.message:"Parse error"}),{valid:!1,errors:e,warnings:s,referencedPaths:i,usedFunctions:n}}}clearCache(){this.astCache.clear()}collectReferences(t,e,s){switch(t.type){case"identifier":e.push(t.name);break;case"member":{const s=this.buildMemberPath(t);s&&e.push(s);break}case"call":s.push(t.callee),t.arguments.forEach(t=>this.collectReferences(t,e,s));break;case"binary":this.collectReferences(t.left,e,s),this.collectReferences(t.right,e,s);break;case"unary":this.collectReferences(t.argument,e,s);break;case"conditional":this.collectReferences(t.test,e,s),this.collectReferences(t.consequent,e,s),this.collectReferences(t.alternate,e,s);break;case"array":t.elements.forEach(t=>this.collectReferences(t,e,s))}}buildMemberPath(t){if("identifier"===t.type)return t.name;if("member"===t.type&&!t.computed){const e=this.buildMemberPath(t.object);if(e)return`${e}.${t.property}`}return null}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},k=class{constructor(t){this.loadingCount=0,this.loadingElement=null,this.clipboard={write:async t=>{try{return await navigator.clipboard.writeText(t),!0}catch(e){return this.log("error","Clipboard write failed:",e),this.fallbackCopy(t)}},read:async()=>{try{return await navigator.clipboard.readText()}catch(t){return this.log("error","Clipboard read failed:",t),null}}},this.storage={get:t=>{const e=`${this.storageNamespace}:${t}`,s=localStorage.getItem(e);if(!s)return null;try{const t=JSON.parse(s);return t.expires&&Date.now()>t.expires?(localStorage.removeItem(e),null):t.value}catch{return null}},set:(t,e,s)=>{const i=`${this.storageNamespace}:${t}`,n={value:e,expires:s?.ttlSeconds?Date.now()+1e3*s.ttlSeconds:void 0};("session"===s?.level?sessionStorage:localStorage).setItem(i,JSON.stringify(n))},remove:t=>{const e=`${this.storageNamespace}:${t}`;localStorage.removeItem(e),sessionStorage.removeItem(e)},clear:()=>{const t=`${this.storageNamespace}:`;for(let e=localStorage.length-1;e>=0;e--){const s=localStorage.key(e);s?.startsWith(t)&&localStorage.removeItem(s)}for(let e=sessionStorage.length-1;e>=0;e--){const s=sessionStorage.key(e);s?.startsWith(t)&&sessionStorage.removeItem(s)}}},this.options=t,this.storageNamespace=`djvlc:${t.context.appId}`}async navigate(t){this.log("debug","Navigate:",t),this.track({eventName:"djvlc_navigate",params:{to:t.to,type:t.type},type:"click"});let e=t.to;if(t.query){const s=new URLSearchParams(t.query);e+=(e.includes("?")?"&":"?")+s.toString()}switch(t.type){case"external":t.newWindow?window.open(e,"_blank","noopener,noreferrer"):window.location.href=e;break;case"replace":window.location.replace(e);break;default:t.newWindow?window.open(e,"_blank"):window.location.href=e}}track(t){this.log("debug","Track event:",t);const e=this.options.context;this.options.userApiAdapter.track({eventName:t.eventName,params:t.params,type:t.type||"custom",timestamp:Date.now(),context:{pageVersionId:e.pageVersionId,runtimeVersion:e.runtimeVersion,userId:e.userId,deviceId:e.deviceId,channel:e.channel,appId:e.appId,env:e.env}})}async requestData(t,e){this.log("debug",`Requesting data: ${t}`,e);const s=performance.now(),i=this.options.context;try{const n=await this.options.userApiAdapter.executeQuery({queryVersionId:t,params:e??{},context:{pageVersionId:i.pageVersionId,uid:i.userId,deviceId:i.deviceId}}),r=performance.now()-s;if(this.log("debug",`Data query completed in ${r.toFixed(2)}ms`),!n.success)throw new Error(n.message||n.errorMessage||"Query failed");return this.options.stateManager.setQuery(t,n.data),n.data}catch(e){const i=performance.now()-s;throw this.log("error",`Data query failed: ${t} (${i.toFixed(2)}ms)`,e),e}}async executeAction(t,e={}){this.log("debug",`Executing action: ${t}`,e);const s=performance.now(),i=this.options.context,n=this.generateIdempotencyKey(t,e);this.track({eventName:"djvlc_action_start",params:{actionType:t,idempotencyKey:n},type:"custom"});try{const r=await this.options.userApiAdapter.executeAction({actionType:t,params:e||{},context:{pageVersionId:i.pageVersionId,uid:i.userId,deviceId:i.deviceId,channel:i.channel,appId:i.appId},idempotencyKey:n}),o=performance.now()-s;return this.log("debug",`Action completed in ${o.toFixed(2)}ms`,{success:r.success}),this.track({eventName:r.success?"djvlc_action_success":"djvlc_action_fail",params:{actionType:t,idempotencyKey:n,duration:Math.round(o),errorCode:r.errorCode},type:"custom"}),r}catch(e){const i=performance.now()-s;return this.log("error",`Action failed: ${t} (${i.toFixed(2)}ms)`,e),this.track({eventName:"djvlc_action_error",params:{actionType:t,idempotencyKey:n,duration:Math.round(i),errorMessage:e instanceof Error?e.message:"Unknown error"},type:"custom"}),{success:!1,errorCode:"NETWORK_ERROR",errorMessage:e instanceof Error?e.message:"Action failed"}}}async openDialog(t){return this.log("debug","Open dialog:",t),new Promise(e=>{const s=new CustomEvent("djvlc:openDialog",{detail:{options:t,resolve:t=>e(t)}});document.dispatchEvent(s),setTimeout(()=>{e({confirmed:!1})},6e4)})}closeDialog(t){this.log("debug","Close dialog:",t);const e=new CustomEvent("djvlc:closeDialog",{detail:{dialogId:t}});document.dispatchEvent(e)}showToast(t){this.log("debug","Show toast:",t);const e=document.createElement("div");switch(e.className=`djvlc-toast djvlc-toast-${t.type||"info"} djvlc-toast-${t.position||"top"}`,e.setAttribute("role","alert"),e.textContent=t.message,Object.assign(e.style,{position:"fixed",left:"50%",transform:"translateX(-50%)",padding:"12px 24px",borderRadius:"8px",color:"#fff",fontSize:"14px",zIndex:"10000",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",transition:"opacity 0.3s, transform 0.3s",opacity:"0"}),e.style.backgroundColor={success:"#52c41a",error:"#ff4d4f",warning:"#faad14",info:"#1890ff"}[t.type||"info"],t.position){case"center":e.style.top="50%",e.style.transform="translate(-50%, -50%)";break;case"bottom":e.style.bottom="20px";break;default:e.style.top="20px"}document.body.appendChild(e),requestAnimationFrame(()=>{e.style.opacity="1"}),setTimeout(()=>{e.style.opacity="0",setTimeout(()=>e.remove(),300)},t.duration||3e3)}showLoading(t){this.loadingCount++,1===this.loadingCount&&(this.loadingElement=document.createElement("div"),this.loadingElement.className="djvlc-loading-overlay",this.loadingElement.innerHTML=`\n <div class="djvlc-loading-content">\n <div class="djvlc-loading-spinner"></div>\n <div class="djvlc-loading-message">${t||"加载中..."}</div>\n </div>\n `,Object.assign(this.loadingElement.style,{position:"fixed",top:"0",left:"0",right:"0",bottom:"0",backgroundColor:"rgba(0,0,0,0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"10001"}),document.body.appendChild(this.loadingElement))}hideLoading(){this.loadingCount=Math.max(0,this.loadingCount-1),0===this.loadingCount&&this.loadingElement&&(this.loadingElement.remove(),this.loadingElement=null)}async share(t){if(this.log("debug","Share:",t),navigator.share)try{return await navigator.share({title:t.title,text:t.description,url:t.url}),{success:!0,channel:"native"}}catch(t){if("AbortError"===t.name)return{success:!1,cancelReason:"User cancelled"};throw t}return t.url&&await this.clipboard.write(t.url)?(this.showToast({message:"链接已复制",type:"success"}),{success:!0,channel:"link"}):{success:!1,cancelReason:"Share not supported"}}async confirm(t){return this.log("debug","Confirm:",t),window.confirm(t.content)}async showActionSheet(t){return this.log("debug","Show action sheet:",t),new Promise(e=>{const s=new CustomEvent("djvlc:showActionSheet",{detail:{options:t,resolve:t=>e(t)}});document.dispatchEvent(s),setTimeout(()=>{e({cancelled:!0})},6e4)})}previewImage(t){this.log("debug","Preview image:",t);const e=new CustomEvent("djvlc:previewImage",{detail:t});document.dispatchEvent(e)}async scanCode(){return this.log("debug","Scan code"),new Promise(t=>{const e=new CustomEvent("djvlc:scanCode",{detail:{resolve:e=>t(e)}});document.dispatchEvent(e),setTimeout(()=>{t({success:!1,cancelReason:"Timeout"})},6e4)})}getState(t){return this.options.stateManager.getVariable(t)}setState(t,e){this.options.stateManager.setVariable(t,e)}getContext(){const t=this.options.context;return{pageVersionId:t.pageVersionId,componentVersionId:"",instanceId:"",userId:t.userId,deviceId:t.deviceId,channel:t.channel,appId:t.appId,env:t.env}}generateIdempotencyKey(t,e){const s=Date.now(),i=JSON.stringify(e||{});return`${t}:${s}:${this.simpleHash(i)}`}simpleHash(t){let e=0;for(let s=0;s<t.length;s++)e=(e<<5)-e+t.charCodeAt(s),e&=e;return Math.abs(e).toString(36)}fallbackCopy(t){const e=document.createElement("textarea");e.value=t,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select();try{return document.execCommand("copy"),!0}catch{return!1}finally{document.body.removeChild(e)}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},E=class{constructor(t={}){this.blockedComponentsMap=new Map,this.blockedActionsSet=new Set,this.allowedCapabilitiesSet=null,this.options={enableSRI:!0,cdnDomains:[],apiDomains:[],blockedComponents:[],blockedActions:[],applyCSPOnInit:!1,...t},this.updateBlockedList(t.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[],t.blockedActions||[]),t.allowedCapabilities&&(this.allowedCapabilitiesSet=new Set(t.allowedCapabilities)),t.applyCSPOnInit&&this.applyCSP()}updateBlockedList(t,e){this.blockedComponentsMap.clear(),t.forEach(t=>{const[e,s]=t.split("@");e&&s&&this.blockedComponentsMap.set(t,{name:e,version:s,reason:"Blocked by registry"})}),this.blockedActionsSet=new Set(e)}addBlockedComponent(t){const e=`${t.name}@${t.version}`;this.blockedComponentsMap.set(e,t),this.log("warn",`Component blocked: ${e} - ${t.reason}`)}removeBlockedComponent(t,e){const s=`${t}@${e}`;this.blockedComponentsMap.delete(s),this.log("info",`Component unblocked: ${s}`)}isComponentBlocked(t,e){return this.blockedComponentsMap.has(`${t}@${e}`)}getBlockedInfo(t,e){return this.blockedComponentsMap.get(`${t}@${e}`)}getAllBlockedComponents(){return Array.from(this.blockedComponentsMap.values())}isActionBlocked(t){return this.blockedActionsSet.has(t)}isCapabilityAllowed(t){return!this.allowedCapabilitiesSet||this.allowedCapabilitiesSet.has(t)}validateCapabilities(t,e,s){if(!this.allowedCapabilitiesSet)return{valid:!0,disallowed:[]};const i=s.filter(t=>!this.allowedCapabilitiesSet.has(t));return i.length>0&&this.log("warn",`Component ${t}@${e} uses disallowed capabilities: ${i.join(", ")}`),{valid:0===i.length,disallowed:i}}async validateIntegrity(t,e,s,i){if(!this.options.enableSRI)return;const[r,o]=i.split("-");if(!r||!o)throw new n(t,e,i,"Invalid integrity format");const a=await this.computeHash(s,r);if(a!==o)throw this.log("error",`Integrity check failed for ${t}@${e}`),new n(t,e,o,a);this.log("debug",`Integrity check passed for ${t}@${e}`)}async generateIntegrity(t,e="sha384"){return`${e}-${await this.computeHash(t,e)}`}isAllowedUrl(t,e){const s="cdn"===e?this.options.cdnDomains:this.options.apiDomains;if(!s||0===s.length)return!0;try{const e=new URL(t);return s.some(t=>{if(t.startsWith("*.")){const s=t.slice(2);return e.hostname.endsWith(s)||e.hostname===s.slice(1)}return e.hostname===t})}catch{return!1}}validateExternalUrl(t){try{const e=new URL(t);if(!["http:","https:"].includes(e.protocol))return{safe:!1,reason:`Unsafe protocol: ${e.protocol}`};const s=e.hostname;return"localhost"===s||"127.0.0.1"===s||s.startsWith("192.168.")||s.startsWith("10.")||s.startsWith("172.16.")?{safe:!1,reason:"Internal network address not allowed"}:{safe:!0}}catch{return{safe:!1,reason:"Invalid URL format"}}}generateCSPPolicy(){const t=this.options.cdnDomains||[],e=this.options.apiDomains||[],s=["'self'",...t].join(" "),i=["'self'",...e,...t].join(" ");return["default-src 'self'",`script-src ${s}`,`style-src ${["'self'","'unsafe-inline'",...t].join(" ")}`,`img-src ${["'self'","data:","blob:",...t].join(" ")}`,`font-src ${["'self'","data:",...t].join(" ")}`,`connect-src ${i}`,"frame-ancestors 'self'","base-uri 'self'","form-action 'self'","upgrade-insecure-requests"].join("; ")}applyCSP(){if(document.querySelector('meta[http-equiv="Content-Security-Policy"]'))return void this.log("debug","CSP meta tag already exists, skipping");const t=document.createElement("meta");t.httpEquiv="Content-Security-Policy",t.content=this.generateCSPPolicy(),document.head.appendChild(t),this.log("info","CSP policy applied")}assertNotBlocked(t,e){const s=this.getBlockedInfo(t,e);if(s)throw new r(t,e,s.reason)}createSafeEvaluator(){return(t,e)=>{const s=Object.keys(e),i=Object.values(e);return new Function(...s,`"use strict"; return (${t});`)(...i)}}async computeHash(t,e){const s=(new TextEncoder).encode(t),i=await crypto.subtle.digest(e.toUpperCase(),s),n=Array.from(new Uint8Array(i));return btoa(String.fromCharCode(...n))}log(t,e,...s){this.options.logger&&this.options.logger[t](e,...s)}},I=class{constructor(t){this.spans=new Map,this.metrics=[],this.errors=[],this.options={enabled:!0,sampleRate:1,batchSize:50,flushInterval:3e4,...t},this.traceId=this.generateTraceId(),this.shouldSample=Math.random()<(this.options.sampleRate??1),this.options.enabled&&this.options.endpoint&&this.startAutoFlush(),"undefined"!=typeof window&&(window.addEventListener("beforeunload",()=>this.flush()),window.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.flush()}))}getTraceId(){return this.traceId}getTraceparent(t){const e=t||this.generateSpanId(),s=this.shouldSample?"01":"00";return`00-${this.traceId}-${e}-${s}`}parseTraceparent(t){const e=t.split("-");if(4!==e.length)return null;const[,s,i,n]=e;return{traceId:s,parentSpanId:i,sampled:"01"===n}}startSpan(t,e,s){const i={spanId:this.generateSpanId(),traceId:this.traceId,parentSpanId:e,name:t,startTime:performance.now(),attributes:{pageVersionId:this.options.pageVersionId,...s}};return this.spans.set(i.spanId,i),this.log("debug",`Span started: ${t} (${i.spanId})`),i}endSpan(t,e="ok",s){const i=this.spans.get(t);if(i){i.endTime=performance.now(),i.status=e,s&&(i.attributes={...i.attributes,...s});const n=i.endTime-i.startTime;this.log("debug",`Span ended: ${i.name} (${t}) - ${n.toFixed(2)}ms [${e}]`)}}recordPageLoad(t){this.recordMetricInternal({type:"pageLoadTime",value:t,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordComponentLoad(t,e,s,i){this.recordMetricInternal({type:"componentLoadTime",value:s,pageVersionId:this.options.pageVersionId,componentName:t,componentVersion:e,timestamp:Date.now()}),i||this.recordError(new Error(`Component load failed: ${t}@${e}`),{componentVersion:`${t}@${e}`})}recordFirstRender(t){this.recordMetricInternal({type:"firstRenderTime",value:t,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordActionExecute(t,e,s,i){this.recordMetricInternal({type:"actionExecuteTime",value:s,pageVersionId:this.options.pageVersionId,actionType:t,timestamp:Date.now()}),i||this.recordError(new Error(`Action failed: ${t}`),{actionId:e})}recordQueryExecute(t,e,s,i=!1){this.recordMetricInternal({type:"queryFetchTime",value:e,pageVersionId:this.options.pageVersionId,queryId:t,timestamp:Date.now()}),this.log("debug",`Query ${t}: ${e.toFixed(2)}ms, cache: ${i}, success: ${s}`)}recordExpressionEval(t,e,s){e>1&&this.recordMetricInternal({type:"expressionEvalTime",value:e,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordError(t,e){const s={type:t.name||"Error",message:t.message,stack:t.stack,traceId:this.traceId,pageVersionId:this.options.pageVersionId,componentVersion:e?.componentVersion,actionId:e?.actionId,context:e,timestamp:Date.now()};this.errors.push(s),this.log("error",`Error recorded: ${t.message}`),this.options.onError?.(s),this.errors.length>=(this.options.batchSize??50)&&this.flush()}getMetrics(){return[...this.metrics]}getSpans(){return Array.from(this.spans.values())}getErrors(){return[...this.errors]}getPerformanceSummary(){const t=this.metrics.filter(t=>"componentLoadTime"===t.type),e=this.metrics.find(t=>"pageLoadTime"===t.type),s=this.metrics.find(t=>"firstRenderTime"===t.type);return{pageLoadTime:e?.value,firstRenderTime:s?.value,componentCount:t.length,avgComponentLoadTime:t.length>0?t.reduce((t,e)=>t+e.value,0)/t.length:0,errorCount:this.errors.length}}clear(){this.spans.clear(),this.metrics=[],this.errors=[]}async flush(){if(!this.shouldSample||!this.options.enabled)return;if(0===this.metrics.length&&0===this.errors.length&&0===this.spans.size)return;const t={traceId:this.traceId,pageVersionId:this.options.pageVersionId,appId:this.options.appId,runtimeVersion:this.options.runtimeVersion,spans:this.getSpans(),metrics:this.metrics,errors:this.errors,timestamp:Date.now()};if(this.clear(),this.options.endpoint)try{await fetch(this.options.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:!0}),this.log("debug","Telemetry flushed successfully")}catch(t){this.log("warn","Failed to flush telemetry:",t)}else this.log("debug","No endpoint configured, telemetry data discarded")}destroy(){this.flushTimer&&clearInterval(this.flushTimer),this.flush()}recordMetricInternal(t){this.metrics.push(t),this.options.onMetric?.(t),this.metrics.length>=(this.options.batchSize??50)&&this.flush()}startAutoFlush(){const t=this.options.flushInterval??3e4;this.flushTimer=setInterval(()=>this.flush(),t)}generateTraceId(){const t=new Uint8Array(16);return crypto.getRandomValues(t),Array.from(t,t=>t.toString(16).padStart(2,"0")).join("")}generateSpanId(){const t=new Uint8Array(8);return crypto.getRandomValues(t),Array.from(t,t=>t.toString(16).padStart(2,"0")).join("")}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},A=class t{constructor(t){this.container=null,this.renderedElements=new Map,this.componentEventListeners=new Map,this.expressionContext={state:{},binding:{},local:{}},this.loopContextStack=[],this.styleElement=null,this.options=t}init(){this.log("debug","Renderer initialized")}render(t,e){this.container=e,this.log("debug","Rendering page",t.pageId),this.cleanup(),e.innerHTML="",this.applyPageConfig(t,e),this.initializePageState(t);const s=this.renderNode(t.root);s&&e.appendChild(s),this.log("info",`Page rendered with root component: ${t.root.componentType}`)}updateComponent(t,e){const s=this.renderedElements.get(t);s?this.applyProps(s,e):this.log("warn",`Component not found: ${t}`)}updateContext(t){this.expressionContext={...this.expressionContext,...t}}getContext(){return{...this.expressionContext}}destroy(){this.cleanup(),this.container&&(this.container.innerHTML=""),this.log("debug","Renderer destroyed")}cleanup(){this.componentEventListeners.forEach((t,e)=>{const s=this.renderedElements.get(e);s&&t.forEach(({event:t,handler:e})=>{s.removeEventListener(t,e)})}),this.componentEventListeners.clear(),this.renderedElements.forEach(t=>{t.remove()}),this.renderedElements.clear(),this.styleElement&&(this.styleElement.remove(),this.styleElement=null),this.loopContextStack=[]}renderNode(t){const{id:e,componentType:s,componentVersion:i}=t;try{if(t.condition&&!this.evaluateCondition(t.condition))return this.log("debug",`Component ${e} hidden by condition`),null;if(t.loop)return this.renderLoop(t);const n=this.createElement(t);if(!n)return null;n.setAttribute("data-component-id",e),n.setAttribute("data-component-type",s),i&&n.setAttribute("data-component-version",i);const r=this.resolveProps(t.props);if(this.applyProps(n,r),t.style&&this.applyStyles(n,t.style),t.layout&&this.applyLayout(n,t.layout),this.options.injectHostApi(n,e),t.eventHandlers&&t.eventHandlers.length>0&&this.bindEventHandlers(n,e,t.eventHandlers),this.renderChildren(n,t),t.ref){const e=this.expressionContext.local,s=e.$refs||{};s[t.ref]=n,this.expressionContext={...this.expressionContext,local:{...e,$refs:s}}}return this.renderedElements.set(e,n),n}catch(t){return this.log("error",`Failed to render component: ${e}`,t),this.options.onRenderError?this.options.onRenderError(e,t):this.createErrorFallback(e,s,t)}}createElement(t){const{componentType:e}=t,s=this.options.components.get(e);if(s&&customElements.get(e))return document.createElement(e);const i=`${e}-${t.componentVersion?.replace(/\./g,"-")}`;if(customElements.get(i))return document.createElement(i);const n=document.createElement("div");return n.className=`djvlc-component djvlc-${e}`,s||(this.log("warn",`Component not loaded: ${e}`),n.classList.add("djvlc-component-fallback")),n}renderLoop(t){const{loop:e}=t;if(!e)return null;const s=this.evaluateExpression(e.items);if(!Array.isArray(s))return this.log("warn",`Loop items is not an array for ${t.id}`),null;const i=document.createDocumentFragment();s.forEach((s,n)=>{this.loopContextStack.push({item:s,index:n,loopConfig:e});const r={...this.expressionContext},o={...this.expressionContext.local,[e.itemName]:s,item:s,index:n};e.indexName&&(o[e.indexName]=n),this.expressionContext={...this.expressionContext,local:o};const a={...t,id:`${t.id}_${n}`,loop:void 0},c=this.renderNode(a);if(c){const t=this.evaluateExpression(e.key);c.setAttribute("data-loop-key",String(t??n)),i.appendChild(c)}this.expressionContext=r,this.loopContextStack.pop()});const n=document.createElement("div");return n.className="djvlc-loop-container",n.setAttribute("data-loop-id",t.id),n.appendChild(i),n}renderChildren(t,e){if(e.slots&&Object.keys(e.slots).length>0)for(const[s,i]of Object.entries(e.slots)){const e=this.createSlotContainer(s);for(const t of i){const s=this.renderNode(t);s&&e.appendChild(s)}t.appendChild(e)}}createSlotContainer(t){const e=document.createElement("div");return e.className=`djvlc-slot djvlc-slot-${t}`,e.setAttribute("data-slot",t),e}bindEventHandlers(t,e,s){const i=[];for(const n of s){const{eventName:s,preventDefault:r,stopPropagation:o,throttle:a,debounce:c,condition:h}=n;let l=t=>{if(h&&!this.evaluateCondition(h))return;r&&t.preventDefault(),o&&t.stopPropagation();const i=t.detail||{};this.options.onComponentEvent&&this.options.onComponentEvent(e,s,[n],i)};a&&a>0&&(l=this.createThrottledHandler(l,a)),c&&c>0&&(l=this.createDebouncedHandler(l,c)),t.addEventListener(s,l),i.push({event:s,handler:l})}this.componentEventListeners.set(e,i)}createThrottledHandler(t,e){let s=0;return i=>{const n=Date.now();n-s>=e&&(s=n,t(i))}}createDebouncedHandler(t,e){let s=null;return i=>{s&&clearTimeout(s),s=setTimeout(()=>{t(i),s=null},e)}}evaluateCondition(t){const e=this.evaluateExpression(t);return Boolean(e)}evaluateExpression(t){if(null==t)return t;if("object"==typeof t&&"type"in t&&"value"in t){const e=t,s=this.buildExpressionContext();return this.options.expressionEngine.evaluateWithFallback(e.value,s,e.fallback)}if("string"==typeof t){const e=this.buildExpressionContext();return this.options.expressionEngine.evaluateWithFallback(t,e,void 0)}return t}buildExpressionContext(){const t={};for(const e of this.loopContextStack)t[e.loopConfig.itemName]=e.item,t.item=e.item,t.index=e.index,e.loopConfig.indexName&&(t[e.loopConfig.indexName]=e.index);return{...this.expressionContext,local:{...this.expressionContext.local,...t}}}resolveProps(t){const e={};for(const[s,i]of Object.entries(t))e[s]=this.resolveValue(i);return e}resolveValue(e){if(null==e)return e;if("string"==typeof e)return e.includes("${")?this.options.expressionEngine.evaluateTemplate(e,this.buildExpressionContext()):e;if("number"==typeof e||"boolean"==typeof e)return e;if(Array.isArray(e))return e.map(t=>this.resolveValue(t));if("object"==typeof e){const s=e;if("string"==typeof s.type&&t.EXPRESSION_TYPES.includes(s.type)&&"string"==typeof s.value){const t=s;return this.options.expressionEngine.evaluateWithFallback(t.value,this.buildExpressionContext(),t.fallback)}const i={};for(const[t,e]of Object.entries(s))i[t]=this.resolveValue(e);return i}return e}applyProps(t,e){for(const[s,i]of Object.entries(e))null!=i&&(t.tagName.includes("-")?t[s]=i:"boolean"==typeof i?i?t.setAttribute(s,""):t.removeAttribute(s):"object"==typeof i?t.setAttribute(s,JSON.stringify(i)):t.setAttribute(s,String(i)))}applyStyles(t,e){if(e.inline)for(const[s,i]of Object.entries(e.inline)){if(null==i)continue;const e=this.resolveValue(i);let n;n="number"==typeof e?["zIndex","opacity","flex","fontWeight","lineHeight"].includes(s)?String(e):`${e}px`:String(e);const r=s.replace(/([A-Z])/g,"-$1").toLowerCase();t.style.setProperty(r,n)}e.className&&t.classList.add(...String(e.className).split(" ").filter(Boolean))}applyLayout(t,e){const{x:s,y:i,width:n,height:r,rotation:o,zIndex:a,responsive:c}=e;t.style.position="absolute",void 0!==s&&(t.style.left=`${s}px`),void 0!==i&&(t.style.top=`${i}px`),void 0!==n&&(t.style.width=`${n}px`),void 0!==r&&(t.style.height=`${r}px`),void 0!==o&&(t.style.transform=`rotate(${o}deg)`),void 0!==a&&(t.style.zIndex=String(a)),c&&this.applyResponsiveLayout(t,c)}applyResponsiveLayout(t,e){const s=t.getAttribute("data-component-id");if(!s)return;let i="";if(e.mobile&&(i+=`\n @media (max-width: 767px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.mobile)}\n }\n }\n `),e.tablet&&(i+=`\n @media (min-width: 768px) and (max-width: 1023px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.tablet)}\n }\n }\n `),e.desktop&&(i+=`\n @media (min-width: 1440px) {\n [data-component-id="${s}"] {\n ${this.layoutToCSS(e.desktop)}\n }\n }\n `),i){const t=document.createElement("style");t.setAttribute("data-djvlc-responsive",s),t.textContent=i,document.head.appendChild(t)}}layoutToCSS(t){const e=[];return void 0!==t.x&&e.push(`left: ${t.x}px`),void 0!==t.y&&e.push(`top: ${t.y}px`),void 0!==t.width&&e.push(`width: ${t.width}px`),void 0!==t.height&&e.push(`height: ${t.height}px`),void 0!==t.rotation&&e.push(`transform: rotate(${t.rotation}deg)`),void 0!==t.zIndex&&e.push(`z-index: ${t.zIndex}`),e.join("; ")}applyPageConfig(t,e){e.classList.add("djvlc-page"),e.setAttribute("data-page-id",t.pageId),e.setAttribute("data-page-version",t.pageVersion),e.setAttribute("data-schema-version",t.schemaVersion);const s=t.config;s&&(this.applyLayoutConfig(e,s.layout),s.styles&&this.applyStylesConfig(e,s.styles),s.behavior&&this.applyBehaviorConfig(e,s.behavior))}applyBehaviorConfig(t,e){e.debug&&t.setAttribute("data-debug","true"),e.i18n&&this.applyI18nConfig(t,e.i18n)}applyI18nConfig(t,e){const s=this.detectLocale(e);t.setAttribute("lang",s),t.setAttribute("data-locale",s),t.setAttribute("data-default-locale",e.defaultLocale),t.setAttribute("data-supported-locales",e.supportedLocales.join(",")),e.translationBundleId&&t.setAttribute("data-translation-bundle",e.translationBundleId),t.style.setProperty("--djvlc-locale",s),t.style.setProperty("--djvlc-dir",this.getTextDirection(s)),"rtl"===this.getTextDirection(s)?(t.setAttribute("dir","rtl"),t.classList.add("djvlc-rtl")):t.setAttribute("dir","ltr"),this.expressionContext={...this.expressionContext,local:{...this.expressionContext.local,$locale:s,$defaultLocale:e.defaultLocale,$supportedLocales:e.supportedLocales}},this.log("debug",`I18n configured: locale=${s}, default=${e.defaultLocale}`)}detectLocale(t){const{defaultLocale:e,supportedLocales:s,detection:i="browser"}=t;let n=null;switch(i){case"browser":case"header":n=this.detectBrowserLocale(s);break;case"url":n=this.detectUrlLocale(s);break;case"path":n=this.detectPathLocale(s);break;case"cookie":n=this.detectCookieLocale(s);break;case"manual":n=e;break;default:n=null}return n&&s.includes(n)?n:e}detectBrowserLocale(t){if("undefined"==typeof navigator)return null;const e=navigator.languages||[navigator.language];for(const s of e){if(t.includes(s))return s;const e=s.split("-")[0],i=t.find(t=>t===e||t.startsWith(`${e}-`));if(i)return i}return null}detectUrlLocale(t){if("undefined"==typeof window)return null;const e=new URLSearchParams(window.location.search),s=e.get("lang")||e.get("locale");return s&&t.includes(s)?s:null}detectPathLocale(t){if("undefined"==typeof window)return null;const e=window.location.pathname.split("/").filter(Boolean);if(e.length>0){const s=e[0];if(t.includes(s))return s}return null}detectCookieLocale(t){if("undefined"==typeof document)return null;const e=document.cookie.split(";");for(const s of e){const[e,i]=s.trim().split("=");if("lang"===e||"locale"===e||"language"===e){const e=decodeURIComponent(i);if(t.includes(e))return e}}return null}getTextDirection(t){const e=t.split("-")[0];return["ar","ar-SA","ar-EG","ar-AE","he","he-IL","fa","fa-IR","ur","ur-PK","yi","ps","dv"].some(s=>s===t||s===e)?"rtl":"ltr"}applyLayoutConfig(t,e){if(t.setAttribute("data-canvas-type",e.canvasType),e.canvasSize&&"responsive"!==e.canvasType&&(t.style.width=`${e.canvasSize.width}px`,t.style.minHeight=`${e.canvasSize.height}px`),e.maxWidth&&(t.style.maxWidth=`${e.maxWidth}px`,t.style.marginLeft="auto",t.style.marginRight="auto"),e.padding){const{top:s=0,right:i=0,bottom:n=0,left:r=0}=e.padding;t.style.padding=`${s}px ${i}px ${n}px ${r}px`}e.viewport&&(e.viewport.mobile&&t.style.setProperty("--djvlc-breakpoint-mobile",`${e.viewport.mobile}px`),e.viewport.tablet&&t.style.setProperty("--djvlc-breakpoint-tablet",`${e.viewport.tablet}px`),e.viewport.desktop&&t.style.setProperty("--djvlc-breakpoint-desktop",`${e.viewport.desktop}px`))}applyStylesConfig(t,e){if(e.theme&&this.applyThemeConfig(t,e.theme),e.background&&this.applyBackgroundConfig(t,e.background),e.cssVariables)for(const[s,i]of Object.entries(e.cssVariables)){const e=s.startsWith("--")?s:`--${s}`;t.style.setProperty(e,i)}e.customCSS&&this.injectCustomCSS(e.customCSS)}applyThemeConfig(t,e){if(e.preset&&(t.setAttribute("data-theme",e.preset),"system"===e.preset)){const e=window.matchMedia("(prefers-color-scheme: dark)").matches;t.setAttribute("data-theme-resolved",e?"dark":"light")}if(e.variables)for(const[s,i]of Object.entries(e.variables)){const e=s.startsWith("--")?s:`--theme-${s}`;t.style.setProperty(e,i)}e.transition&&t.style.setProperty("--djvlc-theme-transition","all 0.3s ease")}applyBackgroundConfig(t,e){switch(e.type){case"color":t.style.backgroundColor=e.value;break;case"image":t.style.backgroundImage=`url(${e.value})`,t.style.backgroundSize=e.size||"cover",t.style.backgroundPosition=e.position||"center",t.style.backgroundRepeat=e.repeat||"no-repeat";break;case"gradient":t.style.backgroundImage=e.value}}injectCustomCSS(t){t.trim()&&(this.styleElement=document.createElement("style"),this.styleElement.setAttribute("data-djvlc-custom","true"),this.styleElement.textContent=t,document.head.appendChild(this.styleElement))}initializePageState(t){if(t.state&&t.state.fields){const e={};for(const[s,i]of Object.entries(t.state.fields))i&&"object"==typeof i&&(e[s]=i.initialValue);this.expressionContext={...this.expressionContext,state:e}}}createErrorFallback(t,e,s){const i=document.createElement("div");return i.className="djvlc-error-boundary",i.setAttribute("data-component-id",t),i.setAttribute("data-error","true"),i.innerHTML=`\n <div class="djvlc-error-content">\n <span class="djvlc-error-icon">⚠️</span>\n <span class="djvlc-error-message">组件渲染失败: ${e}</span>\n ${this.options.debug?`<pre class="djvlc-error-detail">${s.message}</pre>`:""}\n </div>\n `,i}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}};A.EXPRESSION_TYPES=["state","binding","local","template","computed"];var C=A;function N(){customElements.get("djvlc-fallback")||customElements.define("djvlc-fallback",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML='\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #fff2f0;\n border: 1px solid #ffccc7;\n border-radius: 4px;\n color: #ff4d4f;\n font-size: 14px;\n }\n .title {\n font-weight: 600;\n margin-bottom: 8px;\n }\n .message {\n color: #666;\n }\n </style>\n <div class="title">组件加载失败</div>\n <div class="message"><slot>请刷新页面重试</slot></div>\n '}static get observedAttributes(){return["message","component-name"]}attributeChangedCallback(t,e,s){if("message"===t&&this.shadowRoot){const t=this.shadowRoot.querySelector(".message");t&&(t.textContent=s)}if("component-name"===t&&this.shadowRoot){const t=this.shadowRoot.querySelector(".title");t&&(t.textContent=`组件 ${s} 加载失败`)}}}),customElements.get("djvlc-blocked")||customElements.define("djvlc-blocked",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML='\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #fffbe6;\n border: 1px solid #ffe58f;\n border-radius: 4px;\n color: #faad14;\n font-size: 14px;\n }\n .icon {\n margin-right: 8px;\n }\n </style>\n <span class="icon">⚠️</span>\n <span>此组件已被暂停使用</span>\n '}}),customElements.get("djvlc-error-boundary")||customElements.define("djvlc-error-boundary",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML="\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #f5f5f5;\n border: 1px dashed #d9d9d9;\n border-radius: 4px;\n color: #999;\n font-size: 14px;\n text-align: center;\n }\n </style>\n <slot>渲染出错</slot>\n "}})}function j(t,e,s){const i=`djvlc-${"error"===t?"error-boundary":t}`,n=document.createElement(i);return e&&n.setAttribute("message",e),s&&n.setAttribute("component-name",s),n}var D=class{constructor(t){this.lifecycle=null,this.mounted=!1,this.destroyed=!1,this.cleanupFns=[],this.options=t}register(t){t?(this.lifecycle=t,this.log("debug","Lifecycle hooks registered",{onMounted:t.onMounted?.length??0,onBeforeUnmount:t.onBeforeUnmount?.length??0,onVisibilityChange:t.onVisibilityChange?.length??0}),t.onVisibilityChange&&t.onVisibilityChange.length>0&&this.setupVisibilityListener()):this.log("debug","No lifecycle hooks defined")}async triggerMounted(){this.mounted||this.destroyed||(this.mounted=!0,this.log("debug","Triggering onMounted lifecycle"),await this.executeLifecycleActions("mounted",this.lifecycle?.onMounted),this.options.onLifecycleEvent?.("mounted"))}async triggerBeforeUnmount(){this.mounted&&!this.destroyed&&(this.log("debug","Triggering onBeforeUnmount lifecycle"),await this.executeLifecycleActions("beforeUnmount",this.lifecycle?.onBeforeUnmount),this.options.onLifecycleEvent?.("beforeUnmount"))}async triggerVisibilityChange(t){if(!this.mounted||this.destroyed)return;this.log("debug","Triggering onVisibilityChange lifecycle",{isVisible:t});const e=this.options.getContext(),s={...e,local:{...e.local,$visible:t,$hidden:!t}};await this.executeLifecycleActionsWithContext("visibilityChange",this.lifecycle?.onVisibilityChange,s),this.options.onLifecycleEvent?.("visibilityChange",{isVisible:t})}async destroy(){this.destroyed||(await this.triggerBeforeUnmount(),this.cleanupFns.forEach(t=>t()),this.cleanupFns=[],this.destroyed=!0,this.lifecycle=null,this.log("debug","LifecycleManager destroyed"))}isMounted(){return this.mounted&&!this.destroyed}isDestroyed(){return this.destroyed}setupVisibilityListener(){const t=()=>{const t="visible"===document.visibilityState;this.triggerVisibilityChange(t).catch(t=>{this.log("error","Failed to handle visibility change",t)})};document.addEventListener("visibilitychange",t),this.cleanupFns.push(()=>{document.removeEventListener("visibilitychange",t)}),this.log("debug","Visibility listener registered")}async executeLifecycleActions(t,e){if(!e||0===e.length)return;const s=this.options.getContext();await this.executeLifecycleActionsWithContext(t,e,s)}async executeLifecycleActionsWithContext(t,e,s){if(e&&0!==e.length){this.log("debug",`Executing ${e.length} actions for ${t}`);try{const i={id:`lifecycle_${t}`,eventName:t,actions:e};await this.options.actionBridge.handleEvent(i,{lifecycle:t},s),this.log("debug",`Lifecycle ${t} actions completed`)}catch(e){this.log("error",`Failed to execute lifecycle ${t} actions`,e)}}}log(t,e,...s){this.options.logger?this.options.logger[t](e,...s):this.options.debug}},T=t.CURRENT_SCHEMA_VERSION,R="1.0.0",M=class{constructor(t){if(this.container=null,!t.pageId)throw new Error("pageId is required");if(this.options={channel:"prod",debug:!1,enableSRI:!0,env:"production",...t},this.logger=this.createLogger(),this.stateManager=new p,this.eventBus=new m({debug:t.debug,logger:this.logger}),this.expressionEngine=new S({debug:t.debug,logger:this.logger}),!t.userApiAdapter)throw new Error("userApiAdapter is required. Inject a UserApiAdapter implementation (e.g. from @djvlc/runtime-web or your host).");this.userApiAdapter=t.userApiAdapter,this.pageLoader=new h({apiBaseUrl:t.apiBaseUrl,userApiAdapter:this.userApiAdapter,channel:t.channel,previewToken:t.previewToken,headers:t.headers,logger:this.logger}),this.componentLoader=new u({cdnBaseUrl:t.cdnBaseUrl,enableSRI:t.enableSRI,headers:t.headers,logger:this.logger}),this.assetLoader=new d({cdnHosts:[new URL(t.cdnBaseUrl).host],apiHosts:[new URL(t.apiBaseUrl).host]}),this.securityManager=new E({enableSRI:t.enableSRI,cdnDomains:[new URL(t.cdnBaseUrl).host],apiDomains:[new URL(t.apiBaseUrl).host],logger:this.logger}),this.log("info","Runtime created",{version:R})}async init(){this.log("info","Initializing runtime");const t=performance.now();try{this.container=this.resolveContainer(),this.assetLoader.preconnectAll(),this.pageLoader.preconnect(),N(),this.stateManager.setPhase("resolving");const e=performance.now()-t;this.log("info",`Runtime initialized in ${e.toFixed(2)}ms`)}catch(t){throw this.handleError(t),t}}async loadFromResolved(t){this.log("info","Loading from resolved page:",t.pageId);const e=performance.now();try{if(this.stateManager.setPhase("resolving"),this.validateSchemaVersion(t.pageJson),this.stateManager.setPage(t),this.telemetryManager=new I({pageVersionId:t.pageVersionId,appId:this.options.appId,debug:this.options.debug,logger:this.logger,onMetric:this.options.onMetric}),t.runtimeConfig){const e=t.runtimeConfig.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[];this.securityManager.updateBlockedList(e,[]),this.componentLoader.updateBlockedList(e)}this.stateManager.setPhase("loading"),this.componentLoader.preload(t.manifest.components),(await this.componentLoader.loadAll(t.manifest)).forEach((t,e)=>{this.stateManager.setComponentStatus(e,t),this.telemetryManager.recordComponentLoad(t.name,t.version,t.loadTime||0,"loaded"===t.status)}),this.initHostApi(t),this.initActionBridge(),this.initDataBindingManager(t.pageJson),this.initRenderer(),this.initLifecycleManager(t.pageJson);const s=performance.now()-e;return this.telemetryManager.recordPageLoad(s),this.log("info",`Page loaded from resolved in ${s.toFixed(2)}ms`),this.emitEvent("page:loaded",{page:t,loadTime:s}),this.options.onLoad?.(t),t}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}setPrefetchedData(t){for(const[e,s]of Object.entries(t))this.stateManager.setQuery(e,s)}async load(){this.log("info","Loading page:",this.options.pageId);const t=performance.now();try{this.stateManager.setPhase("resolving");const e=await this.pageLoader.resolve(this.options.pageId,{uid:this.options.userId,deviceId:this.options.deviceId});if(this.validateSchemaVersion(e.pageJson),this.stateManager.setPage(e),this.telemetryManager=new I({pageVersionId:e.pageVersionId,appId:this.options.appId,debug:this.options.debug,logger:this.logger,onMetric:this.options.onMetric}),e.runtimeConfig){const t=e.runtimeConfig.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[];this.securityManager.updateBlockedList(t,[]),this.componentLoader.updateBlockedList(t)}this.stateManager.setPhase("loading"),this.componentLoader.preload(e.manifest.components),(await this.componentLoader.loadAll(e.manifest)).forEach((t,e)=>{this.stateManager.setComponentStatus(e,t),this.telemetryManager.recordComponentLoad(t.name,t.version,t.loadTime||0,"loaded"===t.status)}),this.initHostApi(e),this.initActionBridge(),this.initDataBindingManager(e.pageJson),this.initRenderer(),this.initLifecycleManager(e.pageJson);const s=performance.now()-t;return this.telemetryManager.recordPageLoad(s),this.log("info",`Page loaded in ${s.toFixed(2)}ms`),this.emitEvent("page:loaded",{page:e,loadTime:s}),this.options.onLoad?.(e),e}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}async render(){const t=this.stateManager.getState();if(!t.page||!this.container)throw new s("Page not loaded");this.log("info","Rendering page");const e=performance.now();try{this.stateManager.setPhase("rendering"),this.renderer.updateContext(this.stateManager.getExpressionContext()),this.renderer.render(t.page.pageJson,this.container),await this.dataBindingManager.initializeBindings(this.stateManager.getExpressionContext()),this.stateManager.setPhase("ready");const s=performance.now()-e;this.telemetryManager.recordFirstRender(s),this.log("info",`Page rendered in ${s.toFixed(2)}ms`),await this.lifecycleManager.triggerMounted(),this.emitEvent("page:rendered",{renderTime:s})}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}getHostApi(){return this.hostApi}getState(){return this.stateManager.getState()}onStateChange(t){return this.stateManager.subscribe(t)}on(t,e){return this.eventBus.on(t,e)}updateComponent(t,e){this.renderer.updateComponent(t,e)}setVariable(t,e){this.stateManager.setVariable(t,e),this.renderer.updateContext(this.stateManager.getExpressionContext()),this.dataBindingManager.onStateChange(t,this.stateManager.getExpressionContext())}getVariable(t){return this.stateManager.getVariable(t)}async refreshData(t){await this.dataBindingManager.refreshBinding(t,this.stateManager.getExpressionContext()),this.renderer.updateContext(this.stateManager.getExpressionContext())}async executeAction(t,e){return this.hostApi.executeAction(t,e)}async destroy(){this.log("info","Destroying runtime"),await(this.lifecycleManager?.destroy()),this.telemetryManager?.flush(),this.dataBindingManager?.destroy(),this.actionBridge?.destroy(),this.renderer?.destroy(),this.eventBus.clear(),this.stateManager.setDestroyed(),this.container&&(this.container.innerHTML=""),this.emitEvent("page:destroyed",{}),this.log("info","Runtime destroyed")}validateSchemaVersion(t){if(t.schemaVersion!==T)throw new s(`Unsupported schema version: ${t.schemaVersion}. Only ${T} is supported.`,{schemaVersion:t.schemaVersion,supportedVersion:T})}resolveContainer(){const{container:t}=this.options;if("string"==typeof t){const e=document.querySelector(t);if(!e)throw new Error(`Container not found: ${t}`);return e}return t}initHostApi(t){this.hostApi=new k({userApiAdapter:this.userApiAdapter,stateManager:this.stateManager,eventBus:this.eventBus,expressionEngine:this.expressionEngine,context:{pageId:t.pageId,pageVersionId:t.pageVersionId,runtimeVersion:R,userId:this.options.userId,deviceId:this.options.deviceId,channel:this.options.channel,appId:this.options.appId||"",env:this.options.env||"production",isEditMode:!1,isPreviewMode:t.isPreview||!1},debug:this.options.debug,logger:this.logger})}initActionBridge(){this.actionBridge=new y({executor:{executeAction:(t,e)=>this.hostApi.executeAction(t,e),requestData:(t,e)=>this.hostApi.requestData(t,e),navigate:t=>this.hostApi.navigate(t),openDialog:t=>this.hostApi.openDialog(t),closeDialog:()=>this.hostApi.closeDialog(),showToast:t=>this.hostApi.showToast(t),showLoading:t=>this.hostApi.showLoading(t),hideLoading:()=>this.hostApi.hideLoading(),track:t=>this.hostApi.track(t),setState:(t,e)=>this.stateManager.setVariable(t,e),getState:t=>this.stateManager.getVariable(t),refreshData:t=>this.refreshData(t)},expressionEngine:this.expressionEngine,debug:this.options.debug,logger:this.logger,onActionStart:(t,e)=>{this.emitEvent("action:executing",{action:t,params:e})},onActionComplete:(t,e)=>{e.success?this.emitEvent("action:executed",{action:t,data:e.data}):this.emitEvent("action:error",{action:t,error:e.error?.message})}})}initDataBindingManager(t){this.dataBindingManager=new f({requester:{requestData:(t,e)=>this.hostApi.requestData(t,e)},stateSetter:{setVariable:(t,e)=>this.stateManager.setVariable(t,e),getVariable:t=>this.stateManager.getVariable(t)},expressionEngine:this.expressionEngine,debug:this.options.debug,logger:this.logger,onDataLoaded:(t,e)=>{this.emitEvent("query:fetched",{bindingId:t,data:e}),this.renderer?.updateContext(this.stateManager.getExpressionContext())},onDataError:(t,e)=>{this.emitEvent("query:error",{bindingId:t,error:e.message})}}),t.dataBindings&&this.dataBindingManager.registerBindings(t.dataBindings),this.stateManager.onStateChange(({key:t})=>{this.dataBindingManager.onStateChange(t,this.stateManager.getExpressionContext())})}initLifecycleManager(t){this.lifecycleManager=new D({actionBridge:this.actionBridge,getContext:()=>this.stateManager.getExpressionContext(),debug:this.options.debug,logger:this.logger,onLifecycleEvent:(t,e)=>{this.emitEvent(`page:lifecycle:${t}`,e??{})}}),this.lifecycleManager.register(t.lifecycle)}initRenderer(){const t=new Map;this.stateManager.getState().components.forEach((e,s)=>{if("loaded"===e.status&&e.component){const[i,n]=s.split("@");t.set(i,{name:i,version:n,Component:e.component,loadTime:e.loadTime||0})}}),this.renderer=new C({expressionEngine:this.expressionEngine,components:t,injectHostApi:(t,e)=>{t.hostApi=this.hostApi,t.componentId=e},onComponentEvent:(t,e,s,i)=>{this.handleComponentEvent(t,e,s,i)},debug:this.options.debug,logger:this.logger,onRenderError:(t,e)=>(this.log("error",`Render error in ${t}:`,e),this.emitEvent("component:error",{componentId:t,error:e.message}),j("error",e.message))}),this.renderer.init()}handleComponentEvent(t,e,s,i){this.log("debug",`Component event: ${t}.${e}`,i);for(const t of s)this.actionBridge.handleEvent(t,i,this.stateManager.getExpressionContext())}handleError(t){const s=t instanceof e?{type:"LOAD_ERROR",message:t.message,code:t.code,details:t.details,traceId:t.traceId,timestamp:t.timestamp}:{type:"UNKNOWN_ERROR",message:t.message,cause:t,timestamp:Date.now()};this.stateManager.setError(s),this.telemetryManager?.recordError(t),this.emitEvent("page:error",{error:t.message}),this.options.onError&&this.options.onError(s)}emitEvent(t,e){const s=m.createEvent(t,e,this.telemetryManager?.getTraceId());this.eventBus.emit(s),this.options.onEvent&&this.options.onEvent(s)}createLogger(){return{debug:(...t)=>{this.options.debug},info:(...t)=>{},warn:(...t)=>{},error:(...t)=>{}}}log(t,e,...s){this.logger[t](e,...s)}};Object.defineProperty(exports,"ErrorCode",{enumerable:!0,get:function(){return t.ErrorCode}}),Object.defineProperty(exports,"ErrorMessages",{enumerable:!0,get:function(){return t.ErrorMessages}}),exports.ActionBridge=y,exports.ActionError=a,exports.AssetLoader=d,exports.BaseRenderer=C,exports.ComponentBlockedError=r,exports.ComponentLoadError=i,exports.ComponentLoader=u,exports.DjvlcRuntime=M,exports.DjvlcRuntimeError=e,exports.Evaluator=x,exports.EventBus=m,exports.ExpressionEngine=S,exports.ExpressionError=o,exports.HostAPIImpl=k,exports.IntegrityError=n,exports.Lexer=b,exports.LifecycleManager=D,exports.MockUserApiAdapter=class{constructor(t={}){this.calls={resolvePage:[],executeAction:[],executeQuery:[],track:[]},this.options={delay:0,...t}}async resolvePage(t){if(this.calls.resolvePage.push(t),await this.delay(),this.options.resolvePageThrow)throw this.options.resolvePageThrow;return(this.options.resolvePageResponse??this.options.mockPage)||{pageId:t.pageId,resolvedVersionId:"pv_mock",cdnBase:"https://cdn.mock.com",snapshotUrl:"https://cdn.mock.com/snapshot.json",manifestUrl:"https://cdn.mock.com/manifest.json",ops:{killSwitch:[],blockedComponents:[],flags:{}},etag:"mock-etag",cacheTtlSeconds:300}}async executeAction(t){return this.calls.executeAction.push(t),await this.delay(),this.options.mockActionResult?this.options.mockActionResult():{success:!0,data:{result:"mock"}}}async executeQuery(t){return this.calls.executeQuery.push(t),await this.delay(),this.options.mockQueryResult?this.options.mockQueryResult():{success:!0,data:{}}}track(t){this.calls.track.push(t)}delay(){const t=this.options.delay??0;return t<=0?Promise.resolve():new Promise(e=>setTimeout(e,t))}resetCalls(){this.calls={resolvePage:[],executeAction:[],executeQuery:[],track:[]}}},exports.PageLoadError=s,exports.PageLoader=h,exports.Parser=$,exports.QueryError=c,exports.RUNTIME_VERSION="1.0.0",exports.RenderError=class extends e{constructor(e,s,i,n){super(t.ErrorCode.SYSTEM_INTERNAL_ERROR,i,{...n,componentId:e,componentType:s}),this.name="RenderError",this.componentId=e,this.componentType=s}},exports.SCHEMA_VERSION=T,exports.SUPPORTED_SCHEMA_VERSION=T,exports.SecurityManager=E,exports.StateManager=p,exports.TelemetryManager=I,exports.builtinFunctions=w,exports.createFallbackElement=j,exports.createRuntime=function(t){return new M(t)},exports.registerFallbackComponents=N;
|
|
1
|
+
"use strict";var t=require("@djvlc/contracts-types"),e=class extends Error{constructor(e,n,s,i){super(n||t.ErrorMessages[e]||"Unknown error"),this.name="DjvlcRuntimeError",this.code=e,this.details=s,this.traceId=i,this.timestamp=Date.now()}toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,traceId:this.traceId,timestamp:this.timestamp}}},n=class extends e{constructor(e,n,s){super(t.ErrorCode.RESOURCE_PAGE_NOT_FOUND,e,n,s),this.name="PageLoadError"}},s=class extends e{constructor(e,n,s,i=t.ErrorCode.COMPONENT_LOAD_FAILED,r){super(i,s,{...r,componentName:e,componentVersion:n}),this.name="ComponentLoadError",this.componentName=e,this.componentVersion=n}},i=class extends e{constructor(e,n,s,i){super(t.ErrorCode.COMPONENT_INTEGRITY_MISMATCH,`Integrity check failed for ${e}@${n}`,{expectedHash:s,actualHash:i}),this.name="IntegrityError",this.componentName=e,this.componentVersion=n,this.expectedHash=s,this.actualHash=i}},r=class extends e{constructor(e,n,s){super(t.ErrorCode.COMPONENT_BLOCKED,`Component ${e}@${n} is blocked`,{componentName:e,componentVersion:n,reason:s}),this.name="ComponentBlockedError",this.componentName=e,this.componentVersion=n,this.reason=s}},o=class extends e{constructor(e,n,s,i){super(t.ErrorCode.VALIDATION_EXPRESSION_ERROR,n,{...i,expression:e,position:s}),this.name="ExpressionError",this.expression=e,this.position=s}},a=class extends e{constructor(e,n,s=t.ErrorCode.SYSTEM_INTERNAL_ERROR,i,r){super(s,n,{...r,actionType:e,actionId:i}),this.name="ActionError",this.actionType=e,this.actionId=i}},c=class extends e{constructor(e,n,s=t.ErrorCode.SYSTEM_INTERNAL_ERROR,i){super(s,n,{...i,queryId:e}),this.name="QueryError",this.queryId=e}},h=class{constructor(t){this.cache=new Map,this.options={env:"prod",cache:{enabled:!0,maxAge:300},...t}}async resolve(t,e){const s=this.getCacheKey(t,e);if(this.options.cache?.enabled){const e=this.cache.get(s);if(e&&this.isCacheValid(e.timestamp))return this.log("debug",`Page ${t} loaded from cache`),e.data}const i=performance.now();try{const n=await this.callResolveViaAdapter(t,e),r=await this.loadFromCdn(n,t);this.options.cache?.enabled&&this.cache.set(s,{data:r,timestamp:Date.now()});const o=performance.now()-i;return this.log("info",`Page ${t} resolved in ${o.toFixed(2)}ms`),r}catch(e){if(e instanceof n)throw e;throw new n(`Failed to resolve page: ${e instanceof Error?e.message:"Unknown error"}`,{pageId:t})}}async callResolveViaAdapter(t,e){const s=await this.options.userApiAdapter.resolvePage({pageId:t,uid:e?.uid,deviceId:e?.deviceId,env:this.options.env,channel:this.options.channel,previewToken:this.options.previewToken});if(!this.isValidPageResolveResponse(s))throw new n("Invalid page resolve response",{pageId:t});return s}async loadFromCdn(t,e){try{const s=await fetch(t.snapshotUrl,{headers:this.buildHeaders()});if(!s.ok)throw new n(`Failed to load snapshot: ${s.status}`,{pageId:e});const i=await s.json();if(!i.page||!i.manifest)throw new n('Invalid snapshot format: missing "page" or "manifest" field. Expected PageSnapshotJson.',{pageId:e});return this.convertSnapshotToResult(i,t,e)}catch(t){if(t instanceof n)throw t;throw new n(`Failed to load from CDN: ${t instanceof Error?t.message:"Unknown error"}`,{pageId:e})}}convertSnapshotToResult(t,e,n){const s=this.convertSnapshotPageToPageSchema(t.page),i=this.convertSnapshotManifestToPageManifest(t.manifest),r=t.definitionsDigest?.actions?.map(t=>t.versionId)||[],o=t.definitionsDigest?.queries?.map(t=>t.versionId)||[];return i.actionDefinitionVersionIds=r,i.dataQueryVersionIds=o,{pageId:e.pageId,pageVersionId:e.resolvedVersionId,pageJson:s,manifest:i,runtimeConfig:{blockedComponents:e.ops.blockedComponents.map(t=>({name:t.name,version:t.version||"",reason:t.reason})),killSwitches:e.ops.killSwitch.map(t=>({type:t.targetType,enabled:t.enabled})),features:e.ops.flags},isPreview:"preview"===this.options.env||!!this.options.previewToken}}convertSnapshotPageToPageSchema(t){const e={layout:{canvasType:t.config.canvasType,canvasSize:t.config.canvasSize},styles:t.config.background||t.config.cssVariables?{background:t.config.background,cssVariables:t.config.cssVariables}:void 0},n=Object.keys(t.initialState).length>0?{fields:Object.keys(t.initialState).reduce((e,n)=>{const s=t.initialState[n];let i="string";return"number"==typeof s?i="number":"boolean"==typeof s?i="boolean":Array.isArray(s)?i="array":null!==s&&"object"==typeof s&&(i="object"),e[n]={type:i,initialValue:s},e},{})}:void 0,s={title:t.title};return{schemaVersion:t.schemaVersion,pageId:t.pageId,pageVersion:t.pageVersion,runtime:{name:"djvlc-runtime",version:"1.0.0"},meta:s,config:e,seo:t.seo,state:n,dataBindings:t.bindings,root:t.root}}convertSnapshotManifestToPageManifest(t){return{id:"",pageVersionId:"",manifestVersion:"1.0.0",createdAt:(new Date).toISOString(),contentHash:"",components:t.components.map(t=>({componentId:"",name:t.name,version:t.version,source:t.source,entry:"remote"===t.source&&t.assetsUrl&&t.entrypoints?`${t.assetsUrl}/${t.entrypoints.js}`:void 0,styleEntry:"remote"===t.source&&t.assetsUrl&&t.entrypoints?.css?`${t.assetsUrl}/${t.entrypoints.css}`:void 0,integrity:t.integrity,preload:t.preload,priority:t.priority})),actionDefinitionVersionIds:[],dataQueryVersionIds:[],runtimeVersion:{min:t.runtime.minVersion,recommended:t.runtime.version}}}isValidPageResolveResponse(t){if(!t||"object"!=typeof t)return!1;const e=t;return"string"==typeof e.pageId&&"string"==typeof e.resolvedVersionId&&"string"==typeof e.cdnBase&&"string"==typeof e.snapshotUrl&&"string"==typeof e.manifestUrl&&void 0!==e.ops&&"string"==typeof e.etag&&"number"==typeof e.cacheTtlSeconds}preconnect(){const t=document.createElement("link");t.rel="preconnect",t.href=this.options.apiBaseUrl,document.head.appendChild(t)}clearCache(t){if(t)for(const e of this.cache.keys())e.startsWith(t)&&this.cache.delete(e);else this.cache.clear()}buildHeaders(){return{"Content-Type":"application/json",...this.options.headers}}getCacheKey(t,e){const n=[t,this.options.env,this.options.channel];return e?.uid&&n.push(e.uid),e?.deviceId&&n.push(e.deviceId),n.filter(Boolean).join(":")}isCacheValid(t){const e=1e3*(this.options.cache?.maxAge??300);return Date.now()-t<e}log(t,e){this.options.logger&&this.options.logger[t](e)}},l={sha256:"SHA-256",sha384:"SHA-384",sha512:"SHA-512"},d=class{constructor(t){this.loadedComponents=new Map,this.loadingPromises=new Map,this.options={enableSRI:!0,concurrency:4,timeout:3e4,blockedComponents:[],...t},this.blockedSet=new Set(this.options.blockedComponents)}async load(t){const e=this.getComponentKey(t.name,t.version);if(this.isBlocked(t.name,t.version))throw new r(t.name,t.version,"Component is blocked");const n=this.loadedComponents.get(e);if(n)return n;if("bundled"===t.source){const n=customElements.get(t.name),s={name:t.name,version:t.version,Component:n??t.name,loadTime:0};return this.loadedComponents.set(e,s),this.log("debug",`Bundled component ${t.name}@${t.version} registered (skipped CDN)`),s}const s=this.loadingPromises.get(e);if(s)return s;const i=this.loadComponent(t);this.loadingPromises.set(e,i);try{const t=await i;return this.loadedComponents.set(e,t),t}finally{this.loadingPromises.delete(e)}}async loadAll(t){const e=new Map,{concurrency:n=4}=this.options,s=t.components;for(let t=0;t<s.length;t+=n){const i=s.slice(t,t+n).map(async t=>{const n=this.getComponentKey(t.name,t.version),s=performance.now();try{const i=await this.load(t);e.set(n,{name:t.name,version:t.version,status:"loaded",component:i.Component,loadTime:performance.now()-s})}catch(i){const o=i instanceof r?"blocked":"failed";if(e.set(n,{name:t.name,version:t.version,status:o,error:i instanceof Error?i.message:"Unknown error",loadTime:performance.now()-s}),"critical"===t.priority)throw i}});await Promise.all(i)}return e}preload(t){t.forEach(t=>{if("bundled"===t.source)return;if(!t.entry)return void this.log("warn",`Skipping preload for ${t.name}@${t.version}: no entry URL`);const e=document.createElement("link");e.rel="preload",e.as="script",e.href=this.resolveUrl(t.entry),this.options.enableSRI&&t.integrity&&(e.integrity=t.integrity,e.crossOrigin="anonymous"),document.head.appendChild(e)})}isLoaded(t,e){return this.loadedComponents.has(this.getComponentKey(t,e))}get(t,e){return this.loadedComponents.get(this.getComponentKey(t,e))}isBlocked(t,e){return this.blockedSet.has(`${t}@${e}`)||this.blockedSet.has(t)}updateBlockedList(t){this.blockedSet=new Set(t)}async loadComponent(t){if(!t.entry)throw new s(t.name,t.version,"Remote component is missing entry URL");const e=performance.now(),n=this.resolveUrl(t.entry);this.log("debug",`Loading component ${t.name}@${t.version}`);try{const i=await this.fetchWithTimeout(n);if(!i.ok)throw new s(t.name,t.version,`Failed to fetch component: ${i.status} ${i.statusText}`);const r=await i.text();this.options.enableSRI&&t.integrity&&await this.validateIntegrity(t,r);const o=await this.executeScript(r,t),a=performance.now()-e;return this.log("info",`Component ${t.name}@${t.version} loaded in ${a.toFixed(2)}ms`),{name:t.name,version:t.version,Component:o,loadTime:a}}catch(e){if(e instanceof s||e instanceof i||e instanceof r)throw e;throw new s(t.name,t.version,`Failed to load component: ${e instanceof Error?e.message:"Unknown error"}`)}}async fetchWithTimeout(t){const e=new AbortController,n=setTimeout(()=>e.abort(),this.options.timeout),s={signal:e.signal,credentials:"omit",headers:this.options.headers?{...this.options.headers}:void 0},i=this.options.fetchComponentScript??fetch;try{return await i(t,s)}finally{clearTimeout(n)}}async validateIntegrity(t,e){if(!t.integrity)return;const[n,s]=t.integrity.split("-");if(!n||!s)throw new i(t.name,t.version,t.integrity,"Invalid format");const r=l[n.toLowerCase()];if(!r)throw new i(t.name,t.version,t.integrity,`Unsupported SRI algorithm: ${n}, expected sha256/sha384/sha512`);const o=await crypto.subtle.digest(r,(new TextEncoder).encode(e)),a=Array.from(new Uint8Array(o)),c=btoa(String.fromCharCode(...a));if(c!==s)throw new i(t.name,t.version,s,c)}async executeScript(t,e){const n=new Blob([t],{type:"application/javascript"}),i=URL.createObjectURL(n);try{const t=await import(i),n=t.default??t[e.name]??t[this.kebabToPascal(e.name)]??t.Component;if(!n)throw new s(e.name,e.version,"Component module does not export a valid component (expected default or Component)");return n}finally{URL.revokeObjectURL(i)}}kebabToPascal(t){return t.split("-").map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}resolveUrl(t){if(!t)throw new s("unknown","","Cannot resolve URL: entry is undefined");return t.startsWith("http://")||t.startsWith("https://")?t:`${this.options.cdnBaseUrl}/${t.replace(/^\//,"")}`}getComponentKey(t,e){return`${t}@${e}`}log(t,e){this.options.logger&&this.options.logger[t](e)}},u=class{constructor(t){this.preconnectedHosts=new Set,this.preloadedAssets=new Set,this.options=t}preconnectAll(){[...this.options.cdnHosts,...this.options.apiHosts].forEach(t=>this.preconnect(t))}preconnect(t){if(this.preconnectedHosts.has(t))return;const e=document.createElement("link");e.rel="preconnect",e.href=t.startsWith("http")?t:`https://${t}`,e.crossOrigin="anonymous",document.head.appendChild(e),this.preconnectedHosts.add(t)}dnsPrefetch(t){const e=document.createElement("link");e.rel="dns-prefetch",e.href=t.startsWith("http")?t:`https://${t}`,document.head.appendChild(e)}preloadScript(t,e){if(this.preloadedAssets.has(t))return;const n=document.createElement("link");n.rel="preload",n.setAttribute("as","script"),n.href=t,e&&(n.setAttribute("integrity",e),n.setAttribute("crossorigin","anonymous")),document.head.appendChild(n),this.preloadedAssets.add(t)}preloadStyle(t,e){if(this.preloadedAssets.has(t))return;const n=document.createElement("link");n.rel="preload",n.setAttribute("as","style"),n.href=t,e&&(n.setAttribute("integrity",e),n.setAttribute("crossorigin","anonymous")),document.head.appendChild(n),this.preloadedAssets.add(t)}preloadImage(t){if(this.preloadedAssets.has(t))return;const e=document.createElement("link");e.rel="preload",e.setAttribute("as","image"),e.href=t,document.head.appendChild(e),this.preloadedAssets.add(t)}prefetch(t,e){const n=document.createElement("link");n.rel="prefetch",n.href=t,e&&n.setAttribute("as",e),document.head.appendChild(n)}loadStylesheet(t,e){return new Promise((n,s)=>{const i=document.createElement("link");i.rel="stylesheet",i.href=t,e&&(i.integrity=e,i.crossOrigin="anonymous"),i.onload=()=>n(),i.onerror=()=>s(new Error(`Failed to load stylesheet: ${t}`)),document.head.appendChild(i)})}loadScript(t,e){return new Promise((n,s)=>{const i=document.createElement("script");i.src=t,i.async=!0,e&&(i.integrity=e,i.crossOrigin="anonymous"),i.onload=()=>n(),i.onerror=()=>s(new Error(`Failed to load script: ${t}`)),document.body.appendChild(i)})}},p=class{constructor(){this.listeners=new Set,this.changeCallbacks=new Set,this.state=this.createInitialState()}getState(){return this.state}getPhase(){return this.state.phase}setPhase(t){this.setState({phase:t})}setPage(t){const e=t.pageJson,n=this.initializePageState(e);t.preloadedData&&Object.assign(n,t.preloadedData),this.setState({page:t,variables:n})}initializePageState(t){const e={};if(t.state&&t.state.fields)for(const[n,s]of Object.entries(t.state.fields))if(s&&"object"==typeof s){const t=s;e[n]=t.initialValue}return e}setError(t){this.setState({phase:"error",error:t})}clearError(){this.state.error&&this.setState({error:null})}getVariable(t){return t.includes(".")?this.getNestedValue(this.state.variables,t):this.state.variables[t]}setVariable(t,e){const n=this.getVariable(t);if(t.includes(".")){const n={...this.state.variables};this.setNestedValue(n,t,e),this.setState({variables:n})}else this.setState({variables:{...this.state.variables,[t]:e}});this.notifyChange({key:t,oldValue:n,newValue:e})}setVariables(t){const e=[];for(const[n,s]of Object.entries(t)){const t=this.getVariable(n);e.push({key:n,oldValue:t,newValue:s})}this.setState({variables:{...this.state.variables,...t}}),e.forEach(t=>this.notifyChange(t))}getQuery(t){return this.state.queries[t]}setQuery(t,e){this.setState({queries:{...this.state.queries,[t]:e}})}clearQuery(t){const{[t]:e,...n}=this.state.queries;this.setState({queries:n})}setComponentStatus(t,e){const n=new Map(this.state.components);n.set(t,e),this.setState({components:n})}getComponentStatus(t){return this.state.components.get(t)}setDestroyed(){this.setState({phase:"destroyed",destroyed:!0})}isDestroyed(){return this.state.destroyed}subscribe(t){return this.listeners.add(t),()=>{this.listeners.delete(t)}}onStateChange(t){return this.changeCallbacks.add(t),()=>{this.changeCallbacks.delete(t)}}reset(){this.state=this.createInitialState(),this.notifyListeners()}getExpressionContext(){return{state:this.state.variables,binding:this.state.queries,local:{},context:{pageVersionId:this.state.page?.pageVersionId,pageId:this.state.page?.pageId,phase:this.state.phase,$now:Date.now()}}}setState(t){this.state={...this.state,...t},this.notifyListeners()}notifyListeners(){this.listeners.forEach(t=>{try{t(this.state)}catch(t){}})}notifyChange(t){this.changeCallbacks.forEach(e=>{try{e(t)}catch(t){}})}getNestedValue(t,e){const n=e.split(".");let s=t;for(const t of n){if(null==s)return;s=s[t]}return s}setNestedValue(t,e,n){const s=e.split(".");let i=t;for(let t=0;t<s.length-1;t++){const e=s[t];void 0!==i[e]&&null!==i[e]||(i[e]={}),i=i[e]}i[s[s.length-1]]=n}createInitialState(){return{phase:"idle",page:null,variables:{},queries:{},components:new Map,error:null,destroyed:!1}}},f=class{constructor(t){this.bindings=new Map,this.dependencyGraph=new Map,this.bindingDependencies=new Map,this.options=t}registerBindings(t){for(const e of t)this.registerBinding(e)}registerBinding(t){if(this.bindings.set(t.id,{binding:t,loading:!1,retryCount:0}),t.dependencies)for(const e of t.dependencies)this.dependencyGraph.has(e)||this.dependencyGraph.set(e,new Set),this.dependencyGraph.get(e).add(t.id);this.updateBindingDependencies(t),this.log("debug",`Registered data binding: ${t.id}`)}updateBindingDependencies(t){for(const[e,n]of this.bindings){if(e===t.id)continue;const s=n.binding;s.dependencies?.includes(t.targetState)&&(this.bindingDependencies.has(t.id)||this.bindingDependencies.set(t.id,new Set),this.bindingDependencies.get(t.id).add(e))}if(t.dependencies)for(const e of t.dependencies)for(const[n,s]of this.bindings)n!==t.id&&s.binding.targetState===e&&(this.bindingDependencies.has(n)||this.bindingDependencies.set(n,new Set),this.bindingDependencies.get(n).add(t.id))}async initializeBindings(t){const e=[];for(const t of this.bindings.values())"eager"===t.binding.loadStrategy&&e.push(t.binding);const n=this.topologicalSort(e),s=this.createLoadBatches(n);for(const e of s){const n=await Promise.allSettled(e.map(e=>this.loadBinding(e.id,t))),s=new Map;n.forEach((t,n)=>{const i=e[n].id;"fulfilled"===t.status?s.set(i,{success:!0,data:t.value}):s.set(i,{success:!1,error:t.reason})}),this.options.onBatchComplete?.(s)}}topologicalSort(t){const e=new Map(t.map(t=>[t.id,t])),n=new Set,s=[],i=t=>{if(!n.has(t.id)){if(n.add(t.id),t.dependencies)for(const s of t.dependencies)for(const[t,r]of e)r.targetState!==s||n.has(t)||i(r);s.push(t)}};for(const e of t)i(e);return s}createLoadBatches(t){const e=[],n=new Set;for(;n.size<t.length;){const s=[];for(const e of t){if(n.has(e.id))continue;let i=!0;if(e.dependencies)for(const s of e.dependencies){for(const e of t)if(e.targetState===s&&!n.has(e.id)){i=!1;break}if(!i)break}i&&s.push(e)}if(0===s.length)for(const e of t)if(!n.has(e.id)){s.push(e),this.log("warn",`Possible circular dependency detected at binding: ${e.id}`);break}s.forEach(t=>n.add(t.id)),s.length>0&&e.push(s)}return e}async loadBinding(t,e,n=!1){const s=this.bindings.get(t);if(!s)throw new c(t,`Data binding not found: ${t}`);const{binding:i}=s;if(!i.condition||this.evaluateCondition(i.condition,e)){if(!n&&this.isCacheValid(s))return this.log("debug",`Binding ${t} returned from cache`),s.cachedData;if(s.loading)this.log("debug",`Binding ${t} is already loading`);else{s.loading=!0;try{const n=this.resolveParams(i.params||{},e),r=await this.executeWithRetry(i,n),o=i.transform?this.applyTransform(r,i.transform,e):r;return s.cachedData=o,s.lastLoadTime=Date.now(),i.cache?.ttl&&(s.cacheExpireTime=Date.now()+1e3*i.cache.ttl),s.retryCount=0,this.options.stateSetter.setVariable(i.targetState,o),this.setupAutoRefresh(s,e),this.options.onDataLoaded?.(t,o),this.log("info",`Binding ${t} loaded successfully`),o}catch(t){throw await this.handleLoadError(s,t,e),t}finally{s.loading=!1}}}else this.log("debug",`Binding ${t} skipped by condition`)}async refreshBinding(t,e){await this.loadBinding(t,e,!0)}async refreshAll(t){const e=Array.from(this.bindings.keys()).map(e=>this.loadBinding(e,t,!0));await Promise.allSettled(e)}async onStateChange(t,e){const n=this.dependencyGraph.get(t);if(!n||0===n.size)return;this.log("debug",`State ${t} changed, refreshing dependent bindings`);const s=Array.from(n).map(t=>this.loadBinding(t,e,!0));await Promise.allSettled(s)}async triggerManualLoad(t,e){const n=this.bindings.get(t);if(!n)throw new c(t,`Data binding not found: ${t}`);return"manual"!==n.binding.loadStrategy&&this.log("warn",`Binding ${t} is not manual strategy`),this.loadBinding(t,e,!0)}checkVisibility(t,e,n){const s=this.bindings.get(t);s&&"lazy"===s.binding.loadStrategy&&e&&!s.lastLoadTime&&this.loadBinding(t,n).catch(e=>{this.log("error",`Lazy binding ${t} failed to load`,e)})}destroy(){for(const t of this.bindings.values())t.refreshTimer&&clearInterval(t.refreshTimer);this.bindings.clear(),this.dependencyGraph.clear(),this.log("debug","DataBindingManager destroyed")}async executeWithRetry(t,e){const n=t.onError?.retry?.maxRetries??0,s=t.onError?.retry?.backoffMs??1e3,i=t.onError?.retry?.backoff??"fixed";let r;for(let o=0;o<=n;o++)try{const n=await this.options.requester.requestData(t.queryVersionId,e);if(!n.success)throw new c(t.queryVersionId,n.message||"Query failed",void 0,{params:e});return n.data}catch(t){if(r=t,this.log("warn",`Query attempt ${o+1}/${n+1} failed:`,t),o<n){const t="exponential"===i?s*Math.pow(2,o):s;await this.delay(t)}}throw r||new Error("Query failed after all retries")}async handleLoadError(t,e,n){const{binding:s}=t,i=s.onError;t.retryCount++,void 0!==i?.fallbackValue&&this.options.stateSetter.setVariable(s.targetState,i.fallbackValue),i?.showError&&this.options.onDataError?.(s.id,e),this.log("error",`Binding ${s.id} load failed:`,e)}setupAutoRefresh(t,e){t.refreshTimer&&(clearInterval(t.refreshTimer),t.refreshTimer=void 0);const n=t.binding.refreshInterval;!n||n<=0||(t.refreshTimer=setInterval(()=>{this.loadBinding(t.binding.id,e,!0).catch(e=>{this.log("error",`Auto refresh for ${t.binding.id} failed:`,e)})},1e3*n))}isCacheValid(t){return!(!t.cachedData||!t.lastLoadTime||t.cacheExpireTime&&Date.now()>t.cacheExpireTime)}resolveParams(t,e){const n={};for(const[s,i]of Object.entries(t))n[s]=this.resolveValue(i,e);return n}resolveValue(t,e){if(null==t)return t;if("object"==typeof t&&!Array.isArray(t)){const n=t;if("expression"===n.type||"binding"===n.type)return this.options.expressionEngine.evaluateWithFallback(n.expression,e,n.fallback);const s={};for(const[t,i]of Object.entries(n))s[t]=this.resolveValue(i,e);return s}return"string"==typeof t&&t.includes("${")?this.options.expressionEngine.evaluateTemplate(t,e):t}evaluateCondition(t,e){const n=void 0===t.fallback||t.fallback,s=this.options.expressionEngine.evaluateWithFallback(t.value,e,n);return Boolean(s)}applyTransform(t,e,n){const s={...n,local:{...n.local||{},$data:t,$response:t}},i=void 0!==e.fallback?e.fallback:t;return this.options.expressionEngine.evaluateWithFallback(e.value,s,i)}delay(t){return new Promise(e=>setTimeout(e,t))}log(t,e,...n){this.options.logger?this.options.logger[t](e,...n):this.options.debug}},m=class{constructor(t={}){this.handlers=new Map,this.options={debug:!1,maxListeners:100,...t}}emit(t){this.options.debug&&this.log("debug",`Event emitted: ${t.type}`,t);const e=this.handlers.get(t.type);e&&e.forEach(e=>{try{e(t)}catch(e){this.log("error",`Error in event handler for ${t.type}:`,e)}})}on(t,e){let n=this.handlers.get(t);return n||(n=new Set,this.handlers.set(t,n)),n.size>=(this.options.maxListeners??100)&&this.log("warn",`Max listeners (${this.options.maxListeners}) reached for event: ${t}`),n.add(e),()=>{n?.delete(e),0===n?.size&&this.handlers.delete(t)}}off(t,e){const n=this.handlers.get(t);n&&(n.delete(e),0===n.size&&this.handlers.delete(t))}once(t,e){const n=this.on(t,t=>{n(),e(t)});return n}clear(t){t?this.handlers.delete(t):this.handlers.clear()}listenerCount(t){return this.handlers.get(t)?.size??0}static createEvent(t,e,n){return{type:t,data:e,timestamp:Date.now(),traceId:n}}log(t,e,...n){this.options.logger?this.options.logger[t](e,...n):this.options.debug}},g=class t{constructor(t){this.debounceTimers=new Map,this.throttleTimers=new Map,this.options=t}async handleEvent(t,e,n){if(t.condition&&!this.evaluateCondition(t.condition,n,e))return void this.log("debug",`Handler ${t.id} skipped by condition`);if(t.throttle&&t.throttle>0&&!this.throttle(t.id,t.throttle))return void this.log("debug",`Handler ${t.id} throttled`);t.debounce&&t.debounce>0&&await this.debounce(t.id,t.debounce);const s={$event:e,$prevResult:void 0,$results:{}};await this.executeActionChain(t.actions,n,s)}async executeActionChain(t,e,n){const s=[];for(let i=0;i<t.length;i++){const r=t[i];if(r.condition){const t=this.buildActionContext(e,n);if(!this.evaluateCondition(r.condition,t,n.$event)){this.log("debug",`Action ${r.id||i} skipped by condition`);continue}}const o=this.executeSingleAction(r,e,n);r.async?s.push(o):await o}s.length>0&&await Promise.allSettled(s)}async executeSingleAction(t,e,n){const s=t.id||t.alias||t.builtinAction||t.actionDefinitionVersionId||"unknown";t.silent||this.options.executor.showLoading();try{const i=this.buildActionContext(e,n),r=this.resolveParams(t.params||{},i);this.options.onActionStart?.(t,r);const o=await this.executeWithRetry(t,r);n.$prevResult=o,t.id&&(n.$results[t.id]=o),this.options.onActionComplete?.(t,{success:!0,data:o}),this.log("debug",`Action ${s} completed successfully`),t.onSuccess&&t.onSuccess.length>0&&await this.executeActionChain(t.onSuccess,e,n)}catch(i){this.log("error",`Action ${s} failed:`,i),this.options.onActionComplete?.(t,{success:!1,error:i}),t.onError&&t.onError.length>0&&await this.executeActionChain(t.onError,e,{...n,$prevResult:{error:i.message}})}finally{t.silent||this.options.executor.hideLoading(),t.onFinally&&t.onFinally.length>0&&await this.executeActionChain(t.onFinally,e,n)}}async executeWithRetry(t,e){const n=t.policy?.retry?.maxAttempts??1,s=t.policy?.retry?.backoffMs??1e3,i=t.policy?.timeoutMs;let r;for(let o=1;o<=n;o++)try{let n;if(t.builtinAction)n=this.executeBuiltinAction(t.builtinAction,e);else{if(!t.actionDefinitionVersionId)throw new a("unknown","Action must specify builtinAction or actionDefinitionVersionId");n=this.executeCustomAction(t.actionDefinitionVersionId,e)}return i&&(n=this.withTimeout(n,i)),await n}catch(t){r=t,this.log("warn",`Action attempt ${o}/${n} failed:`,t),o<n&&await this.delay(s*o)}throw r||new Error("Action failed after all retries")}async executeBuiltinAction(t,e){switch(t){case"setState":return this.options.executor.setState(e.key,e.value),{success:!0};case"navigate":return this.options.executor.navigate({to:e.to??e.url,type:e.replace?"replace":e.external?"external":"push",params:e.params,query:e.query,newWindow:e.newWindow??e.newTab}),{success:!0};case"openDialog":if(e.dialogId){const t=document.querySelector(`[data-component-id="${e.dialogId}"]`);return t?(t.visible=!0,{success:!0}):(this.log("warn",`Dialog component not found: ${e.dialogId}`),{success:!1,error:`Dialog not found: ${e.dialogId}`})}return await this.options.executor.openDialog({type:e.type,content:e.content,title:e.title});case"closeDialog":if(e.dialogId){const t=document.querySelector(`[data-component-id="${e.dialogId}"]`);t&&(t.visible=!1)}else this.options.executor.closeDialog(e.dialogId);return{success:!0};case"showToast":return this.options.executor.showToast({message:e.message,type:e.type,duration:e.duration}),{success:!0};case"showLoading":return this.options.executor.showLoading(e.message),{success:!0};case"hideLoading":return this.options.executor.hideLoading(),{success:!0};case"refreshData":return await this.options.executor.refreshData(e.queryId),{success:!0};case"track":return this.options.executor.track({eventName:e.eventName,params:e.params}),{success:!0};default:throw new a(t,`Unknown builtin action: ${t}`)}}async executeCustomAction(t,e){const n=t.split("@")[0],s=await this.options.executor.executeAction(n,{...e,actionDefinitionVersionId:t});if(!s.success)throw new a(n,s.errorMessage||"Action execution failed",void 0,t,{errorCode:s.errorCode});return s.data}resolveParams(t,e){const n={};for(const[s,i]of Object.entries(t))n[s]=this.resolveValue(i,e);return n}resolveValue(e,n){if(null==e)return e;if("string"==typeof e){if(e.startsWith("${")&&e.endsWith("}")){const t=e.slice(2,-1);return this.options.expressionEngine.evaluateWithFallback(t,n,e)}return e.includes("${")?this.options.expressionEngine.evaluateTemplate(e,n):e}if("number"==typeof e||"boolean"==typeof e)return e;if(Array.isArray(e))return e.map(t=>this.resolveValue(t,n));if("object"==typeof e){const s=e;if("string"==typeof s.type&&t.EXPRESSION_TYPES.includes(s.type)&&"string"==typeof s.value){const t=s;return this.options.expressionEngine.evaluateWithFallback(t.value,n,t.fallback)}const i={};for(const[t,e]of Object.entries(s))i[t]=this.resolveValue(e,n);return i}return e}evaluateCondition(t,e,n){const s={...e,local:{...e.local||{},$event:n}},i=void 0===t.fallback||t.fallback,r=this.options.expressionEngine.evaluateWithFallback(t.value,s,i);return Boolean(r)}buildActionContext(t,e){return{...t,local:{...t.local||{},$event:e.$event,$prevResult:e.$prevResult,$results:e.$results}}}withTimeout(t,e){return new Promise((n,s)=>{const i=setTimeout(()=>{s(new Error(`Action timed out after ${e}ms`))},e);t.then(t=>{clearTimeout(i),n(t)}).catch(t=>{clearTimeout(i),s(t)})})}debounce(t,e){return new Promise(n=>{const s=this.debounceTimers.get(t);s&&clearTimeout(s);const i=setTimeout(()=>{this.debounceTimers.delete(t),n()},e);this.debounceTimers.set(t,i)})}throttle(t,e){const n=Date.now();return!(n-(this.throttleTimers.get(t)??0)<e||(this.throttleTimers.set(t,n),0))}delay(t){return new Promise(e=>setTimeout(e,t))}destroy(){this.debounceTimers.forEach(t=>clearTimeout(t)),this.debounceTimers.clear(),this.throttleTimers.clear()}log(t,e,...n){this.options.logger?this.options.logger[t](e,...n):this.options.debug}};g.EXPRESSION_TYPES=["state","binding","local","template","computed"];var y=g,b=class{constructor(t){this.pos=0,this.tokens=[],this.input=t}tokenize(){for(this.pos=0,this.tokens=[];this.pos<this.input.length&&(this.skipWhitespace(),!(this.pos>=this.input.length));){const t=this.readToken();t&&this.tokens.push(t)}return this.tokens.push({type:"EOF",value:null,start:this.input.length,end:this.input.length}),this.tokens}readToken(){const t=this.input[this.pos],e=this.pos;if(this.isDigit(t)||"-"===t&&this.isDigit(this.peek(1)))return this.readNumber();if('"'===t||"'"===t)return this.readString(t);if(this.isIdentifierStart(t))return this.readIdentifier();const n=this.readOperator();if(n)return n;switch(t){case".":return this.pos++,{type:"DOT",value:".",start:e,end:this.pos};case"[":return this.pos++,{type:"LBRACKET",value:"[",start:e,end:this.pos};case"]":return this.pos++,{type:"RBRACKET",value:"]",start:e,end:this.pos};case"(":return this.pos++,{type:"LPAREN",value:"(",start:e,end:this.pos};case")":return this.pos++,{type:"RPAREN",value:")",start:e,end:this.pos};case",":return this.pos++,{type:"COMMA",value:",",start:e,end:this.pos};case"?":return this.pos++,{type:"QUESTION",value:"?",start:e,end:this.pos};case":":return this.pos++,{type:"COLON",value:":",start:e,end:this.pos}}throw new Error(`Unexpected character '${t}' at position ${this.pos}`)}readNumber(){const t=this.pos;let e="";for("-"===this.input[this.pos]&&(e+="-",this.pos++);this.isDigit(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;if("."===this.input[this.pos]&&this.isDigit(this.peek(1)))for(e+=".",this.pos++;this.isDigit(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;return{type:"NUMBER",value:parseFloat(e),start:t,end:this.pos}}readString(t){const e=this.pos;this.pos++;let n="";for(;this.pos<this.input.length&&this.input[this.pos]!==t;){if("\\"===this.input[this.pos]){this.pos++;const t=this.input[this.pos];switch(t){case"n":n+="\n";break;case"t":n+="\t";break;case"r":n+="\r";break;case"\\":n+="\\";break;case'"':n+='"';break;case"'":n+="'";break;default:n+=t}}else n+=this.input[this.pos];this.pos++}if(this.input[this.pos]!==t)throw new Error(`Unterminated string at position ${e}`);return this.pos++,{type:"STRING",value:n,start:e,end:this.pos}}readIdentifier(){const t=this.pos;let e="";for(;this.pos<this.input.length&&this.isIdentifierChar(this.input[this.pos]);)e+=this.input[this.pos],this.pos++;return"true"===e?{type:"BOOLEAN",value:!0,start:t,end:this.pos}:"false"===e?{type:"BOOLEAN",value:!1,start:t,end:this.pos}:"null"===e?{type:"NULL",value:null,start:t,end:this.pos}:{type:"IDENTIFIER",value:e,start:t,end:this.pos}}readOperator(){const t=this.pos,e=this.input.slice(this.pos,this.pos+2),n=this.input[this.pos];return["==","!=",">=","<=","&&","||","??"].includes(e)?(this.pos+=2,{type:"OPERATOR",value:e,start:t,end:this.pos}):["+","-","*","/","%",">","<","!"].includes(n)?(this.pos++,{type:"OPERATOR",value:n,start:t,end:this.pos}):null}skipWhitespace(){for(;this.pos<this.input.length&&/\s/.test(this.input[this.pos]);)this.pos++}isDigit(t){return/[0-9]/.test(t)}isIdentifierStart(t){return/[a-zA-Z_$]/.test(t)}isIdentifierChar(t){return/[a-zA-Z0-9_$]/.test(t)}peek(t=1){return this.input[this.pos+t]||""}},w={len:t=>"string"==typeof t||Array.isArray(t)?t.length:0,trim:t=>String(t??"").trim(),upper:t=>String(t??"").toUpperCase(),lower:t=>String(t??"").toLowerCase(),substr:(t,e,n)=>{const s=String(t??""),i=Number(e)||0,r=void 0!==n?Number(n):void 0;return s.substring(i,void 0!==r?i+r:void 0)},concat:(...t)=>t.map(t=>String(t??"")).join(""),replace:(t,e,n)=>String(t??"").split(String(e)).join(String(n)),split:(t,e)=>String(t??"").split(String(e)),join:(t,e)=>Array.isArray(t)?t.join(void 0!==e?String(e):","):"",startsWith:(t,e)=>String(t??"").startsWith(String(e)),endsWith:(t,e)=>String(t??"").endsWith(String(e)),contains:(t,e)=>String(t??"").includes(String(e)),toNumber:t=>{const e=Number(t);return isNaN(e)?0:e},toString:t=>String(t??""),toInt:t=>Math.trunc(Number(t)||0),toFloat:t=>parseFloat(String(t))||0,round:(t,e)=>{const n=Number(t)||0,s=Number(e)||0,i=Math.pow(10,s);return Math.round(n*i)/i},floor:t=>Math.floor(Number(t)||0),ceil:t=>Math.ceil(Number(t)||0),abs:t=>Math.abs(Number(t)||0),min:(...t)=>{const e=t.map(t=>Number(t)).filter(t=>!isNaN(t));return e.length>0?Math.min(...e):0},max:(...t)=>{const e=t.map(t=>Number(t)).filter(t=>!isNaN(t));return e.length>0?Math.max(...e):0},sum:t=>Array.isArray(t)?t.reduce((t,e)=>t+(Number(e)||0),0):0,avg:t=>Array.isArray(t)&&0!==t.length?t.reduce((t,e)=>t+(Number(e)||0),0)/t.length:0,random:()=>Math.random(),randomInt:(t,e)=>{const n=Math.ceil(Number(t)||0),s=Math.floor(Number(e)||100);return Math.floor(Math.random()*(s-n+1))+n},now:()=>Date.now(),today:()=>(new Date).toISOString().split("T")[0],dateFormat:(t,e)=>{const n=new Date(Number(t)||Date.now()),s=t=>t.toString().padStart(2,"0");return String(e||"YYYY-MM-DD").replace("YYYY",n.getFullYear().toString()).replace("MM",s(n.getMonth()+1)).replace("DD",s(n.getDate())).replace("HH",s(n.getHours())).replace("mm",s(n.getMinutes())).replace("ss",s(n.getSeconds()))},dateParse:t=>new Date(String(t)).getTime(),year:t=>new Date(Number(t)||Date.now()).getFullYear(),month:t=>new Date(Number(t)||Date.now()).getMonth()+1,day:t=>new Date(Number(t)||Date.now()).getDate(),addDays:(t,e)=>{const n=new Date(Number(t)||Date.now());return n.setDate(n.getDate()+(Number(e)||0)),n.getTime()},diffDays:(t,e)=>{const n=new Date(Number(t)||Date.now()),s=new Date(Number(e)||Date.now()),i=Math.abs(s.getTime()-n.getTime());return Math.floor(i/864e5)},isNull:t=>null==t,isUndefined:t=>void 0===t,isEmpty:t=>null==t||("string"==typeof t||Array.isArray(t)?0===t.length:"object"==typeof t&&0===Object.keys(t).length),isArray:t=>Array.isArray(t),isObject:t=>null!==t&&"object"==typeof t&&!Array.isArray(t),isString:t=>"string"==typeof t,isNumber:t=>"number"==typeof t&&!isNaN(t),isBoolean:t=>"boolean"==typeof t,typeOf:t=>null===t?"null":Array.isArray(t)?"array":typeof t,default:(t,e)=>t??e,coalesce:(...t)=>{for(const e of t)if(null!=e)return e;return null},ifElse:(t,e,n)=>t?e:n,first:t=>{if(Array.isArray(t))return t[0]},last:t=>{if(Array.isArray(t))return t[t.length-1]},at:(t,e)=>{if(Array.isArray(t))return t[Number(e)||0]},slice:(t,e,n)=>Array.isArray(t)?t.slice(Number(e)||0,void 0!==n?Number(n):void 0):[],includes:(t,e)=>!!Array.isArray(t)&&t.includes(e),indexOf:(t,e)=>Array.isArray(t)?t.indexOf(e):-1,reverse:t=>Array.isArray(t)?[...t].reverse():[],sort:t=>Array.isArray(t)?[...t].sort():[],unique:t=>Array.isArray(t)?[...new Set(t)]:[],flatten:t=>Array.isArray(t)?t.flat():[],count:t=>Array.isArray(t)?t.length:0,get:(t,e,n)=>{if(null==t)return n;const s=String(e).split(".");let i=t;for(const t of s){if(null==i)return n;i=i[t]}return i??n},keys:t=>"object"!=typeof t||null===t?[]:Object.keys(t),values:t=>"object"!=typeof t||null===t?[]:Object.values(t),entries:t=>"object"!=typeof t||null===t?[]:Object.entries(t),has:(t,e)=>"object"==typeof t&&null!==t&&String(e)in t,merge:(...t)=>{const e={};for(const n of t)"object"==typeof n&&null!==n&&Object.assign(e,n);return e},and:(...t)=>t.every(t=>Boolean(t)),or:(...t)=>t.some(t=>Boolean(t)),not:t=>!t,eq:(t,e)=>t===e,ne:(t,e)=>t!==e,gt:(t,e)=>Number(t)>Number(e),gte:(t,e)=>Number(t)>=Number(e),lt:(t,e)=>Number(t)<Number(e),lte:(t,e)=>Number(t)<=Number(e),between:(t,e,n)=>{const s=Number(t);return s>=Number(e)&&s<=Number(n)},formatNumber:(t,e)=>{const n=Number(t)||0,s=Number(e)??0;return n.toLocaleString(void 0,{minimumFractionDigits:s,maximumFractionDigits:s})},formatCurrency:(t,e)=>{const n=Number(t)||0,s=String(e||"CNY");return n.toLocaleString("zh-CN",{style:"currency",currency:s})},formatPercent:(t,e)=>{const n=Number(t)||0,s=Number(e)??0;return(100*n).toFixed(s)+"%"},currency:(t,e,n)=>{const s=Number(t)||0,i=String(e??"¥"),r=Number(n)??2;return`${i}${s.toLocaleString(void 0,{minimumFractionDigits:r,maximumFractionDigits:r})}`},percent:(t,e)=>{const n=Number(t)||0,s=Number(e)??0;return(100*n).toFixed(s)+"%"},number:(t,e)=>{const n=Number(t)||0,s=Number(e)??0;return n.toLocaleString(void 0,{minimumFractionDigits:s,maximumFractionDigits:s})},pluralize:(t,e,n)=>{const s=Number(t)||0;return`${s} ${String(1===s?e:n)}`},mask:(t,e,n,s)=>{const i=String(t??""),r=Number(e)||3,o=Number(n)||4,a=String(s??"*");if(i.length<=r+o)return i;const c=i.slice(0,r),h=i.slice(-o);return c+a.repeat(i.length-r-o)+h},jsonParse:t=>{try{return JSON.parse(String(t))}catch{return null}},jsonStringify:t=>JSON.stringify(t),toJSON:t=>JSON.stringify(t),fromJSON:t=>{try{return JSON.parse(String(t))}catch{return null}},clamp:(t,e,n)=>{const s=Number(t)||0,i=Number(e)||0,r=Number(n)||100;return Math.min(Math.max(s,i),r)},length:t=>Array.isArray(t)||"string"==typeof t?t.length:0,average:t=>Array.isArray(t)&&0!==t.length?t.reduce((t,e)=>t+(Number(e)||0),0)/t.length:0,dateAdd:(t,e,n)=>{const s=new Date(Number(t)||Date.now()),i=Number(e)||0;switch(String(n??"day").toLowerCase()){case"year":case"years":s.setFullYear(s.getFullYear()+i);break;case"month":case"months":s.setMonth(s.getMonth()+i);break;case"week":case"weeks":s.setDate(s.getDate()+7*i);break;case"day":case"days":default:s.setDate(s.getDate()+i);break;case"hour":case"hours":s.setHours(s.getHours()+i);break;case"minute":case"minutes":s.setMinutes(s.getMinutes()+i)}return s.getTime()},dateDiff:(t,e,n)=>{const s=new Date(Number(t)||Date.now()),i=new Date(Number(e)||Date.now()).getTime()-s.getTime();switch(String(n??"day").toLowerCase()){case"year":case"years":return Math.floor(i/31536e6);case"month":case"months":return Math.floor(i/2592e6);case"week":case"weeks":return Math.floor(i/6048e5);case"day":case"days":default:return Math.floor(i/864e5);case"hour":case"hours":return Math.floor(i/36e5);case"minute":case"minutes":return Math.floor(i/6e4)}},$if:(t,e,n)=>t?e:n,toBoolean:t=>"string"==typeof t?"false"!==t.toLowerCase()&&"0"!==t&&""!==t:Boolean(t),substring:(t,e,n)=>{const s=String(t??""),i=Number(e)||0,r=void 0!==n?Number(n):void 0;return s.substring(i,r)},padStart:(t,e,n)=>{const s=String(t??""),i=Number(e)||0,r=String(n??" ");return s.padStart(i,r)},padEnd:(t,e,n)=>{const s=String(t??""),i=Number(e)||0,r=String(n??" ");return s.padEnd(i,r)},repeat:(t,e)=>{const n=String(t??""),s=Math.max(0,Math.floor(Number(e)||0));return n.repeat(s)}},v={"||":1,"??":1,"&&":2,"==":3,"!=":3,"<":4,">":4,"<=":4,">=":4,"+":5,"-":5,"*":6,"/":6,"%":6},$=class{constructor(t){this.pos=0,this.tokens=t}parse(){const t=this.parseExpression();if("EOF"!==this.current().type)throw new Error(`Unexpected token '${this.current().value}' at position ${this.current().start}`);return t}parseExpression(){return this.parseTernary()}parseTernary(){const t=this.parseBinary(0);if("QUESTION"===this.current().type){this.advance();const e=this.parseExpression();return this.expect("COLON"),{type:"conditional",test:t,consequent:e,alternate:this.parseExpression(),raw:void 0}}return t}parseBinary(t){let e=this.parseUnary();for(;;){const n=this.current();if("OPERATOR"!==n.type)break;const s=v[n.value];if(void 0===s||s<t)break;this.advance();const i=this.parseBinary(s+1);e={type:"binary",operator:n.value,left:e,right:i,raw:void 0}}return e}parseUnary(){const t=this.current();if("OPERATOR"===t.type&&("!"===t.value||"-"===t.value)){this.advance();const e=this.parseUnary();return{type:"unary",operator:t.value,argument:e,raw:void 0}}return this.parsePostfix()}parsePostfix(){let t=this.parsePrimary();for(;;){const e=this.current();if("DOT"===e.type)this.advance(),t={type:"member",object:t,property:this.expect("IDENTIFIER").value,computed:!1,raw:void 0};else if("LBRACKET"===e.type){this.advance();const e=this.parseExpression();this.expect("RBRACKET"),t={type:"member",object:t,property:e,computed:!0,raw:void 0}}else{if("LPAREN"!==e.type||"identifier"!==t.type)break;{const n=t.name;if(!(n in w))throw new Error(`Unknown function '${n}' at position ${e.start}`);this.advance();const s=this.parseArguments();this.expect("RPAREN"),t={type:"call",callee:n,arguments:s,raw:void 0}}}}return t}parsePrimary(){const t=this.current();if("NUMBER"===t.type||"STRING"===t.type||"BOOLEAN"===t.type||"NULL"===t.type)return this.advance(),{type:"literal",value:t.value,start:t.start,end:t.end,raw:void 0};if("IDENTIFIER"===t.type)return this.advance(),{type:"identifier",name:t.value,start:t.start,end:t.end,raw:void 0};if("LBRACKET"===t.type)return this.parseArray();if("LPAREN"===t.type){this.advance();const t=this.parseExpression();return this.expect("RPAREN"),t}throw new Error(`Unexpected token '${t.value}' at position ${t.start}`)}parseArray(){const t=this.current().start;this.advance();const e=[];for(;"RBRACKET"!==this.current().type&&(e.push(this.parseExpression()),"COMMA"===this.current().type);)this.advance();const n=this.current().end;return this.expect("RBRACKET"),{type:"array",elements:e,start:t,end:n,raw:void 0}}parseArguments(){const t=[];if("RPAREN"!==this.current().type)for(t.push(this.parseExpression());"COMMA"===this.current().type;)this.advance(),t.push(this.parseExpression());return t}current(){return this.tokens[this.pos]}advance(){return this.tokens[this.pos++]}expect(t){const e=this.current();if(e.type!==t)throw new Error(`Expected '${t}' but got '${e.type}' at position ${e.start}`);return this.advance()}},x=class{constructor(t={}){this.depth=0,this.startTime=0,this.options={maxDepth:100,timeout:1e3,debug:!1,...t}}evaluate(t,e){this.depth=0,this.startTime=Date.now();try{return{value:this.evaluateNode(t,e)}}catch(t){return{value:void 0,error:t instanceof Error?t:new Error(String(t))}}}evaluateNode(t,e){switch(this.checkLimits(),t.type){case"literal":return this.evaluateLiteral(t);case"identifier":return this.evaluateIdentifier(t,e);case"member":return this.evaluateMember(t,e);case"call":return this.evaluateCall(t,e);case"binary":return this.evaluateBinary(t,e);case"unary":return this.evaluateUnary(t,e);case"conditional":return this.evaluateConditional(t,e);case"array":return this.evaluateArray(t,e);default:throw new o("",`Unknown node type: ${t.type}`)}}evaluateLiteral(t){return t.value}evaluateIdentifier(t,e){const n=t.name;switch(n){case"state":return e.state;case"binding":case"query":return e.binding;case"local":return e.local;case"props":return e.props;case"event":return e.event;case"item":return e.local?.item;case"index":return e.local?.index;default:if(e.local&&n in e.local)return e.local[n];throw new o("",`Unknown variable '${n}'. Available: state, binding, local, props, event`)}}evaluateMember(t,e){const n=this.evaluateNode(t.object,e);if(null==n)return;let s;return s=t.computed?this.evaluateNode(t.property,e):t.property,"object"==typeof n&&null!==n?n[s]:void 0}evaluateCall(t,e){const n=w[t.callee];if(!n)throw new o("",`Unknown function '${t.callee}'`);return n(...t.arguments.map(t=>this.evaluateNode(t,e)))}evaluateBinary(t,e){const n=t.operator;if("&&"===n){const n=this.evaluateNode(t.left,e);return n?this.evaluateNode(t.right,e):n}if("||"===n){return this.evaluateNode(t.left,e)||this.evaluateNode(t.right,e)}if("??"===n){const n=this.evaluateNode(t.left,e);return null!=n?n:this.evaluateNode(t.right,e)}const s=this.evaluateNode(t.left,e),i=this.evaluateNode(t.right,e);switch(n){case"+":return"string"==typeof s||"string"==typeof i?String(s)+String(i):s+i;case"-":return s-i;case"*":return s*i;case"/":return s/i;case"%":return s%i;case"==":return s===i;case"!=":return s!==i;case"<":return s<i;case">":return s>i;case"<=":return s<=i;case">=":return s>=i;default:throw new o("",`Unknown operator '${n}'`)}}evaluateUnary(t,e){const n=this.evaluateNode(t.argument,e);switch(t.operator){case"!":return!n;case"-":return-n;default:throw new o("",`Unknown unary operator '${t.operator}'`)}}evaluateConditional(t,e){return this.evaluateNode(t.test,e)?this.evaluateNode(t.consequent,e):this.evaluateNode(t.alternate,e)}evaluateArray(t,e){return t.elements.map(t=>this.evaluateNode(t,e))}checkLimits(){if(this.depth++,this.depth>(this.options.maxDepth??100))throw new o("","Maximum recursion depth exceeded");if(Date.now()-this.startTime>(this.options.timeout??1e3))throw new o("","Expression evaluation timeout")}},k=class{constructor(t={}){this.astCache=new Map,this.options={cacheAST:!0,maxCacheSize:1e3,...t},this.evaluator=new x(t)}evaluate(t,e){try{const n=this.parse(t);return this.evaluator.evaluate(n,e)}catch(t){return{value:void 0,error:t instanceof Error?t:new Error(String(t))}}}evaluateWithFallback(t,e,n){const s="string"==typeof t?t:t.value,i="object"==typeof t&&void 0!==t.fallback?t.fallback:n,r=this.evaluate(s,e);return r.error?(this.log("warn",`Expression evaluation failed: ${r.error.message}`,s),i):r.value}evaluateTemplate(t,e){return t.replace(/\$\{([^}]+)\}/g,(t,n)=>{const s=this.evaluate(n.trim(),e);return s.error?(this.log("warn",`Template expression failed: ${s.error.message}`,n),""):String(s.value??"")})}parse(t){if(this.options.cacheAST){const e=this.astCache.get(t);if(e)return e}try{const e=new b(t).tokenize(),n=new $(e).parse();return this.options.cacheAST&&(this.astCache.size>=(this.options.maxCacheSize??1e3)&&Array.from(this.astCache.keys()).slice(0,Math.floor(this.astCache.size/2)).forEach(t=>this.astCache.delete(t)),this.astCache.set(t,n)),n}catch(e){throw new o(t,e instanceof Error?e.message:"Parse error")}}validate(t){const e=[],n=[],s=[],i=[];try{const e=this.parse(t);return this.collectReferences(e,s,i),{valid:!0,errors:[],warnings:n,referencedPaths:s,usedFunctions:i}}catch(t){return e.push({type:"invalid_syntax",message:t instanceof Error?t.message:"Parse error"}),{valid:!1,errors:e,warnings:n,referencedPaths:s,usedFunctions:i}}}clearCache(){this.astCache.clear()}collectReferences(t,e,n){switch(t.type){case"identifier":e.push(t.name);break;case"member":{const n=this.buildMemberPath(t);n&&e.push(n);break}case"call":n.push(t.callee),t.arguments.forEach(t=>this.collectReferences(t,e,n));break;case"binary":this.collectReferences(t.left,e,n),this.collectReferences(t.right,e,n);break;case"unary":this.collectReferences(t.argument,e,n);break;case"conditional":this.collectReferences(t.test,e,n),this.collectReferences(t.consequent,e,n),this.collectReferences(t.alternate,e,n);break;case"array":t.elements.forEach(t=>this.collectReferences(t,e,n))}}buildMemberPath(t){if("identifier"===t.type)return t.name;if("member"===t.type&&!t.computed){const e=this.buildMemberPath(t.object);if(e)return`${e}.${t.property}`}return null}log(t,e,...n){this.options.logger?this.options.logger[t](e,...n):this.options.debug}},S=class{constructor(t){this.loadingCount=0,this.loadingElement=null,this.clipboard={write:async t=>{try{return await navigator.clipboard.writeText(t),!0}catch(e){return this.log("error","Clipboard write failed:",e),this.fallbackCopy(t)}},read:async()=>{try{return await navigator.clipboard.readText()}catch(t){return this.log("error","Clipboard read failed:",t),null}}},this.storage={get:t=>{const e=`${this.storageNamespace}:${t}`,n=localStorage.getItem(e);if(!n)return null;try{const t=JSON.parse(n);return t.expires&&Date.now()>t.expires?(localStorage.removeItem(e),null):t.value}catch{return null}},set:(t,e,n)=>{const s=`${this.storageNamespace}:${t}`,i={value:e,expires:n?.ttlSeconds?Date.now()+1e3*n.ttlSeconds:void 0};("session"===n?.level?sessionStorage:localStorage).setItem(s,JSON.stringify(i))},remove:t=>{const e=`${this.storageNamespace}:${t}`;localStorage.removeItem(e),sessionStorage.removeItem(e)},clear:()=>{const t=`${this.storageNamespace}:`;for(let e=localStorage.length-1;e>=0;e--){const n=localStorage.key(e);n?.startsWith(t)&&localStorage.removeItem(n)}for(let e=sessionStorage.length-1;e>=0;e--){const n=sessionStorage.key(e);n?.startsWith(t)&&sessionStorage.removeItem(n)}}},this.options=t,this.storageNamespace=`djvlc:${t.context.appId}`}async navigate(t){this.log("debug","Navigate:",t),this.track({eventName:"djvlc_navigate",params:{to:t.to,type:t.type},type:"click"});let e=t.to;if(t.query){const n=new URLSearchParams(t.query);e+=(e.includes("?")?"&":"?")+n.toString()}switch(t.type){case"external":t.newWindow?window.open(e,"_blank","noopener,noreferrer"):window.location.href=e;break;case"replace":window.location.replace(e);break;default:t.newWindow?window.open(e,"_blank"):window.location.href=e}}track(t){this.log("debug","Track event:",t);const e=this.options.context;this.options.userApiAdapter.track({eventName:t.eventName,params:t.params,type:t.type||"custom",timestamp:Date.now(),context:{pageVersionId:e.pageVersionId,runtimeVersion:e.runtimeVersion,userId:e.userId,deviceId:e.deviceId,channel:e.channel,appId:e.appId,env:e.env}})}async requestData(t,e){this.log("debug",`Requesting data: ${t}`,e);const n=performance.now(),s=this.options.context;try{const i=await this.options.userApiAdapter.executeQuery({queryVersionId:t,params:e??{},context:{pageVersionId:s.pageVersionId,uid:s.userId,deviceId:s.deviceId}}),r=performance.now()-n;if(this.log("debug",`Data query completed in ${r.toFixed(2)}ms`),!i.success)throw new Error(i.message||i.errorMessage||"Query failed");return this.options.stateManager.setQuery(t,i.data),i.data}catch(e){const s=performance.now()-n;throw this.log("error",`Data query failed: ${t} (${s.toFixed(2)}ms)`,e),e}}async executeAction(t,e={}){this.log("debug",`Executing action: ${t}`,e);const n=performance.now(),s=this.options.context,i=this.generateIdempotencyKey(t,e);this.track({eventName:"djvlc_action_start",params:{actionType:t,idempotencyKey:i},type:"custom"});try{const r=await this.options.userApiAdapter.executeAction({actionType:t,params:e||{},context:{pageVersionId:s.pageVersionId,uid:s.userId,deviceId:s.deviceId,channel:s.channel,appId:s.appId},idempotencyKey:i}),o=performance.now()-n;return this.log("debug",`Action completed in ${o.toFixed(2)}ms`,{success:r.success}),this.track({eventName:r.success?"djvlc_action_success":"djvlc_action_fail",params:{actionType:t,idempotencyKey:i,duration:Math.round(o),errorCode:r.errorCode},type:"custom"}),r}catch(e){const s=performance.now()-n;return this.log("error",`Action failed: ${t} (${s.toFixed(2)}ms)`,e),this.track({eventName:"djvlc_action_error",params:{actionType:t,idempotencyKey:i,duration:Math.round(s),errorMessage:e instanceof Error?e.message:"Unknown error"},type:"custom"}),{success:!1,errorCode:"NETWORK_ERROR",errorMessage:e instanceof Error?e.message:"Action failed"}}}async openDialog(t){return this.log("debug","Open dialog:",t),new Promise(e=>{const n=new CustomEvent("djvlc:openDialog",{detail:{options:t,resolve:t=>e(t)}});document.dispatchEvent(n),setTimeout(()=>{e({confirmed:!1})},6e4)})}closeDialog(t){this.log("debug","Close dialog:",t);const e=new CustomEvent("djvlc:closeDialog",{detail:{dialogId:t}});document.dispatchEvent(e)}showToast(t){this.log("debug","Show toast:",t);const e=document.createElement("div");switch(e.className=`djvlc-toast djvlc-toast-${t.type||"info"} djvlc-toast-${t.position||"top"}`,e.setAttribute("role","alert"),e.textContent=t.message,Object.assign(e.style,{position:"fixed",left:"50%",transform:"translateX(-50%)",padding:"12px 24px",borderRadius:"8px",color:"#fff",fontSize:"14px",zIndex:"10000",boxShadow:"0 4px 12px rgba(0,0,0,0.15)",transition:"opacity 0.3s, transform 0.3s",opacity:"0"}),e.style.backgroundColor={success:"#52c41a",error:"#ff4d4f",warning:"#faad14",info:"#1890ff"}[t.type||"info"],t.position){case"center":e.style.top="50%",e.style.transform="translate(-50%, -50%)";break;case"bottom":e.style.bottom="20px";break;default:e.style.top="20px"}document.body.appendChild(e),requestAnimationFrame(()=>{e.style.opacity="1"}),setTimeout(()=>{e.style.opacity="0",setTimeout(()=>e.remove(),300)},t.duration||3e3)}showLoading(t){this.loadingCount++,1===this.loadingCount&&(this.loadingElement=document.createElement("div"),this.loadingElement.className="djvlc-loading-overlay",this.loadingElement.innerHTML=`\n <div class="djvlc-loading-content">\n <div class="djvlc-loading-spinner"></div>\n <div class="djvlc-loading-message">${t||"加载中..."}</div>\n </div>\n `,Object.assign(this.loadingElement.style,{position:"fixed",top:"0",left:"0",right:"0",bottom:"0",backgroundColor:"rgba(0,0,0,0.5)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"10001"}),document.body.appendChild(this.loadingElement))}hideLoading(){this.loadingCount=Math.max(0,this.loadingCount-1),0===this.loadingCount&&this.loadingElement&&(this.loadingElement.remove(),this.loadingElement=null)}async share(t){if(this.log("debug","Share:",t),navigator.share)try{return await navigator.share({title:t.title,text:t.description,url:t.url}),{success:!0,channel:"native"}}catch(t){if("AbortError"===t.name)return{success:!1,cancelReason:"User cancelled"};throw t}return t.url&&await this.clipboard.write(t.url)?(this.showToast({message:"链接已复制",type:"success"}),{success:!0,channel:"link"}):{success:!1,cancelReason:"Share not supported"}}async confirm(t){return this.log("debug","Confirm:",t),window.confirm(t.content)}async showActionSheet(t){return this.log("debug","Show action sheet:",t),new Promise(e=>{const n=new CustomEvent("djvlc:showActionSheet",{detail:{options:t,resolve:t=>e(t)}});document.dispatchEvent(n),setTimeout(()=>{e({cancelled:!0})},6e4)})}previewImage(t){this.log("debug","Preview image:",t);const e=new CustomEvent("djvlc:previewImage",{detail:t});document.dispatchEvent(e)}async scanCode(){return this.log("debug","Scan code"),new Promise(t=>{const e=new CustomEvent("djvlc:scanCode",{detail:{resolve:e=>t(e)}});document.dispatchEvent(e),setTimeout(()=>{t({success:!1,cancelReason:"Timeout"})},6e4)})}getState(t){return this.options.stateManager.getVariable(t)}setState(t,e){this.options.stateManager.setVariable(t,e)}getContext(){const t=this.options.context;return{pageVersionId:t.pageVersionId,componentVersionId:"",instanceId:"",userId:t.userId,deviceId:t.deviceId,channel:t.channel,appId:t.appId,env:t.env}}generateIdempotencyKey(t,e){const n=Date.now(),s=JSON.stringify(e||{});return`${t}:${n}:${this.simpleHash(s)}`}simpleHash(t){let e=0;for(let n=0;n<t.length;n++)e=(e<<5)-e+t.charCodeAt(n),e&=e;return Math.abs(e).toString(36)}fallbackCopy(t){const e=document.createElement("textarea");e.value=t,e.style.position="fixed",e.style.opacity="0",document.body.appendChild(e),e.select();try{return document.execCommand("copy"),!0}catch{return!1}finally{document.body.removeChild(e)}}log(t,e,...n){this.options.logger?this.options.logger[t](e,...n):this.options.debug}},C=class{constructor(t={}){this.blockedComponentsMap=new Map,this.blockedActionsSet=new Set,this.allowedCapabilitiesSet=null,this.options={enableSRI:!0,cdnDomains:[],apiDomains:[],blockedComponents:[],blockedActions:[],applyCSPOnInit:!1,...t},this.updateBlockedList(t.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[],t.blockedActions||[]),t.allowedCapabilities&&(this.allowedCapabilitiesSet=new Set(t.allowedCapabilities)),t.applyCSPOnInit&&this.applyCSP()}updateBlockedList(t,e){this.blockedComponentsMap.clear(),t.forEach(t=>{const[e,n]=t.split("@");e&&n&&this.blockedComponentsMap.set(t,{name:e,version:n,reason:"Blocked by registry"})}),this.blockedActionsSet=new Set(e)}addBlockedComponent(t){const e=`${t.name}@${t.version}`;this.blockedComponentsMap.set(e,t),this.log("warn",`Component blocked: ${e} - ${t.reason}`)}removeBlockedComponent(t,e){const n=`${t}@${e}`;this.blockedComponentsMap.delete(n),this.log("info",`Component unblocked: ${n}`)}isComponentBlocked(t,e){return this.blockedComponentsMap.has(`${t}@${e}`)}getBlockedInfo(t,e){return this.blockedComponentsMap.get(`${t}@${e}`)}getAllBlockedComponents(){return Array.from(this.blockedComponentsMap.values())}isActionBlocked(t){return this.blockedActionsSet.has(t)}isCapabilityAllowed(t){return!this.allowedCapabilitiesSet||this.allowedCapabilitiesSet.has(t)}validateCapabilities(t,e,n){if(!this.allowedCapabilitiesSet)return{valid:!0,disallowed:[]};const s=n.filter(t=>!this.allowedCapabilitiesSet.has(t));return s.length>0&&this.log("warn",`Component ${t}@${e} uses disallowed capabilities: ${s.join(", ")}`),{valid:0===s.length,disallowed:s}}async validateIntegrity(t,e,n,s){if(!this.options.enableSRI)return;const[r,o]=s.split("-");if(!r||!o)throw new i(t,e,s,"Invalid integrity format");const a=await this.computeHash(n,r);if(a!==o)throw this.log("error",`Integrity check failed for ${t}@${e}`),new i(t,e,o,a);this.log("debug",`Integrity check passed for ${t}@${e}`)}async generateIntegrity(t,e="sha384"){return`${e}-${await this.computeHash(t,e)}`}isAllowedUrl(t,e){const n="cdn"===e?this.options.cdnDomains:this.options.apiDomains;if(!n||0===n.length)return!0;try{const e=new URL(t);return n.some(t=>{if(t.startsWith("*.")){const n=t.slice(2);return e.hostname.endsWith(n)||e.hostname===n.slice(1)}return e.hostname===t})}catch{return!1}}validateExternalUrl(t){try{const e=new URL(t);if(!["http:","https:"].includes(e.protocol))return{safe:!1,reason:`Unsafe protocol: ${e.protocol}`};const n=e.hostname;return"localhost"===n||"127.0.0.1"===n||n.startsWith("192.168.")||n.startsWith("10.")||n.startsWith("172.16.")?{safe:!1,reason:"Internal network address not allowed"}:{safe:!0}}catch{return{safe:!1,reason:"Invalid URL format"}}}generateCSPPolicy(){const t=this.options.cdnDomains||[],e=this.options.apiDomains||[],n=["'self'",...t].join(" "),s=["'self'",...e,...t].join(" ");return["default-src 'self'",`script-src ${n}`,`style-src ${["'self'","'unsafe-inline'",...t].join(" ")}`,`img-src ${["'self'","data:","blob:",...t].join(" ")}`,`font-src ${["'self'","data:",...t].join(" ")}`,`connect-src ${s}`,"frame-ancestors 'self'","base-uri 'self'","form-action 'self'","upgrade-insecure-requests"].join("; ")}applyCSP(){if(document.querySelector('meta[http-equiv="Content-Security-Policy"]'))return void this.log("debug","CSP meta tag already exists, skipping");const t=document.createElement("meta");t.httpEquiv="Content-Security-Policy",t.content=this.generateCSPPolicy(),document.head.appendChild(t),this.log("info","CSP policy applied")}assertNotBlocked(t,e){const n=this.getBlockedInfo(t,e);if(n)throw new r(t,e,n.reason)}createSafeEvaluator(){return(t,e)=>{const n=Object.keys(e),s=Object.values(e);return new Function(...n,`"use strict"; return (${t});`)(...s)}}async computeHash(t,e){const n=(new TextEncoder).encode(t),s=await crypto.subtle.digest(e.toUpperCase(),n),i=Array.from(new Uint8Array(s));return btoa(String.fromCharCode(...i))}log(t,e,...n){this.options.logger&&this.options.logger[t](e,...n)}},E=class{constructor(t){this.spans=new Map,this.metrics=[],this.errors=[],this.options={enabled:!0,sampleRate:1,batchSize:50,flushInterval:3e4,...t},this.traceId=this.generateTraceId(),this.shouldSample=Math.random()<(this.options.sampleRate??1),this.options.enabled&&this.options.endpoint&&this.startAutoFlush(),"undefined"!=typeof window&&(window.addEventListener("beforeunload",()=>this.flush()),window.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&this.flush()}))}getTraceId(){return this.traceId}getTraceparent(t){const e=t||this.generateSpanId(),n=this.shouldSample?"01":"00";return`00-${this.traceId}-${e}-${n}`}parseTraceparent(t){const e=t.split("-");if(4!==e.length)return null;const[,n,s,i]=e;return{traceId:n,parentSpanId:s,sampled:"01"===i}}startSpan(t,e,n){const s={spanId:this.generateSpanId(),traceId:this.traceId,parentSpanId:e,name:t,startTime:performance.now(),attributes:{pageVersionId:this.options.pageVersionId,...n}};return this.spans.set(s.spanId,s),this.log("debug",`Span started: ${t} (${s.spanId})`),s}endSpan(t,e="ok",n){const s=this.spans.get(t);if(s){s.endTime=performance.now(),s.status=e,n&&(s.attributes={...s.attributes,...n});const i=s.endTime-s.startTime;this.log("debug",`Span ended: ${s.name} (${t}) - ${i.toFixed(2)}ms [${e}]`)}}recordPageLoad(t){this.recordMetricInternal({type:"pageLoadTime",value:t,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordComponentLoad(t,e,n,s){this.recordMetricInternal({type:"componentLoadTime",value:n,pageVersionId:this.options.pageVersionId,componentName:t,componentVersion:e,timestamp:Date.now()}),s||this.recordError(new Error(`Component load failed: ${t}@${e}`),{componentVersion:`${t}@${e}`})}recordFirstRender(t){this.recordMetricInternal({type:"firstRenderTime",value:t,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordActionExecute(t,e,n,s){this.recordMetricInternal({type:"actionExecuteTime",value:n,pageVersionId:this.options.pageVersionId,actionType:t,timestamp:Date.now()}),s||this.recordError(new Error(`Action failed: ${t}`),{actionId:e})}recordQueryExecute(t,e,n,s=!1){this.recordMetricInternal({type:"queryFetchTime",value:e,pageVersionId:this.options.pageVersionId,queryId:t,timestamp:Date.now()}),this.log("debug",`Query ${t}: ${e.toFixed(2)}ms, cache: ${s}, success: ${n}`)}recordExpressionEval(t,e,n){e>1&&this.recordMetricInternal({type:"expressionEvalTime",value:e,pageVersionId:this.options.pageVersionId,timestamp:Date.now()})}recordError(t,e){const n={type:t.name||"Error",message:t.message,stack:t.stack,traceId:this.traceId,pageVersionId:this.options.pageVersionId,componentVersion:e?.componentVersion,actionId:e?.actionId,context:e,timestamp:Date.now()};this.errors.push(n),this.log("error",`Error recorded: ${t.message}`),this.options.onError?.(n),this.errors.length>=(this.options.batchSize??50)&&this.flush()}getMetrics(){return[...this.metrics]}getSpans(){return Array.from(this.spans.values())}getErrors(){return[...this.errors]}getPerformanceSummary(){const t=this.metrics.filter(t=>"componentLoadTime"===t.type),e=this.metrics.find(t=>"pageLoadTime"===t.type),n=this.metrics.find(t=>"firstRenderTime"===t.type);return{pageLoadTime:e?.value,firstRenderTime:n?.value,componentCount:t.length,avgComponentLoadTime:t.length>0?t.reduce((t,e)=>t+e.value,0)/t.length:0,errorCount:this.errors.length}}clear(){this.spans.clear(),this.metrics=[],this.errors=[]}async flush(){if(!this.shouldSample||!this.options.enabled)return;if(0===this.metrics.length&&0===this.errors.length&&0===this.spans.size)return;const t={traceId:this.traceId,pageVersionId:this.options.pageVersionId,appId:this.options.appId,runtimeVersion:this.options.runtimeVersion,spans:this.getSpans(),metrics:this.metrics,errors:this.errors,timestamp:Date.now()};if(this.clear(),this.options.endpoint)try{await fetch(this.options.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),keepalive:!0}),this.log("debug","Telemetry flushed successfully")}catch(t){this.log("warn","Failed to flush telemetry:",t)}else this.log("debug","No endpoint configured, telemetry data discarded")}destroy(){this.flushTimer&&clearInterval(this.flushTimer),this.flush()}recordMetricInternal(t){this.metrics.push(t),this.options.onMetric?.(t),this.metrics.length>=(this.options.batchSize??50)&&this.flush()}startAutoFlush(){const t=this.options.flushInterval??3e4;this.flushTimer=setInterval(()=>this.flush(),t)}generateTraceId(){const t=new Uint8Array(16);return crypto.getRandomValues(t),Array.from(t,t=>t.toString(16).padStart(2,"0")).join("")}generateSpanId(){const t=new Uint8Array(8);return crypto.getRandomValues(t),Array.from(t,t=>t.toString(16).padStart(2,"0")).join("")}log(t,e,...n){this.options.logger?this.options.logger[t](e,...n):this.options.debug}},j=class t{constructor(t){this.container=null,this.renderedElements=new Map,this.componentEventListeners=new Map,this.expressionContext={state:{},binding:{},local:{}},this.loopContextStack=[],this.styleElement=null,this.options=t}init(){this.log("debug","Renderer initialized")}render(t,e){this.container=e,this.log("debug","Rendering page",t.pageId),this.cleanup(),e.innerHTML="",this.applyPageConfig(t,e),this.initializePageState(t);const n=this.renderNode(t.root);n&&e.appendChild(n),this.log("info",`Page rendered with root component: ${t.root.componentType}`)}updateComponent(t,e){const n=this.renderedElements.get(t);n?this.applyProps(n,e):this.log("warn",`Component not found: ${t}`)}updateContext(t){this.expressionContext={...this.expressionContext,...t}}getContext(){return{...this.expressionContext}}destroy(){this.cleanup(),this.container&&(this.container.innerHTML=""),this.log("debug","Renderer destroyed")}cleanup(){this.componentEventListeners.forEach((t,e)=>{const n=this.renderedElements.get(e);n&&t.forEach(({event:t,handler:e})=>{n.removeEventListener(t,e)})}),this.componentEventListeners.clear(),this.renderedElements.forEach(t=>{t.remove()}),this.renderedElements.clear(),this.styleElement&&(this.styleElement.remove(),this.styleElement=null),this.loopContextStack=[]}renderNode(t){const{id:e,componentType:n,componentVersion:s}=t;try{if(t.condition&&!this.evaluateCondition(t.condition))return this.log("debug",`Component ${e} hidden by condition`),null;if(t.loop)return this.renderLoop(t);const i=this.createElement(t);if(!i)return null;i.setAttribute("data-component-id",e),i.setAttribute("data-component-type",n),s&&i.setAttribute("data-component-version",s);const r=this.resolveProps(t.props);if(this.applyProps(i,r),t.style&&this.applyStyles(i,t.style),t.layout&&this.applyLayout(i,t.layout),this.options.injectHostApi(i,e),t.eventHandlers&&t.eventHandlers.length>0&&this.bindEventHandlers(i,e,t.eventHandlers),this.renderChildren(i,t),t.ref){const e=this.expressionContext.local,n=e.$refs||{};n[t.ref]=i,this.expressionContext={...this.expressionContext,local:{...e,$refs:n}}}return this.renderedElements.set(e,i),i}catch(t){return this.log("error",`Failed to render component: ${e}`,t),this.options.onRenderError?this.options.onRenderError(e,t):this.createErrorFallback(e,n,t)}}createElement(t){const{componentType:e}=t,n=this.options.components.get(e);if(n&&customElements.get(e))return document.createElement(e);const s=`${e}-${t.componentVersion?.replace(/\./g,"-")}`;if(customElements.get(s))return document.createElement(s);const i=document.createElement("div");return i.className=`djvlc-component djvlc-${e}`,n||(this.log("warn",`Component not loaded: ${e}`),i.classList.add("djvlc-component-fallback")),i}renderLoop(t){const{loop:e}=t;if(!e)return null;const n=this.evaluateExpression(e.items);if(!Array.isArray(n))return this.log("warn",`Loop items is not an array for ${t.id}`),null;const s=document.createDocumentFragment();n.forEach((n,i)=>{this.loopContextStack.push({item:n,index:i,loopConfig:e});const r={...this.expressionContext},o={...this.expressionContext.local,[e.itemName]:n,item:n,index:i};e.indexName&&(o[e.indexName]=i),this.expressionContext={...this.expressionContext,local:o};const a={...t,id:`${t.id}_${i}`,loop:void 0},c=this.renderNode(a);if(c){const t=this.evaluateExpression(e.key);c.setAttribute("data-loop-key",String(t??i)),s.appendChild(c)}this.expressionContext=r,this.loopContextStack.pop()});const i=document.createElement("div");return i.className="djvlc-loop-container",i.setAttribute("data-loop-id",t.id),i.appendChild(s),i}renderChildren(t,e){if(e.slots&&Object.keys(e.slots).length>0)for(const[n,s]of Object.entries(e.slots)){const e=this.createSlotContainer(n);for(const t of s){const n=this.renderNode(t);n&&e.appendChild(n)}t.appendChild(e)}}createSlotContainer(t){const e=document.createElement("div");return e.className=`djvlc-slot djvlc-slot-${t}`,e.setAttribute("data-slot",t),e}bindEventHandlers(t,e,n){const s=[];for(const i of n){const{eventName:n,preventDefault:r,stopPropagation:o,throttle:a,debounce:c,condition:h}=i;let l=t=>{if(h&&!this.evaluateCondition(h))return;r&&t.preventDefault(),o&&t.stopPropagation();const s=t.detail||{};this.options.onComponentEvent&&this.options.onComponentEvent(e,n,[i],s)};a&&a>0&&(l=this.createThrottledHandler(l,a)),c&&c>0&&(l=this.createDebouncedHandler(l,c)),t.addEventListener(n,l),s.push({event:n,handler:l})}this.componentEventListeners.set(e,s)}createThrottledHandler(t,e){let n=0;return s=>{const i=Date.now();i-n>=e&&(n=i,t(s))}}createDebouncedHandler(t,e){let n=null;return s=>{n&&clearTimeout(n),n=setTimeout(()=>{t(s),n=null},e)}}evaluateCondition(t){const e=this.evaluateExpression(t);return Boolean(e)}evaluateExpression(t){if(null==t)return t;if("object"==typeof t&&"type"in t&&"value"in t){const e=t,n=this.buildExpressionContext();return this.options.expressionEngine.evaluateWithFallback(e.value,n,e.fallback)}if("string"==typeof t){const e=this.buildExpressionContext();return this.options.expressionEngine.evaluateWithFallback(t,e,void 0)}return t}buildExpressionContext(){const t={};for(const e of this.loopContextStack)t[e.loopConfig.itemName]=e.item,t.item=e.item,t.index=e.index,e.loopConfig.indexName&&(t[e.loopConfig.indexName]=e.index);return{...this.expressionContext,local:{...this.expressionContext.local,...t}}}resolveProps(t){const e={};for(const[n,s]of Object.entries(t))e[n]=this.resolveValue(s);return e}resolveValue(e){if(null==e)return e;if("string"==typeof e)return e.includes("${")?this.options.expressionEngine.evaluateTemplate(e,this.buildExpressionContext()):e;if("number"==typeof e||"boolean"==typeof e)return e;if(Array.isArray(e))return e.map(t=>this.resolveValue(t));if("object"==typeof e){const n=e;if("string"==typeof n.type&&t.EXPRESSION_TYPES.includes(n.type)&&"string"==typeof n.value){const t=n;return this.options.expressionEngine.evaluateWithFallback(t.value,this.buildExpressionContext(),t.fallback)}const s={};for(const[t,e]of Object.entries(n))s[t]=this.resolveValue(e);return s}return e}applyProps(t,e){for(const[n,s]of Object.entries(e))null!=s&&(t.tagName.includes("-")?t[n]=s:"boolean"==typeof s?s?t.setAttribute(n,""):t.removeAttribute(n):"object"==typeof s?t.setAttribute(n,JSON.stringify(s)):t.setAttribute(n,String(s)))}applyStyles(t,e){if(e.inline)for(const[n,s]of Object.entries(e.inline)){if(null==s)continue;const e=this.resolveValue(s);let i;i="number"==typeof e?["zIndex","opacity","flex","fontWeight","lineHeight"].includes(n)?String(e):`${e}px`:String(e);const r=n.replace(/([A-Z])/g,"-$1").toLowerCase();t.style.setProperty(r,i)}e.className&&t.classList.add(...String(e.className).split(" ").filter(Boolean))}applyLayout(t,e){const{x:n,y:s,width:i,height:r,rotation:o,zIndex:a,responsive:c}=e;t.style.position="absolute",void 0!==n&&(t.style.left=`${n}px`),void 0!==s&&(t.style.top=`${s}px`),void 0!==i&&(t.style.width=`${i}px`),void 0!==r&&(t.style.height=`${r}px`),void 0!==o&&(t.style.transform=`rotate(${o}deg)`),void 0!==a&&(t.style.zIndex=String(a)),c&&this.applyResponsiveLayout(t,c)}applyResponsiveLayout(t,e){const n=t.getAttribute("data-component-id");if(!n)return;let s="";if(e.mobile&&(s+=`\n @media (max-width: 767px) {\n [data-component-id="${n}"] {\n ${this.layoutToCSS(e.mobile)}\n }\n }\n `),e.tablet&&(s+=`\n @media (min-width: 768px) and (max-width: 1023px) {\n [data-component-id="${n}"] {\n ${this.layoutToCSS(e.tablet)}\n }\n }\n `),e.desktop&&(s+=`\n @media (min-width: 1440px) {\n [data-component-id="${n}"] {\n ${this.layoutToCSS(e.desktop)}\n }\n }\n `),s){const t=document.createElement("style");t.setAttribute("data-djvlc-responsive",n),t.textContent=s,document.head.appendChild(t)}}layoutToCSS(t){const e=[];return void 0!==t.x&&e.push(`left: ${t.x}px`),void 0!==t.y&&e.push(`top: ${t.y}px`),void 0!==t.width&&e.push(`width: ${t.width}px`),void 0!==t.height&&e.push(`height: ${t.height}px`),void 0!==t.rotation&&e.push(`transform: rotate(${t.rotation}deg)`),void 0!==t.zIndex&&e.push(`z-index: ${t.zIndex}`),e.join("; ")}applyPageConfig(t,e){e.classList.add("djvlc-page"),e.setAttribute("data-page-id",t.pageId),e.setAttribute("data-page-version",t.pageVersion),e.setAttribute("data-schema-version",t.schemaVersion);const n=t.config;n&&(this.applyLayoutConfig(e,n.layout),n.styles&&this.applyStylesConfig(e,n.styles),n.behavior&&this.applyBehaviorConfig(e,n.behavior))}applyBehaviorConfig(t,e){e.debug&&t.setAttribute("data-debug","true"),e.i18n&&this.applyI18nConfig(t,e.i18n)}applyI18nConfig(t,e){const n=this.detectLocale(e);t.setAttribute("lang",n),t.setAttribute("data-locale",n),t.setAttribute("data-default-locale",e.defaultLocale),t.setAttribute("data-supported-locales",e.supportedLocales.join(",")),e.translationBundleId&&t.setAttribute("data-translation-bundle",e.translationBundleId),t.style.setProperty("--djvlc-locale",n),t.style.setProperty("--djvlc-dir",this.getTextDirection(n)),"rtl"===this.getTextDirection(n)?(t.setAttribute("dir","rtl"),t.classList.add("djvlc-rtl")):t.setAttribute("dir","ltr"),this.expressionContext={...this.expressionContext,local:{...this.expressionContext.local,$locale:n,$defaultLocale:e.defaultLocale,$supportedLocales:e.supportedLocales}},this.log("debug",`I18n configured: locale=${n}, default=${e.defaultLocale}`)}detectLocale(t){const{defaultLocale:e,supportedLocales:n,detection:s="browser"}=t;let i=null;switch(s){case"browser":case"header":i=this.detectBrowserLocale(n);break;case"url":i=this.detectUrlLocale(n);break;case"path":i=this.detectPathLocale(n);break;case"cookie":i=this.detectCookieLocale(n);break;case"manual":i=e;break;default:i=null}return i&&n.includes(i)?i:e}detectBrowserLocale(t){if("undefined"==typeof navigator)return null;const e=navigator.languages||[navigator.language];for(const n of e){if(t.includes(n))return n;const e=n.split("-")[0],s=t.find(t=>t===e||t.startsWith(`${e}-`));if(s)return s}return null}detectUrlLocale(t){if("undefined"==typeof window)return null;const e=new URLSearchParams(window.location.search),n=e.get("lang")||e.get("locale");return n&&t.includes(n)?n:null}detectPathLocale(t){if("undefined"==typeof window)return null;const e=window.location.pathname.split("/").filter(Boolean);if(e.length>0){const n=e[0];if(t.includes(n))return n}return null}detectCookieLocale(t){if("undefined"==typeof document)return null;const e=document.cookie.split(";");for(const n of e){const[e,s]=n.trim().split("=");if("lang"===e||"locale"===e||"language"===e){const e=decodeURIComponent(s);if(t.includes(e))return e}}return null}getTextDirection(t){const e=t.split("-")[0];return["ar","ar-SA","ar-EG","ar-AE","he","he-IL","fa","fa-IR","ur","ur-PK","yi","ps","dv"].some(n=>n===t||n===e)?"rtl":"ltr"}applyLayoutConfig(t,e){if(t.setAttribute("data-canvas-type",e.canvasType),e.canvasSize&&"responsive"!==e.canvasType&&(t.style.width=`${e.canvasSize.width}px`,t.style.minHeight=`${e.canvasSize.height}px`),e.maxWidth&&(t.style.maxWidth=`${e.maxWidth}px`,t.style.marginLeft="auto",t.style.marginRight="auto"),e.padding){const{top:n=0,right:s=0,bottom:i=0,left:r=0}=e.padding;t.style.padding=`${n}px ${s}px ${i}px ${r}px`}e.viewport&&(e.viewport.mobile&&t.style.setProperty("--djvlc-breakpoint-mobile",`${e.viewport.mobile}px`),e.viewport.tablet&&t.style.setProperty("--djvlc-breakpoint-tablet",`${e.viewport.tablet}px`),e.viewport.desktop&&t.style.setProperty("--djvlc-breakpoint-desktop",`${e.viewport.desktop}px`))}applyStylesConfig(t,e){if(e.theme&&this.applyThemeConfig(t,e.theme),e.background&&this.applyBackgroundConfig(t,e.background),e.cssVariables)for(const[n,s]of Object.entries(e.cssVariables)){const e=n.startsWith("--")?n:`--${n}`;t.style.setProperty(e,s)}e.customCSS&&this.injectCustomCSS(e.customCSS)}applyThemeConfig(t,e){if(e.preset&&(t.setAttribute("data-theme",e.preset),"system"===e.preset)){const e=window.matchMedia("(prefers-color-scheme: dark)").matches;t.setAttribute("data-theme-resolved",e?"dark":"light")}if(e.variables)for(const[n,s]of Object.entries(e.variables)){const e=n.startsWith("--")?n:`--theme-${n}`;t.style.setProperty(e,s)}e.transition&&t.style.setProperty("--djvlc-theme-transition","all 0.3s ease")}applyBackgroundConfig(t,e){switch(e.type){case"color":t.style.backgroundColor=e.value;break;case"image":t.style.backgroundImage=`url(${e.value})`,t.style.backgroundSize=e.size||"cover",t.style.backgroundPosition=e.position||"center",t.style.backgroundRepeat=e.repeat||"no-repeat";break;case"gradient":t.style.backgroundImage=e.value}}injectCustomCSS(t){t.trim()&&(this.styleElement=document.createElement("style"),this.styleElement.setAttribute("data-djvlc-custom","true"),this.styleElement.textContent=t,document.head.appendChild(this.styleElement))}initializePageState(t){if(t.state&&t.state.fields){const e={};for(const[n,s]of Object.entries(t.state.fields))s&&"object"==typeof s&&(e[n]=s.initialValue);this.expressionContext={...this.expressionContext,state:e}}}createErrorFallback(t,e,n){const s=document.createElement("div");return s.className="djvlc-error-boundary",s.setAttribute("data-component-id",t),s.setAttribute("data-error","true"),s.innerHTML=`\n <div class="djvlc-error-content">\n <span class="djvlc-error-icon">⚠️</span>\n <span class="djvlc-error-message">组件渲染失败: ${e}</span>\n ${this.options.debug?`<pre class="djvlc-error-detail">${n.message}</pre>`:""}\n </div>\n `,s}log(t,e,...n){this.options.logger?this.options.logger[t](e,...n):this.options.debug}};j.EXPRESSION_TYPES=["state","binding","local","template","computed"];var I=j;function A(){customElements.get("djvlc-fallback")||customElements.define("djvlc-fallback",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML='\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #fff2f0;\n border: 1px solid #ffccc7;\n border-radius: 4px;\n color: #ff4d4f;\n font-size: 14px;\n }\n .title {\n font-weight: 600;\n margin-bottom: 8px;\n }\n .message {\n color: #666;\n }\n </style>\n <div class="title">组件加载失败</div>\n <div class="message"><slot>请刷新页面重试</slot></div>\n '}static get observedAttributes(){return["message","component-name"]}attributeChangedCallback(t,e,n){if("message"===t&&this.shadowRoot){const t=this.shadowRoot.querySelector(".message");t&&(t.textContent=n)}if("component-name"===t&&this.shadowRoot){const t=this.shadowRoot.querySelector(".title");t&&(t.textContent=`组件 ${n} 加载失败`)}}}),customElements.get("djvlc-blocked")||customElements.define("djvlc-blocked",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML='\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #fffbe6;\n border: 1px solid #ffe58f;\n border-radius: 4px;\n color: #faad14;\n font-size: 14px;\n }\n .icon {\n margin-right: 8px;\n }\n </style>\n <span class="icon">⚠️</span>\n <span>此组件已被暂停使用</span>\n '}}),customElements.get("djvlc-error-boundary")||customElements.define("djvlc-error-boundary",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).innerHTML="\n <style>\n :host {\n display: block;\n padding: 16px;\n background: #f5f5f5;\n border: 1px dashed #d9d9d9;\n border-radius: 4px;\n color: #999;\n font-size: 14px;\n text-align: center;\n }\n </style>\n <slot>渲染出错</slot>\n "}})}function N(t,e,n){const s=`djvlc-${"error"===t?"error-boundary":t}`,i=document.createElement(s);return e&&i.setAttribute("message",e),n&&i.setAttribute("component-name",n),i}function T(t,e,n){const s=`__${e}`;Object.defineProperty(t,e,{get(){return this[s]??n},set(t){this[s]=t,"function"==typeof this.t&&this.t()},configurable:!0,enumerable:!0})}var D=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.content??"请输入文本",e=this.fontSize??14,n=this.textAlign??"left",s=this.fontWeight??400,i=this.lineHeight??1.6,r=this.color??"#333333";this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: block;\n box-sizing: border-box;\n word-break: break-word;\n }\n .text {\n font-size: ${e}px;\n text-align: ${n};\n font-weight: ${s};\n line-height: ${i};\n color: ${r};\n margin: 0;\n white-space: pre-wrap;\n }\n </style>\n <p class="text">${this.i(t)}</p>\n `}i(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}};T(D.prototype,"content",""),T(D.prototype,"fontSize",14),T(D.prototype,"textAlign","left"),T(D.prototype,"fontWeight",400),T(D.prototype,"lineHeight",1.6),T(D.prototype,"color","#333333");var M=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.src??"",e=this.alt??"",n=this.objectFit??"cover",s=this.borderRadius??0,i=this.placeholder??"";this.shadowRoot.innerHTML=`\n <style>\n :host { display: block; overflow: hidden; }\n img {\n width: 100%;\n height: 100%;\n object-fit: ${n};\n border-radius: ${s}px;\n display: block;\n }\n .placeholder {\n width: 100%; height: 100%;\n display: flex; align-items: center; justify-content: center;\n background: #f5f5f5; color: #bbb; font-size: 14px;\n border-radius: ${s}px;\n }\n </style>\n ${t?`<img src="${this.o(t)}" alt="${this.o(e)}" loading="lazy" />`:`<div class="placeholder">${i||"暂无图片"}</div>`}\n `}o(t){return t.replace(/"/g,""").replace(/</g,"<")}};T(M.prototype,"src",""),T(M.prototype,"alt",""),T(M.prototype,"objectFit","cover"),T(M.prototype,"borderRadius",0),T(M.prototype,"placeholder","");var R=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.text??"按钮",e=this.type??"primary",n=this.size??"middle",s=this.block??!1,i=this.shape??"default",r=this.disabled??!1,o={small:{h:28,px:12,fs:12},middle:{h:36,px:16,fs:14},large:{h:44,px:20,fs:16}},a=o[n]||o.middle,c={primary:{bg:"#1677ff",fg:"#fff",border:"#1677ff",hoverBg:"#4096ff"},default:{bg:"#fff",fg:"#333",border:"#d9d9d9",hoverBg:"#f5f5f5"},danger:{bg:"#ff4d4f",fg:"#fff",border:"#ff4d4f",hoverBg:"#ff7875"},link:{bg:"transparent",fg:"#1677ff",border:"transparent",hoverBg:"transparent"}},h=c[e]||c.primary,l="round"===i?a.h/2+"px":"circle"===i?"50%":"6px";this.shadowRoot.innerHTML=`\n <style>\n :host { display: ${s?"block":"inline-block"}; }\n button {\n display: inline-flex; align-items: center; justify-content: center;\n height: ${a.h}px; padding: 0 ${a.px}px; font-size: ${a.fs}px;\n background: ${h.bg}; color: ${h.fg};\n border: 1px solid ${h.border}; border-radius: ${l};\n cursor: ${r?"not-allowed":"pointer"};\n opacity: ${r?.6:1};\n width: ${s?"100%":"auto"};\n font-family: inherit; transition: all 0.2s;\n outline: none; user-select: none;\n line-height: 1;\n }\n button:hover:not(:disabled) {\n background: ${h.hoverBg};\n ${"link"===e?"color: #4096ff; text-decoration: underline;":""}\n }\n button:active:not(:disabled) {\n transform: scale(0.97);\n }\n </style>\n <button ${r?"disabled":""}>${this.i(t)}</button>\n `;const d=this.shadowRoot.querySelector("button");d?.addEventListener("click",t=>{r||this.dispatchEvent(new CustomEvent("onClick",{detail:{originalEvent:t},bubbles:!0,composed:!0}))})}i(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}};T(R.prototype,"text","按钮"),T(R.prototype,"type","primary"),T(R.prototype,"size","middle"),T(R.prototype,"block",!1),T(R.prototype,"shape","default"),T(R.prototype,"disabled",!1);var L=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.name??"star",e=this.size??16,n=this.color??"currentColor";this.shadowRoot.innerHTML=`\n <style>\n :host { display: inline-flex; align-items: center; justify-content: center; }\n .icon { font-size: ${e}px; color: ${n}; line-height: 1; }\n </style>\n <span class="icon">${{star:"⭐",heart:"❤️",check:"✅",close:"✖",info:"ℹ️",warning:"⚠️",error:"❌",success:"✔️",search:"🔍",home:"🏠",user:"👤",setting:"⚙️",delete:"🗑️",edit:"✏️",add:"➕",arrow_right:"→",arrow_left:"←",arrow_up:"↑",arrow_down:"↓"}[t]??t}</span>\n `}};T(L.prototype,"name","star"),T(L.prototype,"size",16),T(L.prototype,"color","currentColor");var O=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.href??"#",e=this.text??"链接",n=this.target??"_self",s=this.color??"#1677ff",i=!1!==this.underline;this.shadowRoot.innerHTML=`\n <style>\n :host { display: inline; }\n a {\n color: ${s};\n text-decoration: ${i?"underline":"none"};\n cursor: pointer; transition: opacity 0.2s;\n }\n a:hover { opacity: 0.8; }\n </style>\n <a href="${t}" target="${n}" rel="noopener noreferrer">${this.i(e)}</a>\n `;const r=this.shadowRoot.querySelector("a");r?.addEventListener("click",e=>{this.dispatchEvent(new CustomEvent("onClick",{detail:{href:t,originalEvent:e},bubbles:!0,composed:!0}))})}i(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}};T(O.prototype,"href","#"),T(O.prototype,"text","链接"),T(O.prototype,"target","_self"),T(O.prototype,"color","#1677ff"),T(O.prototype,"underline",!0);var P=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.direction??"horizontal",e=this.color??"#e8e8e8",n=this.thickness??1,s=this.dashed??!1,i=this.text??"",r=s?"dashed":"solid";this.shadowRoot.innerHTML="vertical"===t?`\n <style>\n :host { display: inline-flex; align-self: stretch; }\n .divider { width: ${n}px; background: ${e}; min-height: 1em;\n ${s?`background: none; border-left: ${n}px ${r} ${e};`:""} }\n </style>\n <div class="divider"></div>\n `:`\n <style>\n :host { display: block; margin: 12px 0; }\n .divider {\n display: flex; align-items: center; width: 100%;\n }\n .line {\n flex: 1; height: 0; border-top: ${n}px ${r} ${e};\n }\n .text {\n padding: 0 12px; color: #999; font-size: 12px; white-space: nowrap;\n }\n </style>\n <div class="divider">\n <div class="line"></div>\n ${i?`<span class="text">${i}</span><div class="line"></div>`:""}\n </div>\n `}};function B(t,e,n){const s=`__${e}`;Object.defineProperty(t,e,{get(){return this[s]??n},set(t){this[s]=t,"function"==typeof this.t&&this.t()},configurable:!0,enumerable:!0})}T(P.prototype,"direction","horizontal"),T(P.prototype,"color","#e8e8e8"),T(P.prototype,"thickness",1),T(P.prototype,"dashed",!1),T(P.prototype,"text","");var V=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.background??"transparent",e=this.overflow??"visible";this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: block;\n position: relative;\n box-sizing: border-box;\n background: ${t};\n overflow: ${e};\n width: 100%;\n min-height: 100%;\n }\n /* 默认 slot 容器 */\n ::slotted(*) {\n box-sizing: border-box;\n }\n </style>\n <slot></slot>\n `}};B(V.prototype,"direction","column"),B(V.prototype,"align","stretch"),B(V.prototype,"justify","flex-start"),B(V.prototype,"gap",0),B(V.prototype,"padding",0),B(V.prototype,"background","transparent"),B(V.prototype,"overflow","visible");var U=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.gutter??0,e=this.align??"stretch",n=this.justify??"flex-start",s=!1!==this.wrap;this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: flex;\n flex-wrap: ${s?"wrap":"nowrap"};\n align-items: ${e};\n justify-content: ${n};\n gap: ${t}px;\n box-sizing: border-box;\n width: 100%;\n }\n ::slotted(*) { box-sizing: border-box; }\n </style>\n <slot></slot>\n `}};B(U.prototype,"gutter",0),B(U.prototype,"align","stretch"),B(U.prototype,"justify","flex-start"),B(U.prototype,"wrap",!0);var z=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=Math.min(24,Math.max(1,this.span??24)),e=Math.min(23,Math.max(0,this.offset??0)),n=(t/24*100).toFixed(4),s=e>0?`${(e/24*100).toFixed(4)}%`:"0";this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: block;\n box-sizing: border-box;\n flex: 0 0 ${n}%;\n max-width: ${n}%;\n margin-left: ${s};\n }\n ::slotted(*) { box-sizing: border-box; }\n </style>\n <slot></slot>\n `}};B(z.prototype,"span",24),B(z.prototype,"offset",0);var _=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.size??16,e="horizontal"===(this.direction??"vertical");this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: ${e?"inline-block":"block"};\n width: ${e?`${t}px`:"100%"};\n height: ${e?"auto":`${t}px`};\n flex-shrink: 0;\n }\n </style>\n `}};function H(t,e,n){const s=`__${e}`;Object.defineProperty(t,e,{get(){return this[s]??n},set(t){this[s]=t,"function"==typeof this.t&&this.t()},configurable:!0,enumerable:!0})}B(_.prototype,"size",16),B(_.prototype,"direction","vertical");var F=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t="horizontal"===(this.layout??"vertical");this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: block;\n box-sizing: border-box;\n width: 100%;\n }\n form {\n display: flex;\n flex-direction: ${t?"row":"column"};\n flex-wrap: ${t?"wrap":"nowrap"};\n gap: 16px;\n width: 100%;\n }\n ::slotted(*) { box-sizing: border-box; }\n </style>\n <form>\n <slot></slot>\n </form>\n `;const e=this.shadowRoot.querySelector("form");e?.addEventListener("submit",t=>{t.preventDefault(),this.dispatchEvent(new CustomEvent("onSubmit",{detail:{},bubbles:!0,composed:!0}))}),e?.addEventListener("reset",()=>{this.dispatchEvent(new CustomEvent("onReset",{detail:{},bubbles:!0,composed:!0}))})}};function q(t,e,n){const s=`__${e}`;Object.defineProperty(t,e,{get(){return this[s]??n},set(t){this[s]=t,"function"==typeof this.t&&this.t()},configurable:!0,enumerable:!0})}H(F.prototype,"layout","vertical"),H(F.prototype,"labelWidth",80),H(F.prototype,"labelAlign","right"),H(F.prototype,"disabled",!1);var K=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.src??"",e=this.size??"cover",n=this.position??"center",s=this.repeat??"no-repeat",i=this.opacity??1;this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: block;\n position: relative;\n width: 100%;\n height: 100%;\n overflow: hidden;\n }\n .bg {\n position: absolute; inset: 0;\n ${t?`\n background-image: url(${t});\n background-size: ${e};\n background-position: ${n};\n background-repeat: ${s};\n `:"background: #f5f5f5;"}\n opacity: ${i};\n z-index: 0;\n }\n .content {\n position: relative;\n z-index: 1;\n width: 100%; height: 100%;\n }\n </style>\n <div class="bg"></div>\n <div class="content"><slot></slot></div>\n `}};function Q(t,e,n){const s=`__${e}`;Object.defineProperty(t,e,{get(){return this[s]??n},set(t){this[s]=t,"function"==typeof this.t&&this.t()},configurable:!0,enumerable:!0})}q(K.prototype,"src",""),q(K.prototype,"size","cover"),q(K.prototype,"position","center"),q(K.prototype,"repeat","no-repeat"),q(K.prototype,"opacity",1);var J=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}open(){this.visible=!0}close(){this.visible=!1}t(){if(!this.shadowRoot)return;const t=this.title??"",e=this.content??"",n=this.variant??"center",s=this.visible??!1,i=!1!==this.showClose,r=!1!==this.showConfirm,o=this.showCancel??!1,a=this.confirmText??"确定",c=this.cancelText??"取消",h=!1!==this.maskClosable,l=this.maskColor??"#000000",d=this.maskOpacity??50,u=this.widthPercent??80,p=this.borderRadius??12,f=this.backgroundColor??"#ffffff",m=this.backgroundImage??"",g="bottom"===n?"flex-end":"center",y="fullscreen"===n?"100%":`${u}%`,b="fullscreen"===n?"100%":"480px",w="fullscreen"===n?"0":"bottom"===n?`${p}px ${p}px 0 0`:`${p}px`,v=m?`background-image: url(${m}); background-size: cover; background-position: center;`:`background: ${f};`;this.shadowRoot.innerHTML=`\n <style>\n :host { display: block; }\n .overlay {\n display: ${s?"flex":"none"};\n position: fixed; inset: 0; z-index: 9999;\n align-items: ${g}; justify-content: center;\n animation: fadeIn 0.2s ease;\n }\n .mask {\n position: absolute; inset: 0;\n background: ${l};\n opacity: ${d/100};\n }\n .dialog {\n position: relative;\n width: ${y};\n max-width: ${b};\n ${"fullscreen"===n?"height: 100%;":"max-height: 85vh;"}\n border-radius: ${w};\n ${v}\n box-shadow: 0 8px 32px rgba(0,0,0,0.12);\n display: flex; flex-direction: column;\n overflow: hidden;\n animation: ${"bottom"===n?"slideUp":"scaleIn"} 0.25s ease;\n }\n .header {\n display: flex; align-items: center; justify-content: space-between;\n padding: 16px 20px 0;\n ${t?"":"display: none;"}\n }\n .title {\n font-size: 16px; font-weight: 600; color: #333;\n flex: 1; margin: 0;\n }\n .close-btn {\n width: 24px; height: 24px;\n display: ${i?"flex":"none"};\n align-items: center; justify-content: center;\n background: none; border: none;\n font-size: 18px; color: #999;\n cursor: pointer; border-radius: 50%;\n transition: all 0.2s;\n }\n .close-btn:hover { background: #f5f5f5; color: #333; }\n .body {\n flex: 1; padding: 16px 20px;\n font-size: 14px; line-height: 1.6; color: #666;\n overflow-y: auto;\n }\n .footer {\n display: ${r||o?"flex":"none"};\n padding: 0 20px 16px;\n gap: 12px; justify-content: center;\n }\n .btn {\n flex: 1; max-width: 160px; height: 40px;\n border-radius: 20px; font-size: 14px;\n cursor: pointer; border: none;\n transition: all 0.2s; outline: none;\n }\n .btn-cancel {\n background: #f5f5f5; color: #666;\n display: ${o?"block":"none"};\n }\n .btn-cancel:hover { background: #e8e8e8; }\n .btn-confirm {\n background: #1677ff; color: #fff;\n display: ${r?"block":"none"};\n }\n .btn-confirm:hover { background: #4096ff; }\n .btn:active { transform: scale(0.97); }\n\n @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }\n @keyframes scaleIn { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: scale(1); } }\n @keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }\n </style>\n <div class="overlay">\n <div class="mask"></div>\n <div class="dialog">\n <div class="header">\n <h3 class="title">${this.i(t)}</h3>\n <button class="close-btn">✕</button>\n </div>\n <div class="body">\n ${this.i(e)}\n <slot></slot>\n </div>\n <div class="footer">\n <button class="btn btn-cancel">${this.i(c)}</button>\n <button class="btn btn-confirm">${this.i(a)}</button>\n </div>\n </div>\n </div>\n `;const $=this.shadowRoot.querySelector(".mask"),x=this.shadowRoot.querySelector(".close-btn"),k=this.shadowRoot.querySelector(".btn-cancel"),S=this.shadowRoot.querySelector(".btn-confirm");h&&$?.addEventListener("click",()=>this.l()),x?.addEventListener("click",()=>this.l()),k?.addEventListener("click",()=>this.u()),S?.addEventListener("click",()=>this.p())}l(){this.visible=!1,this.dispatchEvent(new CustomEvent("onClose",{detail:{},bubbles:!0,composed:!0}))}u(){this.visible=!1,this.dispatchEvent(new CustomEvent("onCancel",{detail:{},bubbles:!0,composed:!0}))}p(){this.visible=!1,this.dispatchEvent(new CustomEvent("onConfirm",{detail:{},bubbles:!0,composed:!0}))}i(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}};Q(J.prototype,"title",""),Q(J.prototype,"content",""),Q(J.prototype,"variant","center"),Q(J.prototype,"visible",!1),Q(J.prototype,"showClose",!0),Q(J.prototype,"showConfirm",!0),Q(J.prototype,"showCancel",!1),Q(J.prototype,"confirmText","确定"),Q(J.prototype,"cancelText","取消"),Q(J.prototype,"maskClosable",!0),Q(J.prototype,"maskColor","#000000"),Q(J.prototype,"maskOpacity",50),Q(J.prototype,"widthPercent",80),Q(J.prototype,"borderRadius",12),Q(J.prototype,"backgroundColor","#ffffff"),Q(J.prototype,"backgroundImage","");var W=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.text??"",e=this.size??"default",n=this.color??"#1677ff",s={small:20,default:32,large:48},i=s[e]||s.default;this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 16px; gap: 8px;\n }\n .spinner {\n width: ${i}px; height: ${i}px;\n border: 3px solid #f0f0f0;\n border-top-color: ${n};\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n }\n .text { font-size: 14px; color: #999; }\n @keyframes spin { to { transform: rotate(360deg); } }\n </style>\n <div class="spinner"></div>\n ${t?`<span class="text">${t}</span>`:""}\n `}};Q(W.prototype,"text",""),Q(W.prototype,"size","default"),Q(W.prototype,"color","#1677ff");var Y=class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"})}connectedCallback(){this.t()}t(){if(!this.shadowRoot)return;const t=this.description??"暂无数据",e=this.image??"",n=this.imageSize??80,s=`\n <svg width="${n}" height="${n}" viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">\n <rect x="15" y="25" width="50" height="35" rx="3" fill="#f5f5f5" stroke="#d9d9d9" stroke-width="1.5"/>\n <line x1="25" y1="35" x2="55" y2="35" stroke="#d9d9d9" stroke-width="1.5"/>\n <line x1="25" y1="42" x2="45" y2="42" stroke="#d9d9d9" stroke-width="1.5"/>\n <line x1="25" y1="49" x2="50" y2="49" stroke="#d9d9d9" stroke-width="1.5"/>\n <circle cx="58" cy="52" r="12" fill="#fafafa" stroke="#d9d9d9" stroke-width="1.5"/>\n <path d="M55 49L61 55M61 49L55 55" stroke="#bbb" stroke-width="1.5" stroke-linecap="round"/>\n </svg>\n `;this.shadowRoot.innerHTML=`\n <style>\n :host {\n display: flex; flex-direction: column;\n align-items: center; justify-content: center;\n padding: 32px 16px;\n color: #bbb;\n }\n .image { margin-bottom: 12px; }\n .image img { width: ${n}px; height: ${n}px; object-fit: contain; }\n .desc { font-size: 14px; color: #999; text-align: center; }\n </style>\n <div class="image">\n ${e?`<img src="${e}" alt="empty" />`:s}\n </div>\n <div class="desc">${t}</div>\n <slot></slot>\n `}};Q(Y.prototype,"description","暂无数据"),Q(Y.prototype,"image",""),Q(Y.prototype,"imageSize",80);var G={"djvlc-text":D,"djvlc-image":M,"djvlc-button":R,"djvlc-icon":L,"djvlc-link":O,"djvlc-divider":P,"djvlc-container":V,"djvlc-row":U,"djvlc-col":z,"djvlc-spacer":_,"djvlc-form":F,"djvlc-background-image":K,"djvlc-dialog":J,"djvlc-loading":W,"djvlc-empty":Y};function Z(e=!1){for(const e of t.BUILTIN_COMPONENT_NAMES){if(customElements.get(e))continue;const t=G[e];if(t)try{customElements.define(e,t)}catch(t){}}}var X=class{constructor(t){this.lifecycle=null,this.mounted=!1,this.destroyed=!1,this.cleanupFns=[],this.options=t}register(t){t?(this.lifecycle=t,this.log("debug","Lifecycle hooks registered",{onMounted:t.onMounted?.length??0,onBeforeUnmount:t.onBeforeUnmount?.length??0,onVisibilityChange:t.onVisibilityChange?.length??0}),t.onVisibilityChange&&t.onVisibilityChange.length>0&&this.setupVisibilityListener()):this.log("debug","No lifecycle hooks defined")}async triggerMounted(){this.mounted||this.destroyed||(this.mounted=!0,this.log("debug","Triggering onMounted lifecycle"),await this.executeLifecycleActions("mounted",this.lifecycle?.onMounted),this.options.onLifecycleEvent?.("mounted"))}async triggerBeforeUnmount(){this.mounted&&!this.destroyed&&(this.log("debug","Triggering onBeforeUnmount lifecycle"),await this.executeLifecycleActions("beforeUnmount",this.lifecycle?.onBeforeUnmount),this.options.onLifecycleEvent?.("beforeUnmount"))}async triggerVisibilityChange(t){if(!this.mounted||this.destroyed)return;this.log("debug","Triggering onVisibilityChange lifecycle",{isVisible:t});const e=this.options.getContext(),n={...e,local:{...e.local,$visible:t,$hidden:!t}};await this.executeLifecycleActionsWithContext("visibilityChange",this.lifecycle?.onVisibilityChange,n),this.options.onLifecycleEvent?.("visibilityChange",{isVisible:t})}async destroy(){this.destroyed||(await this.triggerBeforeUnmount(),this.cleanupFns.forEach(t=>t()),this.cleanupFns=[],this.destroyed=!0,this.lifecycle=null,this.log("debug","LifecycleManager destroyed"))}isMounted(){return this.mounted&&!this.destroyed}isDestroyed(){return this.destroyed}setupVisibilityListener(){const t=()=>{const t="visible"===document.visibilityState;this.triggerVisibilityChange(t).catch(t=>{this.log("error","Failed to handle visibility change",t)})};document.addEventListener("visibilitychange",t),this.cleanupFns.push(()=>{document.removeEventListener("visibilitychange",t)}),this.log("debug","Visibility listener registered")}async executeLifecycleActions(t,e){if(!e||0===e.length)return;const n=this.options.getContext();await this.executeLifecycleActionsWithContext(t,e,n)}async executeLifecycleActionsWithContext(t,e,n){if(e&&0!==e.length){this.log("debug",`Executing ${e.length} actions for ${t}`);try{const s={id:`lifecycle_${t}`,eventName:t,actions:e};await this.options.actionBridge.handleEvent(s,{lifecycle:t},n),this.log("debug",`Lifecycle ${t} actions completed`)}catch(e){this.log("error",`Failed to execute lifecycle ${t} actions`,e)}}}log(t,e,...n){this.options.logger?this.options.logger[t](e,...n):this.options.debug}},tt=t.CURRENT_SCHEMA_VERSION,et="1.0.0",nt=class{constructor(t){if(this.container=null,!t.pageId)throw new Error("pageId is required");if(this.options={channel:"prod",debug:!1,enableSRI:!0,env:"production",...t},this.logger=this.createLogger(),this.stateManager=new p,this.eventBus=new m({debug:t.debug,logger:this.logger}),this.expressionEngine=new k({debug:t.debug,logger:this.logger}),!t.userApiAdapter)throw new Error("userApiAdapter is required. Inject a UserApiAdapter implementation (e.g. from @djvlc/runtime-web or your host).");this.userApiAdapter=t.userApiAdapter,this.pageLoader=new h({apiBaseUrl:t.apiBaseUrl,userApiAdapter:this.userApiAdapter,channel:t.channel,previewToken:t.previewToken,headers:t.headers,logger:this.logger}),this.componentLoader=new d({cdnBaseUrl:t.cdnBaseUrl,enableSRI:t.enableSRI,headers:t.headers,logger:this.logger});const e=this.safeParseHost(t.cdnBaseUrl),n=this.safeParseHost(t.apiBaseUrl);this.assetLoader=new u({cdnHosts:e?[e]:[],apiHosts:n?[n]:[]}),this.securityManager=new C({enableSRI:t.enableSRI,cdnDomains:e?[e]:[],apiDomains:n?[n]:[],logger:this.logger}),this.log("info","Runtime created",{version:et})}async init(){this.log("info","Initializing runtime");const t=performance.now();try{this.container=this.resolveContainer(),this.assetLoader.preconnectAll(),this.pageLoader.preconnect(),Z(this.options.debug),A(),this.stateManager.setPhase("resolving");const e=performance.now()-t;this.log("info",`Runtime initialized in ${e.toFixed(2)}ms`)}catch(t){throw this.handleError(t),t}}async loadFromResolved(t){this.log("info","Loading from resolved page:",t.pageId);const e=performance.now();try{if(this.stateManager.setPhase("resolving"),this.validateSchemaVersion(t.pageJson),this.stateManager.setPage(t),this.telemetryManager=new E({pageVersionId:t.pageVersionId,appId:this.options.appId,debug:this.options.debug,logger:this.logger,onMetric:this.options.onMetric}),t.runtimeConfig){const e=t.runtimeConfig.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[];this.securityManager.updateBlockedList(e,[]),this.componentLoader.updateBlockedList(e)}this.stateManager.setPhase("loading"),this.componentLoader.preload(t.manifest.components),(await this.componentLoader.loadAll(t.manifest)).forEach((t,e)=>{this.stateManager.setComponentStatus(e,t),this.telemetryManager.recordComponentLoad(t.name,t.version,t.loadTime||0,"loaded"===t.status)}),this.initHostApi(t),this.initActionBridge(),this.initDataBindingManager(t.pageJson),this.initRenderer(),this.initLifecycleManager(t.pageJson);const n=performance.now()-e;return this.telemetryManager.recordPageLoad(n),this.log("info",`Page loaded from resolved in ${n.toFixed(2)}ms`),this.emitEvent("page:loaded",{page:t,loadTime:n}),this.options.onLoad?.(t),t}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}setPrefetchedData(t){for(const[e,n]of Object.entries(t))this.stateManager.setQuery(e,n)}async load(){this.log("info","Loading page:",this.options.pageId);const t=performance.now();try{this.stateManager.setPhase("resolving");const e=await this.pageLoader.resolve(this.options.pageId,{uid:this.options.userId,deviceId:this.options.deviceId});if(this.validateSchemaVersion(e.pageJson),this.stateManager.setPage(e),this.telemetryManager=new E({pageVersionId:e.pageVersionId,appId:this.options.appId,debug:this.options.debug,logger:this.logger,onMetric:this.options.onMetric}),e.runtimeConfig){const t=e.runtimeConfig.blockedComponents?.map(t=>`${t.name}@${t.version}`)||[];this.securityManager.updateBlockedList(t,[]),this.componentLoader.updateBlockedList(t)}this.stateManager.setPhase("loading"),this.componentLoader.preload(e.manifest.components),(await this.componentLoader.loadAll(e.manifest)).forEach((t,e)=>{this.stateManager.setComponentStatus(e,t),this.telemetryManager.recordComponentLoad(t.name,t.version,t.loadTime||0,"loaded"===t.status)}),this.initHostApi(e),this.initActionBridge(),this.initDataBindingManager(e.pageJson),this.initRenderer(),this.initLifecycleManager(e.pageJson);const n=performance.now()-t;return this.telemetryManager.recordPageLoad(n),this.log("info",`Page loaded in ${n.toFixed(2)}ms`),this.emitEvent("page:loaded",{page:e,loadTime:n}),this.options.onLoad?.(e),e}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}async render(){const t=this.stateManager.getState();if(!t.page||!this.container)throw new n("Page not loaded");this.log("info","Rendering page");const e=performance.now();try{this.stateManager.setPhase("rendering"),this.renderer.updateContext(this.stateManager.getExpressionContext()),this.renderer.render(t.page.pageJson,this.container),await this.dataBindingManager.initializeBindings(this.stateManager.getExpressionContext()),this.stateManager.setPhase("ready");const n=performance.now()-e;this.telemetryManager.recordFirstRender(n),this.log("info",`Page rendered in ${n.toFixed(2)}ms`),await this.lifecycleManager.triggerMounted(),this.emitEvent("page:rendered",{renderTime:n})}catch(t){throw this.stateManager.setPhase("error"),this.handleError(t),t}}getHostApi(){return this.hostApi}getState(){return this.stateManager.getState()}onStateChange(t){return this.stateManager.subscribe(t)}on(t,e){return this.eventBus.on(t,e)}updateComponent(t,e){this.renderer.updateComponent(t,e)}setVariable(t,e){this.stateManager.setVariable(t,e),this.renderer.updateContext(this.stateManager.getExpressionContext()),this.dataBindingManager.onStateChange(t,this.stateManager.getExpressionContext())}getVariable(t){return this.stateManager.getVariable(t)}async refreshData(t){await this.dataBindingManager.refreshBinding(t,this.stateManager.getExpressionContext()),this.renderer.updateContext(this.stateManager.getExpressionContext())}async executeAction(t,e){return this.hostApi.executeAction(t,e)}async destroy(){this.log("info","Destroying runtime"),await(this.lifecycleManager?.destroy()),this.telemetryManager?.flush(),this.dataBindingManager?.destroy(),this.actionBridge?.destroy(),this.renderer?.destroy(),this.eventBus.clear(),this.stateManager.setDestroyed(),this.container&&(this.container.innerHTML=""),this.emitEvent("page:destroyed",{}),this.log("info","Runtime destroyed")}validateSchemaVersion(t){if(t.schemaVersion!==tt)throw new n(`Unsupported schema version: ${t.schemaVersion}. Only ${tt} is supported.`,{schemaVersion:t.schemaVersion,supportedVersion:tt})}safeParseHost(t){if(!t)return"";try{return new URL(t).host}catch{try{const e="undefined"!=typeof window?window.location.origin:"http://localhost";return new URL(t,e).host}catch{return this.log("warn",`Cannot parse URL host: ${t}`),""}}}resolveContainer(){const{container:t}=this.options;if("string"==typeof t){const e=document.querySelector(t);if(!e)throw new Error(`Container not found: ${t}`);return e}return t}initHostApi(t){this.hostApi=new S({userApiAdapter:this.userApiAdapter,stateManager:this.stateManager,eventBus:this.eventBus,expressionEngine:this.expressionEngine,context:{pageId:t.pageId,pageVersionId:t.pageVersionId,runtimeVersion:et,userId:this.options.userId,deviceId:this.options.deviceId,channel:this.options.channel,appId:this.options.appId||"",env:this.options.env||"production",isEditMode:!1,isPreviewMode:t.isPreview||!1},debug:this.options.debug,logger:this.logger})}initActionBridge(){this.actionBridge=new y({executor:{executeAction:(t,e)=>this.hostApi.executeAction(t,e),requestData:(t,e)=>this.hostApi.requestData(t,e),navigate:t=>this.hostApi.navigate(t),openDialog:t=>this.hostApi.openDialog(t),closeDialog:()=>this.hostApi.closeDialog(),showToast:t=>this.hostApi.showToast(t),showLoading:t=>this.hostApi.showLoading(t),hideLoading:()=>this.hostApi.hideLoading(),track:t=>this.hostApi.track(t),setState:(t,e)=>this.stateManager.setVariable(t,e),getState:t=>this.stateManager.getVariable(t),refreshData:t=>this.refreshData(t)},expressionEngine:this.expressionEngine,debug:this.options.debug,logger:this.logger,onActionStart:(t,e)=>{this.emitEvent("action:executing",{action:t,params:e})},onActionComplete:(t,e)=>{e.success?this.emitEvent("action:executed",{action:t,data:e.data}):this.emitEvent("action:error",{action:t,error:e.error?.message})}})}initDataBindingManager(t){this.dataBindingManager=new f({requester:{requestData:(t,e)=>this.hostApi.requestData(t,e)},stateSetter:{setVariable:(t,e)=>this.stateManager.setVariable(t,e),getVariable:t=>this.stateManager.getVariable(t)},expressionEngine:this.expressionEngine,debug:this.options.debug,logger:this.logger,onDataLoaded:(t,e)=>{this.emitEvent("query:fetched",{bindingId:t,data:e}),this.renderer?.updateContext(this.stateManager.getExpressionContext())},onDataError:(t,e)=>{this.emitEvent("query:error",{bindingId:t,error:e.message})}}),t.dataBindings&&this.dataBindingManager.registerBindings(t.dataBindings),this.stateManager.onStateChange(({key:t})=>{this.dataBindingManager.onStateChange(t,this.stateManager.getExpressionContext())})}initLifecycleManager(t){this.lifecycleManager=new X({actionBridge:this.actionBridge,getContext:()=>this.stateManager.getExpressionContext(),debug:this.options.debug,logger:this.logger,onLifecycleEvent:(t,e)=>{this.emitEvent(`page:lifecycle:${t}`,e??{})}}),this.lifecycleManager.register(t.lifecycle)}initRenderer(){const t=new Map;this.stateManager.getState().components.forEach((e,n)=>{if("loaded"===e.status&&e.component){const[s,i]=n.split("@");t.set(s,{name:s,version:i,Component:e.component,loadTime:e.loadTime||0})}}),this.renderer=new I({expressionEngine:this.expressionEngine,components:t,injectHostApi:(t,e)=>{t.hostApi=this.hostApi,t.componentId=e},onComponentEvent:(t,e,n,s)=>{this.handleComponentEvent(t,e,n,s)},debug:this.options.debug,logger:this.logger,onRenderError:(t,e)=>(this.log("error",`Render error in ${t}:`,e),this.emitEvent("component:error",{componentId:t,error:e.message}),N("error",e.message))}),this.renderer.init()}handleComponentEvent(t,e,n,s){this.log("debug",`Component event: ${t}.${e}`,s);for(const t of n)this.actionBridge.handleEvent(t,s,this.stateManager.getExpressionContext())}handleError(t){const n=t instanceof e?{type:"LOAD_ERROR",message:t.message,code:t.code,details:t.details,traceId:t.traceId,timestamp:t.timestamp}:{type:"UNKNOWN_ERROR",message:t.message,cause:t,timestamp:Date.now()};this.stateManager.setError(n),this.telemetryManager?.recordError(t),this.emitEvent("page:error",{error:t.message}),this.options.onError&&this.options.onError(n)}emitEvent(t,e){const n=m.createEvent(t,e,this.telemetryManager?.getTraceId());this.eventBus.emit(n),this.options.onEvent&&this.options.onEvent(n)}createLogger(){return{debug:(...t)=>{this.options.debug},info:(...t)=>{},warn:(...t)=>{},error:(...t)=>{}}}log(t,e,...n){this.logger[t](e,...n)}};Object.defineProperty(exports,"ErrorCode",{enumerable:!0,get:function(){return t.ErrorCode}}),Object.defineProperty(exports,"ErrorMessages",{enumerable:!0,get:function(){return t.ErrorMessages}}),exports.ActionBridge=y,exports.ActionError=a,exports.AssetLoader=u,exports.BaseRenderer=I,exports.ComponentBlockedError=r,exports.ComponentLoadError=s,exports.ComponentLoader=d,exports.DjvlcRuntime=nt,exports.DjvlcRuntimeError=e,exports.Evaluator=x,exports.EventBus=m,exports.ExpressionEngine=k,exports.ExpressionError=o,exports.HostAPIImpl=S,exports.IntegrityError=i,exports.Lexer=b,exports.LifecycleManager=X,exports.MockUserApiAdapter=class{constructor(t={}){this.calls={resolvePage:[],executeAction:[],executeQuery:[],track:[]},this.options={delay:0,...t}}async resolvePage(t){if(this.calls.resolvePage.push(t),await this.delay(),this.options.resolvePageThrow)throw this.options.resolvePageThrow;return(this.options.resolvePageResponse??this.options.mockPage)||{pageId:t.pageId,resolvedVersionId:"pv_mock",cdnBase:"https://cdn.mock.com",snapshotUrl:"https://cdn.mock.com/snapshot.json",manifestUrl:"https://cdn.mock.com/manifest.json",ops:{killSwitch:[],blockedComponents:[],flags:{}},etag:"mock-etag",cacheTtlSeconds:300}}async executeAction(t){return this.calls.executeAction.push(t),await this.delay(),this.options.mockActionResult?this.options.mockActionResult():{success:!0,data:{result:"mock"}}}async executeQuery(t){return this.calls.executeQuery.push(t),await this.delay(),this.options.mockQueryResult?this.options.mockQueryResult():{success:!0,data:{}}}track(t){this.calls.track.push(t)}delay(){const t=this.options.delay??0;return t<=0?Promise.resolve():new Promise(e=>setTimeout(e,t))}resetCalls(){this.calls={resolvePage:[],executeAction:[],executeQuery:[],track:[]}}},exports.PageLoadError=n,exports.PageLoader=h,exports.Parser=$,exports.QueryError=c,exports.RUNTIME_VERSION="1.0.0",exports.RenderError=class extends e{constructor(e,n,s,i){super(t.ErrorCode.SYSTEM_INTERNAL_ERROR,s,{...i,componentId:e,componentType:n}),this.name="RenderError",this.componentId=e,this.componentType=n}},exports.SCHEMA_VERSION=tt,exports.SUPPORTED_SCHEMA_VERSION=tt,exports.SecurityManager=C,exports.StateManager=p,exports.TelemetryManager=E,exports.builtinFunctions=w,exports.createFallbackElement=N,exports.createRuntime=function(t){return new nt(t)},exports.registerBuiltinComponents=Z,exports.registerFallbackComponents=A;
|