dolphin-client 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dolphin-client.js +37 -6
- package/dist/dolphin-client.min.js +14 -14
- package/dist/index.cjs +37 -6
- package/dist/index.js +37 -6
- package/package.json +1 -1
package/dist/dolphin-client.js
CHANGED
|
@@ -107,7 +107,7 @@ var DolphinModule = (() => {
|
|
|
107
107
|
*/
|
|
108
108
|
async requestDirect(method, path, body = null, options = {}) {
|
|
109
109
|
const _isRetry = options._isRetry === true;
|
|
110
|
-
const url = `${this.client.httpUrl}${path.startsWith("/") ? path : "/" + path}`;
|
|
110
|
+
const url = path.startsWith("http://") || path.startsWith("https://") ? path : `${this.client.httpUrl}${path.startsWith("/") ? path : "/" + path}`;
|
|
111
111
|
if (this.client.options.debug) {
|
|
112
112
|
console.log(`%c\u{1F680} [Dolphin API Request]:`, "color: #3b82f6; font-weight: bold;", method.toUpperCase(), path, body || "");
|
|
113
113
|
}
|
|
@@ -894,8 +894,28 @@ var DolphinModule = (() => {
|
|
|
894
894
|
}
|
|
895
895
|
}
|
|
896
896
|
`;
|
|
897
|
+
let safeContext = context;
|
|
898
|
+
if (typeof Proxy !== "undefined" && context !== null && typeof context === "object") {
|
|
899
|
+
safeContext = new Proxy(context, {
|
|
900
|
+
has(target, key) {
|
|
901
|
+
if (typeof key === "symbol") return false;
|
|
902
|
+
return true;
|
|
903
|
+
},
|
|
904
|
+
get(target, key) {
|
|
905
|
+
if (key === Symbol.unscopables) return void 0;
|
|
906
|
+
if (key in target) return target[key];
|
|
907
|
+
if (typeof globalThis !== "undefined" && key in globalThis) {
|
|
908
|
+
return globalThis[key];
|
|
909
|
+
}
|
|
910
|
+
if (typeof window !== "undefined" && key in window) {
|
|
911
|
+
return window[key];
|
|
912
|
+
}
|
|
913
|
+
return void 0;
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
}
|
|
897
917
|
const fn = new Function("context", fnBody);
|
|
898
|
-
return fn(
|
|
918
|
+
return fn(safeContext);
|
|
899
919
|
} catch (e) {
|
|
900
920
|
console.error("[Dolphin Template Compiler Error]:", e);
|
|
901
921
|
let fallback = templateStr;
|
|
@@ -1047,6 +1067,9 @@ var DolphinModule = (() => {
|
|
|
1047
1067
|
});
|
|
1048
1068
|
}
|
|
1049
1069
|
this.publish(`store/${storeName}`, store);
|
|
1070
|
+
if (typeof this._updateDOM === "function") {
|
|
1071
|
+
this._updateDOM(`store/${storeName}`, store);
|
|
1072
|
+
}
|
|
1050
1073
|
};
|
|
1051
1074
|
clientProto.getStoreState = function(storeName, key) {
|
|
1052
1075
|
this.uiStores = this.uiStores || /* @__PURE__ */ new Map();
|
|
@@ -1344,10 +1367,17 @@ var DolphinModule = (() => {
|
|
|
1344
1367
|
if (!path) continue;
|
|
1345
1368
|
try {
|
|
1346
1369
|
const result = await this.api.get(path);
|
|
1370
|
+
const apiStore = el.getAttribute("data-api-store");
|
|
1371
|
+
if (apiStore) {
|
|
1372
|
+
const parts = apiStore.split(".");
|
|
1373
|
+
if (parts.length === 2) {
|
|
1374
|
+
this.setStoreState(parts[0], parts[1], result);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1347
1377
|
const rtBind = el.getAttribute("data-rt-bind");
|
|
1348
|
-
if (rtBind) {
|
|
1378
|
+
if (rtBind && !apiStore) {
|
|
1349
1379
|
this._updateDOM(rtBind, result);
|
|
1350
|
-
} else {
|
|
1380
|
+
} else if (!apiStore) {
|
|
1351
1381
|
const template = resolveTemplate(el);
|
|
1352
1382
|
if (template && typeof result === "object" && result !== null) {
|
|
1353
1383
|
if (Array.isArray(result)) {
|
|
@@ -1412,10 +1442,11 @@ var DolphinModule = (() => {
|
|
|
1412
1442
|
if (parts.length === 2) {
|
|
1413
1443
|
const className = parts[0].trim();
|
|
1414
1444
|
const key = parts[1].trim();
|
|
1445
|
+
const classNames = className.split(/\s+/).filter(Boolean);
|
|
1415
1446
|
if (payload[key]) {
|
|
1416
|
-
node.classList.add(
|
|
1447
|
+
classNames.forEach((c) => node.classList.add(c));
|
|
1417
1448
|
} else {
|
|
1418
|
-
node.classList.remove(
|
|
1449
|
+
classNames.forEach((c) => node.classList.remove(c));
|
|
1419
1450
|
}
|
|
1420
1451
|
}
|
|
1421
1452
|
});
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
var DolphinModule=(()=>{var $=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var J=(p,t)=>{for(var e in t)$(p,e,{get:t[e],enumerable:!0})},Q=(p,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of K(t))!V.call(p,r)&&r!==e&&$(p,r,{get:()=>t[r],enumerable:!(n=z(t,r))||n.enumerable});return p};var X=p=>Q($({},"__esModule",{value:!0}),p);var Z={};J(Z,{DolphinClient:()=>v});var x=class{client;constructor(t){return this.client=t,this._createProxy([])}_createProxy(t){let e=t.join("/"),n=i=>this.request("GET",e,null,i);n.get=(i,a)=>typeof i=="string"?this.request("GET",i,null,a):this.request("GET",e,null,i),n.post=(i,a,l)=>typeof i=="string"?this.request("POST",i,a,l):this.request("POST",e,i,a),n.put=(i,a,l)=>typeof i=="string"?this.request("PUT",i,a,l):this.request("PUT",e,i,a),n.patch=(i,a,l)=>typeof i=="string"?this.request("PATCH",i,a,l):this.request("PATCH",e,i,a),n.del=(i,a)=>typeof i=="string"?this.request("DELETE",i,null,a):this.request("DELETE",e,null,i),n.request=(i,a,l,b)=>{let T=a?`${e}/${a.startsWith("/")?a.slice(1):a}`:e;return this.request(i,T,l,b)},n.requestDirect=(i,a,l,b)=>this.requestDirect(i,a,l,b);let r=["get","post","put","patch","del","request","requestDirect"];return new Proxy(n,{get:(i,a)=>typeof a=="string"&&!r.includes(a)?this._createProxy([...t,a]):i[a]})}async request(t,e,n=null,r={}){if(this.client.offline){let i=this.client.offline.isOnline,a=`${t.toUpperCase()}:${e}`;if(t.toUpperCase()==="GET")if(i)try{let l=await this.requestDirect(t,e,n,r);return await this.client.offline.setCache(a,l),l}catch(l){let b=await this.client.offline.getCache(a);if(b!=null)return b;throw l}else{let l=await this.client.offline.getCache(a);if(l!=null)return l;throw{status:503,data:{error:"Offline, no cache available"}}}else return i?this.requestDirect(t,e,n,r):(await this.client.offline.queueMutation(t,e,n),this.client._dispatch("offline:queued",{method:t,path:e,body:n}),{success:!0,offline:!0,message:"Mutation queued offline"})}return this.requestDirect(t,e,n,r)}async requestDirect(t,e,n=null,r={}){let i=r._isRetry===!0,a=`${this.client.httpUrl}${e.startsWith("/")?e:"/"+e}`;this.client.options.debug&&console.log("%c\u{1F680} [Dolphin API Request]:","color: #3b82f6; font-weight: bold;",t.toUpperCase(),e,n||"");let l=new AbortController,b=setTimeout(()=>l.abort(),this.client.options.timeout),T={"Content-Type":"application/json",...r.headers||{}};this.client.accessToken&&(T.Authorization=`Bearer ${this.client.accessToken}`);let h={...r};delete h._isRetry;try{let o=await fetch(a,{method:t,headers:T,signal:l.signal,...n?{body:JSON.stringify(n)}:{},...h});if(clearTimeout(b),o.status===401&&!i&&this.client.options.autoRefreshToken&&await this.client.auth._silentRefresh())return this.request(t,e,n,{...r,_isRetry:!0});let s=(o.headers.get("content-type")||"").includes("application/json")?await o.json():await o.text();if(!o.ok)throw{status:o.status,data:s};if(this.client.options.debug&&console.log("%c\u2705 [Dolphin API Success]:","color: #10b981; font-weight: bold;",t.toUpperCase(),e,s),s&&typeof s=="object"&&s.accessToken&&(this.client.setToken(s.accessToken),s.user&&(this.client.auth.user=s.user)),this.client.options.autoBroadcast&&["POST","PUT","PATCH","DELETE"].includes(t.toUpperCase())){let c=e.startsWith("/")?e.substring(1):e;this.client.publish(c,{method:t.toUpperCase(),payload:n,result:s})}return s}catch(o){throw clearTimeout(b),this.client.options.debug&&console.error("%c\u274C [Dolphin API Error]:","color: #ef4444; font-weight: bold;",t.toUpperCase(),e,o),o.name==="AbortError"?{status:408,data:{error:"Request timed out"}}:o}}};var C=class{client;user;_refreshing;constructor(t){this.client=t,this.user=null,this._refreshing=!1}async login(t,e){let n=await this.client.api.post("/api/auth/login",{email:t,password:e});return n.accessToken&&(this.client.setToken(n.accessToken),this.user=n.user||null),n}async register(t){return this.client.api.post("/api/auth/register",t)}async me(){let t=await this.client.api.get("/api/auth/me");return t.success&&(this.user=t.data),t}async logout(){try{await this.client.api.post("/api/auth/logout")}catch{}this.client.setToken(null),this.user=null}async refresh(){return this._silentRefresh()}async _silentRefresh(){if(this._refreshing)return!1;this._refreshing=!0;try{let t=await this.client.api.post("/api/auth/refresh",null,{_isRetry:!0});return t.accessToken?(this.client.setToken(t.accessToken),!0):!1}catch{return this.client.setToken(null),!1}finally{this._refreshing=!1}}async verify2FA(t,e){let n={code:t,email:e||this.user?.email},r=await this.client.api.post("/api/auth/2fa/verify",n);return r.accessToken&&(this.client.setToken(r.accessToken),r.user&&(this.user=r.user)),r}async enable2FA(){return this.client.api.post("/api/auth/2fa/enable")}async disable2FA(t){return this.client.api.post("/api/auth/2fa/disable",{code:t})}async forgotPassword(t){return this.client.api.post("/api/auth/forgot-password",{email:t})}async resetPassword(t,e){return this.client.api.post("/api/auth/reset-password",{token:t,newPassword:e})}};var M=class{client;data;listeners;subscribed;constructor(t){return this.client=t,this.data=new Map,this.listeners=new Set,this.subscribed=new Set,new Proxy(this,{get:(e,n)=>{if(n in e)return e[n];if(typeof n=="string")return this._getCollection(n)}})}_getCollection(t){if(!this.data.has(t)){let e={_rawItems:[],items:[],loading:!0,error:null,success:!1,_filter:null,_sort:null,where:n=>(e._filter=n,this._applyTransform(e),e),orderBy:(n,r="asc")=>(e._sort={key:n,direction:r},this._applyTransform(e),e),reset:()=>(e._filter=null,e._sort=null,this._applyTransform(e),e)};this.data.set(t,e),this._fetchAndSync(t)}return this.data.get(t)}async _fetchAndSync(t){let e=this.data.get(t);try{let n=await this.client.api.get(`/${t.toLowerCase()}`);e._rawItems=Array.isArray(n)?n:n.data||[],e.loading=!1,e.success=!0,e.error=null,this._applyTransform(e),this.subscribed.has(t)||(this.client.subscribe(`db:sync/${t.toLowerCase()}`,r=>{this._handleRemoteUpdate(t,r)}),this.subscribed.add(t))}catch(n){e.loading=!1,e.success=!1,e.error=n.data?.error||n.message||"Fetch failed",this._notify()}}_applyTransform(t){let e=[...t._rawItems];if(t._filter&&(e=e.filter(t._filter)),t._sort){let{key:n,direction:r}=t._sort;e.sort((i,a)=>i[n]===a[n]?0:(i[n]>a[n]?1:-1)*(r==="asc"?1:-1))}t.items=e,this._notify()}_handleRemoteUpdate(t,e){let n=this.data.get(t);if(!n)return;let{type:r,data:i}=e,a=n._rawItems;r==="create"?a=[...a,i]:r==="update"?a=a.map(l=>l.id===i.id||l._id===i._id?{...l,...i}:l):r==="delete"&&(a=a.filter(l=>!(i.id!=null&&l.id===i.id||i._id!=null&&l._id===i._id))),n._rawItems=a,this._applyTransform(n)}subscribe(t){return this.listeners.add(t),()=>this.listeners.delete(t)}getSnapshot(t){return this.data.get(t)||{items:[],loading:!1,error:null,success:!1}}_notify(){this.listeners.forEach(t=>t())}};var v=class{host;httpUrl;deviceId;options;socket;storage;accessToken;api;auth;store;handlers;signalHandlers;fileHandlers;_offlineQueue;reconnectAttempts;_attachedListeners;constructor(t="",e="",n={}){!t&&typeof window<"u"&&(t=window.location.host);let r="http:";t.startsWith("https://")?r="https:":t.startsWith("http://")?r="http:":typeof window<"u"&&(r=window.location.protocol),this.host=(t||"localhost").replace(/\/$/,"").replace(/^https?:\/\//,""),this.httpUrl=`${r}//${this.host}`,this.deviceId=e||"web_"+Math.random().toString(36).substr(2,8),this.options={timeout:15e3,chunkSize:65536,maxReconnect:5,autoRefreshToken:!0,debug:!1,...n},this.socket=null,this.storage=typeof localStorage<"u"?localStorage:{getItem:()=>null,setItem:()=>{},removeItem:()=>{}},this.accessToken=this.storage.getItem("dolphin_token"),this.api=new x(this),this.auth=new C(this),this.store=new M(this),this.handlers=new Map,this.signalHandlers=new Set,this.fileHandlers=new Set,this._offlineQueue=[],this.reconnectAttempts=0,this._attachedListeners=[],typeof window<"u"&&typeof this._initDOMBinding=="function"&&this._initDOMBinding(),typeof this._initOffline=="function"&&this._initOffline(),typeof this._initA11y=="function"&&this._initA11y(),typeof this._initI18n=="function"&&this._initI18n(),typeof this._initDragDrop=="function"&&this._initDragDrop(),typeof this._initCollab=="function"&&this._initCollab()}setToken(t){this.accessToken=t,t?this.storage.setItem("dolphin_token",t):this.storage.removeItem("dolphin_token")}async connect(){return new Promise((t,e)=>{let r=`${this.httpUrl.startsWith("https")?"wss:":"ws:"}//${this.host}/realtime?deviceId=${this.deviceId}`;console.log(`[Dolphin] Connecting to ${r}...`),this.socket=new WebSocket(r),this.socket.onopen=()=>{console.log(`[Dolphin] Connected as "${this.deviceId}" \u{1F42C}`),this.reconnectAttempts=0,this._flushOfflineQueue(),t()},this.socket.onmessage=i=>this._handleMessage(i.data),this.socket.onclose=()=>{console.warn("[Dolphin] Connection closed"),this._maybeReconnect()},this.socket.onerror=i=>{console.error("[Dolphin] WebSocket error:",i),e(i)}})}disconnect(){this.socket&&(this.socket.onclose=null,this.socket.close(),this.socket=null),this.cleanupDomListeners()}_handleMessage(t){try{let e=JSON.parse(t);this.options.debug&&console.log("%c\u{1F4E5} [Dolphin WS Incoming]:","color: #eab308; font-weight: bold;",e),e.type&&e.from&&(e.to===this.deviceId||e.to==="all")&&(e.msgId&&e.type!=="ACK"&&this._sendAck(e.from,e.msgId),this.signalHandlers.forEach(n=>n(e))),e.type==="FILE_AVAILABLE"&&this.fileHandlers.forEach(n=>n(e)),e.type==="FILE_CHUNK"&&(this.saveFileProgress(e.fileId,e.chunkIndex),this._dispatch("file:chunk",e),this._dispatch(`file:chunk/${e.fileId}`,e)),e.type==="FILE_UPLOAD_ACK"&&this._dispatch(`file:upload:ack/${e.fileId}`,e),e.type==="PULL_RESPONSE"&&(this._dispatch("pull:response",e.payload,e.topic),this._dispatch(`pull:response/${e.topic}`,e.payload,e.topic)),e.topic&&e.payload!==void 0&&this.handlers.forEach((n,r)=>{this._matchTopic(r,e.topic)&&n.forEach(i=>i(e.payload,e.topic))})}catch{this._dispatch("raw",t)}}_dispatch(t,e,n){let r=this.handlers.get(t);r&&r.forEach(i=>i(e,n||t))}_sendRaw(t){this.options.debug&&console.log("%c\u{1F4E4} [Dolphin WS Outgoing]:","color: #8b5cf6; font-weight: bold;",t);let e=typeof t=="string"?t:JSON.stringify(t);this.socket&&this.socket.readyState===WebSocket.OPEN?this.socket.send(e):this._offlineQueue.length<100&&this._offlineQueue.push(e)}_flushOfflineQueue(){for(;this._offlineQueue.length>0;){let t=this._offlineQueue.shift();this.socket&&this.socket.readyState===WebSocket.OPEN&&this.socket.send(t)}}_sendAck(t,e){this._sendRaw({type:"ACK",from:this.deviceId,to:t,data:{ackId:e},timestamp:Date.now()})}_matchTopic(t,e){if(t===e||t==="#")return!0;let n=t.split("/"),r=e.split("/");if(n.length!==r.length&&!t.includes("#"))return!1;for(let i=0;i<n.length;i++){if(n[i]==="#")return!0;if(n[i]!=="+"&&n[i]!==r[i])return!1}return n.length===r.length}_maybeReconnect(){if(this.reconnectAttempts<this.options.maxReconnect){this.reconnectAttempts++;let t=Math.pow(2,this.reconnectAttempts)*1e3;console.log(`[Dolphin] Reconnecting in ${t/1e3}s (attempt ${this.reconnectAttempts})...`),setTimeout(()=>this.connect().catch(()=>{}),t)}else console.error("[Dolphin] Max reconnect attempts reached.")}subscribe(t,e){this.handlers.has(t)||(this.handlers.set(t,new Set),this._sendRaw({type:"sub",topic:t})),this.handlers.get(t).add(e)}unsubscribe(t,e){if(this.handlers.has(t)){let n=this.handlers.get(t);n.delete(e),n.size===0&&(this.handlers.delete(t),this._sendRaw({type:"unsub",topic:t}))}}publish(t,e){this._sendRaw({topic:t,payload:e})}pubPush(t,e){this._sendRaw({type:"pub",topic:t,payload:e})}subPull(t,e=10){this._sendRaw({type:"PULL_REQUEST",topic:t,count:e})}async pubFile(t,e,n="",r){let i;e instanceof Blob?i=await e.arrayBuffer():e instanceof ArrayBuffer?i=e:i=e.buffer||e;let a=new Uint8Array(i),l=this.options.chunkSize,b=Math.ceil(a.length/l);this._sendRaw({type:"FILE_UPLOAD_START",fileId:t,name:n,size:a.length,totalChunks:b,chunkSize:l});for(let T=0;T<b;T++){let h=a.slice(T*l,(T+1)*l),o=this._uint8ToBase64(h);this._sendRaw({type:"FILE_UPLOAD_CHUNK",fileId:t,chunkIndex:T,totalChunks:b,data:o}),r&&r(Math.round((T+1)/b*100)),T%10===0&&await new Promise(u=>setTimeout(u,0))}this._sendRaw({type:"FILE_UPLOAD_DONE",fileId:t})}_uint8ToBase64(t){let e="";for(let n=0;n<t.length;n++)e+=String.fromCharCode(t[n]);return typeof btoa<"u"?btoa(e):Buffer.from(e,"binary").toString("base64")}subFile(t,e=0){this._sendRaw({type:"FILE_REQUEST",fileId:t,startChunk:e})}resumeFile(t){let e=parseInt(this.storage.getItem(`dolphin_file_${t}`)||"-1");this.subFile(t,e+1)}saveFileProgress(t,e){this.storage.setItem(`dolphin_file_${t}`,e.toString())}onSignal(t){this.signalHandlers.add(t)}offSignal(t){this.signalHandlers.delete(t)}onFileAvailable(t){this.fileHandlers.add(t)}offFileAvailable(t){this.fileHandlers.delete(t)}addDomListener(t,e,n){t&&(t.addEventListener(e,n),this._attachedListeners=this._attachedListeners||[],this._attachedListeners.push({target:t,event:e,cb:n}))}cleanupDomListeners(){this._attachedListeners&&(this._attachedListeners.forEach(({target:t,event:e,cb:n})=>{try{t.removeEventListener(e,n)}catch{}}),this._attachedListeners=[])}};function R(p){function t(h){return h.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function e(h){let o=h.getAttribute("data-rt-template");if(!o)return null;if(typeof document<"u"&&!o.includes("<"))try{let u=document.querySelector(o);if(u)return u.innerHTML}catch{}return o}function n(h,o){if(!h.includes("{#if")&&!h.includes("{#each")){let u=h;for(let s in o){let c=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");u=u.replace(new RegExp(`\\{\\{${c}\\}\\}`,"g"),o[s]!==void 0&&o[s]!==null?o[s]:"")}return u}try{let u=g=>g.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t"),s=`let out = "";
|
|
2
|
-
`,c=0,
|
|
3
|
-
`);let
|
|
4
|
-
`}else if(
|
|
5
|
-
`}else if(
|
|
6
|
-
`}else if(
|
|
7
|
-
`;else if(
|
|
8
|
-
`;else if(
|
|
9
|
-
`,
|
|
10
|
-
`),s+=` for (let ${
|
|
11
|
-
`}else if(
|
|
1
|
+
var DolphinModule=(()=>{var $=Object.defineProperty;var z=Object.getOwnPropertyDescriptor;var K=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var J=(p,t)=>{for(var e in t)$(p,e,{get:t[e],enumerable:!0})},Q=(p,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of K(t))!V.call(p,r)&&r!==e&&$(p,r,{get:()=>t[r],enumerable:!(n=z(t,r))||n.enumerable});return p};var X=p=>Q($({},"__esModule",{value:!0}),p);var Z={};J(Z,{DolphinClient:()=>k});var x=class{client;constructor(t){return this.client=t,this._createProxy([])}_createProxy(t){let e=t.join("/"),n=i=>this.request("GET",e,null,i);n.get=(i,o)=>typeof i=="string"?this.request("GET",i,null,o):this.request("GET",e,null,i),n.post=(i,o,l)=>typeof i=="string"?this.request("POST",i,o,l):this.request("POST",e,i,o),n.put=(i,o,l)=>typeof i=="string"?this.request("PUT",i,o,l):this.request("PUT",e,i,o),n.patch=(i,o,l)=>typeof i=="string"?this.request("PATCH",i,o,l):this.request("PATCH",e,i,o),n.del=(i,o)=>typeof i=="string"?this.request("DELETE",i,null,o):this.request("DELETE",e,null,i),n.request=(i,o,l,w)=>{let T=o?`${e}/${o.startsWith("/")?o.slice(1):o}`:e;return this.request(i,T,l,w)},n.requestDirect=(i,o,l,w)=>this.requestDirect(i,o,l,w);let r=["get","post","put","patch","del","request","requestDirect"];return new Proxy(n,{get:(i,o)=>typeof o=="string"&&!r.includes(o)?this._createProxy([...t,o]):i[o]})}async request(t,e,n=null,r={}){if(this.client.offline){let i=this.client.offline.isOnline,o=`${t.toUpperCase()}:${e}`;if(t.toUpperCase()==="GET")if(i)try{let l=await this.requestDirect(t,e,n,r);return await this.client.offline.setCache(o,l),l}catch(l){let w=await this.client.offline.getCache(o);if(w!=null)return w;throw l}else{let l=await this.client.offline.getCache(o);if(l!=null)return l;throw{status:503,data:{error:"Offline, no cache available"}}}else return i?this.requestDirect(t,e,n,r):(await this.client.offline.queueMutation(t,e,n),this.client._dispatch("offline:queued",{method:t,path:e,body:n}),{success:!0,offline:!0,message:"Mutation queued offline"})}return this.requestDirect(t,e,n,r)}async requestDirect(t,e,n=null,r={}){let i=r._isRetry===!0,o=e.startsWith("http://")||e.startsWith("https://")?e:`${this.client.httpUrl}${e.startsWith("/")?e:"/"+e}`;this.client.options.debug&&console.log("%c\u{1F680} [Dolphin API Request]:","color: #3b82f6; font-weight: bold;",t.toUpperCase(),e,n||"");let l=new AbortController,w=setTimeout(()=>l.abort(),this.client.options.timeout),T={"Content-Type":"application/json",...r.headers||{}};this.client.accessToken&&(T.Authorization=`Bearer ${this.client.accessToken}`);let h={...r};delete h._isRetry;try{let a=await fetch(o,{method:t,headers:T,signal:l.signal,...n?{body:JSON.stringify(n)}:{},...h});if(clearTimeout(w),a.status===401&&!i&&this.client.options.autoRefreshToken&&await this.client.auth._silentRefresh())return this.request(t,e,n,{...r,_isRetry:!0});let s=(a.headers.get("content-type")||"").includes("application/json")?await a.json():await a.text();if(!a.ok)throw{status:a.status,data:s};if(this.client.options.debug&&console.log("%c\u2705 [Dolphin API Success]:","color: #10b981; font-weight: bold;",t.toUpperCase(),e,s),s&&typeof s=="object"&&s.accessToken&&(this.client.setToken(s.accessToken),s.user&&(this.client.auth.user=s.user)),this.client.options.autoBroadcast&&["POST","PUT","PATCH","DELETE"].includes(t.toUpperCase())){let c=e.startsWith("/")?e.substring(1):e;this.client.publish(c,{method:t.toUpperCase(),payload:n,result:s})}return s}catch(a){throw clearTimeout(w),this.client.options.debug&&console.error("%c\u274C [Dolphin API Error]:","color: #ef4444; font-weight: bold;",t.toUpperCase(),e,a),a.name==="AbortError"?{status:408,data:{error:"Request timed out"}}:a}}};var C=class{client;user;_refreshing;constructor(t){this.client=t,this.user=null,this._refreshing=!1}async login(t,e){let n=await this.client.api.post("/api/auth/login",{email:t,password:e});return n.accessToken&&(this.client.setToken(n.accessToken),this.user=n.user||null),n}async register(t){return this.client.api.post("/api/auth/register",t)}async me(){let t=await this.client.api.get("/api/auth/me");return t.success&&(this.user=t.data),t}async logout(){try{await this.client.api.post("/api/auth/logout")}catch{}this.client.setToken(null),this.user=null}async refresh(){return this._silentRefresh()}async _silentRefresh(){if(this._refreshing)return!1;this._refreshing=!0;try{let t=await this.client.api.post("/api/auth/refresh",null,{_isRetry:!0});return t.accessToken?(this.client.setToken(t.accessToken),!0):!1}catch{return this.client.setToken(null),!1}finally{this._refreshing=!1}}async verify2FA(t,e){let n={code:t,email:e||this.user?.email},r=await this.client.api.post("/api/auth/2fa/verify",n);return r.accessToken&&(this.client.setToken(r.accessToken),r.user&&(this.user=r.user)),r}async enable2FA(){return this.client.api.post("/api/auth/2fa/enable")}async disable2FA(t){return this.client.api.post("/api/auth/2fa/disable",{code:t})}async forgotPassword(t){return this.client.api.post("/api/auth/forgot-password",{email:t})}async resetPassword(t,e){return this.client.api.post("/api/auth/reset-password",{token:t,newPassword:e})}};var M=class{client;data;listeners;subscribed;constructor(t){return this.client=t,this.data=new Map,this.listeners=new Set,this.subscribed=new Set,new Proxy(this,{get:(e,n)=>{if(n in e)return e[n];if(typeof n=="string")return this._getCollection(n)}})}_getCollection(t){if(!this.data.has(t)){let e={_rawItems:[],items:[],loading:!0,error:null,success:!1,_filter:null,_sort:null,where:n=>(e._filter=n,this._applyTransform(e),e),orderBy:(n,r="asc")=>(e._sort={key:n,direction:r},this._applyTransform(e),e),reset:()=>(e._filter=null,e._sort=null,this._applyTransform(e),e)};this.data.set(t,e),this._fetchAndSync(t)}return this.data.get(t)}async _fetchAndSync(t){let e=this.data.get(t);try{let n=await this.client.api.get(`/${t.toLowerCase()}`);e._rawItems=Array.isArray(n)?n:n.data||[],e.loading=!1,e.success=!0,e.error=null,this._applyTransform(e),this.subscribed.has(t)||(this.client.subscribe(`db:sync/${t.toLowerCase()}`,r=>{this._handleRemoteUpdate(t,r)}),this.subscribed.add(t))}catch(n){e.loading=!1,e.success=!1,e.error=n.data?.error||n.message||"Fetch failed",this._notify()}}_applyTransform(t){let e=[...t._rawItems];if(t._filter&&(e=e.filter(t._filter)),t._sort){let{key:n,direction:r}=t._sort;e.sort((i,o)=>i[n]===o[n]?0:(i[n]>o[n]?1:-1)*(r==="asc"?1:-1))}t.items=e,this._notify()}_handleRemoteUpdate(t,e){let n=this.data.get(t);if(!n)return;let{type:r,data:i}=e,o=n._rawItems;r==="create"?o=[...o,i]:r==="update"?o=o.map(l=>l.id===i.id||l._id===i._id?{...l,...i}:l):r==="delete"&&(o=o.filter(l=>!(i.id!=null&&l.id===i.id||i._id!=null&&l._id===i._id))),n._rawItems=o,this._applyTransform(n)}subscribe(t){return this.listeners.add(t),()=>this.listeners.delete(t)}getSnapshot(t){return this.data.get(t)||{items:[],loading:!1,error:null,success:!1}}_notify(){this.listeners.forEach(t=>t())}};var k=class{host;httpUrl;deviceId;options;socket;storage;accessToken;api;auth;store;handlers;signalHandlers;fileHandlers;_offlineQueue;reconnectAttempts;_attachedListeners;constructor(t="",e="",n={}){!t&&typeof window<"u"&&(t=window.location.host);let r="http:";t.startsWith("https://")?r="https:":t.startsWith("http://")?r="http:":typeof window<"u"&&(r=window.location.protocol),this.host=(t||"localhost").replace(/\/$/,"").replace(/^https?:\/\//,""),this.httpUrl=`${r}//${this.host}`,this.deviceId=e||"web_"+Math.random().toString(36).substr(2,8),this.options={timeout:15e3,chunkSize:65536,maxReconnect:5,autoRefreshToken:!0,debug:!1,...n},this.socket=null,this.storage=typeof localStorage<"u"?localStorage:{getItem:()=>null,setItem:()=>{},removeItem:()=>{}},this.accessToken=this.storage.getItem("dolphin_token"),this.api=new x(this),this.auth=new C(this),this.store=new M(this),this.handlers=new Map,this.signalHandlers=new Set,this.fileHandlers=new Set,this._offlineQueue=[],this.reconnectAttempts=0,this._attachedListeners=[],typeof window<"u"&&typeof this._initDOMBinding=="function"&&this._initDOMBinding(),typeof this._initOffline=="function"&&this._initOffline(),typeof this._initA11y=="function"&&this._initA11y(),typeof this._initI18n=="function"&&this._initI18n(),typeof this._initDragDrop=="function"&&this._initDragDrop(),typeof this._initCollab=="function"&&this._initCollab()}setToken(t){this.accessToken=t,t?this.storage.setItem("dolphin_token",t):this.storage.removeItem("dolphin_token")}async connect(){return new Promise((t,e)=>{let r=`${this.httpUrl.startsWith("https")?"wss:":"ws:"}//${this.host}/realtime?deviceId=${this.deviceId}`;console.log(`[Dolphin] Connecting to ${r}...`),this.socket=new WebSocket(r),this.socket.onopen=()=>{console.log(`[Dolphin] Connected as "${this.deviceId}" \u{1F42C}`),this.reconnectAttempts=0,this._flushOfflineQueue(),t()},this.socket.onmessage=i=>this._handleMessage(i.data),this.socket.onclose=()=>{console.warn("[Dolphin] Connection closed"),this._maybeReconnect()},this.socket.onerror=i=>{console.error("[Dolphin] WebSocket error:",i),e(i)}})}disconnect(){this.socket&&(this.socket.onclose=null,this.socket.close(),this.socket=null),this.cleanupDomListeners()}_handleMessage(t){try{let e=JSON.parse(t);this.options.debug&&console.log("%c\u{1F4E5} [Dolphin WS Incoming]:","color: #eab308; font-weight: bold;",e),e.type&&e.from&&(e.to===this.deviceId||e.to==="all")&&(e.msgId&&e.type!=="ACK"&&this._sendAck(e.from,e.msgId),this.signalHandlers.forEach(n=>n(e))),e.type==="FILE_AVAILABLE"&&this.fileHandlers.forEach(n=>n(e)),e.type==="FILE_CHUNK"&&(this.saveFileProgress(e.fileId,e.chunkIndex),this._dispatch("file:chunk",e),this._dispatch(`file:chunk/${e.fileId}`,e)),e.type==="FILE_UPLOAD_ACK"&&this._dispatch(`file:upload:ack/${e.fileId}`,e),e.type==="PULL_RESPONSE"&&(this._dispatch("pull:response",e.payload,e.topic),this._dispatch(`pull:response/${e.topic}`,e.payload,e.topic)),e.topic&&e.payload!==void 0&&this.handlers.forEach((n,r)=>{this._matchTopic(r,e.topic)&&n.forEach(i=>i(e.payload,e.topic))})}catch{this._dispatch("raw",t)}}_dispatch(t,e,n){let r=this.handlers.get(t);r&&r.forEach(i=>i(e,n||t))}_sendRaw(t){this.options.debug&&console.log("%c\u{1F4E4} [Dolphin WS Outgoing]:","color: #8b5cf6; font-weight: bold;",t);let e=typeof t=="string"?t:JSON.stringify(t);this.socket&&this.socket.readyState===WebSocket.OPEN?this.socket.send(e):this._offlineQueue.length<100&&this._offlineQueue.push(e)}_flushOfflineQueue(){for(;this._offlineQueue.length>0;){let t=this._offlineQueue.shift();this.socket&&this.socket.readyState===WebSocket.OPEN&&this.socket.send(t)}}_sendAck(t,e){this._sendRaw({type:"ACK",from:this.deviceId,to:t,data:{ackId:e},timestamp:Date.now()})}_matchTopic(t,e){if(t===e||t==="#")return!0;let n=t.split("/"),r=e.split("/");if(n.length!==r.length&&!t.includes("#"))return!1;for(let i=0;i<n.length;i++){if(n[i]==="#")return!0;if(n[i]!=="+"&&n[i]!==r[i])return!1}return n.length===r.length}_maybeReconnect(){if(this.reconnectAttempts<this.options.maxReconnect){this.reconnectAttempts++;let t=Math.pow(2,this.reconnectAttempts)*1e3;console.log(`[Dolphin] Reconnecting in ${t/1e3}s (attempt ${this.reconnectAttempts})...`),setTimeout(()=>this.connect().catch(()=>{}),t)}else console.error("[Dolphin] Max reconnect attempts reached.")}subscribe(t,e){this.handlers.has(t)||(this.handlers.set(t,new Set),this._sendRaw({type:"sub",topic:t})),this.handlers.get(t).add(e)}unsubscribe(t,e){if(this.handlers.has(t)){let n=this.handlers.get(t);n.delete(e),n.size===0&&(this.handlers.delete(t),this._sendRaw({type:"unsub",topic:t}))}}publish(t,e){this._sendRaw({topic:t,payload:e})}pubPush(t,e){this._sendRaw({type:"pub",topic:t,payload:e})}subPull(t,e=10){this._sendRaw({type:"PULL_REQUEST",topic:t,count:e})}async pubFile(t,e,n="",r){let i;e instanceof Blob?i=await e.arrayBuffer():e instanceof ArrayBuffer?i=e:i=e.buffer||e;let o=new Uint8Array(i),l=this.options.chunkSize,w=Math.ceil(o.length/l);this._sendRaw({type:"FILE_UPLOAD_START",fileId:t,name:n,size:o.length,totalChunks:w,chunkSize:l});for(let T=0;T<w;T++){let h=o.slice(T*l,(T+1)*l),a=this._uint8ToBase64(h);this._sendRaw({type:"FILE_UPLOAD_CHUNK",fileId:t,chunkIndex:T,totalChunks:w,data:a}),r&&r(Math.round((T+1)/w*100)),T%10===0&&await new Promise(u=>setTimeout(u,0))}this._sendRaw({type:"FILE_UPLOAD_DONE",fileId:t})}_uint8ToBase64(t){let e="";for(let n=0;n<t.length;n++)e+=String.fromCharCode(t[n]);return typeof btoa<"u"?btoa(e):Buffer.from(e,"binary").toString("base64")}subFile(t,e=0){this._sendRaw({type:"FILE_REQUEST",fileId:t,startChunk:e})}resumeFile(t){let e=parseInt(this.storage.getItem(`dolphin_file_${t}`)||"-1");this.subFile(t,e+1)}saveFileProgress(t,e){this.storage.setItem(`dolphin_file_${t}`,e.toString())}onSignal(t){this.signalHandlers.add(t)}offSignal(t){this.signalHandlers.delete(t)}onFileAvailable(t){this.fileHandlers.add(t)}offFileAvailable(t){this.fileHandlers.delete(t)}addDomListener(t,e,n){t&&(t.addEventListener(e,n),this._attachedListeners=this._attachedListeners||[],this._attachedListeners.push({target:t,event:e,cb:n}))}cleanupDomListeners(){this._attachedListeners&&(this._attachedListeners.forEach(({target:t,event:e,cb:n})=>{try{t.removeEventListener(e,n)}catch{}}),this._attachedListeners=[])}};function R(p){function t(h){return h.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function e(h){let a=h.getAttribute("data-rt-template");if(!a)return null;if(typeof document<"u"&&!a.includes("<"))try{let u=document.querySelector(a);if(u)return u.innerHTML}catch{}return a}function n(h,a){if(!h.includes("{#if")&&!h.includes("{#each")){let u=h;for(let s in a){let c=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");u=u.replace(new RegExp(`\\{\\{${c}\\}\\}`,"g"),a[s]!==void 0&&a[s]!==null?a[s]:"")}return u}try{let u=b=>b.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t"),s=`let out = "";
|
|
2
|
+
`,c=0,g=/(\{\{([\s\S]*?)\}\}|\{#if\s+([\s\S]*?)\}|\{:else\s+if\s+([\s\S]*?)\}|\{:else\}|\{\/if\}|\{#each\s+([\s\S]*?)\s+as\s+([a-zA-Z_$][a-zA-Z0-9_$]*)(?:\s*,\s*([a-zA-Z_$][a-zA-Z0-9_$]*))?\}|\{\/each\}|\{([^{}]+?)\})/g,d=[],f;for(;(f=g.exec(h))!==null;){let b=h.slice(c,f.index);b&&(s+=`out += "${u(b)}";
|
|
3
|
+
`);let A=f[0];if(A.startsWith("{{")){let E=f[2];s+=`out += (${E} !== undefined && ${E} !== null ? ${E} : "");
|
|
4
|
+
`}else if(A.startsWith("{#if")){let E=f[3];s+=`if (${E}) {
|
|
5
|
+
`}else if(A.startsWith("{:else if")){let E=f[4];s+=`} else if (${E}) {
|
|
6
|
+
`}else if(A.startsWith("{:else}"))s+=`} else {
|
|
7
|
+
`;else if(A.startsWith("{/if}"))s+=`}
|
|
8
|
+
`;else if(A.startsWith("{#each")){let E=f[5],v=f[6],D=f[7];d.push({indexVar:D}),s+=`if (typeof ${E} !== "undefined" && ${E} !== null && Array.isArray(${E})) {
|
|
9
|
+
`,D&&(s+=` let ${D} = 0;
|
|
10
|
+
`),s+=` for (let ${v} of ${E}) {
|
|
11
|
+
`}else if(A.startsWith("{/each}")){let E=d.pop();E&&E.indexVar&&(s+=` ${E.indexVar}++;
|
|
12
12
|
`),s+=` }
|
|
13
13
|
}
|
|
14
|
-
`}else if(
|
|
15
|
-
`)}c=
|
|
14
|
+
`}else if(A.startsWith("{")){let E=f[8];E&&(s+=`out += (${E} !== undefined && ${E} !== null ? ${E} : "");
|
|
15
|
+
`)}c=g.lastIndex}let m=h.slice(c);m&&(s+=`out += "${u(m)}";
|
|
16
16
|
`),s+=`return out;
|
|
17
17
|
`;let _=`
|
|
18
18
|
with (context) {
|
|
@@ -23,4 +23,4 @@ var DolphinModule=(()=>{var $=Object.defineProperty;var z=Object.getOwnPropertyD
|
|
|
23
23
|
return '';
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
`;return new Function("context",_)(o)}catch(u){console.error("[Dolphin Template Compiler Error]:",u);let s=h;for(let c in o){let m=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");s=s.replace(new RegExp(`\\{\\{${m}\\}\\}`,"g"),o[c]!==void 0&&o[c]!==null?o[c]:"")}return s}}function r(h){if(typeof document>"u")return h;try{let s=new DOMParser().parseFromString(h,"text/html").body,c=m=>{let f=m.tagName.toLowerCase();if(["script","iframe","object","embed","link","style","meta","applet","svg"].includes(f)){m.parentNode?.removeChild(m);return}let d=m.attributes;for(let y=d.length-1;y>=0;y--){let _=d[y].name.toLowerCase(),E=d[y].value.toLowerCase();(_.startsWith("on")||["src","href","data"].includes(_)&&(E.includes("javascript:")||E.includes("data:text/html")))&&m.removeAttribute(d[y].name)}Array.from(m.children).forEach(c)};return Array.from(s.children).forEach(c),s.innerHTML}catch{return h}}function i(h,o){if(h.nodeType!==o.nodeType){h.parentNode?.replaceChild(o.cloneNode(!0),h);return}if(h.nodeType===Node.TEXT_NODE){h.textContent!==o.textContent&&(h.textContent=o.textContent);return}if(h.nodeType===Node.ELEMENT_NODE){let u=h,s=o;if(u.tagName!==s.tagName){u.parentNode?.replaceChild(s.cloneNode(!0),u);return}let c=u.attributes,m=s.attributes;for(let g=c.length-1;g>=0;g--){let w=c[g].name;s.hasAttribute(w)||u.removeAttribute(w)}for(let g=0;g<m.length;g++){let w=m[g].name,A=m[g].value;u.getAttribute(w)!==A&&u.setAttribute(w,A)}u.tagName==="INPUT"||u.tagName==="TEXTAREA"?(u.value!==s.value&&(u.value=s.value),u.checked!==s.checked&&(u.checked=s.checked)):u.tagName==="SELECT"&&u.value!==s.value&&(u.value=s.value);let f=Array.from(u.childNodes),d=Array.from(s.childNodes),y=f.length,_=d.length,E=Math.max(y,_);for(let g=0;g<E;g++)g>=y?u.appendChild(d[g].cloneNode(!0)):g>=_?u.removeChild(f[g]):i(f[g],d[g])}}function a(h,o){if(typeof document>"u")return;let u=document.createElement(h.tagName);u.innerHTML=o;let s=Array.from(h.childNodes),c=Array.from(u.childNodes),m=s.length,f=c.length,d=Math.max(m,f);for(let y=0;y<d;y++)y>=m?h.appendChild(c[y].cloneNode(!0)):y>=f?h.removeChild(s[y]):i(s[y],c[y])}let l=new Map,b=!1;function T(h,o){l.set(h,o),b||(b=!0,(typeof requestAnimationFrame<"u"?requestAnimationFrame:s=>setTimeout(s,0))(()=>{l.forEach((s,c)=>{a(c,s)}),l.clear(),b=!1}))}p.setStoreState=function(h,o,u){this.uiStores=this.uiStores||new Map,this.uiStores.has(h)||this.uiStores.set(h,{});let s=this.uiStores.get(h);s[o]=u,this.options.debug&&console.log("%c\u{1F4BE} [Dolphin Store Update]:","color: #ec4899; font-weight: bold;",`${h}.${o}`,"=",u),typeof document<"u"&&document.querySelectorAll(`[data-store-read="${h}.${o}"]`).forEach(m=>{m.tagName==="INPUT"||m.tagName==="TEXTAREA"?m.type==="checkbox"?m.checked=!!u:m.value=u??"":m.textContent=u??""}),this.publish(`store/${h}`,s)},p.getStoreState=function(h,o){this.uiStores=this.uiStores||new Map;let u=this.uiStores.get(h);return u?u[o]:void 0},p._scanStoreBinds=function(){if(typeof document>"u")return;document.querySelectorAll("[data-store-write]").forEach(u=>{let s=u.getAttribute("data-store-write");if(s){let c=s.split(".");if(c.length===2){let m=c[0],f=c[1],d=u.type==="checkbox"?u.checked:u.value;this.uiStores=this.uiStores||new Map,this.uiStores.has(m)||this.uiStores.set(m,{});let y=this.uiStores.get(m);y[f]===void 0&&(y[f]=d)}}}),document.querySelectorAll("[data-store-read]").forEach(u=>{let s=u.getAttribute("data-store-read");if(s){let c=s.split(".");if(c.length===2){let m=c[0],f=c[1],d=this.getStoreState(m,f);d!=null&&(u.tagName==="INPUT"||u.tagName==="TEXTAREA"?u.type==="checkbox"?u.checked=!!d:u.value=d:u.textContent=d)}}})},p.getClosestContext=function(h,o){let u=h;for(;u;){if(u._rtContext){let s=u._rtContext;return o?s[o]:s}u=u.parentElement}return null},p._executeStoreAction=function(h,o){this.uiStores=this.uiStores||new Map;let u=new Proxy({},{has:(s,c)=>!0,get:(s,c)=>{if(typeof c=="string")return new Proxy({},{get:(m,f)=>{if(typeof f=="string")return this.getStoreState(c,f)},set:(m,f,d)=>typeof f=="string"?(this.setStoreState(c,f,d),!0):!1})}});try{new Function("ctx",`with(ctx) { ${h} }`)(u)}catch(s){console.error("%c[Dolphin Store Action Error]:","color: #ef4444; font-weight: bold;",s),o&&console.error("%cFailed Element:","color: #f97316; font-weight: bold;",o),console.error("%cFailed Expression:","color: #3b82f6; font-style: italic;",h)}},p._initDOMBinding=function(){if(this._domInitialized)return;this._domInitialized=!0;let h=["input","change","keyup","paste","blur"],o=new Map;h.forEach(s=>{this.addDomListener(document,s,c=>{if(!c.target||!c.target.getAttribute)return;let m=c.target.getAttribute("data-store-write");if(m){let _=m.split(".");if(_.length===2){let E=_[0],g=_[1],w=c.target.type==="checkbox"?c.target.checked:c.target.value;this.setStoreState(E,g,w)}}let f=c.target.getAttribute("data-rt-validate"),d=c.target.name;if(f&&d&&typeof this.validateField=="function"){let _=c.target.closest("form"),E=_?Object.fromEntries(new FormData(_).entries()):{},g=this.validateField(c.target.value,f,E);g?(c.target.classList.add("invalid"),this.publish(`errors/${d}`,g)):(c.target.classList.remove("invalid"),this.publish(`errors/${d}`,""))}let y=c.target.getAttribute("data-rt-push");if(y){let _=c.target.getAttribute("data-rt-debounce"),E=_?parseInt(_,10):0,g=()=>{let w={name:c.target.name,value:c.target.value};this.pubPush(y,w)};if(E>0){o.has(c.target)&&clearTimeout(o.get(c.target));let w=setTimeout(g,E);o.set(c.target,w)}else g()}})}),this.addDomListener(document,"submit",async s=>{if(!s.target||!s.target.getAttribute)return;let c=s.target.getAttribute("data-rt-submit"),m=s.target.getAttribute("data-api-submit");if(c||m){let f=s.target.querySelectorAll("[data-rt-validate]"),d=!0;if(f.length>0&&typeof this.validateField=="function"){let g=Object.fromEntries(new FormData(s.target).entries());f.forEach(w=>{let A=w.getAttribute("data-rt-validate"),D=w.name;if(A&&D){let S=this.validateField(w.value,A,g);S?(d=!1,w.classList.add("invalid"),this.publish(`errors/${D}`,S)):(w.classList.remove("invalid"),this.publish(`errors/${D}`,""))}})}if(!d){s.preventDefault(),s.stopPropagation();return}s.preventDefault();let y=this.getClosestContext(s.target)||{},_=new FormData(s.target),E=Object.fromEntries(_.entries());if(c){let g=c;for(let w in y){let A=t(w);g=g.replace(new RegExp(`\\{\\{${A}\\}\\}`,"g"),y[w]!==void 0&&y[w]!==null?y[w]:"")}this.publish(g,E)}else if(m){let g=m;for(let S in y){let k=t(S);g=g.replace(new RegExp(`\\{\\{${k}\\}\\}`,"g"),y[S]!==void 0&&y[S]!==null?y[S]:"")}let w=g.trim().split(" "),A=w.length>1?w[0].toUpperCase():"POST",D=w.length>1?w[1]:w[0];try{let S=await this.api.request(A,D,E),k=s.target.getAttribute("data-api-result");k&&this._updateDOM(k,S);let L=s.target.getAttribute("data-api-redirect");L&&(window.location.href=L),s.target.hasAttribute("data-api-reload")&&window.location.reload()}catch(S){console.error("[Dolphin] API Submit Error:",S)}}}}),["click","change","submit","input","keydown","keyup","dblclick","focus","blur","mouseenter","mouseleave"].forEach(s=>{this.addDomListener(document,s,async c=>{if(!c.target||!c.target.closest)return;let m=c.target.closest(`[data-rt-${s}]`),f=c.target.closest(`[data-api-${s}]`);if(m){s==="submit"&&c.preventDefault();let y=m.getAttribute(`data-rt-${s}`),_=m.getAttribute("data-rt-payload"),E=this.getClosestContext(m)||{},g={};if(_){let w=_;for(let A in E){let D=t(A);w=w.replace(new RegExp(`\\{\\{${D}\\}\\}`,"g"),E[A]!==void 0&&E[A]!==null?E[A]:"")}try{g=JSON.parse(w)}catch{g={}}}this.publish(y,g)}if(f){s==="submit"&&c.preventDefault();let y=f.getAttribute(`data-api-${s}`),_=f.getAttribute("data-api-payload"),E=this.getClosestContext(f)||{},g=y.trim().split(" "),w=g.length>1?g[0].toUpperCase():"POST",A=g.length>1?g[1]:g[0],D=null;if(_){let S=_;for(let k in E){let L=t(k);S=S.replace(new RegExp(`\\{\\{${L}\\}\\}`,"g"),E[k]!==void 0&&E[k]!==null?E[k]:"")}try{D=JSON.parse(S)}catch{D=null}}try{let S=await this.api.request(w,A,D),k=f.getAttribute("data-api-result");k&&this._updateDOM(k,S);let L=f.getAttribute("data-api-redirect");L&&(window.location.href=L),f.hasAttribute("data-api-reload")&&window.location.reload()}catch(S){console.error(`[Dolphin] API ${s} Error:`,S)}}let d=c.target.closest(`[data-store-${s}]`);if(d){s==="submit"&&c.preventDefault();let y=d.getAttribute(`data-store-${s}`);y&&this._executeStoreAction(y,d)}})}),this.subscribe("#",(s,c)=>{this._updateDOM(c,s)}),this._scanAndFetchAPIBinds(),this._scanStoreBinds()},p._scanAndFetchAPIBinds=async function(){if(typeof document>"u")return;let h=document.querySelectorAll("[data-api-get]");for(let o of Array.from(h)){let u=o.getAttribute("data-api-get");if(u)try{let s=await this.api.get(u),c=o.getAttribute("data-rt-bind");if(c)this._updateDOM(c,s);else{let m=e(o);if(m&&typeof s=="object"&&s!==null)if(Array.isArray(s)){let f="";for(let d of s)f+=n(m,d);T(o,f)}else T(o,n(m,s));else o.tagName==="INPUT"||o.tagName==="TEXTAREA"?o.value=typeof s=="object"?s.value!==void 0?s.value:"":s:o.innerHTML=typeof s=="object"?s.html||s.text||JSON.stringify(s):s}}catch(s){console.error("[Dolphin] API Get Error:",s)}}},p._updateDOM=function(h,o){if(typeof document>"u")return;document.querySelectorAll(`[data-rt-bind="${h}"]`).forEach(s=>{if(s.getAttribute("data-rt-type")==="context"&&typeof o=="object"&&o!==null){s._rtContext=o;let m=f=>{if(f.hasAttribute("data-rt-text")){let d=f.getAttribute("data-rt-text");d&&o[d]!==void 0&&o[d]!==null&&(f.textContent=o[d])}if(f.hasAttribute("data-rt-html")){let d=f.getAttribute("data-rt-html");d&&o[d]!==void 0&&o[d]!==null&&(f.innerHTML=r(o[d]))}if(f.hasAttribute("data-rt-attr")){let d=f.getAttribute("data-rt-attr");d&&d.split(",").forEach(y=>{let _=y.split(":");if(_.length===2){let E=_[0].trim(),g=_[1].trim();E&&g&&o[g]!==void 0&&o[g]!==null&&f.setAttribute(E,o[g])}})}if(f.hasAttribute("data-rt-class")){let d=f.getAttribute("data-rt-class");d&&d.split(",").forEach(y=>{let _=y.split(":");if(_.length===2){let E=_[0].trim(),g=_[1].trim();o[g]?f.classList.add(E):f.classList.remove(E)}})}if(f.hasAttribute("data-rt-if")){let d=f.getAttribute("data-rt-if");d&&(o[d]?f.style.display="":f.style.display="none")}if(f.hasAttribute("data-rt-hide")){let d=f.getAttribute("data-rt-hide");d&&(o[d]?f.style.display="none":f.style.display="")}};m(s),s.querySelectorAll("[data-rt-text], [data-rt-html], [data-rt-attr], [data-rt-class], [data-rt-if], [data-rt-hide]").forEach(m);return}let c=e(s);if(c&&typeof o=="object"&&o!==null){if(Array.isArray(o)){let m="";for(let f of o)m+=n(c,f);T(s,m)}else T(s,n(c,o));return}s.tagName==="INPUT"||s.tagName==="TEXTAREA"?s.value=typeof o=="object"?o.value!==void 0?o.value:"":o:s.innerHTML=typeof o=="object"?o.html||o.text||JSON.stringify(o):o})}}var I=class{client;db;isOnline;memoryCache=new Map;memoryMutations=[];constructor(t){this.client=t,this.isOnline=typeof window<"u"&&typeof navigator<"u"?navigator.onLine:!0,this.initDB(),this.setupNetworkListeners()}initDB(){if(!(typeof indexedDB>"u"))try{let t=indexedDB.open("dolphin_offline",1);t.onupgradeneeded=e=>{let n=e.target.result;n.objectStoreNames.contains("cache")||n.createObjectStore("cache"),n.objectStoreNames.contains("mutations")||n.createObjectStore("mutations",{keyPath:"id",autoIncrement:!0})},t.onsuccess=e=>{this.db=e.target.result,this.isOnline&&this.syncMutations()}}catch(t){console.warn("[Dolphin Offline] Failed to initialize IndexedDB:",t)}}setupNetworkListeners(){typeof window>"u"||(this.client.addDomListener(window,"online",()=>{this.isOnline=!0,this.client._dispatch("network:status",{online:!0}),this.syncMutations()}),this.client.addDomListener(window,"offline",()=>{this.isOnline=!1,this.client._dispatch("network:status",{online:!1})}))}async getCache(t){return this.db?new Promise(e=>{try{let i=this.db.transaction("cache","readonly").objectStore("cache").get(t);i.onsuccess=()=>e(i.result?i.result.data:null),i.onerror=()=>e(null)}catch{e(null)}}):this.memoryCache.get(t)}async setCache(t,e){if(!this.db){this.memoryCache.set(t,e);return}return new Promise(n=>{try{let r=this.db.transaction("cache","readwrite");r.objectStore("cache").put({data:e,timestamp:Date.now()},t),r.oncomplete=()=>n()}catch{n()}})}async queueMutation(t,e,n){let r={method:t,path:e,payload:n,timestamp:Date.now()};if(!this.db){this.memoryMutations.push(r);return}return new Promise(i=>{try{let a=this.db.transaction("mutations","readwrite");a.objectStore("mutations").add(r),a.oncomplete=()=>i()}catch{i()}})}async getMutations(){return this.db?new Promise(t=>{try{let r=this.db.transaction("mutations","readonly").objectStore("mutations").getAll();r.onsuccess=()=>t(r.result||[]),r.onerror=()=>t([])}catch{t([])}}):[...this.memoryMutations]}async removeMutation(t){if(!this.db){this.memoryMutations=this.memoryMutations.filter(e=>e.id!==t);return}return new Promise(e=>{try{let n=this.db.transaction("mutations","readwrite");n.objectStore("mutations").delete(t),n.oncomplete=()=>e()}catch{e()}})}async syncMutations(){let t=await this.getMutations();if(t.length!==0){console.log(`[Dolphin Offline] Syncing ${t.length} queued mutations...`);for(let e of t)try{await this.client.api.requestDirect(e.method,e.path,e.payload),e.id!==void 0?await this.removeMutation(e.id):this.memoryMutations.shift()}catch(n){if(console.error(`[Dolphin Offline] Sync failed for mutation ${e.method} ${e.path}:`,n),n&&n.status&&n.status>=400&&n.status<500)console.warn("[Dolphin Offline] Discarding invalid mutation."),e.id!==void 0?await this.removeMutation(e.id):this.memoryMutations.shift();else break}}}};function q(p){p._initOffline=function(){this.offline=new I(this)}}function Y(p,t,e){let n=t.split(",");for(let r of n){let i=r.trim().split(":"),a=i[0],l=i[1];if(a==="required"){if(!p||p.trim()==="")return"This field is required"}else if(a==="email"){if(p&&p.trim()!==""&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(p))return"Please enter a valid email address"}else if(a==="min"){let b=parseInt(l,10);if(!p||p.length<b)return`Must be at least ${b} characters`}else if(a==="match"&&e&&p!==e[l])return`Must match ${l}`}return null}function O(p){p.validateField=Y}function N(p){p.animateElement=function(t,e,n=300){if(typeof t.animate!="function"){t.classList.add(e),setTimeout(()=>t.classList.remove(e),n);return}e==="fade-in"?t.animate([{opacity:0,transform:"translateY(10px)"},{opacity:1,transform:"translateY(0)"}],{duration:n,easing:"ease-out"}):e==="fade-out"&&t.animate([{opacity:1,transform:"translateY(0)"},{opacity:0,transform:"translateY(10px)"}],{duration:n,easing:"ease-in"})},p.staggerListItems=function(t,e,n=50){if(typeof document>"u")return;t.querySelectorAll(e).forEach((i,a)=>{i.style.animationDelay=`${a*n}ms`,i.classList.add("staggered-item")})}}function U(p){p._initA11y=function(){typeof document>"u"||(this.addDomListener(document,"keydown",t=>{if(t.key!=="Tab")return;document.querySelectorAll("[data-rt-a11y-focus-trap]").forEach(n=>{if(n.style.display==="none"||n.hasAttribute("aria-hidden")&&n.getAttribute("aria-hidden")==="true")return;let i=Array.from(n.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]'));if(i.length===0)return;let a=i[0],l=i[i.length-1];t.shiftKey?document.activeElement===a&&(l.focus(),t.preventDefault()):document.activeElement===l&&(a.focus(),t.preventDefault())})}),this.addDomListener(document,"keydown",t=>{if(!["ArrowUp","ArrowDown","Enter"].includes(t.key))return;document.querySelectorAll("[data-rt-keynav]").forEach(n=>{let r=Array.from(n.children);if(r.length===0)return;let i=r.findIndex(a=>a.classList.contains("active")||document.activeElement===a);t.key==="ArrowDown"?(i=(i+1)%r.length,r[i].focus(),r.forEach((a,l)=>{l===i?a.classList.add("active"):a.classList.remove("active")}),t.preventDefault()):t.key==="ArrowUp"?(i=(i-1+r.length)%r.length,r[i].focus(),r.forEach((a,l)=>{l===i?a.classList.add("active"):a.classList.remove("active")}),t.preventDefault()):t.key==="Enter"&&i!==-1&&(r[i].click(),t.preventDefault())})}))},p.autoAriaModal=function(t,e){e?(t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-hidden","false"),t.focus()):t.setAttribute("aria-hidden","true")}}function F(p){p._initI18n=function(){if(this.i18n=this.i18n||{locale:"en",dicts:{}},typeof document>"u")return;if(document.querySelectorAll("[data-i18n-dict]").forEach(e=>{let n=e.getAttribute("data-i18n-dict");if(n)try{let r=JSON.parse(e.textContent||"{}");this.i18n.dicts[n]={...this.i18n.dicts[n]||{},...r}}catch(r){console.warn("[Dolphin i18n] Failed to parse dictionary for locale:",n,r)}}),!this.i18n.locale&&typeof navigator<"u"){let e=navigator.language.split("-")[0];this.i18n.dicts[e]&&(this.i18n.locale=e)}this.addDomListener(document,"click",e=>{let n=e.target.closest("[data-i18n-switch]");if(n){let r=n.getAttribute("data-i18n-switch");r&&this.setLocale(r)}}),this.translateDOM()},p.setLocale=function(t){this.i18n=this.i18n||{locale:"en",dicts:{}},this.i18n.locale=t,this.translateDOM(),this.publish("i18n/locale",t)},p.translateDOM=function(){if(typeof document>"u")return;this.i18n=this.i18n||{locale:"en",dicts:{}};let t=this.i18n.locale||"en",e=this.i18n.dicts[t]||{};document.querySelectorAll("[data-i18n-key]").forEach(r=>{let i=r.getAttribute("data-i18n-key");if(!i)return;let a=i.split(".").reduce((b,T)=>b?b[T]:null,e);a==null&&(a=i);let l=r.getAttribute("data-i18n-params");if(l)try{let b=JSON.parse(l),T=h=>h.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");for(let h in b){let o=T(h);a=a.replace(new RegExp(`\\{\\{${o}\\}\\}`,"g"),b[h])}}catch{}r.tagName==="INPUT"||r.tagName==="TEXTAREA"?r.placeholder=a:r.textContent=a})}}function H(p){p._initDragDrop=function(){typeof document>"u"||(this.addDomListener(document,"dragstart",t=>{let e=t.target.closest("[data-drag]");if(!e)return;let n=e.getAttribute("data-drag");n&&(t.dataTransfer.setData("text/plain",n),t.dataTransfer.effectAllowed="move",e.classList.add("dragging"))}),this.addDomListener(document,"dragend",t=>{let e=t.target.closest("[data-drag]");e&&e.classList.remove("dragging")}),this.addDomListener(document,"dragover",t=>{let e=t.target.closest("[data-drop]");e&&(t.preventDefault(),e.classList.add("drag-over"))}),this.addDomListener(document,"dragleave",t=>{let e=t.target.closest("[data-drop]");e&&e.classList.remove("drag-over")}),this.addDomListener(document,"drop",t=>{let e=t.target.closest("[data-drop]");if(!e)return;t.preventDefault(),e.classList.remove("drag-over");let n=e.getAttribute("data-drop"),r=t.dataTransfer.getData("text/plain");if(n&&r)try{let i=JSON.parse(r);this.publish(n,i)}catch{this.publish(n,{value:r})}}),this.addDomListener(document,"dragover",t=>{let e=t.target.closest("[data-sortable]");if(!e)return;t.preventDefault();let n=e.querySelector(".dragging");if(!n)return;let i=Array.from(e.querySelectorAll("[data-drag]:not(.dragging)")).find(a=>{let l=a.getBoundingClientRect();return t.clientY-l.top-l.height/2<0});i?e.insertBefore(n,i):e.appendChild(n)}),this.addDomListener(document,"drop",t=>{let e=t.target.closest("[data-sortable]");if(!e)return;let n=e.getAttribute("data-sortable");if(!n)return;let i=Array.from(e.querySelectorAll("[data-drag]")).map((a,l)=>{let b=a.getAttribute("data-drag");try{return{index:l,payload:JSON.parse(b||"{}")}}catch{return{index:l,payload:b}}});this.publish(n,i)}))}}function W(p){p._initCollab=function(){typeof document>"u"||(this.addDomListener(document,"mousemove",t=>{document.querySelectorAll("[data-rt-cursor-share]").forEach(n=>{let r=n.getAttribute("data-rt-cursor-share");if(!r)return;let i=n.getBoundingClientRect(),a=(t.clientX-i.left)/i.width,l=(t.clientY-i.top)/i.height,b=Date.now();(!n._lastSent||b-n._lastSent>50)&&(n._lastSent=b,this.pubPush(`collab/${r}/cursor/${this.deviceId}`,{deviceId:this.deviceId,x:a,y:l}))})}),this.addDomListener(document,"input",t=>{let e=t.target.getAttribute("data-rt-typing");if(!e)return;let n=e,r=i=>{this.pubPush(`collab/${n}/typing/${this.deviceId}`,{deviceId:this.deviceId,typing:i})};t.target._isTyping||(t.target._isTyping=!0,r(!0)),t.target._typingTimer&&clearTimeout(t.target._typingTimer),t.target._typingTimer=setTimeout(()=>{t.target._isTyping=!1,r(!1)},2e3)}),this.addDomListener(document,"input",t=>{let e=t.target.getAttribute("data-rt-crdt");if(!e)return;let n=e,r=t.target.value,i=Date.now();this.publish(`collab/${n}/crdt`,{deviceId:this.deviceId,value:r,timestamp:i,cursorPos:t.target.selectionStart})}),this.subscribe("collab/+/cursor/+",(t,e)=>{let n=e.split("/"),r=n[1],i=n[3];if(i===this.deviceId)return;let a=document.querySelector(`[data-rt-cursor-share="${r}"]`);if(!a)return;let l=a.querySelector(`.rt-cursor-${i}`);l||(l=document.createElement("div"),l.className=`rt-cursor rt-cursor-${i}`,l.style.position="absolute",l.style.width="10px",l.style.height="10px",l.style.borderRadius="50%",l.style.backgroundColor="#"+Math.floor(Math.random()*16777215).toString(16),l.style.pointerEvents="none",a.appendChild(l));let b=a.getBoundingClientRect();l.style.left=t.x*b.width+"px",l.style.top=t.y*b.height+"px"}),this.subscribe("collab/+/crdt",(t,e)=>{if(t.deviceId===this.deviceId)return;let r=e.split("/")[1];document.querySelectorAll(`[data-rt-crdt="${r}"]`).forEach(a=>{if(!a._lastUpdate||t.timestamp>a._lastUpdate){a._lastUpdate=t.timestamp;let l=a.selectionStart;a.value=t.value,document.activeElement===a&&a.setSelectionRange(l,l)}})}))}}function j(p){p.registerServiceWorker=async function(t="/sw.js"){if(typeof navigator>"u"||!("serviceWorker"in navigator))return console.warn("[Dolphin PWA] Service Workers are not supported in this browser."),null;try{let e=await navigator.serviceWorker.register(t);return console.log("[Dolphin PWA] Service Worker registered successfully with scope:",e.scope),e}catch(e){return console.error("[Dolphin PWA] Service Worker registration failed:",e),null}},p.subscribePushNotifications=async function(t){if(typeof window>"u"||!("serviceWorker"in navigator)||!("PushManager"in window))return console.warn("[Dolphin PWA] Push notifications are not supported in this browser."),null;try{let e=await navigator.serviceWorker.ready,n=await e.pushManager.getSubscription();if(!n){let r="=".repeat((4-t.length%4)%4),i=(t+r).replace(/\-/g,"+").replace(/_/g,"/"),a=window.atob(i),l=new Uint8Array(a.length);for(let b=0;b<a.length;++b)l[b]=a.charCodeAt(b);n=await e.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:l})}return console.log("[Dolphin PWA] Subscribed to push notifications:",n),n}catch(e){return console.error("[Dolphin PWA] Push notification subscription failed:",e),null}}}var P=class{static render(t){if(typeof document>"u")throw new Error("DolphinTestUtils.render requires a DOM document environment to execute.");let e=document.createElement("div");return e.innerHTML=t,document.body.appendChild(e),{container:e,find:n=>e.querySelector(n),fireEvent:(n,r)=>{let i=document.createEvent("Event");i.initEvent(r,!0,!0),n.dispatchEvent(i)}}}static mockWebSocket(){let t=[],e={readyState:1,send:n=>{t.push(n)},close:jest.fn(),onopen:jest.fn(),onmessage:jest.fn(),onclose:jest.fn(),onerror:jest.fn(),sentMessages:t};return global.WebSocket=class{static OPEN=1;readyState=e.readyState;send=e.send;close=e.close;set onopen(n){e.onopen=n}get onopen(){return e.onopen}set onmessage(n){e.onmessage=n}get onmessage(){return e.onmessage}set onclose(n){e.onclose=n}get getonclose(){return e.onclose}constructor(){setTimeout(()=>e.onopen&&e.onopen(),0)}},e}static simulateClick(t){let e={target:t,preventDefault:jest.fn(),stopPropagation:jest.fn()};(global.document._listeners?.click||[]).forEach(r=>r(e))}static simulateChange(t,e){t.value=e;let n={target:t,preventDefault:jest.fn(),stopPropagation:jest.fn()};(global.document._listeners?.change||[]).forEach(i=>i(n))}};function B(p){p.testing=P}R(v.prototype);q(v.prototype);O(v.prototype);N(v.prototype);U(v.prototype);F(v.prototype);H(v.prototype);W(v.prototype);j(v.prototype);B(v.prototype);typeof window<"u"&&(window.DolphinClient=v,document.addEventListener("DOMContentLoaded",()=>{if(!window.dolphin){let p=document.querySelector('script[src*="dolphin-client"]'),t=p?p.getAttribute("data-debug")==="true":!1,e=new v(void 0,void 0,{debug:t});window.dolphin=e,t&&(console.log("%c\u{1F42C} [Dolphin Client] Auto-initialized local reactive engine!","color: #06b6d4; font-weight: bold; font-size: 14px;"),console.log('%c\u{1F449} Tip: You can access the client instance via "window.dolphin" in console.',"color: #94a3b8; font-style: italic;")),document.querySelector('[data-store-write="app.username"]')&&e.setStoreState("app","username","\u0928\u092E\u0938\u094D\u0924\u0947 \u0938\u093E\u0925\u0940!")}}));return X(Z);})();
|
|
26
|
+
`,S=a;return typeof Proxy<"u"&&a!==null&&typeof a=="object"&&(S=new Proxy(a,{has(b,A){return typeof A!="symbol"},get(b,A){if(A!==Symbol.unscopables){if(A in b)return b[A];if(typeof globalThis<"u"&&A in globalThis)return globalThis[A];if(typeof window<"u"&&A in window)return window[A]}}})),new Function("context",_)(S)}catch(u){console.error("[Dolphin Template Compiler Error]:",u);let s=h;for(let c in a){let g=c.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");s=s.replace(new RegExp(`\\{\\{${g}\\}\\}`,"g"),a[c]!==void 0&&a[c]!==null?a[c]:"")}return s}}function r(h){if(typeof document>"u")return h;try{let s=new DOMParser().parseFromString(h,"text/html").body,c=g=>{let d=g.tagName.toLowerCase();if(["script","iframe","object","embed","link","style","meta","applet","svg"].includes(d)){g.parentNode?.removeChild(g);return}let f=g.attributes;for(let m=f.length-1;m>=0;m--){let _=f[m].name.toLowerCase(),S=f[m].value.toLowerCase();(_.startsWith("on")||["src","href","data"].includes(_)&&(S.includes("javascript:")||S.includes("data:text/html")))&&g.removeAttribute(f[m].name)}Array.from(g.children).forEach(c)};return Array.from(s.children).forEach(c),s.innerHTML}catch{return h}}function i(h,a){if(h.nodeType!==a.nodeType){h.parentNode?.replaceChild(a.cloneNode(!0),h);return}if(h.nodeType===Node.TEXT_NODE){h.textContent!==a.textContent&&(h.textContent=a.textContent);return}if(h.nodeType===Node.ELEMENT_NODE){let u=h,s=a;if(u.tagName!==s.tagName){u.parentNode?.replaceChild(s.cloneNode(!0),u);return}let c=u.attributes,g=s.attributes;for(let y=c.length-1;y>=0;y--){let b=c[y].name;s.hasAttribute(b)||u.removeAttribute(b)}for(let y=0;y<g.length;y++){let b=g[y].name,A=g[y].value;u.getAttribute(b)!==A&&u.setAttribute(b,A)}u.tagName==="INPUT"||u.tagName==="TEXTAREA"?(u.value!==s.value&&(u.value=s.value),u.checked!==s.checked&&(u.checked=s.checked)):u.tagName==="SELECT"&&u.value!==s.value&&(u.value=s.value);let d=Array.from(u.childNodes),f=Array.from(s.childNodes),m=d.length,_=f.length,S=Math.max(m,_);for(let y=0;y<S;y++)y>=m?u.appendChild(f[y].cloneNode(!0)):y>=_?u.removeChild(d[y]):i(d[y],f[y])}}function o(h,a){if(typeof document>"u")return;let u=document.createElement(h.tagName);u.innerHTML=a;let s=Array.from(h.childNodes),c=Array.from(u.childNodes),g=s.length,d=c.length,f=Math.max(g,d);for(let m=0;m<f;m++)m>=g?h.appendChild(c[m].cloneNode(!0)):m>=d?h.removeChild(s[m]):i(s[m],c[m])}let l=new Map,w=!1;function T(h,a){l.set(h,a),w||(w=!0,(typeof requestAnimationFrame<"u"?requestAnimationFrame:s=>setTimeout(s,0))(()=>{l.forEach((s,c)=>{o(c,s)}),l.clear(),w=!1}))}p.setStoreState=function(h,a,u){this.uiStores=this.uiStores||new Map,this.uiStores.has(h)||this.uiStores.set(h,{});let s=this.uiStores.get(h);s[a]=u,this.options.debug&&console.log("%c\u{1F4BE} [Dolphin Store Update]:","color: #ec4899; font-weight: bold;",`${h}.${a}`,"=",u),typeof document<"u"&&document.querySelectorAll(`[data-store-read="${h}.${a}"]`).forEach(g=>{g.tagName==="INPUT"||g.tagName==="TEXTAREA"?g.type==="checkbox"?g.checked=!!u:g.value=u??"":g.textContent=u??""}),this.publish(`store/${h}`,s),typeof this._updateDOM=="function"&&this._updateDOM(`store/${h}`,s)},p.getStoreState=function(h,a){this.uiStores=this.uiStores||new Map;let u=this.uiStores.get(h);return u?u[a]:void 0},p._scanStoreBinds=function(){if(typeof document>"u")return;document.querySelectorAll("[data-store-write]").forEach(u=>{let s=u.getAttribute("data-store-write");if(s){let c=s.split(".");if(c.length===2){let g=c[0],d=c[1],f=u.type==="checkbox"?u.checked:u.value;this.uiStores=this.uiStores||new Map,this.uiStores.has(g)||this.uiStores.set(g,{});let m=this.uiStores.get(g);m[d]===void 0&&(m[d]=f)}}}),document.querySelectorAll("[data-store-read]").forEach(u=>{let s=u.getAttribute("data-store-read");if(s){let c=s.split(".");if(c.length===2){let g=c[0],d=c[1],f=this.getStoreState(g,d);f!=null&&(u.tagName==="INPUT"||u.tagName==="TEXTAREA"?u.type==="checkbox"?u.checked=!!f:u.value=f:u.textContent=f)}}})},p.getClosestContext=function(h,a){let u=h;for(;u;){if(u._rtContext){let s=u._rtContext;return a?s[a]:s}u=u.parentElement}return null},p._executeStoreAction=function(h,a){this.uiStores=this.uiStores||new Map;let u=new Proxy({},{has:(s,c)=>!0,get:(s,c)=>{if(typeof c=="string")return new Proxy({},{get:(g,d)=>{if(typeof d=="string")return this.getStoreState(c,d)},set:(g,d,f)=>typeof d=="string"?(this.setStoreState(c,d,f),!0):!1})}});try{new Function("ctx",`with(ctx) { ${h} }`)(u)}catch(s){console.error("%c[Dolphin Store Action Error]:","color: #ef4444; font-weight: bold;",s),a&&console.error("%cFailed Element:","color: #f97316; font-weight: bold;",a),console.error("%cFailed Expression:","color: #3b82f6; font-style: italic;",h)}},p._initDOMBinding=function(){if(this._domInitialized)return;this._domInitialized=!0;let h=["input","change","keyup","paste","blur"],a=new Map;h.forEach(s=>{this.addDomListener(document,s,c=>{if(!c.target||!c.target.getAttribute)return;let g=c.target.getAttribute("data-store-write");if(g){let _=g.split(".");if(_.length===2){let S=_[0],y=_[1],b=c.target.type==="checkbox"?c.target.checked:c.target.value;this.setStoreState(S,y,b)}}let d=c.target.getAttribute("data-rt-validate"),f=c.target.name;if(d&&f&&typeof this.validateField=="function"){let _=c.target.closest("form"),S=_?Object.fromEntries(new FormData(_).entries()):{},y=this.validateField(c.target.value,d,S);y?(c.target.classList.add("invalid"),this.publish(`errors/${f}`,y)):(c.target.classList.remove("invalid"),this.publish(`errors/${f}`,""))}let m=c.target.getAttribute("data-rt-push");if(m){let _=c.target.getAttribute("data-rt-debounce"),S=_?parseInt(_,10):0,y=()=>{let b={name:c.target.name,value:c.target.value};this.pubPush(m,b)};if(S>0){a.has(c.target)&&clearTimeout(a.get(c.target));let b=setTimeout(y,S);a.set(c.target,b)}else y()}})}),this.addDomListener(document,"submit",async s=>{if(!s.target||!s.target.getAttribute)return;let c=s.target.getAttribute("data-rt-submit"),g=s.target.getAttribute("data-api-submit");if(c||g){let d=s.target.querySelectorAll("[data-rt-validate]"),f=!0;if(d.length>0&&typeof this.validateField=="function"){let y=Object.fromEntries(new FormData(s.target).entries());d.forEach(b=>{let A=b.getAttribute("data-rt-validate"),E=b.name;if(A&&E){let v=this.validateField(b.value,A,y);v?(f=!1,b.classList.add("invalid"),this.publish(`errors/${E}`,v)):(b.classList.remove("invalid"),this.publish(`errors/${E}`,""))}})}if(!f){s.preventDefault(),s.stopPropagation();return}s.preventDefault();let m=this.getClosestContext(s.target)||{},_=new FormData(s.target),S=Object.fromEntries(_.entries());if(c){let y=c;for(let b in m){let A=t(b);y=y.replace(new RegExp(`\\{\\{${A}\\}\\}`,"g"),m[b]!==void 0&&m[b]!==null?m[b]:"")}this.publish(y,S)}else if(g){let y=g;for(let v in m){let D=t(v);y=y.replace(new RegExp(`\\{\\{${D}\\}\\}`,"g"),m[v]!==void 0&&m[v]!==null?m[v]:"")}let b=y.trim().split(" "),A=b.length>1?b[0].toUpperCase():"POST",E=b.length>1?b[1]:b[0];try{let v=await this.api.request(A,E,S),D=s.target.getAttribute("data-api-result");D&&this._updateDOM(D,v);let L=s.target.getAttribute("data-api-redirect");L&&(window.location.href=L),s.target.hasAttribute("data-api-reload")&&window.location.reload()}catch(v){console.error("[Dolphin] API Submit Error:",v)}}}}),["click","change","submit","input","keydown","keyup","dblclick","focus","blur","mouseenter","mouseleave"].forEach(s=>{this.addDomListener(document,s,async c=>{if(!c.target||!c.target.closest)return;let g=c.target.closest(`[data-rt-${s}]`),d=c.target.closest(`[data-api-${s}]`);if(g){s==="submit"&&c.preventDefault();let m=g.getAttribute(`data-rt-${s}`),_=g.getAttribute("data-rt-payload"),S=this.getClosestContext(g)||{},y={};if(_){let b=_;for(let A in S){let E=t(A);b=b.replace(new RegExp(`\\{\\{${E}\\}\\}`,"g"),S[A]!==void 0&&S[A]!==null?S[A]:"")}try{y=JSON.parse(b)}catch{y={}}}this.publish(m,y)}if(d){s==="submit"&&c.preventDefault();let m=d.getAttribute(`data-api-${s}`),_=d.getAttribute("data-api-payload"),S=this.getClosestContext(d)||{},y=m.trim().split(" "),b=y.length>1?y[0].toUpperCase():"POST",A=y.length>1?y[1]:y[0],E=null;if(_){let v=_;for(let D in S){let L=t(D);v=v.replace(new RegExp(`\\{\\{${L}\\}\\}`,"g"),S[D]!==void 0&&S[D]!==null?S[D]:"")}try{E=JSON.parse(v)}catch{E=null}}try{let v=await this.api.request(b,A,E),D=d.getAttribute("data-api-result");D&&this._updateDOM(D,v);let L=d.getAttribute("data-api-redirect");L&&(window.location.href=L),d.hasAttribute("data-api-reload")&&window.location.reload()}catch(v){console.error(`[Dolphin] API ${s} Error:`,v)}}let f=c.target.closest(`[data-store-${s}]`);if(f){s==="submit"&&c.preventDefault();let m=f.getAttribute(`data-store-${s}`);m&&this._executeStoreAction(m,f)}})}),this.subscribe("#",(s,c)=>{this._updateDOM(c,s)}),this._scanAndFetchAPIBinds(),this._scanStoreBinds()},p._scanAndFetchAPIBinds=async function(){if(typeof document>"u")return;let h=document.querySelectorAll("[data-api-get]");for(let a of Array.from(h)){let u=a.getAttribute("data-api-get");if(u)try{let s=await this.api.get(u),c=a.getAttribute("data-api-store");if(c){let d=c.split(".");d.length===2&&this.setStoreState(d[0],d[1],s)}let g=a.getAttribute("data-rt-bind");if(g&&!c)this._updateDOM(g,s);else if(!c){let d=e(a);if(d&&typeof s=="object"&&s!==null)if(Array.isArray(s)){let f="";for(let m of s)f+=n(d,m);T(a,f)}else T(a,n(d,s));else a.tagName==="INPUT"||a.tagName==="TEXTAREA"?a.value=typeof s=="object"?s.value!==void 0?s.value:"":s:a.innerHTML=typeof s=="object"?s.html||s.text||JSON.stringify(s):s}}catch(s){console.error("[Dolphin] API Get Error:",s)}}},p._updateDOM=function(h,a){if(typeof document>"u")return;document.querySelectorAll(`[data-rt-bind="${h}"]`).forEach(s=>{if(s.getAttribute("data-rt-type")==="context"&&typeof a=="object"&&a!==null){s._rtContext=a;let g=d=>{if(d.hasAttribute("data-rt-text")){let f=d.getAttribute("data-rt-text");f&&a[f]!==void 0&&a[f]!==null&&(d.textContent=a[f])}if(d.hasAttribute("data-rt-html")){let f=d.getAttribute("data-rt-html");f&&a[f]!==void 0&&a[f]!==null&&(d.innerHTML=r(a[f]))}if(d.hasAttribute("data-rt-attr")){let f=d.getAttribute("data-rt-attr");f&&f.split(",").forEach(m=>{let _=m.split(":");if(_.length===2){let S=_[0].trim(),y=_[1].trim();S&&y&&a[y]!==void 0&&a[y]!==null&&d.setAttribute(S,a[y])}})}if(d.hasAttribute("data-rt-class")){let f=d.getAttribute("data-rt-class");f&&f.split(",").forEach(m=>{let _=m.split(":");if(_.length===2){let S=_[0].trim(),y=_[1].trim(),b=S.split(/\s+/).filter(Boolean);a[y]?b.forEach(A=>d.classList.add(A)):b.forEach(A=>d.classList.remove(A))}})}if(d.hasAttribute("data-rt-if")){let f=d.getAttribute("data-rt-if");f&&(a[f]?d.style.display="":d.style.display="none")}if(d.hasAttribute("data-rt-hide")){let f=d.getAttribute("data-rt-hide");f&&(a[f]?d.style.display="none":d.style.display="")}};g(s),s.querySelectorAll("[data-rt-text], [data-rt-html], [data-rt-attr], [data-rt-class], [data-rt-if], [data-rt-hide]").forEach(g);return}let c=e(s);if(c&&typeof a=="object"&&a!==null){if(Array.isArray(a)){let g="";for(let d of a)g+=n(c,d);T(s,g)}else T(s,n(c,a));return}s.tagName==="INPUT"||s.tagName==="TEXTAREA"?s.value=typeof a=="object"?a.value!==void 0?a.value:"":a:s.innerHTML=typeof a=="object"?a.html||a.text||JSON.stringify(a):a})}}var I=class{client;db;isOnline;memoryCache=new Map;memoryMutations=[];constructor(t){this.client=t,this.isOnline=typeof window<"u"&&typeof navigator<"u"?navigator.onLine:!0,this.initDB(),this.setupNetworkListeners()}initDB(){if(!(typeof indexedDB>"u"))try{let t=indexedDB.open("dolphin_offline",1);t.onupgradeneeded=e=>{let n=e.target.result;n.objectStoreNames.contains("cache")||n.createObjectStore("cache"),n.objectStoreNames.contains("mutations")||n.createObjectStore("mutations",{keyPath:"id",autoIncrement:!0})},t.onsuccess=e=>{this.db=e.target.result,this.isOnline&&this.syncMutations()}}catch(t){console.warn("[Dolphin Offline] Failed to initialize IndexedDB:",t)}}setupNetworkListeners(){typeof window>"u"||(this.client.addDomListener(window,"online",()=>{this.isOnline=!0,this.client._dispatch("network:status",{online:!0}),this.syncMutations()}),this.client.addDomListener(window,"offline",()=>{this.isOnline=!1,this.client._dispatch("network:status",{online:!1})}))}async getCache(t){return this.db?new Promise(e=>{try{let i=this.db.transaction("cache","readonly").objectStore("cache").get(t);i.onsuccess=()=>e(i.result?i.result.data:null),i.onerror=()=>e(null)}catch{e(null)}}):this.memoryCache.get(t)}async setCache(t,e){if(!this.db){this.memoryCache.set(t,e);return}return new Promise(n=>{try{let r=this.db.transaction("cache","readwrite");r.objectStore("cache").put({data:e,timestamp:Date.now()},t),r.oncomplete=()=>n()}catch{n()}})}async queueMutation(t,e,n){let r={method:t,path:e,payload:n,timestamp:Date.now()};if(!this.db){this.memoryMutations.push(r);return}return new Promise(i=>{try{let o=this.db.transaction("mutations","readwrite");o.objectStore("mutations").add(r),o.oncomplete=()=>i()}catch{i()}})}async getMutations(){return this.db?new Promise(t=>{try{let r=this.db.transaction("mutations","readonly").objectStore("mutations").getAll();r.onsuccess=()=>t(r.result||[]),r.onerror=()=>t([])}catch{t([])}}):[...this.memoryMutations]}async removeMutation(t){if(!this.db){this.memoryMutations=this.memoryMutations.filter(e=>e.id!==t);return}return new Promise(e=>{try{let n=this.db.transaction("mutations","readwrite");n.objectStore("mutations").delete(t),n.oncomplete=()=>e()}catch{e()}})}async syncMutations(){let t=await this.getMutations();if(t.length!==0){console.log(`[Dolphin Offline] Syncing ${t.length} queued mutations...`);for(let e of t)try{await this.client.api.requestDirect(e.method,e.path,e.payload),e.id!==void 0?await this.removeMutation(e.id):this.memoryMutations.shift()}catch(n){if(console.error(`[Dolphin Offline] Sync failed for mutation ${e.method} ${e.path}:`,n),n&&n.status&&n.status>=400&&n.status<500)console.warn("[Dolphin Offline] Discarding invalid mutation."),e.id!==void 0?await this.removeMutation(e.id):this.memoryMutations.shift();else break}}}};function q(p){p._initOffline=function(){this.offline=new I(this)}}function Y(p,t,e){let n=t.split(",");for(let r of n){let i=r.trim().split(":"),o=i[0],l=i[1];if(o==="required"){if(!p||p.trim()==="")return"This field is required"}else if(o==="email"){if(p&&p.trim()!==""&&!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(p))return"Please enter a valid email address"}else if(o==="min"){let w=parseInt(l,10);if(!p||p.length<w)return`Must be at least ${w} characters`}else if(o==="match"&&e&&p!==e[l])return`Must match ${l}`}return null}function O(p){p.validateField=Y}function N(p){p.animateElement=function(t,e,n=300){if(typeof t.animate!="function"){t.classList.add(e),setTimeout(()=>t.classList.remove(e),n);return}e==="fade-in"?t.animate([{opacity:0,transform:"translateY(10px)"},{opacity:1,transform:"translateY(0)"}],{duration:n,easing:"ease-out"}):e==="fade-out"&&t.animate([{opacity:1,transform:"translateY(0)"},{opacity:0,transform:"translateY(10px)"}],{duration:n,easing:"ease-in"})},p.staggerListItems=function(t,e,n=50){if(typeof document>"u")return;t.querySelectorAll(e).forEach((i,o)=>{i.style.animationDelay=`${o*n}ms`,i.classList.add("staggered-item")})}}function U(p){p._initA11y=function(){typeof document>"u"||(this.addDomListener(document,"keydown",t=>{if(t.key!=="Tab")return;document.querySelectorAll("[data-rt-a11y-focus-trap]").forEach(n=>{if(n.style.display==="none"||n.hasAttribute("aria-hidden")&&n.getAttribute("aria-hidden")==="true")return;let i=Array.from(n.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex="0"], [contenteditable]'));if(i.length===0)return;let o=i[0],l=i[i.length-1];t.shiftKey?document.activeElement===o&&(l.focus(),t.preventDefault()):document.activeElement===l&&(o.focus(),t.preventDefault())})}),this.addDomListener(document,"keydown",t=>{if(!["ArrowUp","ArrowDown","Enter"].includes(t.key))return;document.querySelectorAll("[data-rt-keynav]").forEach(n=>{let r=Array.from(n.children);if(r.length===0)return;let i=r.findIndex(o=>o.classList.contains("active")||document.activeElement===o);t.key==="ArrowDown"?(i=(i+1)%r.length,r[i].focus(),r.forEach((o,l)=>{l===i?o.classList.add("active"):o.classList.remove("active")}),t.preventDefault()):t.key==="ArrowUp"?(i=(i-1+r.length)%r.length,r[i].focus(),r.forEach((o,l)=>{l===i?o.classList.add("active"):o.classList.remove("active")}),t.preventDefault()):t.key==="Enter"&&i!==-1&&(r[i].click(),t.preventDefault())})}))},p.autoAriaModal=function(t,e){e?(t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-hidden","false"),t.focus()):t.setAttribute("aria-hidden","true")}}function F(p){p._initI18n=function(){if(this.i18n=this.i18n||{locale:"en",dicts:{}},typeof document>"u")return;if(document.querySelectorAll("[data-i18n-dict]").forEach(e=>{let n=e.getAttribute("data-i18n-dict");if(n)try{let r=JSON.parse(e.textContent||"{}");this.i18n.dicts[n]={...this.i18n.dicts[n]||{},...r}}catch(r){console.warn("[Dolphin i18n] Failed to parse dictionary for locale:",n,r)}}),!this.i18n.locale&&typeof navigator<"u"){let e=navigator.language.split("-")[0];this.i18n.dicts[e]&&(this.i18n.locale=e)}this.addDomListener(document,"click",e=>{let n=e.target.closest("[data-i18n-switch]");if(n){let r=n.getAttribute("data-i18n-switch");r&&this.setLocale(r)}}),this.translateDOM()},p.setLocale=function(t){this.i18n=this.i18n||{locale:"en",dicts:{}},this.i18n.locale=t,this.translateDOM(),this.publish("i18n/locale",t)},p.translateDOM=function(){if(typeof document>"u")return;this.i18n=this.i18n||{locale:"en",dicts:{}};let t=this.i18n.locale||"en",e=this.i18n.dicts[t]||{};document.querySelectorAll("[data-i18n-key]").forEach(r=>{let i=r.getAttribute("data-i18n-key");if(!i)return;let o=i.split(".").reduce((w,T)=>w?w[T]:null,e);o==null&&(o=i);let l=r.getAttribute("data-i18n-params");if(l)try{let w=JSON.parse(l),T=h=>h.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");for(let h in w){let a=T(h);o=o.replace(new RegExp(`\\{\\{${a}\\}\\}`,"g"),w[h])}}catch{}r.tagName==="INPUT"||r.tagName==="TEXTAREA"?r.placeholder=o:r.textContent=o})}}function H(p){p._initDragDrop=function(){typeof document>"u"||(this.addDomListener(document,"dragstart",t=>{let e=t.target.closest("[data-drag]");if(!e)return;let n=e.getAttribute("data-drag");n&&(t.dataTransfer.setData("text/plain",n),t.dataTransfer.effectAllowed="move",e.classList.add("dragging"))}),this.addDomListener(document,"dragend",t=>{let e=t.target.closest("[data-drag]");e&&e.classList.remove("dragging")}),this.addDomListener(document,"dragover",t=>{let e=t.target.closest("[data-drop]");e&&(t.preventDefault(),e.classList.add("drag-over"))}),this.addDomListener(document,"dragleave",t=>{let e=t.target.closest("[data-drop]");e&&e.classList.remove("drag-over")}),this.addDomListener(document,"drop",t=>{let e=t.target.closest("[data-drop]");if(!e)return;t.preventDefault(),e.classList.remove("drag-over");let n=e.getAttribute("data-drop"),r=t.dataTransfer.getData("text/plain");if(n&&r)try{let i=JSON.parse(r);this.publish(n,i)}catch{this.publish(n,{value:r})}}),this.addDomListener(document,"dragover",t=>{let e=t.target.closest("[data-sortable]");if(!e)return;t.preventDefault();let n=e.querySelector(".dragging");if(!n)return;let i=Array.from(e.querySelectorAll("[data-drag]:not(.dragging)")).find(o=>{let l=o.getBoundingClientRect();return t.clientY-l.top-l.height/2<0});i?e.insertBefore(n,i):e.appendChild(n)}),this.addDomListener(document,"drop",t=>{let e=t.target.closest("[data-sortable]");if(!e)return;let n=e.getAttribute("data-sortable");if(!n)return;let i=Array.from(e.querySelectorAll("[data-drag]")).map((o,l)=>{let w=o.getAttribute("data-drag");try{return{index:l,payload:JSON.parse(w||"{}")}}catch{return{index:l,payload:w}}});this.publish(n,i)}))}}function W(p){p._initCollab=function(){typeof document>"u"||(this.addDomListener(document,"mousemove",t=>{document.querySelectorAll("[data-rt-cursor-share]").forEach(n=>{let r=n.getAttribute("data-rt-cursor-share");if(!r)return;let i=n.getBoundingClientRect(),o=(t.clientX-i.left)/i.width,l=(t.clientY-i.top)/i.height,w=Date.now();(!n._lastSent||w-n._lastSent>50)&&(n._lastSent=w,this.pubPush(`collab/${r}/cursor/${this.deviceId}`,{deviceId:this.deviceId,x:o,y:l}))})}),this.addDomListener(document,"input",t=>{let e=t.target.getAttribute("data-rt-typing");if(!e)return;let n=e,r=i=>{this.pubPush(`collab/${n}/typing/${this.deviceId}`,{deviceId:this.deviceId,typing:i})};t.target._isTyping||(t.target._isTyping=!0,r(!0)),t.target._typingTimer&&clearTimeout(t.target._typingTimer),t.target._typingTimer=setTimeout(()=>{t.target._isTyping=!1,r(!1)},2e3)}),this.addDomListener(document,"input",t=>{let e=t.target.getAttribute("data-rt-crdt");if(!e)return;let n=e,r=t.target.value,i=Date.now();this.publish(`collab/${n}/crdt`,{deviceId:this.deviceId,value:r,timestamp:i,cursorPos:t.target.selectionStart})}),this.subscribe("collab/+/cursor/+",(t,e)=>{let n=e.split("/"),r=n[1],i=n[3];if(i===this.deviceId)return;let o=document.querySelector(`[data-rt-cursor-share="${r}"]`);if(!o)return;let l=o.querySelector(`.rt-cursor-${i}`);l||(l=document.createElement("div"),l.className=`rt-cursor rt-cursor-${i}`,l.style.position="absolute",l.style.width="10px",l.style.height="10px",l.style.borderRadius="50%",l.style.backgroundColor="#"+Math.floor(Math.random()*16777215).toString(16),l.style.pointerEvents="none",o.appendChild(l));let w=o.getBoundingClientRect();l.style.left=t.x*w.width+"px",l.style.top=t.y*w.height+"px"}),this.subscribe("collab/+/crdt",(t,e)=>{if(t.deviceId===this.deviceId)return;let r=e.split("/")[1];document.querySelectorAll(`[data-rt-crdt="${r}"]`).forEach(o=>{if(!o._lastUpdate||t.timestamp>o._lastUpdate){o._lastUpdate=t.timestamp;let l=o.selectionStart;o.value=t.value,document.activeElement===o&&o.setSelectionRange(l,l)}})}))}}function j(p){p.registerServiceWorker=async function(t="/sw.js"){if(typeof navigator>"u"||!("serviceWorker"in navigator))return console.warn("[Dolphin PWA] Service Workers are not supported in this browser."),null;try{let e=await navigator.serviceWorker.register(t);return console.log("[Dolphin PWA] Service Worker registered successfully with scope:",e.scope),e}catch(e){return console.error("[Dolphin PWA] Service Worker registration failed:",e),null}},p.subscribePushNotifications=async function(t){if(typeof window>"u"||!("serviceWorker"in navigator)||!("PushManager"in window))return console.warn("[Dolphin PWA] Push notifications are not supported in this browser."),null;try{let e=await navigator.serviceWorker.ready,n=await e.pushManager.getSubscription();if(!n){let r="=".repeat((4-t.length%4)%4),i=(t+r).replace(/\-/g,"+").replace(/_/g,"/"),o=window.atob(i),l=new Uint8Array(o.length);for(let w=0;w<o.length;++w)l[w]=o.charCodeAt(w);n=await e.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:l})}return console.log("[Dolphin PWA] Subscribed to push notifications:",n),n}catch(e){return console.error("[Dolphin PWA] Push notification subscription failed:",e),null}}}var P=class{static render(t){if(typeof document>"u")throw new Error("DolphinTestUtils.render requires a DOM document environment to execute.");let e=document.createElement("div");return e.innerHTML=t,document.body.appendChild(e),{container:e,find:n=>e.querySelector(n),fireEvent:(n,r)=>{let i=document.createEvent("Event");i.initEvent(r,!0,!0),n.dispatchEvent(i)}}}static mockWebSocket(){let t=[],e={readyState:1,send:n=>{t.push(n)},close:jest.fn(),onopen:jest.fn(),onmessage:jest.fn(),onclose:jest.fn(),onerror:jest.fn(),sentMessages:t};return global.WebSocket=class{static OPEN=1;readyState=e.readyState;send=e.send;close=e.close;set onopen(n){e.onopen=n}get onopen(){return e.onopen}set onmessage(n){e.onmessage=n}get onmessage(){return e.onmessage}set onclose(n){e.onclose=n}get getonclose(){return e.onclose}constructor(){setTimeout(()=>e.onopen&&e.onopen(),0)}},e}static simulateClick(t){let e={target:t,preventDefault:jest.fn(),stopPropagation:jest.fn()};(global.document._listeners?.click||[]).forEach(r=>r(e))}static simulateChange(t,e){t.value=e;let n={target:t,preventDefault:jest.fn(),stopPropagation:jest.fn()};(global.document._listeners?.change||[]).forEach(i=>i(n))}};function B(p){p.testing=P}R(k.prototype);q(k.prototype);O(k.prototype);N(k.prototype);U(k.prototype);F(k.prototype);H(k.prototype);W(k.prototype);j(k.prototype);B(k.prototype);typeof window<"u"&&(window.DolphinClient=k,document.addEventListener("DOMContentLoaded",()=>{if(!window.dolphin){let p=document.querySelector('script[src*="dolphin-client"]'),t=p?p.getAttribute("data-debug")==="true":!1,e=new k(void 0,void 0,{debug:t});window.dolphin=e,t&&(console.log("%c\u{1F42C} [Dolphin Client] Auto-initialized local reactive engine!","color: #06b6d4; font-weight: bold; font-size: 14px;"),console.log('%c\u{1F449} Tip: You can access the client instance via "window.dolphin" in console.',"color: #94a3b8; font-style: italic;")),document.querySelector('[data-store-write="app.username"]')&&e.setStoreState("app","username","\u0928\u092E\u0938\u094D\u0924\u0947 \u0938\u093E\u0925\u0940!")}}));return X(Z);})();
|
package/dist/index.cjs
CHANGED
|
@@ -107,7 +107,7 @@ var APIHandler = class {
|
|
|
107
107
|
*/
|
|
108
108
|
async requestDirect(method, path, body = null, options = {}) {
|
|
109
109
|
const _isRetry = options._isRetry === true;
|
|
110
|
-
const url = `${this.client.httpUrl}${path.startsWith("/") ? path : "/" + path}`;
|
|
110
|
+
const url = path.startsWith("http://") || path.startsWith("https://") ? path : `${this.client.httpUrl}${path.startsWith("/") ? path : "/" + path}`;
|
|
111
111
|
if (this.client.options.debug) {
|
|
112
112
|
console.log(`%c\u{1F680} [Dolphin API Request]:`, "color: #3b82f6; font-weight: bold;", method.toUpperCase(), path, body || "");
|
|
113
113
|
}
|
|
@@ -894,8 +894,28 @@ function attachDOMBinding(clientProto) {
|
|
|
894
894
|
}
|
|
895
895
|
}
|
|
896
896
|
`;
|
|
897
|
+
let safeContext = context;
|
|
898
|
+
if (typeof Proxy !== "undefined" && context !== null && typeof context === "object") {
|
|
899
|
+
safeContext = new Proxy(context, {
|
|
900
|
+
has(target, key) {
|
|
901
|
+
if (typeof key === "symbol") return false;
|
|
902
|
+
return true;
|
|
903
|
+
},
|
|
904
|
+
get(target, key) {
|
|
905
|
+
if (key === Symbol.unscopables) return void 0;
|
|
906
|
+
if (key in target) return target[key];
|
|
907
|
+
if (typeof globalThis !== "undefined" && key in globalThis) {
|
|
908
|
+
return globalThis[key];
|
|
909
|
+
}
|
|
910
|
+
if (typeof window !== "undefined" && key in window) {
|
|
911
|
+
return window[key];
|
|
912
|
+
}
|
|
913
|
+
return void 0;
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
}
|
|
897
917
|
const fn = new Function("context", fnBody);
|
|
898
|
-
return fn(
|
|
918
|
+
return fn(safeContext);
|
|
899
919
|
} catch (e) {
|
|
900
920
|
console.error("[Dolphin Template Compiler Error]:", e);
|
|
901
921
|
let fallback = templateStr;
|
|
@@ -1047,6 +1067,9 @@ function attachDOMBinding(clientProto) {
|
|
|
1047
1067
|
});
|
|
1048
1068
|
}
|
|
1049
1069
|
this.publish(`store/${storeName}`, store);
|
|
1070
|
+
if (typeof this._updateDOM === "function") {
|
|
1071
|
+
this._updateDOM(`store/${storeName}`, store);
|
|
1072
|
+
}
|
|
1050
1073
|
};
|
|
1051
1074
|
clientProto.getStoreState = function(storeName, key) {
|
|
1052
1075
|
this.uiStores = this.uiStores || /* @__PURE__ */ new Map();
|
|
@@ -1344,10 +1367,17 @@ function attachDOMBinding(clientProto) {
|
|
|
1344
1367
|
if (!path) continue;
|
|
1345
1368
|
try {
|
|
1346
1369
|
const result = await this.api.get(path);
|
|
1370
|
+
const apiStore = el.getAttribute("data-api-store");
|
|
1371
|
+
if (apiStore) {
|
|
1372
|
+
const parts = apiStore.split(".");
|
|
1373
|
+
if (parts.length === 2) {
|
|
1374
|
+
this.setStoreState(parts[0], parts[1], result);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1347
1377
|
const rtBind = el.getAttribute("data-rt-bind");
|
|
1348
|
-
if (rtBind) {
|
|
1378
|
+
if (rtBind && !apiStore) {
|
|
1349
1379
|
this._updateDOM(rtBind, result);
|
|
1350
|
-
} else {
|
|
1380
|
+
} else if (!apiStore) {
|
|
1351
1381
|
const template = resolveTemplate(el);
|
|
1352
1382
|
if (template && typeof result === "object" && result !== null) {
|
|
1353
1383
|
if (Array.isArray(result)) {
|
|
@@ -1412,10 +1442,11 @@ function attachDOMBinding(clientProto) {
|
|
|
1412
1442
|
if (parts.length === 2) {
|
|
1413
1443
|
const className = parts[0].trim();
|
|
1414
1444
|
const key = parts[1].trim();
|
|
1445
|
+
const classNames = className.split(/\s+/).filter(Boolean);
|
|
1415
1446
|
if (payload[key]) {
|
|
1416
|
-
node.classList.add(
|
|
1447
|
+
classNames.forEach((c) => node.classList.add(c));
|
|
1417
1448
|
} else {
|
|
1418
|
-
node.classList.remove(
|
|
1449
|
+
classNames.forEach((c) => node.classList.remove(c));
|
|
1419
1450
|
}
|
|
1420
1451
|
}
|
|
1421
1452
|
});
|
package/dist/index.js
CHANGED
|
@@ -82,7 +82,7 @@ var APIHandler = class {
|
|
|
82
82
|
*/
|
|
83
83
|
async requestDirect(method, path, body = null, options = {}) {
|
|
84
84
|
const _isRetry = options._isRetry === true;
|
|
85
|
-
const url = `${this.client.httpUrl}${path.startsWith("/") ? path : "/" + path}`;
|
|
85
|
+
const url = path.startsWith("http://") || path.startsWith("https://") ? path : `${this.client.httpUrl}${path.startsWith("/") ? path : "/" + path}`;
|
|
86
86
|
if (this.client.options.debug) {
|
|
87
87
|
console.log(`%c\u{1F680} [Dolphin API Request]:`, "color: #3b82f6; font-weight: bold;", method.toUpperCase(), path, body || "");
|
|
88
88
|
}
|
|
@@ -869,8 +869,28 @@ function attachDOMBinding(clientProto) {
|
|
|
869
869
|
}
|
|
870
870
|
}
|
|
871
871
|
`;
|
|
872
|
+
let safeContext = context;
|
|
873
|
+
if (typeof Proxy !== "undefined" && context !== null && typeof context === "object") {
|
|
874
|
+
safeContext = new Proxy(context, {
|
|
875
|
+
has(target, key) {
|
|
876
|
+
if (typeof key === "symbol") return false;
|
|
877
|
+
return true;
|
|
878
|
+
},
|
|
879
|
+
get(target, key) {
|
|
880
|
+
if (key === Symbol.unscopables) return void 0;
|
|
881
|
+
if (key in target) return target[key];
|
|
882
|
+
if (typeof globalThis !== "undefined" && key in globalThis) {
|
|
883
|
+
return globalThis[key];
|
|
884
|
+
}
|
|
885
|
+
if (typeof window !== "undefined" && key in window) {
|
|
886
|
+
return window[key];
|
|
887
|
+
}
|
|
888
|
+
return void 0;
|
|
889
|
+
}
|
|
890
|
+
});
|
|
891
|
+
}
|
|
872
892
|
const fn = new Function("context", fnBody);
|
|
873
|
-
return fn(
|
|
893
|
+
return fn(safeContext);
|
|
874
894
|
} catch (e) {
|
|
875
895
|
console.error("[Dolphin Template Compiler Error]:", e);
|
|
876
896
|
let fallback = templateStr;
|
|
@@ -1022,6 +1042,9 @@ function attachDOMBinding(clientProto) {
|
|
|
1022
1042
|
});
|
|
1023
1043
|
}
|
|
1024
1044
|
this.publish(`store/${storeName}`, store);
|
|
1045
|
+
if (typeof this._updateDOM === "function") {
|
|
1046
|
+
this._updateDOM(`store/${storeName}`, store);
|
|
1047
|
+
}
|
|
1025
1048
|
};
|
|
1026
1049
|
clientProto.getStoreState = function(storeName, key) {
|
|
1027
1050
|
this.uiStores = this.uiStores || /* @__PURE__ */ new Map();
|
|
@@ -1319,10 +1342,17 @@ function attachDOMBinding(clientProto) {
|
|
|
1319
1342
|
if (!path) continue;
|
|
1320
1343
|
try {
|
|
1321
1344
|
const result = await this.api.get(path);
|
|
1345
|
+
const apiStore = el.getAttribute("data-api-store");
|
|
1346
|
+
if (apiStore) {
|
|
1347
|
+
const parts = apiStore.split(".");
|
|
1348
|
+
if (parts.length === 2) {
|
|
1349
|
+
this.setStoreState(parts[0], parts[1], result);
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1322
1352
|
const rtBind = el.getAttribute("data-rt-bind");
|
|
1323
|
-
if (rtBind) {
|
|
1353
|
+
if (rtBind && !apiStore) {
|
|
1324
1354
|
this._updateDOM(rtBind, result);
|
|
1325
|
-
} else {
|
|
1355
|
+
} else if (!apiStore) {
|
|
1326
1356
|
const template = resolveTemplate(el);
|
|
1327
1357
|
if (template && typeof result === "object" && result !== null) {
|
|
1328
1358
|
if (Array.isArray(result)) {
|
|
@@ -1387,10 +1417,11 @@ function attachDOMBinding(clientProto) {
|
|
|
1387
1417
|
if (parts.length === 2) {
|
|
1388
1418
|
const className = parts[0].trim();
|
|
1389
1419
|
const key = parts[1].trim();
|
|
1420
|
+
const classNames = className.split(/\s+/).filter(Boolean);
|
|
1390
1421
|
if (payload[key]) {
|
|
1391
|
-
node.classList.add(
|
|
1422
|
+
classNames.forEach((c) => node.classList.add(c));
|
|
1392
1423
|
} else {
|
|
1393
|
-
node.classList.remove(
|
|
1424
|
+
classNames.forEach((c) => node.classList.remove(c));
|
|
1394
1425
|
}
|
|
1395
1426
|
}
|
|
1396
1427
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dolphin-client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "HTML is back! Hookless, framework-agnostic real-time reactive DOM-binding client for Dolphin Server with WebSockets, WebRTC signaling, and offline REST API fallbacks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|