lingxia-web-runtime 0.1.2
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/boot.d.ts +10 -0
- package/dist/bridge.d.ts +5 -0
- package/dist/error.d.ts +4 -0
- package/dist/image-proxy.d.ts +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/nativecomponents/coverage-monitor.d.ts +7 -0
- package/dist/runtime-env.d.ts +9 -0
- package/dist/runtime.es2020.js +1 -0
- package/dist/runtime.es5.js +1 -0
- package/dist/types.d.ts +118 -0
- package/dist/ui/action-sheet.d.ts +5 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/modal.d.ts +6 -0
- package/dist/ui/toast.d.ts +2 -0
- package/package.json +42 -0
package/dist/boot.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Immediately initialize bridge and render error UI if present.
|
|
3
|
+
* Use this when DOM is already ready.
|
|
4
|
+
*/
|
|
5
|
+
export declare function boot(): void;
|
|
6
|
+
/**
|
|
7
|
+
* Initialize bridge immediately, but wait for DOM to render error UI.
|
|
8
|
+
* Use this at page load time.
|
|
9
|
+
*/
|
|
10
|
+
export declare function bootWhenReady(): void;
|
package/dist/bridge.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { LingXiaBridgeInterface } from './types';
|
|
2
|
+
export declare function registerViewMethodHandler(method: string, handler: (params: unknown) => unknown | Promise<unknown>): void;
|
|
3
|
+
export declare const LingXiaBridge: LingXiaBridgeInterface;
|
|
4
|
+
export declare const host: Record<string, (...args: unknown[]) => Promise<unknown>>;
|
|
5
|
+
export declare function initBridge(): void;
|
package/dist/error.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function setupImageProxy(): void;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LingXia Web Runtime
|
|
3
|
+
*
|
|
4
|
+
* Injected into SPA HTML to handle:
|
|
5
|
+
* - Bridge initialization for native communication
|
|
6
|
+
* - Error UI rendering when page cannot be loaded
|
|
7
|
+
*/
|
|
8
|
+
export type { BridgeConfig, ErrorInfo, LingXiaBridgeInterface, DataSubscriber, NativeComponentMessage, } from './types';
|
|
9
|
+
export { LingXiaBridge, host, initBridge } from './bridge';
|
|
10
|
+
export { renderErrorUI, hasError, getErrorInfo } from './error';
|
|
11
|
+
export { boot, bootWhenReady } from './boot';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BridgeConfig } from './types';
|
|
2
|
+
export type CommunicationMethod = 'messageport' | 'jsinterface' | 'webkit' | 'unknown';
|
|
3
|
+
export type PlatformOS = NonNullable<BridgeConfig['os']> | 'unknown';
|
|
4
|
+
export declare const BRIDGE_CONFIG: BridgeConfig;
|
|
5
|
+
export declare function getPlatformOS(): PlatformOS;
|
|
6
|
+
export declare function isHarmony(): boolean;
|
|
7
|
+
export declare function isIOS(): boolean;
|
|
8
|
+
export declare function isAndroid(): boolean;
|
|
9
|
+
export declare function getCommunicationMethod(): CommunicationMethod;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var LingXiaRuntime=function(e){"use strict";const t="BRIDGE_TIMEOUT",n="BRIDGE_CANCELED",o="BRIDGE_HANDSHAKE_FAILED",r="BRIDGE_MALFORMED_MESSAGE",i="BRIDGE_METHOD_NOT_FOUND",s="BRIDGE_CAPABILITY_DENIED",a="BRIDGE_INTERNAL_ERROR",l="BRIDGE_OUTBOX_FULL";function c({os:e,send:t}){if("undefined"==typeof window)return;if("undefined"==typeof document)return;const n="iOS"===e;if(!n&&!("Android"===e))return;const o=Symbol.for("LingXia.NativeComponentCoverageMonitor"),r=window[o];if(r?.installed)return;const i={installed:!0,coveredById:new Map,coveredCount:0,anyCovered:!1,scheduled:!1,hasAnyVideo:!1,scrollLocked:!1,scrollY:0,htmlOverflow:"",bodyOverflow:"",bodyPosition:"",bodyTop:"",bodyWidth:""};function s(e){const t=e.getBoundingClientRect?.();if(!t)return!1;if(t.width<2||t.height<2)return!1;const n=t.left+t.width/2,o=t.top+t.height/2;if(n<0||o<0||n>=window.innerWidth||o>=window.innerHeight)return!1;const r=document.elementFromPoint?.(n,o);return!!r&&(r!==document.documentElement&&r!==document.body&&!(r===e||e.contains(r)))}function a(){i.scheduled=!1;const e=document.querySelectorAll("lx-video[id]");if(i.hasAnyVideo=e.length>0,!i.hasAnyVideo&&0===i.coveredById.size&&!i.anyCovered)return;const o=new Set;for(const n of Array.from(e)){const e=n.id;if(!e)continue;o.add(e);const r=s(n),a=i.coveredById.get(e);a!==r&&(!0===a&&(i.coveredCount-=1),!0===r&&(i.coveredCount+=1),i.coveredById.set(e,r),t({id:e,action:"component.coverage",covered:r}))}const r=[];for(const[e,t]of i.coveredById.entries())o.has(e)||(r.push(e),!0===t&&(i.coveredCount-=1));for(const e of r)i.coveredById.delete(e),t({id:e,action:"component.coverage",covered:!1});const a=i.coveredCount>0;a!==i.anyCovered&&(i.anyCovered=a,n&&(a?function(){if(!n)return;if(i.scrollLocked)return;const e=document.documentElement,t=document.body;e&&t&&(i.scrollLocked=!0,i.scrollY=window.scrollY||e.scrollTop||0,i.htmlOverflow=e.style.overflow||"",i.bodyOverflow=t.style.overflow||"",i.bodyPosition=t.style.position||"",i.bodyTop=t.style.top||"",i.bodyWidth=t.style.width||"",e.style.overflow="hidden",t.style.overflow="hidden",t.style.position="fixed",t.style.top=-i.scrollY+"px",t.style.width="100%")}():function(){if(!n)return;if(!i.scrollLocked)return;const e=document.documentElement,t=document.body;e&&t&&(i.scrollLocked=!1,e.style.overflow=i.htmlOverflow,t.style.overflow=i.bodyOverflow,t.style.position=i.bodyPosition,t.style.top=i.bodyTop,t.style.width=i.bodyWidth,window.scrollTo(0,i.scrollY))}()))}function l(){i.scheduled||(i.scheduled=!0,requestAnimationFrame(a))}window[o]=i;new MutationObserver(l).observe(document.documentElement,{subtree:!0,childList:!0,attributes:!0}),window.addEventListener("scroll",function(){(i.hasAnyVideo||0!==i.coveredById.size)&&l()},{capture:!0,passive:!0}),window.addEventListener("resize",l),l()}const d="undefined"!=typeof window&&window.__LX_BRIDGE_CFG||{};function u(){return d.os||"unknown"}const m="[LX.Bridge]",p="messageport",f="jsinterface",h={data:!1,proto:!1,all:!1};function g(e){return h.all||h[e]}function x(...e){console.log(m,...e)}function v(...e){console.warn(m,...e)}function b(...e){console.error(m,...e)}function y(e,t){const n=new WeakSet;return JSON.stringify(e,(e,t)=>{if("object"==typeof t&&null!==t){if(n.has(t))return"[Circular]";n.add(t)}return t},t)}function w(e){try{return"function"==typeof structuredClone?structuredClone(e):JSON.parse(JSON.stringify(e))}catch{return{}}}const k="iOS"===d.os||"macOS"===d.os?"webkit":"Harmony"===d.os?"messageport":"Android"===d.os?window.LingXiaProxy?.supportsMessagePort?.()?"messageport":"jsinterface":"unknown";let E=null;const C={listenerInstalled:!1,promise:null,resolve:null,reject:null,timer:null};function L(){C.listenerInstalled||(C.listenerInstalled=!0,window.addEventListener("message",e=>{if("LingXia-port-init"!==e.data)return;const t=e.ports?.[0];t&&(de._connectWebMessagePort(t),C.resolve?.(t))}))}function I(){null!==C.timer&&(window.clearTimeout(C.timer),C.timer=null),C.resolve=null,C.reject=null,C.promise=null}function M(e){const t=e.kind;"req"!==t&&"notify"!==t||x(`postToNative: ${t} ${e.method}`),g("proto")&&console.log("→",JSON.stringify(e,null,2));try{if("webkit"===k)return void window.webkit?.messageHandlers.LingXia?.postMessage(e);const t=y(e);if(k===p&&E)return void E.postMessage(t);if(k===f&&window.LingXiaProxy?.postMessage)return void window.LingXiaProxy.postMessage(t);v("Transport not ready")}catch(e){b("Send error:",e)}}let N=null,S=!1,T=!1,O=0,P=null,_=0;const B=new Map,A=[];let F=-1,R={};const j=new Set,H=new WeakMap,X=new Map;function $(e,t){X.set(e,t)}function D(e){if(e.startsWith("host."))return"host";const t=e.indexOf(".");return t>0?e.slice(0,t):"page"}function z(e){if(null!=e)return"object"!=typeof e||Array.isArray(e)?{value:e}:e}function W(){return k===p?!!E:"webkit"===k||k===f}function q(){return W()&&S}function G(e,t){const n=B.get(e);n&&(B.delete(e),null!==n.timerId&&clearTimeout(n.timerId),n.reject(t))}function U(e){const n=B.get(e);n&&null===n.timerId&&(n.timerId=setTimeout(()=>{B.has(e)&&(B.delete(e),n.reject({code:t,message:`'${n.method}' timed out`}))},n.timeoutMs))}function Y(e){for(let t=A.length-1;t>=0;t--)if(A[t]?.reqId===e)return A.splice(t,1),!0;return!1}function J(e,t){const n=e.kind,o="hello"===n||"helloAck"===n||"ready"===n;if(!q()&&!o)return A.length>=256?(b("Outbox full"),void(t&&G(t,{code:l}))):void A.push({msg:e,reqId:t});t&&U(t),M(e)}function V(){null!==P&&(clearTimeout(P),P=null)}function K(){if(S)return;if(!W())return;V();const e={v:2,kind:"hello",nonce:d.nonce||"",role:"view",protocolsSupported:[2]};T=!0,M(e),P=setTimeout(()=>{if(!S)if(O++,O<3)v(`Handshake timeout (${O}/3), retrying...`),T=!1,K();else for(b("Handshake failed"),V(),T=!1,O=0;A.length;){const e=A.shift();e?.reqId&&G(e.reqId,{code:o})}},1e4)}function Q(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function Z(e,t,n=!1){const o=function(e){if(""===e)return[];if(!e.startsWith("/"))throw new Error(`Invalid JSON pointer: ${e}`);return e.split("/").slice(1).map(Q)}(t);if(0===o.length)return{container:{$root:e},key:"$root"};let r=e;for(let e=0;e<o.length-1;e++){const t=o[e];if(Array.isArray(r))r=r[Number(t)];else{if(!r||"object"!=typeof r)throw new Error(`Invalid container at ${t}`);{const i=r;if(n&&void 0===i[t]){const n=o[e+1];i[t]=n&&/^\d+$/.test(n)?[]:{}}r=i[t]}}}return{container:r,key:o[o.length-1]}}function ee(e){j.forEach(t=>{try{if(!H.has(t))return H.set(t,!0),void t(w(R),{rev:F,initial:!0});t(w(R),{rev:F,initial:e})}catch(e){v("Subscriber error:",e)}})}function te(e){de.call("state.getSnapshot",{scope:e},{cap:"state",timeoutMs:1e4}).catch(()=>{})}function ne(e){if(e&&"object"==typeof e){const t=e;if("event"===t.type&&"nativecomponent"===t.name&&t.payload){const e=t.payload,n=e.id||e.componentId;if("string"==typeof n){const t=oe.get(n);if(t)try{t(e)}catch(e){b("NC handler error:",e)}}return}}const t=function(e){if(!e||"object"!=typeof e)return null;const t=e.v,n=e.kind;return 2!==t||"string"!=typeof n?null:e}(e);if(t)switch(t.kind){case"helloAck":return void(N=t.sessionId);case"ready":return N&&t.sessionId!==N?void v("sessionId mismatch"):(V(),S=!0,O=0,g("proto")&&x("Handshake complete"),void function(){if(q())for(;A.length;){const e=A.shift();e&&(e.reqId&&U(e.reqId),M(e.msg))}}());case"res":{const e=B.get(t.id);if(!e)return;return B.delete(t.id),null!==e.timerId&&clearTimeout(e.timerId),void(t.ok?("state.getSnapshot"===e.method&&(function(e){if(!e||"object"!=typeof e)return!1;const t=e;return!("number"!=typeof t.rev||!Number.isFinite(t.rev)||!t.state||"object"!=typeof t.state||(R=t.state,F=t.rev,g("data")&&(console.group("[LX] snapshot(res)"),console.log("rev:",F,"state:",w(R)),console.groupEnd()),ee(!0),0))}(t.result)||v("Invalid state.getSnapshot result")),e.resolve(t.result)):e.reject(t.error||{code:a}))}case"state.snapshot":return R=t.state||{},F=t.rev,g("data")&&(console.group("[LX] snapshot"),console.log("rev:",F,"state:",w(R)),console.groupEnd()),void ee(!0);case"state.patch":if(t.baseRev!==F)return v("baseRev mismatch",{have:F,want:t.baseRev}),void te(t.scope);try{!function(e,t){for(const n of t){const t="add"===n.op||"replace"===n.op,{container:o,key:r}=Z(e,n.path,t);if("$root"===r){for(const t of Object.keys(e))delete e[t];if("remove"!==n.op){const t=n.value;t&&"object"==typeof t&&Object.assign(e,t)}continue}if(Array.isArray(o)){const e="-"===r?o.length:Number(r);if(!Number.isFinite(e)||e<0)throw new Error("Invalid index");"remove"===n.op?o.splice(e,1):"add"===n.op?o.splice(e,0,n.value):"replace"===n.op&&(o[e]=n.value);continue}if(!o||"object"!=typeof o)throw new Error("Invalid container");const i=o;"remove"===n.op?delete i[r]:i[r]=n.value}}(R,t.ops||[]),F=t.rev}catch(e){return b("Patch failed:",e),void te(t.scope)}return g("data")&&(console.group("[LX] patch"),console.log("rev:",F,"ops:",t.ops),console.groupEnd()),ee(!1),void(t.ack&&J({v:2,kind:"state.ack",scope:t.scope,rev:t.rev}));case"req":{const e=t,n=D(e.method);if(!e.cap||e.cap!==n)return void J({v:2,kind:"res",id:e.id,ok:!1,error:{code:s,message:`Invalid cap for ${e.method}`}});const o=X.get(e.method);return o?void Promise.resolve().then(()=>o(e.params)).then(t=>{J({v:2,kind:"res",id:e.id,ok:!0,result:t})}).catch(t=>{const n=t&&"object"==typeof t?t:{};J({v:2,kind:"res",id:e.id,ok:!1,error:{code:n.code||a,message:n.message||String(t)}})}):void J({v:2,kind:"res",id:e.id,ok:!1,error:{code:i,message:`View handler not found: ${e.method}`}})}}else v("Invalid V2 message:",e)}const oe=new Map,re=[];let ie=!1;function se(){return"undefined"!=typeof window&&!(!window.webkit?.messageHandlers?.NativeComponent&&!window.NativeComponentBridge?.postMessage)}function ae(e){try{if(window.webkit?.messageHandlers?.NativeComponent)return void window.webkit.messageHandlers.NativeComponent.postMessage(e);if(window.NativeComponentBridge?.postMessage)return void window.NativeComponentBridge.postMessage(y(e))}catch(e){b("NativeComponent send error:",e)}}function le(){if(se()&&0!==re.length)for(ie=!0;re.length;){const e=re.shift();try{ae(e)}catch{break}}}function ce(e){try{if(!se())return void re.push(e);ie||le(),ae(e)}catch(e){b("NC send failed:",e)}}const de={call:(e,t,o)=>new Promise((i,s)=>{if(!e||"string"!=typeof e)return void s({code:r});T||K();const a=`c_${Date.now()}_${_++}`,l=o?.cap||D(e),c=o?.timeoutMs??5e3;B.set(a,{method:e,resolve:i,reject:e=>s(e),timeoutMs:c,timerId:null});J({v:2,kind:"req",id:a,method:e,params:z(t),cap:l},a);const d=o?.signal;if(d){if(d.aborted)return Y(a),G(a,{code:n}),void(S&&J({v:2,kind:"cancel",id:a}));const e=()=>{d.removeEventListener("abort",e);const t=Y(a);G(a,{code:n}),!t&&S&&J({v:2,kind:"cancel",id:a})};d.addEventListener("abort",e)}}),notify(e,t,n){e&&"string"==typeof e&&(T||K(),J({v:2,kind:"notify",method:e,params:z(t),cap:n?.cap||D(e)}))},subscribe(e){if("function"!=typeof e)return()=>{};if(j.add(e),F>=0){H.set(e,!0);try{e(w(R),{rev:F,initial:!0})}catch(e){b("Callback error:",e)}}return()=>{j.delete(e),H.delete(e)}},_connectWebMessagePort(e){if(k===p){if(E&&E!==e)try{E.onmessage=null,E.close()}catch{}E=e,e.onmessage=e=>{let t=e.data;if("string"==typeof t)try{t=JSON.parse(t)}catch{return}ne(t)};try{e.start()}catch{}x("Port connected"),K()}},_receiveEvaluateMessage(e){try{e&&ne(JSON.parse(e))}catch(e){b("Parse error:",e)}},debug:new Proxy(h,{get:(e,t)=>e[t],set:(e,t,n)=>t in e&&(e[t]=!!n,console.log(`[LX] ${t}: ${n}`),!0)}),platform:{isHarmony:function(){return"Harmony"===d.os},isIOS:function(){return"iOS"===d.os},isAndroid:function(){return"Android"===d.os},getOS:u},dom:{measureById(e){try{if(!e)return null;const t=document.getElementById(e);if(!t)return null;const n=t.getBoundingClientRect();let o=0;try{o=parseFloat(getComputedStyle(t).borderRadius)||0}catch{}return[n.left+window.scrollX,n.top+window.scrollY,n.width,n.height,o]}catch{return null}}},nativeComponents:{send:ce,hasHandler:se,flush:le,register:(e,t)=>e&&"function"==typeof t?(oe.set(e,t),()=>oe.delete(e)):()=>{},unregister(e){oe.delete(e)}},isReady:()=>S},ue=new Proxy({},{get:(e,t)=>(...e)=>{const n=0===e.length?void 0:1===e.length?e[0]:e;return de.call(`host.${t}`,n,{cap:"host"})}});function me(){x(`Method: ${k}`),window.__LingXiaRecvMessage=de._receiveEvaluateMessage,k===p?(L(),function(){if(E)return Promise.resolve(E);if(C.promise)return C.promise;L(),C.promise=new Promise((e,t)=>{C.resolve=t=>{I(),e(t)},C.reject=e=>{I(),t(e)},C.timer=window.setTimeout(()=>{C.reject?.(new Error("MessagePort init timed out after 5000ms"))},5e3)});try{window.LingXiaProxy?.getPort("LingXiaPort")}catch(e){C.reject?.(e)}return C.promise}().catch(e=>v("Port init failed:",e))):"webkit"===k||k===f?K():v("Unknown method"),window.LingXiaBridge=de,window.host=ue,c({os:u(),send:ce}),x("Init complete")}function pe(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function fe(e){const{failedPath:t,reason:n}=e,o=document.createElement("style");o.textContent="\n* { margin: 0; padding: 0; box-sizing: border-box; }\nbody {\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n background: #f5f5f7;\n color: #1d1d1f;\n padding: 20px;\n -webkit-font-smoothing: antialiased;\n}\n.lx-error {\n text-align: center;\n max-width: 400px;\n}\n.lx-error-code {\n font-size: 120px;\n font-weight: 700;\n color: #d1d1d6;\n line-height: 1;\n letter-spacing: -4px;\n}\n.lx-error-title {\n font-size: 21px;\n font-weight: 600;\n margin: 16px 0 8px;\n color: #1d1d1f;\n}\n.lx-error-desc {\n font-size: 15px;\n color: #86868b;\n line-height: 1.5;\n}\n.lx-error-path {\n display: inline-block;\n margin-top: 20px;\n padding: 10px 16px;\n background: rgba(0,0,0,0.04);\n border-radius: 8px;\n font-family: 'SF Mono', ui-monospace, Menlo, Monaco, monospace;\n font-size: 13px;\n color: #1d1d1f;\n word-break: break-all;\n max-width: 100%;\n}\n@media (prefers-color-scheme: dark) {\n body { background: #000; color: #f5f5f7; }\n .lx-error-code { color: #3a3a3c; }\n .lx-error-title { color: #f5f5f7; }\n .lx-error-desc { color: #86868b; }\n .lx-error-path { background: rgba(255,255,255,0.08); color: #f5f5f7; }\n}\n",document.head.appendChild(o),document.body.innerHTML="",document.body.style.cssText="";const r=document.createElement("div");r.className="lx-error";let i='<div class="lx-error-code">404</div>';i+='<h1 class="lx-error-title">Page Not Found</h1>',i+="<p class=\"lx-error-desc\">The page you're looking for doesn't exist.</p>",t&&(i+=`<div class="lx-error-path">${pe(t)}</div>`),n&&(i+=`<p class="lx-error-desc" style="margin-top:12px">${pe(n)}</p>`),r.innerHTML=i,document.body.appendChild(r)}function he(){const e=window.__LX_RUNTIME_CONFIG;return!(!e||!e.error)}function ge(){const e=window.__LX_RUNTIME_CONFIG;return e?.error||null}function xe(){if(he()){const e=ge();e&&fe(e)}}function ve(){me(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",xe):xe()}function be(e){const t=e.trim();return function(e){return 0!==e.length&&!(e.startsWith("lx://")||e.startsWith("data:")||e.startsWith("blob:")||e.startsWith("file:"))&&(e.startsWith("http://")||e.startsWith("https://"))}(t)?function(e){return`lx://proxy/${btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}`}(t):e}const ye="lx-action-sheet-style";let we=null;function ke(e){const t=e,n=t?.itemList??[],o=t?.cancelText??"Cancel",r=t?.itemColor??"#007AFF",i=(we??Promise.resolve()).then(()=>Ee(n,o,r),()=>Ee(n,o,r));return we=i,i}function Ee(e,t,n){return new Promise(o=>{let r=!1;const i="macOS"===u();!function(){if(document.getElementById(ye))return;const e=document.createElement("style");e.id=ye,e.textContent="\n.lx-as-backdrop {\n position: fixed; inset: 0; z-index: 99999;\n background: rgba(0,0,0,0.4);\n opacity: 0; transition: opacity 300ms ease;\n}\n.lx-as-backdrop.lx-as-visible { opacity: 1; }\n\n.lx-as-sheet {\n position: fixed; left: 0; right: 0; bottom: 0; z-index: 100000;\n transform: translateY(100%);\n transition: transform 300ms ease;\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;\n -webkit-font-smoothing: antialiased;\n}\n.lx-as-sheet.lx-as-visible { transform: translateY(0); }\n.lx-as-sheet.lx-as-desktop {\n left: 50%;\n right: auto;\n bottom: auto;\n top: 50%;\n width: min(92vw, 460px);\n transform: translate(-50%, calc(-50% + 16px));\n}\n.lx-as-sheet.lx-as-desktop.lx-as-visible { transform: translate(-50%, -50%); }\n\n.lx-as-container {\n background: #fff;\n border-radius: 16px 16px 0 0;\n overflow: hidden;\n}\n.lx-as-container.lx-as-desktop {\n border-radius: 16px;\n}\n\n.lx-as-item {\n display: block; width: 100%;\n height: 56px;\n line-height: 56px;\n padding: 0;\n border: none; background: none;\n font-size: 18px; font-weight: 400;\n text-align: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n position: relative;\n}\n.lx-as-item:active { background: rgba(0,0,0,0.08); }\n.lx-as-item + .lx-as-item::before {\n content: ''; position: absolute; top: 0; left: 0; right: 0;\n height: 1px; background: #E0E0E0;\n}\n.lx-as-separator {\n height: 8px;\n background: #F2F2F2;\n}\n.lx-as-cancel-btn { font-weight: 500; color: #000; }\n",document.head.appendChild(e)}();const s=document.createElement("div");s.className="lx-as-backdrop";const a=document.createElement("div");a.className="lx-as-sheet",i&&a.classList.add("lx-as-desktop");const l=document.createElement("div");l.className="lx-as-container",i&&l.classList.add("lx-as-desktop"),e.forEach((e,t)=>{const o=document.createElement("button");o.className="lx-as-item",o.textContent=e,o.style.color=n,o.addEventListener("click",()=>m(t)),l.appendChild(o)});const c=document.createElement("div");c.className="lx-as-separator",l.appendChild(c);const d=document.createElement("button");function m(e){r||(r=!0,s.classList.remove("lx-as-visible"),a.classList.remove("lx-as-visible"),setTimeout(()=>{s.remove(),a.remove(),o({tapIndex:e})},300))}d.className="lx-as-item lx-as-cancel-btn",d.textContent=t,d.addEventListener("click",()=>m(-1)),l.appendChild(d),a.appendChild(l),document.body.appendChild(s),document.body.appendChild(a),requestAnimationFrame(()=>{s.classList.add("lx-as-visible"),a.classList.add("lx-as-visible")}),s.addEventListener("click",()=>m(-1))})}const Ce=200,Le="lx-modal-style";let Ie=null;function Me(e){const t=e,n=t?.title??"",o=t?.content??"",r=t?.showCancel??!0,i=t?.cancelText??"Cancel",s=t?.cancelColor,a=t?.confirmText??"OK",l=t?.confirmColor??"#007AFF",c=(Ie??Promise.resolve()).then(()=>Ne(n,o,r,i,s,a,l),()=>Ne(n,o,r,i,s,a,l));return Ie=c,c}function Ne(e,t,n,o,r,i,s){return new Promise(a=>{let l=!1;!function(){if(document.getElementById(Le))return;const e=document.createElement("style");e.id=Le,e.textContent="\n.lx-modal-backdrop {\n position: fixed; inset: 0; z-index: 99999;\n background: rgba(0,0,0,0.4);\n opacity: 0; transition: opacity 200ms ease;\n display: flex; align-items: center; justify-content: center;\n}\n.lx-modal-backdrop.lx-modal-visible { opacity: 1; }\n\n.lx-modal-dialog {\n width: min(92vw, 320px);\n background: #fff;\n border-radius: 14px;\n overflow: hidden;\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;\n -webkit-font-smoothing: antialiased;\n transform: scale(0.95); opacity: 0;\n transition: transform 200ms ease, opacity 200ms ease;\n}\n.lx-modal-backdrop.lx-modal-visible .lx-modal-dialog {\n transform: scale(1); opacity: 1;\n}\n\n.lx-modal-body {\n padding: 24px 20px 16px;\n text-align: center;\n}\n.lx-modal-title {\n margin: 0 0 8px;\n font-size: 17px;\n font-weight: 600;\n color: #000;\n line-height: 1.35;\n}\n.lx-modal-content {\n margin: 0;\n font-size: 14px;\n color: #666;\n line-height: 1.5;\n word-break: break-word;\n}\n.lx-modal-body:has(.lx-modal-title:empty) .lx-modal-content {\n font-size: 17px;\n font-weight: 600;\n color: #000;\n}\n\n.lx-modal-footer {\n display: flex;\n border-top: 1px solid #E0E0E0;\n}\n.lx-modal-btn {\n flex: 1;\n height: 44px;\n line-height: 44px;\n padding: 0;\n border: none;\n background: none;\n font-size: 17px;\n text-align: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n}\n.lx-modal-btn:active { background: rgba(0,0,0,0.06); }\n.lx-modal-btn + .lx-modal-btn {\n border-left: 1px solid #E0E0E0;\n}\n.lx-modal-btn-cancel {\n color: #666;\n font-weight: 400;\n}\n.lx-modal-btn-confirm {\n font-weight: 600;\n}\n\n@media (prefers-color-scheme: dark) {\n .lx-modal-dialog { background: #2c2c2e; }\n .lx-modal-title { color: #f5f5f7; }\n .lx-modal-content { color: #ababab; }\n .lx-modal-body:has(.lx-modal-title:empty) .lx-modal-content {\n color: #f5f5f7;\n }\n .lx-modal-footer { border-top-color: #3a3a3c; }\n .lx-modal-btn:active { background: rgba(255,255,255,0.08); }\n .lx-modal-btn + .lx-modal-btn { border-left-color: #3a3a3c; }\n .lx-modal-btn-cancel { color: #ababab; }\n}\n",document.head.appendChild(e)}();const c=document.createElement("div");c.className="lx-modal-backdrop";const d=document.createElement("div");d.className="lx-modal-dialog";const u=document.createElement("div");u.className="lx-modal-body";const m=document.createElement("div");if(m.className="lx-modal-title",m.textContent=e,u.appendChild(m),t){const e=document.createElement("p");e.className="lx-modal-content",e.textContent=t,u.appendChild(e)}d.appendChild(u);const p=document.createElement("div");if(p.className="lx-modal-footer",n){const e=document.createElement("button");e.className="lx-modal-btn lx-modal-btn-cancel",e.textContent=o,r&&(e.style.color=r),e.addEventListener("click",()=>h(!1)),p.appendChild(e)}const f=document.createElement("button");function h(e){l||(l=!0,c.classList.remove("lx-modal-visible"),setTimeout(()=>{c.remove(),a({confirm:e,cancel:!e})},Ce))}f.className="lx-modal-btn lx-modal-btn-confirm",f.textContent=i,f.style.color=s,f.addEventListener("click",()=>h(!0)),p.appendChild(f),d.appendChild(p),c.appendChild(d),document.body.appendChild(c),requestAnimationFrame(()=>{c.classList.add("lx-modal-visible")})})}const Se="lx-toast-style";let Te=null;function Oe(e){const t=e,n=t?.title??"",o=t?.icon??"none",r=t?.duration??1500,i=t?.mask??!1,s=t?.position??"center";Te&&(Te.dismiss(),Te=null),function(){if(document.getElementById(Se))return;const e=document.createElement("style");e.id=Se,e.textContent="\n.lx-toast-mask {\n position: fixed; inset: 0; z-index: 99998;\n}\n.lx-toast-container {\n position: fixed; left: 0; right: 0; z-index: 99999;\n display: flex; justify-content: center;\n pointer-events: none;\n}\n.lx-toast-container.lx-toast-top { top: 0; padding-top: 80px; }\n.lx-toast-container.lx-toast-center { top: 0; bottom: 0; align-items: center; }\n.lx-toast-container.lx-toast-bottom { bottom: 0; padding-bottom: 80px; }\n\n.lx-toast-box {\n display: flex; flex-direction: column; align-items: center; gap: 10px;\n min-width: 120px; max-width: 280px;\n padding: 20px;\n background: rgba(0,0,0,0.8);\n border-radius: 12px;\n color: #fff;\n pointer-events: auto;\n transform: scale(0.8); opacity: 0;\n transition: transform 200ms ease, opacity 200ms ease;\n}\n.lx-toast-box.lx-toast-no-icon {\n min-width: auto; min-height: auto;\n padding: 12px 20px;\n}\n.lx-toast-box.lx-toast-visible {\n transform: scale(1); opacity: 1;\n}\n.lx-toast-icon {\n width: 36px; height: 36px;\n color: #fff;\n line-height: 0;\n}\n.lx-toast-title {\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;\n font-size: 16px; font-weight: 500;\n text-align: center;\n line-height: 1.4;\n word-break: break-word;\n -webkit-font-smoothing: antialiased;\n}\n",document.head.appendChild(e)}();let a=null;i&&(a=document.createElement("div"),a.className="lx-toast-mask",document.body.appendChild(a));const l=document.createElement("div");l.className="lx-toast-container","top"===s?l.classList.add("lx-toast-top"):"bottom"===s?l.classList.add("lx-toast-bottom"):l.classList.add("lx-toast-center");const c=document.createElement("div");c.className="lx-toast-box";const d="none"!==o;if(d||c.classList.add("lx-toast-no-icon"),d){const e=document.createElement("div");e.className="lx-toast-icon","success"===o?e.innerHTML='<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="18" cy="18" r="17" stroke="currentColor" stroke-width="2"/><path d="M11 18l5 5 9-9" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>':"error"===o?e.innerHTML='<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="18" cy="18" r="17" stroke="currentColor" stroke-width="2"/><path d="M13 13l10 10M23 13l-10 10" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>':"loading"===o&&(e.innerHTML='<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 4a14 14 0 0 1 14 14" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.8s" repeatCount="indefinite"/></path></svg>'),c.appendChild(e)}const u=document.createElement("div");u.className="lx-toast-title",u.textContent=n,c.appendChild(u),l.appendChild(c),document.body.appendChild(l),requestAnimationFrame(()=>{c.classList.add("lx-toast-visible")});let m=!1;function p(){m||(m=!0,Te?.dismiss===p&&(Te=null),c.classList.remove("lx-toast-visible"),f&&clearTimeout(f),setTimeout(()=>{l.remove(),a?.remove()},200))}let f=null;return r>0&&(f=setTimeout(p,r)),Te={dismiss:p,timer:f},Promise.resolve()}function Pe(){return Te&&(Te.dismiss(),Te=null),Promise.resolve()}return $("ui.showActionSheet",ke),$("ui.showModal",Me),$("ui.showToast",Oe),$("ui.hideToast",Pe),function(){const e=u();if("iOS"!==e&&"macOS"!==e)return;if("undefined"==typeof window||"undefined"==typeof document)return;if("undefined"==typeof HTMLImageElement)return;const t=HTMLImageElement.prototype;if(t.__lxProxyPatched)return;t.__lxProxyPatched=!0;const n=t.setAttribute;t.setAttribute=function(e,t){return"string"==typeof e&&"src"===e.toLowerCase()&&"string"==typeof t?n.call(this,e,be(t)):n.call(this,e,t)};const o=Object.getOwnPropertyDescriptor(t,"src");o?.set&&Object.defineProperty(t,"src",{configurable:o.configurable,enumerable:o.enumerable,get:o.get,set(e){"string"==typeof e?o.set?.call(this,be(e)):o.set?.call(this,e)}});const r=()=>{document.querySelectorAll("img[src]").forEach(e=>{const t=e.getAttribute("src");if(!t)return;const o=be(t);o!==t&&n.call(e,"src",o)})};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",r):r()}(),ve(),e.LingXiaBridge=de,e.boot=function(){me(),xe()},e.bootWhenReady=ve,e.getErrorInfo=ge,e.hasError=he,e.host=ue,e.initBridge=me,e.renderErrorUI=fe,e}({});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var LingXiaRuntime=function(e){"use strict";function n(e){var n="function"==typeof Symbol&&Symbol.iterator,t=n&&e[n],o=0;if(t)return t.call(e);if(e&&"number"==typeof e.length)return{next:function(){return e&&o>=e.length&&(e=void 0),{value:e&&e[o++],done:!e}}};throw new TypeError(n?"Object is not iterable.":"Symbol.iterator is not defined.")}function t(e,n){var t="function"==typeof Symbol&&e[Symbol.iterator];if(!t)return e;var o,r,i=t.call(e),a=[];try{for(;(void 0===n||n-- >0)&&!(o=i.next()).done;)a.push(o.value)}catch(e){r={error:e}}finally{try{o&&!o.done&&(t=i.return)&&t.call(i)}finally{if(r)throw r.error}}return a}function o(e,n,t){if(t||2===arguments.length)for(var o,r=0,i=n.length;r<i;r++)!o&&r in n||(o||(o=Array.prototype.slice.call(n,0,r)),o[r]=n[r]);return e.concat(o||Array.prototype.slice.call(n))}"function"==typeof SuppressedError&&SuppressedError;var r="BRIDGE_TIMEOUT",i="BRIDGE_CANCELED",a="BRIDGE_HANDSHAKE_FAILED",l="BRIDGE_MALFORMED_MESSAGE",c="BRIDGE_METHOD_NOT_FOUND",d="BRIDGE_CAPABILITY_DENIED",s="BRIDGE_INTERNAL_ERROR",u="BRIDGE_OUTBOX_FULL";function f(e){var o=e.os,r=e.send;if("undefined"!=typeof window&&"undefined"!=typeof document){var i="iOS"===o;if(i||"Android"===o){var a=Symbol.for("LingXia.NativeComponentCoverageMonitor"),l=window[a];if(!(null==l?void 0:l.installed)){var c={installed:!0,coveredById:new Map,coveredCount:0,anyCovered:!1,scheduled:!1,hasAnyVideo:!1,scrollLocked:!1,scrollY:0,htmlOverflow:"",bodyOverflow:"",bodyPosition:"",bodyTop:"",bodyWidth:""};window[a]=c,new MutationObserver(u).observe(document.documentElement,{subtree:!0,childList:!0,attributes:!0}),window.addEventListener("scroll",function(){(c.hasAnyVideo||0!==c.coveredById.size)&&u()},{capture:!0,passive:!0}),window.addEventListener("resize",u),u()}}}function d(e){var n,t,o,r=null===(t=(n=e).getBoundingClientRect)||void 0===t?void 0:t.call(n);if(!r)return!1;if(r.width<2||r.height<2)return!1;var i=r.left+r.width/2,a=r.top+r.height/2;if(i<0||a<0||i>=window.innerWidth||a>=window.innerHeight)return!1;var l=null===(o=document.elementFromPoint)||void 0===o?void 0:o.call(document,i,a);return!!l&&(l!==document.documentElement&&l!==document.body&&!(l===e||e.contains(l)))}function s(){var e,o,a,l,s,u;c.scheduled=!1;var f=document.querySelectorAll("lx-video[id]");if(c.hasAnyVideo=f.length>0,c.hasAnyVideo||0!==c.coveredById.size||c.anyCovered){var v=new Set;try{for(var p=n(Array.from(f)),y=p.next();!y.done;y=p.next()){var h=y.value;if(k=h.id){v.add(k);var m=d(h),g=c.coveredById.get(k);g!==m&&(!0===g&&(c.coveredCount-=1),!0===m&&(c.coveredCount+=1),c.coveredById.set(k,m),r({id:k,action:"component.coverage",covered:m}))}}}catch(n){e={error:n}}finally{try{y&&!y.done&&(o=p.return)&&o.call(p)}finally{if(e)throw e.error}}var w=[];try{for(var b=n(c.coveredById.entries()),x=b.next();!x.done;x=b.next()){var I=t(x.value,2),k=I[0];m=I[1];v.has(k)||(w.push(k),!0===m&&(c.coveredCount-=1))}}catch(e){a={error:e}}finally{try{x&&!x.done&&(l=b.return)&&l.call(b)}finally{if(a)throw a.error}}try{for(var E=n(w),L=E.next();!L.done;L=E.next()){k=L.value;c.coveredById.delete(k),r({id:k,action:"component.coverage",covered:!1})}}catch(e){s={error:e}}finally{try{L&&!L.done&&(u=E.return)&&u.call(E)}finally{if(s)throw s.error}}var M=c.coveredCount>0;M!==c.anyCovered&&(c.anyCovered=M,i&&(M?function(){if(i&&!c.scrollLocked){var e=document.documentElement,n=document.body;e&&n&&(c.scrollLocked=!0,c.scrollY=window.scrollY||e.scrollTop||0,c.htmlOverflow=e.style.overflow||"",c.bodyOverflow=n.style.overflow||"",c.bodyPosition=n.style.position||"",c.bodyTop=n.style.top||"",c.bodyWidth=n.style.width||"",e.style.overflow="hidden",n.style.overflow="hidden",n.style.position="fixed",n.style.top="".concat(-c.scrollY,"px"),n.style.width="100%")}}():function(){if(i&&c.scrollLocked){var e=document.documentElement,n=document.body;e&&n&&(c.scrollLocked=!1,e.style.overflow=c.htmlOverflow,n.style.overflow=c.bodyOverflow,n.style.position=c.bodyPosition,n.style.top=c.bodyTop,n.style.width=c.bodyWidth,window.scrollTo(0,c.scrollY))}}()))}}function u(){c.scheduled||(c.scheduled=!0,requestAnimationFrame(s))}}var v="undefined"!=typeof window&&window.__LX_BRIDGE_CFG||{};function p(){return v.os||"unknown"}var y="[LX.Bridge]",h="messageport",m="jsinterface",g={data:!1,proto:!1,all:!1};function w(e){return g.all||g[e]}function b(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];console.log.apply(console,o([y],t(e),!1))}function x(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];console.warn.apply(console,o([y],t(e),!1))}function I(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];console.error.apply(console,o([y],t(e),!1))}function k(e,n){var t=new WeakSet;return JSON.stringify(e,function(e,n){if("object"==typeof n&&null!==n){if(t.has(n))return"[Circular]";t.add(n)}return n},n)}function E(e){try{return"function"==typeof structuredClone?structuredClone(e):JSON.parse(JSON.stringify(e))}catch(e){return{}}}var L,M,S="iOS"===v.os||"macOS"===v.os?"webkit":"Harmony"===v.os?"messageport":"Android"===v.os?(null===(M=null===(L=window.LingXiaProxy)||void 0===L?void 0:L.supportsMessagePort)||void 0===M?void 0:M.call(L))?"messageport":"jsinterface":"unknown",O=null,C={listenerInstalled:!1,promise:null,resolve:null,reject:null,timer:null};function _(){C.listenerInstalled||(C.listenerInstalled=!0,window.addEventListener("message",function(e){var n,t;if("LingXia-port-init"===e.data){var o=null===(n=e.ports)||void 0===n?void 0:n[0];o&&(pe._connectWebMessagePort(o),null===(t=C.resolve)||void 0===t||t.call(C,o))}}))}function N(){null!==C.timer&&(window.clearTimeout(C.timer),C.timer=null),C.resolve=null,C.reject=null,C.promise=null}function A(e){var n,t,o,r=e.kind;"req"!==r&&"notify"!==r||b("postToNative: ".concat(r," ").concat(e.method)),w("proto")&&console.log("→",JSON.stringify(e,null,2));try{if("webkit"===S)return void(null===(t=null===(n=window.webkit)||void 0===n?void 0:n.messageHandlers.LingXia)||void 0===t||t.postMessage(e));var i=k(e);if(S===h&&O)return void O.postMessage(i);if(S===m&&(null===(o=window.LingXiaProxy)||void 0===o?void 0:o.postMessage))return void window.LingXiaProxy.postMessage(i);x("Transport not ready")}catch(e){I("Send error:",e)}}var P=null,T=!1,B=!1,j=0,R=null,X=0,D=new Map,H=[],W=-1,F={},G=new Set,q=new WeakMap,U=new Map;function z(e){if(e.startsWith("host."))return"host";var n=e.indexOf(".");return n>0?e.slice(0,n):"page"}function J(e){if(null!=e)return"object"!=typeof e||Array.isArray(e)?{value:e}:e}function Y(){return S===h?!!O:"webkit"===S||S===m}function V(){return Y()&&T}function $(e,n){var t=D.get(e);t&&(D.delete(e),null!==t.timerId&&clearTimeout(t.timerId),t.reject(n))}function K(e){var n=D.get(e);n&&null===n.timerId&&(n.timerId=setTimeout(function(){D.has(e)&&(D.delete(e),n.reject({code:r,message:"'".concat(n.method,"' timed out")}))},n.timeoutMs))}function Q(e){for(var n,t=H.length-1;t>=0;t--)if((null===(n=H[t])||void 0===n?void 0:n.reqId)===e)return H.splice(t,1),!0;return!1}function Z(e,n){var t=e.kind,o="hello"===t||"helloAck"===t||"ready"===t;if(!V()&&!o)return H.length>=256?(I("Outbox full"),void(n&&$(n,{code:u}))):void H.push({msg:e,reqId:n});n&&K(n),A(e)}function ee(){null!==R&&(clearTimeout(R),R=null)}function ne(){if(!T&&Y()){ee();var e={v:2,kind:"hello",nonce:v.nonce||"",role:"view",protocolsSupported:[2]};B=!0,A(e),R=setTimeout(function(){if(!T)if(++j<3)x("Handshake timeout (".concat(j,"/").concat(3,"), retrying...")),B=!1,ne();else for(I("Handshake failed"),ee(),B=!1,j=0;H.length;){var e=H.shift();(null==e?void 0:e.reqId)&&$(e.reqId,{code:a})}},1e4)}}function te(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function oe(e,n,t){void 0===t&&(t=!1);var o=function(e){if(""===e)return[];if(!e.startsWith("/"))throw new Error("Invalid JSON pointer: ".concat(e));return e.split("/").slice(1).map(te)}(n);if(0===o.length)return{container:{$root:e},key:"$root"};for(var r=e,i=0;i<o.length-1;i++){var a=o[i];if(Array.isArray(r))r=r[Number(a)];else{if(!r||"object"!=typeof r)throw new Error("Invalid container at ".concat(a));var l=r;if(t&&void 0===l[a]){var c=o[i+1];l[a]=c&&/^\d+$/.test(c)?[]:{}}r=l[a]}}return{container:r,key:o[o.length-1]}}function re(e){G.forEach(function(n){try{if(!q.has(n))return q.set(n,!0),void n(E(F),{rev:W,initial:!0});n(E(F),{rev:W,initial:e})}catch(e){x("Subscriber error:",e)}})}function ie(e){pe.call("state.getSnapshot",{scope:e},{cap:"state",timeoutMs:1e4}).catch(function(){})}function ae(e){if(e&&"object"==typeof e){var t=e;if("event"===t.type&&"nativecomponent"===t.name&&t.payload){var o=t.payload,r=o.id||o.componentId;if("string"==typeof r){var i=le.get(r);if(i)try{i(o)}catch(e){I("NC handler error:",e)}}return}}var a=function(e){if(!e||"object"!=typeof e)return null;var n=e.v,t=e.kind;return 2!==n||"string"!=typeof t?null:e}(e);if(a)switch(a.kind){case"helloAck":return void(P=a.sessionId);case"ready":return P&&a.sessionId!==P?void x("sessionId mismatch"):(ee(),T=!0,j=0,w("proto")&&b("Handshake complete"),void function(){if(V())for(;H.length;){var e=H.shift();e&&(e.reqId&&K(e.reqId),A(e.msg))}}());case"res":var l=D.get(a.id);if(!l)return;return D.delete(a.id),null!==l.timerId&&clearTimeout(l.timerId),void(a.ok?("state.getSnapshot"===l.method&&(function(e){if(!e||"object"!=typeof e)return!1;var n=e;return!("number"!=typeof n.rev||!Number.isFinite(n.rev)||!n.state||"object"!=typeof n.state||(F=n.state,W=n.rev,w("data")&&(console.group("[LX] snapshot(res)"),console.log("rev:",W,"state:",E(F)),console.groupEnd()),re(!0),0))}(a.result)||x("Invalid state.getSnapshot result")),l.resolve(a.result)):l.reject(a.error||{code:s}));case"state.snapshot":return F=a.state||{},W=a.rev,w("data")&&(console.group("[LX] snapshot"),console.log("rev:",W,"state:",E(F)),console.groupEnd()),void re(!0);case"state.patch":if(a.baseRev!==W)return x("baseRev mismatch",{have:W,want:a.baseRev}),void ie(a.scope);try{!function(e,t){var o,r,i,a;try{for(var l=n(t),c=l.next();!c.done;c=l.next()){var d=c.value,s="add"===d.op||"replace"===d.op,u=oe(e,d.path,s),f=u.container,v=u.key;if("$root"!==v)if(Array.isArray(f)){var p="-"===v?f.length:Number(v);if(!Number.isFinite(p)||p<0)throw new Error("Invalid index");"remove"===d.op?f.splice(p,1):"add"===d.op?f.splice(p,0,d.value):"replace"===d.op&&(f[p]=d.value)}else{if(!f||"object"!=typeof f)throw new Error("Invalid container");var y=f;"remove"===d.op?delete y[v]:y[v]=d.value}else{try{for(var h=(i=void 0,n(Object.keys(e))),m=h.next();!m.done;m=h.next())delete e[m.value]}catch(e){i={error:e}}finally{try{m&&!m.done&&(a=h.return)&&a.call(h)}finally{if(i)throw i.error}}if("remove"!==d.op){var g=d.value;g&&"object"==typeof g&&Object.assign(e,g)}}}}catch(e){o={error:e}}finally{try{c&&!c.done&&(r=l.return)&&r.call(l)}finally{if(o)throw o.error}}}(F,a.ops||[]),W=a.rev}catch(e){return I("Patch failed:",e),void ie(a.scope)}return w("data")&&(console.group("[LX] patch"),console.log("rev:",W,"ops:",a.ops),console.groupEnd()),re(!1),void(a.ack&&Z({v:2,kind:"state.ack",scope:a.scope,rev:a.rev}));case"req":var u=a,f=z(u.method);if(!u.cap||u.cap!==f)return void Z({v:2,kind:"res",id:u.id,ok:!1,error:{code:d,message:"Invalid cap for ".concat(u.method)}});var v=U.get(u.method);return v?void Promise.resolve().then(function(){return v(u.params)}).then(function(e){Z({v:2,kind:"res",id:u.id,ok:!0,result:e})}).catch(function(e){var n=e&&"object"==typeof e?e:{};Z({v:2,kind:"res",id:u.id,ok:!1,error:{code:n.code||s,message:n.message||String(e)}})}):void Z({v:2,kind:"res",id:u.id,ok:!1,error:{code:c,message:"View handler not found: ".concat(u.method)}})}else x("Invalid V2 message:",e)}var le=new Map,ce=[],de=!1;function se(){var e,n,t;return"undefined"!=typeof window&&!(!(null===(n=null===(e=window.webkit)||void 0===e?void 0:e.messageHandlers)||void 0===n?void 0:n.NativeComponent)&&!(null===(t=window.NativeComponentBridge)||void 0===t?void 0:t.postMessage))}function ue(e){var n,t,o;try{if(null===(t=null===(n=window.webkit)||void 0===n?void 0:n.messageHandlers)||void 0===t?void 0:t.NativeComponent)return void window.webkit.messageHandlers.NativeComponent.postMessage(e);if(null===(o=window.NativeComponentBridge)||void 0===o?void 0:o.postMessage)return void window.NativeComponentBridge.postMessage(k(e))}catch(e){I("NativeComponent send error:",e)}}function fe(){if(se()&&0!==ce.length)for(de=!0;ce.length;){var e=ce.shift();try{ue(e)}catch(e){break}}}function ve(e){try{if(!se())return void ce.push(e);de||fe(),ue(e)}catch(e){I("NC send failed:",e)}}var pe={call:function(e,n,t){return new Promise(function(o,r){var a;if(e&&"string"==typeof e){B||ne();var c="c_".concat(Date.now(),"_").concat(X++),d=(null==t?void 0:t.cap)||z(e),s=null!==(a=null==t?void 0:t.timeoutMs)&&void 0!==a?a:5e3;D.set(c,{method:e,resolve:o,reject:function(e){return r(e)},timeoutMs:s,timerId:null}),Z({v:2,kind:"req",id:c,method:e,params:J(n),cap:d},c);var u=null==t?void 0:t.signal;if(u){if(u.aborted)return Q(c),$(c,{code:i}),void(T&&Z({v:2,kind:"cancel",id:c}));var f=function(){u.removeEventListener("abort",f);var e=Q(c);$(c,{code:i}),!e&&T&&Z({v:2,kind:"cancel",id:c})};u.addEventListener("abort",f)}}else r({code:l})})},notify:function(e,n,t){e&&"string"==typeof e&&(B||ne(),Z({v:2,kind:"notify",method:e,params:J(n),cap:(null==t?void 0:t.cap)||z(e)}))},subscribe:function(e){if("function"!=typeof e)return function(){};if(G.add(e),W>=0){q.set(e,!0);try{e(E(F),{rev:W,initial:!0})}catch(e){I("Callback error:",e)}}return function(){G.delete(e),q.delete(e)}},_connectWebMessagePort:function(e){if(S===h){if(O&&O!==e)try{O.onmessage=null,O.close()}catch(e){}O=e,e.onmessage=function(e){var n=e.data;if("string"==typeof n)try{n=JSON.parse(n)}catch(e){return}ae(n)};try{e.start()}catch(e){}b("Port connected"),ne()}},_receiveEvaluateMessage:function(e){try{e&&ae(JSON.parse(e))}catch(e){I("Parse error:",e)}},debug:new Proxy(g,{get:function(e,n){return e[n]},set:function(e,n,t){return n in e&&(e[n]=!!t,console.log("[LX] ".concat(n,": ").concat(t)),!0)}}),platform:{isHarmony:function(){return"Harmony"===v.os},isIOS:function(){return"iOS"===v.os},isAndroid:function(){return"Android"===v.os},getOS:p},dom:{measureById:function(e){try{if(!e)return null;var n=document.getElementById(e);if(!n)return null;var t=n.getBoundingClientRect(),o=0;try{o=parseFloat(getComputedStyle(n).borderRadius)||0}catch(e){}return[t.left+window.scrollX,t.top+window.scrollY,t.width,t.height,o]}catch(e){return null}}},nativeComponents:{send:ve,hasHandler:se,flush:fe,register:function(e,n){return e&&"function"==typeof n?(le.set(e,n),function(){return le.delete(e)}):function(){}},unregister:function(e){le.delete(e)}},isReady:function(){return T}},ye=new Proxy({},{get:function(e,n){return function(){for(var e=[],t=0;t<arguments.length;t++)e[t]=arguments[t];var o=0===e.length?void 0:1===e.length?e[0]:e;return pe.call("host.".concat(n),o,{cap:"host"})}}});function he(){b("Method: ".concat(S)),window.__LingXiaRecvMessage=pe._receiveEvaluateMessage,S===h?(_(),function(){var e,n;if(O)return Promise.resolve(O);if(C.promise)return C.promise;_(),C.promise=new Promise(function(e,n){C.resolve=function(n){N(),e(n)},C.reject=function(e){N(),n(e)},C.timer=window.setTimeout(function(){var e;null===(e=C.reject)||void 0===e||e.call(C,new Error("MessagePort init timed out after ".concat(5e3,"ms")))},5e3)});try{null===(e=window.LingXiaProxy)||void 0===e||e.getPort("LingXiaPort")}catch(e){null===(n=C.reject)||void 0===n||n.call(C,e)}return C.promise}().catch(function(e){return x("Port init failed:",e)})):"webkit"===S||S===m?ne():x("Unknown method"),window.LingXiaBridge=pe,window.host=ye,f({os:p(),send:ve}),b("Init complete")}function me(e){var n=document.createElement("div");return n.textContent=e,n.innerHTML}function ge(e){var n=e.failedPath,t=e.reason,o=document.createElement("style");o.textContent="\n* { margin: 0; padding: 0; box-sizing: border-box; }\nbody {\n font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Segoe UI', Roboto, sans-serif;\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n background: #f5f5f7;\n color: #1d1d1f;\n padding: 20px;\n -webkit-font-smoothing: antialiased;\n}\n.lx-error {\n text-align: center;\n max-width: 400px;\n}\n.lx-error-code {\n font-size: 120px;\n font-weight: 700;\n color: #d1d1d6;\n line-height: 1;\n letter-spacing: -4px;\n}\n.lx-error-title {\n font-size: 21px;\n font-weight: 600;\n margin: 16px 0 8px;\n color: #1d1d1f;\n}\n.lx-error-desc {\n font-size: 15px;\n color: #86868b;\n line-height: 1.5;\n}\n.lx-error-path {\n display: inline-block;\n margin-top: 20px;\n padding: 10px 16px;\n background: rgba(0,0,0,0.04);\n border-radius: 8px;\n font-family: 'SF Mono', ui-monospace, Menlo, Monaco, monospace;\n font-size: 13px;\n color: #1d1d1f;\n word-break: break-all;\n max-width: 100%;\n}\n@media (prefers-color-scheme: dark) {\n body { background: #000; color: #f5f5f7; }\n .lx-error-code { color: #3a3a3c; }\n .lx-error-title { color: #f5f5f7; }\n .lx-error-desc { color: #86868b; }\n .lx-error-path { background: rgba(255,255,255,0.08); color: #f5f5f7; }\n}\n",document.head.appendChild(o),document.body.innerHTML="",document.body.style.cssText="";var r=document.createElement("div");r.className="lx-error";var i='<div class="lx-error-code">404</div>';i+='<h1 class="lx-error-title">Page Not Found</h1>',i+="<p class=\"lx-error-desc\">The page you're looking for doesn't exist.</p>",n&&(i+='<div class="lx-error-path">'.concat(me(n),"</div>")),t&&(i+='<p class="lx-error-desc" style="margin-top:12px">'.concat(me(t),"</p>")),r.innerHTML=i,document.body.appendChild(r)}function we(){var e=window.__LX_RUNTIME_CONFIG;return!(!e||!e.error)}function be(){var e=window.__LX_RUNTIME_CONFIG;return(null==e?void 0:e.error)||null}function xe(){if(we()){var e=be();e&&ge(e)}}function Ie(){he(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",xe):xe()}function ke(e){var n=e.trim();return function(e){return 0!==e.length&&!(e.startsWith("lx://")||e.startsWith("data:")||e.startsWith("blob:")||e.startsWith("file:"))&&(e.startsWith("http://")||e.startsWith("https://"))}(n)?function(e){var n=btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"");return"".concat("lx://proxy/").concat(n)}(n):e}return function(){var e=p();if(("iOS"===e||"macOS"===e)&&"undefined"!=typeof window&&"undefined"!=typeof document&&"undefined"!=typeof HTMLImageElement){var n=HTMLImageElement.prototype;if(!n.__lxProxyPatched){n.__lxProxyPatched=!0;var t=n.setAttribute;n.setAttribute=function(e,n){return"string"==typeof e&&"src"===e.toLowerCase()&&"string"==typeof n?t.call(this,e,ke(n)):t.call(this,e,n)};var o=Object.getOwnPropertyDescriptor(n,"src");(null==o?void 0:o.set)&&Object.defineProperty(n,"src",{configurable:o.configurable,enumerable:o.enumerable,get:o.get,set:function(e){var n,t;"string"==typeof e?null===(n=o.set)||void 0===n||n.call(this,ke(e)):null===(t=o.set)||void 0===t||t.call(this,e)}});var r=function(){document.querySelectorAll("img[src]").forEach(function(e){var n=e.getAttribute("src");if(n){var o=ke(n);o!==n&&t.call(e,"src",o)}})};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",r):r()}}}(),Ie(),e.LingXiaBridge=pe,e.boot=function(){he(),xe()},e.bootWhenReady=Ie,e.getErrorInfo=be,e.hasError=we,e.host=ye,e.initBridge=he,e.renderErrorUI=ge,e}({});
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export interface BridgeConfig {
|
|
2
|
+
os?: 'Harmony' | 'iOS' | 'Android' | 'macOS';
|
|
3
|
+
nonce?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface RuntimeConfig {
|
|
6
|
+
error?: ErrorInfo;
|
|
7
|
+
}
|
|
8
|
+
export interface ErrorInfo {
|
|
9
|
+
failedPath?: string;
|
|
10
|
+
reason?: string;
|
|
11
|
+
code?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare const BRIDGE_ERROR: {
|
|
14
|
+
readonly NOT_READY: "BRIDGE_NOT_READY";
|
|
15
|
+
readonly TIMEOUT: "BRIDGE_TIMEOUT";
|
|
16
|
+
readonly CANCELED: "BRIDGE_CANCELED";
|
|
17
|
+
readonly PROTOCOL_MISMATCH: "BRIDGE_PROTOCOL_MISMATCH";
|
|
18
|
+
readonly HANDSHAKE_FAILED: "BRIDGE_HANDSHAKE_FAILED";
|
|
19
|
+
readonly MALFORMED_MESSAGE: "BRIDGE_MALFORMED_MESSAGE";
|
|
20
|
+
readonly METHOD_NOT_FOUND: "BRIDGE_METHOD_NOT_FOUND";
|
|
21
|
+
readonly CAPABILITY_DENIED: "BRIDGE_CAPABILITY_DENIED";
|
|
22
|
+
readonly INTERNAL_ERROR: "BRIDGE_INTERNAL_ERROR";
|
|
23
|
+
readonly OUTBOX_FULL: "BRIDGE_OUTBOX_FULL";
|
|
24
|
+
};
|
|
25
|
+
export type BridgeErrorCode = (typeof BRIDGE_ERROR)[keyof typeof BRIDGE_ERROR];
|
|
26
|
+
export interface LxBridgeError {
|
|
27
|
+
code: string;
|
|
28
|
+
message?: string;
|
|
29
|
+
data?: unknown;
|
|
30
|
+
retryable?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface StateInfo {
|
|
33
|
+
rev: number;
|
|
34
|
+
initial: boolean;
|
|
35
|
+
}
|
|
36
|
+
export type DataSubscriber = (data: Record<string, unknown>, info: StateInfo) => void;
|
|
37
|
+
export interface LingXiaBridgeMethodMap {
|
|
38
|
+
}
|
|
39
|
+
export type LxMethodParams<M extends keyof LingXiaBridgeMethodMap> = LingXiaBridgeMethodMap[M] extends {
|
|
40
|
+
params: infer P;
|
|
41
|
+
} ? P : LingXiaBridgeMethodMap[M] extends {
|
|
42
|
+
params?: infer P;
|
|
43
|
+
} ? P | undefined : unknown;
|
|
44
|
+
export type LxMethodResult<M extends keyof LingXiaBridgeMethodMap> = LingXiaBridgeMethodMap[M] extends {
|
|
45
|
+
result: infer R;
|
|
46
|
+
} ? R : unknown;
|
|
47
|
+
export type LxMethod = keyof LingXiaBridgeMethodMap & string;
|
|
48
|
+
export interface NativeComponentMessage {
|
|
49
|
+
id: string;
|
|
50
|
+
action?: string;
|
|
51
|
+
[key: string]: unknown;
|
|
52
|
+
}
|
|
53
|
+
export interface CallOptions {
|
|
54
|
+
cap?: string;
|
|
55
|
+
timeoutMs?: number;
|
|
56
|
+
signal?: AbortSignal;
|
|
57
|
+
}
|
|
58
|
+
export interface NotifyOptions {
|
|
59
|
+
cap?: string;
|
|
60
|
+
}
|
|
61
|
+
declare global {
|
|
62
|
+
function useLingXia<TData = Record<string, unknown>, TActions = Record<string, (...args: unknown[]) => unknown>>(): {
|
|
63
|
+
data: TData;
|
|
64
|
+
} & TActions;
|
|
65
|
+
interface Window {
|
|
66
|
+
__LX_BRIDGE_CFG?: BridgeConfig;
|
|
67
|
+
__LX_RUNTIME_CONFIG?: RuntimeConfig;
|
|
68
|
+
__LingXiaRecvMessage?: (message: string) => void;
|
|
69
|
+
LingXiaBridge?: LingXiaBridgeInterface;
|
|
70
|
+
useLingXia?: typeof useLingXia;
|
|
71
|
+
LingXiaProxy?: {
|
|
72
|
+
supportsMessagePort: () => boolean;
|
|
73
|
+
getPort: (name: string) => string;
|
|
74
|
+
postMessage: (message: string) => void;
|
|
75
|
+
};
|
|
76
|
+
NativeComponentBridge?: {
|
|
77
|
+
postMessage: (message: string) => void;
|
|
78
|
+
};
|
|
79
|
+
host?: Record<string, (...args: unknown[]) => Promise<unknown>>;
|
|
80
|
+
webkit?: {
|
|
81
|
+
messageHandlers: {
|
|
82
|
+
[key: string]: {
|
|
83
|
+
postMessage: (message: unknown) => void;
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export interface LingXiaBridgeInterface {
|
|
90
|
+
call(method: string, params?: unknown, options?: CallOptions): Promise<unknown>;
|
|
91
|
+
call<M extends LxMethod>(method: M, params?: LxMethodParams<M>, options?: CallOptions): Promise<LxMethodResult<M>>;
|
|
92
|
+
notify(method: string, params?: unknown, options?: NotifyOptions): void;
|
|
93
|
+
subscribe(callback: DataSubscriber): () => void;
|
|
94
|
+
_connectWebMessagePort(port: MessagePort): void;
|
|
95
|
+
_receiveEvaluateMessage(messageString: string): void;
|
|
96
|
+
debug: {
|
|
97
|
+
data: boolean;
|
|
98
|
+
proto: boolean;
|
|
99
|
+
all: boolean;
|
|
100
|
+
};
|
|
101
|
+
platform: {
|
|
102
|
+
isHarmony(): boolean;
|
|
103
|
+
isIOS(): boolean;
|
|
104
|
+
isAndroid(): boolean;
|
|
105
|
+
getOS(): string;
|
|
106
|
+
};
|
|
107
|
+
dom: {
|
|
108
|
+
measureById(id: string): [number, number, number, number, number] | null;
|
|
109
|
+
};
|
|
110
|
+
nativeComponents: {
|
|
111
|
+
send(message: NativeComponentMessage): void;
|
|
112
|
+
hasHandler(): boolean;
|
|
113
|
+
flush(): void;
|
|
114
|
+
register(id: string, handler: (message: NativeComponentMessage) => void): () => void;
|
|
115
|
+
unregister(id: string): void;
|
|
116
|
+
};
|
|
117
|
+
isReady(): boolean;
|
|
118
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerUIHandlers(): void;
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lingxia-web-runtime",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "LingXia Web Runtime - Bridge, boot, and error handling for WebView",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/runtime.es2020.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/runtime.es2020.js"
|
|
13
|
+
},
|
|
14
|
+
"./dist/runtime.es2020.js": "./dist/runtime.es2020.js",
|
|
15
|
+
"./dist/runtime.es5.js": "./dist/runtime.es5.js",
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "npm run clean && npm run build:es2020 && npm run build:es5 && npm run types",
|
|
20
|
+
"build:es2020": "RUNTIME_OUTPUT=runtime.es2020.js rollup -c",
|
|
21
|
+
"build:es5": "TARGET=es5 LX_RUNTIME_PLATFORM=mobile RUNTIME_OUTPUT=runtime.es5.js rollup -c",
|
|
22
|
+
"types": "tsc -p tsconfig.json --emitDeclarationOnly",
|
|
23
|
+
"dev": "rollup -c -w",
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
29
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
30
|
+
"rollup": "^4.54.0",
|
|
31
|
+
"tslib": "^2.6.2",
|
|
32
|
+
"typescript": "^5.3.0"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"registry": "https://registry.npmjs.org",
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"license": "MIT"
|
|
42
|
+
}
|