@idosgames/app-shell 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var client=require('react-dom/client'),react$1=require('@idosgames/react'),moduleSdk=require('@idosgames/module-sdk'),react=require('react'),core=require('@idosgames/core'),jsxRuntime=require('react/jsx-runtime');var Ee=50,T="host",ne=e=>typeof e=="string"?e:e.name,re=e=>typeof e=="string"?null:e.shape,se=e=>e.replace(/@\d+$/,"");function D(){let e=new Map,o=new Map,t=[],s=new Set,i=r=>{t.push(r),t.length>Ee&&t.shift();},l=(r,n)=>{s.has(r)||(s.add(r),console.warn(n));},d=(r,n,c)=>{console.error(`[idos events] ${c}`),i({topic:n,from:r,at:Date.now(),delivered:0,rejected:c});},y=(r,n,c,p)=>{if(!moduleSdk.isTopicName(n)){d(r,n,`"${r}" emitted "${n}", which is not a topic name \u2014 use defineTopic("<module-id>:<event>@<major>", shape({\u2026})). Not delivered.`);return}let u=moduleSdk.topicNamespace(n);if(r!==T&&u===T){d(r,n,`"${r}" emitted "${n}", but the "host:" namespace belongs to the host. Not delivered.`);return}if(r!==T&&u!==r){d(r,n,`"${r}" emitted "${n}" into the "${u}" namespace \u2014 a module may only emit its own topics ("${r}:\u2026"). Not delivered.`);return}if(c){let v=c.check(p);v&&l(`emit|${r}|${n}`,`[idos events] "${r}" emitted "${n}" with a payload that does not match its own shape: ${v}. Fix the emit or the topic's shape (and module.meta.json).`);}let m=o.get(n);m||o.set(n,m=new Set),m.add(r);let S=0;for(let v of [...e.get(n)??[]]){if(v.shape){let x=v.shape.check(p);if(x){l(`on|${v.moduleId}|${n}`,`[idos events] "${v.moduleId}" skipped "${n}" from "${r}": ${x}. Its copy of the topic's shape no longer matches the emitter \u2014 re-copy it from the catalog.`);continue}}try{v.handler(p),S+=1;}catch(x){console.error(`[idos events] a "${n}" handler in "${v.moduleId}" threw \u2014 other listeners still received the event.`,x);}}i({topic:n,from:r,at:Date.now(),delivered:S});},g=(r,n,c)=>{let p=e.get(n);return p||e.set(n,p=new Set),p.add(c),()=>{let u=e.get(n);u&&(u.delete(c),u.size===0&&e.delete(n));}};return {forModule(r){let n=new Set,c=false;return {emit(u,m){c||y(r,ne(u),re(u),m);},on(u,m){if(c)return ()=>{};let S=ne(u);moduleSdk.isTopicName(S)||console.warn(`[idos events] "${r}" subscribed to "${S}", which is not a topic name \u2014 nothing can ever be emitted to it.`);let v=g(r,S,{moduleId:r,shape:re(u),handler:m});return n.add(v),()=>{v(),n.delete(v);}},dispose(){c=true;for(let u of n)u();n.clear();}}},emitAsHost(r,n){y(T,r.name,r.shape,n);},describe(){let r={};for(let[p,u]of e)r[p]=[...new Set([...u].map(m=>m.moduleId))];let n={};for(let[p,u]of o)n[p]=[...u];let c=[];for(let[p,u]of Object.entries(r)){if(o.has(p))continue;let m=[...o.keys()].filter(S=>S!==p&&se(S)===se(p));m.length>0&&c.push(`${u.join(", ")} listen${u.length===1?"s":""} to "${p}", but only ${m.map(S=>`"${S}"`).join(", ")} ${m.length===1?"has":"have"} been emitted \u2014 the major versions differ, so these never meet.`);}return {log:t.slice(),listeners:r,emitted:n,mismatches:c}}}}function ke(){let e=new Map;return {emit(o,t){let s=e.get(o);if(s)for(let i of [...s])i(t);},on(o,t){let s=t,i=e.get(o);return i||(i=new Set,e.set(o,i)),i.add(s),()=>{i.delete(s),i.size===0&&e.delete(o);}}}}function le(){return Object.fromEntries(moduleSdk.SHARED_UI_ROLES.map(e=>[e,null]))}function A(e){let o=le(),t=[],s=moduleSdk.SHARED_UI_ROLES.join(", ");for(let i of e)for(let l of i.sharedUi?.provides??[]){if(!moduleSdk.isSharedUiRole(l)){t.push(`module "${i.id}" provides unknown shared UI role "${String(l)}" (known: ${s}) \u2014 ignored.`);continue}let d=o[l];d===null?o[l]=i.id:d!==i.id&&t.push(`shared UI role "${l}" is provided by both "${d}" and "${i.id}" \u2014 "${d}" wins (it comes first in src/modules.ts), "${i.id}" hides its copy.`);}for(let i of e)for(let l of i.sharedUi?.requires??[]){if(!moduleSdk.isSharedUiRole(l)){t.push(`module "${i.id}" requires unknown shared UI role "${String(l)}" (known: ${s}).`);continue}o[l]===null&&t.push(`module "${i.id}" requires shared UI role "${l}", but no installed module provides it \u2014 install game-hud (or another module that provides "${l}").`);}return {owners:o,warnings:t}}function B(e,o){let t=s=>e[s]??null;return {ownerOf:t,shouldDraw:s=>{let i=t(s);return i===null||i===o}}}var Me={position:"absolute",inset:"0"};function N(e){return {request(o){let t=document.createElement("div");return t.dataset.surface=o,Object.assign(t.style,Me),t.style.pointerEvents=o==="fullbleed-canvas"?"auto":"none",e.appendChild(t),{host:t,release(){t.remove();}}}}}var Ce="__IDOS_AGENT__",de={},ce,ue;function He(){try{return typeof window<"u"&&window.self!==window.top}catch{return true}}function z(e,o){de[e]=o,j();}function G(e){ce=e,j();}function _(e){ue=e,j();}function j(){if(!He())return;let e={version:1,modules:de,host:ce,events:ue};globalThis[Ce]=e;}function W(){let e=new Map,o=new Set,t=()=>{for(let s of o)s();};return {registerType(s){if(!s?.type)throw new Error("ctx.content.registerType(): handler.type is required");return e.set(s.type,s),t(),()=>{e.get(s.type)===s&&(e.delete(s.type),t());}},getType:s=>e.get(s),listTypes:()=>[...e.values()],subscribe(s){return o.add(s),()=>{o.delete(s);}}}}function V(){let e=null,o=null;return {navigate(t){t&&(e?e(t):o=t);},bind(t){if(e=t,o!==null){let s=o;o=null,t(s);}return ()=>{e===t&&(e=null);}}}}function F(e,o){let t=o.sharedUi??A(e).owners,s=o.content??W(),i=[];try{for(let l of e){let d=o.events.forModule(l.id),y=[],g={module:l,scenes:[],panels:[],routes:[],dispose:()=>{d.dispose();for(let n of y.splice(0))n();}};i.push(g);let r={client:o.client,titleId:o.client.titleID,events:d,sharedUi:B(t,l.id),surface:o.surface,registerScene:n=>g.scenes.push(n),registerPanel:n=>g.panels.push(n),registerRoute:n=>g.routes.push(n),content:{registerType:n=>{let c=s.registerType(n);return y.push(c),c},getType:n=>s.getType(n),listTypes:()=>s.listTypes(),subscribe:n=>s.subscribe(n)},navigate:n=>o.navigator?.navigate(n),exposeToAgent:n=>z(l.id,n)};l.setup(r);}}catch(l){for(let d of i)d.dispose();throw l}return i}var I=class{constructor(o){this.container=o;}container;hosts=new Map;active=new Set;ensureMounted(o){let t=this.hosts.get(o);return t||(t=document.createElement("div"),Object.assign(t.style,{position:"absolute",inset:"0"}),this.container.appendChild(t),this.hosts.set(o,t),o.mount({host:t})),t}setActive(o){let t=new Set(o);for(let s of this.active){if(t.has(s))continue;s.suspend?.();let i=this.hosts.get(s);i&&(i.style.display="none");}for(let s of t){if(this.active.has(s))continue;let i=this.ensureMounted(s);i.style.display="block",s.activate?.();}this.active=t;}destroy(){for(let[o,t]of this.hosts)o.destroy(),t.remove();this.hosts.clear(),this.active.clear();}};function X({registrations:e,sharedUi:o,events:t,onLogout:s,userID:i,navigator:l}){let d=react.useRef(null),y=react.useRef(null),g=react.useMemo(()=>e.flatMap(a=>a.routes.map(f=>({id:f.id,label:f.label,icon:f.icon,order:f.order??0,moduleId:a.module.id}))).sort((a,f)=>a.order-f.order),[e]),[r,n]=react.useState(()=>g[0]?.id??null);react.useEffect(()=>{r!==null&&g.some(a=>a.id===r)||n(g[0]?.id??null);},[g,r]),react.useEffect(()=>l?.bind(a=>{g.some(f=>f.id===a)&&n(a);}),[l,g]);let c=react.useMemo(()=>g.find(a=>a.id===r)?.moduleId??null,[g,r]),p=react.useRef(null);react.useEffect(()=>{if(r===null||r===p.current)return;let a=p.current;p.current=r,t?.emitAsHost(moduleSdk.hostTopics.modeChanged,a===null?{to:r}:{from:a,to:r});},[r,t]),react.useEffect(()=>{let a=d.current;if(!a)return;let f=y.current??=new I(a),C=e.find(U=>U.module.id===c)?.scenes??[];f.setActive(C);},[e,c]),react.useEffect(()=>()=>{y.current?.destroy(),y.current=null;},[]);let u=react.useMemo(()=>e.flatMap(a=>a.panels.filter(f=>f.activeOnly===false||a.module.id===c).map(f=>{let C=f.component;return {key:`${a.module.id}:${f.id}`,slot:f.slot,order:f.order??0,moduleId:a.module.id,component:jsxRuntime.jsx(C,{})}})).sort((a,f)=>a.order-f.order),[e,c]),m=a=>u.filter(f=>f.slot===a),S=e.length>0,v=m("hud").length,x=g.length>1,b=!o?.account,R=react.useRef(null),k=react.useRef(null),[M,we]=react.useState({top:0,bottom:0});react.useLayoutEffect(()=>{let a=()=>{let C=v>0&&R.current?Math.ceil(R.current.getBoundingClientRect().height):0,U=x&&k.current?Math.ceil(k.current.getBoundingClientRect().height)+fe:0;we(O=>O.top===C&&O.bottom===U?O:{top:C,bottom:U});};if(a(),typeof ResizeObserver>"u")return;let f=new ResizeObserver(a);return R.current&&f.observe(R.current),k.current&&f.observe(k.current),()=>f.disconnect()},[v,x]);let xe={...Ue,"--idos-safe-top":`${M.top}px`,"--idos-safe-bottom":`${M.bottom}px`};return jsxRuntime.jsxs("div",{style:xe,children:[jsxRuntime.jsx("div",{ref:d,style:Te}),jsxRuntime.jsx("div",{style:{...Pe,top:M.top,bottom:M.bottom},children:m("overlay").map(a=>jsxRuntime.jsx("div",{style:K,children:a.component},a.key))}),jsxRuntime.jsx("div",{ref:R,style:De,children:m("hud").map(a=>jsxRuntime.jsx("div",{style:Oe,children:a.component},a.key))}),jsxRuntime.jsx("div",{style:{...Be,top:M.top,bottom:M.bottom},children:m("sidebar").map(a=>jsxRuntime.jsx("div",{style:K,children:a.component},a.key))}),x&&jsxRuntime.jsx("nav",{ref:k,style:Ne,children:g.map(a=>jsxRuntime.jsxs("button",{type:"button",onClick:()=>n(a.id),style:a.id===r?ze:ge,children:[a.icon?`${a.icon} `:"",a.label]},a.id))}),b&&(s||i)&&jsxRuntime.jsxs("div",{style:Ge,children:[s&&jsxRuntime.jsx("button",{type:"button",style:me,onClick:s,title:"Log out",children:"\u{1F6AA} Log out"}),i&&jsxRuntime.jsx(Le,{userID:i})]}),m("modal").length>0&&jsxRuntime.jsx("div",{style:je,children:m("modal").map(a=>jsxRuntime.jsx("div",{style:K,children:a.component},a.key))}),!S&&jsxRuntime.jsx($e,{})]})}function Le({userID:e}){let[o,t]=react.useState(false),s=()=>{(async()=>{try{await navigator.clipboard.writeText(e);}catch{let l=document.createElement("textarea");l.value=e,document.body.appendChild(l),l.select(),document.execCommand("copy"),l.remove();}t(true),window.setTimeout(()=>t(false),1500);})();},i=e.length>12?`${e.slice(0,5)}\u2026${e.slice(-5)}`:e;return jsxRuntime.jsx("button",{type:"button",style:_e,onClick:s,title:`Copy your player ID: ${e}`,children:o?"\u2713 Copied":`ID: ${i} \u29C9`})}function $e(){return jsxRuntime.jsxs("div",{style:We,children:[jsxRuntime.jsx("style",{children:`
1
+ 'use strict';var client=require('react-dom/client'),react$1=require('@idosgames/react'),moduleSdk=require('@idosgames/module-sdk'),react=require('react'),core=require('@idosgames/core'),jsxRuntime=require('react/jsx-runtime');var ke=50,U="host",re=t=>typeof t=="string"?t:t.name,se=t=>typeof t=="string"?null:t.shape,ie=t=>t.replace(/@\d+$/,"");function D(){let t=new Map,o=new Map,e=[],n=new Set,s=i=>{e.push(i),e.length>ke&&e.shift();},a=(i,r)=>{n.has(i)||(n.add(i),console.warn(r));},d=(i,r,c)=>{console.error(`[idos events] ${c}`),s({topic:r,from:i,at:Date.now(),delivered:0,rejected:c});},v=(i,r,c,p)=>{if(!moduleSdk.isTopicName(r)){d(i,r,`"${i}" emitted "${r}", which is not a topic name \u2014 use defineTopic("<module-id>:<event>@<major>", shape({\u2026})). Not delivered.`);return}let u=moduleSdk.topicNamespace(r);if(i!==U&&u===U){d(i,r,`"${i}" emitted "${r}", but the "host:" namespace belongs to the host. Not delivered.`);return}if(i!==U&&u!==i){d(i,r,`"${i}" emitted "${r}" into the "${u}" namespace \u2014 a module may only emit its own topics ("${i}:\u2026"). Not delivered.`);return}if(c){let y=c.check(p);y&&a(`emit|${i}|${r}`,`[idos events] "${i}" emitted "${r}" with a payload that does not match its own shape: ${y}. Fix the emit or the topic's shape (and module.meta.json).`);}let m=o.get(r);m||o.set(r,m=new Set),m.add(i);let S=0;for(let y of [...t.get(r)??[]]){if(y.shape){let x=y.shape.check(p);if(x){a(`on|${y.moduleId}|${r}`,`[idos events] "${y.moduleId}" skipped "${r}" from "${i}": ${x}. Its copy of the topic's shape no longer matches the emitter \u2014 re-copy it from the catalog.`);continue}}try{y.handler(p),S+=1;}catch(x){console.error(`[idos events] a "${r}" handler in "${y.moduleId}" threw \u2014 other listeners still received the event.`,x);}}s({topic:r,from:i,at:Date.now(),delivered:S});},g=(i,r,c)=>{let p=t.get(r);return p||t.set(r,p=new Set),p.add(c),()=>{let u=t.get(r);u&&(u.delete(c),u.size===0&&t.delete(r));}};return {forModule(i){let r=new Set,c=false;return {emit(u,m){c||v(i,re(u),se(u),m);},on(u,m){if(c)return ()=>{};let S=re(u);moduleSdk.isTopicName(S)||console.warn(`[idos events] "${i}" subscribed to "${S}", which is not a topic name \u2014 nothing can ever be emitted to it.`);let y=g(i,S,{moduleId:i,shape:se(u),handler:m});return r.add(y),()=>{y(),r.delete(y);}},dispose(){c=true;for(let u of r)u();r.clear();}}},emitAsHost(i,r){v(U,i.name,i.shape,r);},describe(){let i={};for(let[p,u]of t)i[p]=[...new Set([...u].map(m=>m.moduleId))];let r={};for(let[p,u]of o)r[p]=[...u];let c=[];for(let[p,u]of Object.entries(i)){if(o.has(p))continue;let m=[...o.keys()].filter(S=>S!==p&&ie(S)===ie(p));m.length>0&&c.push(`${u.join(", ")} listen${u.length===1?"s":""} to "${p}", but only ${m.map(S=>`"${S}"`).join(", ")} ${m.length===1?"has":"have"} been emitted \u2014 the major versions differ, so these never meet.`);}return {log:e.slice(),listeners:i,emitted:r,mismatches:c}}}}function Ce(){let t=new Map;return {emit(o,e){let n=t.get(o);if(n)for(let s of [...n])s(e);},on(o,e){let n=e,s=t.get(o);return s||(s=new Set,t.set(o,s)),s.add(n),()=>{s.delete(n),s.size===0&&t.delete(o);}}}}function de(){return Object.fromEntries(moduleSdk.SHARED_UI_ROLES.map(t=>[t,null]))}function I(t){let o=de(),e=[],n=moduleSdk.SHARED_UI_ROLES.join(", ");for(let s of t)for(let a of s.sharedUi?.provides??[]){if(!moduleSdk.isSharedUiRole(a)){e.push(`module "${s.id}" provides unknown shared UI role "${String(a)}" (known: ${n}) \u2014 ignored.`);continue}let d=o[a];d===null?o[a]=s.id:d!==s.id&&e.push(`shared UI role "${a}" is provided by both "${d}" and "${s.id}" \u2014 "${d}" wins (it comes first in src/modules.ts), "${s.id}" hides its copy.`);}for(let s of t)for(let a of s.sharedUi?.requires??[]){if(!moduleSdk.isSharedUiRole(a)){e.push(`module "${s.id}" requires unknown shared UI role "${String(a)}" (known: ${n}).`);continue}o[a]===null&&e.push(`module "${s.id}" requires shared UI role "${a}", but no installed module provides it \u2014 install game-hud (or another module that provides "${a}").`);}return {owners:o,warnings:e}}function B(t,o){let e=n=>t[n]??null;return {ownerOf:e,shouldDraw:n=>{let s=e(n);return s===null||s===o}}}var Ae={position:"absolute",inset:"0"};function z(t){return {request(o){let e=document.createElement("div");return e.dataset.surface=o,Object.assign(e.style,Ae),e.style.pointerEvents=o==="fullbleed-canvas"?"auto":"none",t.appendChild(e),{host:e,release(){e.remove();}}}}}var He="__IDOS_AGENT__",ce={},ue,pe;function Ie(){try{return typeof window<"u"&&window.self!==window.top}catch{return true}}function N(t,o){ce[t]=o,j();}function G(t){ue=t,j();}function _(t){pe=t,j();}function j(){if(!Ie())return;let t={version:1,modules:ce,host:ue,events:pe};globalThis[He]=t;}function W(){let t=new Map,o=new Set,e=()=>{for(let n of o)n();};return {registerType(n){if(!n?.type)throw new Error("ctx.content.registerType(): handler.type is required");return t.set(n.type,n),e(),()=>{t.get(n.type)===n&&(t.delete(n.type),e());}},getType:n=>t.get(n),listTypes:()=>[...t.values()],subscribe(n){return o.add(n),()=>{o.delete(n);}}}}function q(){let t=null,o=null;return {navigate(e){e&&(t?t(e):o=e);},bind(e){if(t=e,o!==null){let n=o;o=null,e(n);}return ()=>{t===e&&(t=null);}}}}function F(t,o){let e=o.sharedUi??I(t).owners,n=o.content??W(),s=[];try{for(let a of t){let d=o.events.forModule(a.id),v=[],g={module:a,scenes:[],panels:[],routes:[],dispose:()=>{d.dispose();for(let r of v.splice(0))r();}};s.push(g);let i={client:o.client,titleId:o.client.titleID,events:d,sharedUi:B(e,a.id),surface:o.surface,registerScene:r=>g.scenes.push(r),registerPanel:r=>g.panels.push(r),registerRoute:r=>g.routes.push(r),content:{registerType:r=>{let c=n.registerType(r);return v.push(c),c},getType:r=>n.getType(r),listTypes:()=>n.listTypes(),subscribe:r=>n.subscribe(r)},navigate:r=>o.navigator?.navigate(r),exposeToAgent:r=>N(a.id,r)};a.setup(i);}}catch(a){for(let d of s)d.dispose();throw a}return s}async function Pe(t){try{let o=await createImageBitmap(t,{resizeWidth:32,resizeHeight:32,resizeQuality:"low"}),e=document.createElement("canvas");e.width=o.width,e.height=o.height;let n=e.getContext("2d");if(!n)return !0;n.drawImage(o,0,0),o.close?.();let{data:s}=n.getImageData(0,0,e.width,e.height);for(let a=4;a<s.length;a+=4)if(s[a]!==s[0]||s[a+1]!==s[1]||s[a+2]!==s[2]||s[a+3]!==s[3])return !0;return !1}catch{return true}}var P=class{constructor(o){this.container=o;}container;hosts=new Map;active=new Set;ensureMounted(o){let e=this.hosts.get(o);return e||(e=document.createElement("div"),Object.assign(e.style,{position:"absolute",inset:"0"}),this.container.appendChild(e),this.hosts.set(o,e),o.mount({host:e})),e}setActive(o){let e=new Set(o);for(let n of this.active){if(e.has(n))continue;n.suspend?.();let s=this.hosts.get(n);s&&(s.style.display="none");}for(let n of e){if(this.active.has(n))continue;let s=this.ensureMounted(n);s.style.display="block",n.activate?.();}this.active=e;}async captureActive(){for(let o of this.active){let e=await o.capture?.().catch(()=>null);if(e)return e;let s=this.hosts.get(o)?.querySelectorAll("canvas"),a=s?.[s.length-1];if(!a)continue;let d=await new Promise(v=>{try{a.toBlob(v,"image/png");}catch{v(null);}});if(d&&await Pe(d))return d}return null}destroy(){for(let[o,e]of this.hosts)o.destroy(),e.remove();this.hosts.clear(),this.active.clear();}};var Te="IDOS_PLATFORM_SHOT_REQUEST",fe="IDOS_PLATFORM_SHOT_RESPONSE";function V(t){if(typeof window>"u"||window.self===window.top)return ()=>{};let o=e=>{let n=e?.data;if(!n||n.type!==Te||typeof n.requestId!="string"||!core.isPlatformParentOrigin(e.origin))return;let s=e.source;if(!s)return;let a=n.requestId;t().catch(()=>null).then(d=>{try{s.postMessage(d?{type:fe,requestId:a,image:d}:{type:fe,requestId:a},e.origin);}catch{}});};return window.addEventListener("message",o),()=>window.removeEventListener("message",o)}function X({registrations:t,sharedUi:o,events:e,onLogout:n,userID:s,navigator:a}){let d=react.useRef(null),v=react.useRef(null),g=react.useMemo(()=>t.flatMap(l=>l.routes.map(f=>({id:f.id,label:f.label,icon:f.icon,order:f.order??0,moduleId:l.module.id}))).sort((l,f)=>l.order-f.order),[t]),[i,r]=react.useState(()=>g[0]?.id??null);react.useEffect(()=>{i!==null&&g.some(l=>l.id===i)||r(g[0]?.id??null);},[g,i]),react.useEffect(()=>a?.bind(l=>{g.some(f=>f.id===l)&&r(l);}),[a,g]);let c=react.useMemo(()=>g.find(l=>l.id===i)?.moduleId??null,[g,i]),p=react.useRef(null);react.useEffect(()=>{if(i===null||i===p.current)return;let l=p.current;p.current=i,e?.emitAsHost(moduleSdk.hostTopics.modeChanged,l===null?{to:i}:{from:l,to:i});},[i,e]),react.useEffect(()=>{let l=d.current;if(!l)return;let f=v.current??=new P(l),C=t.find(T=>T.module.id===c)?.scenes??[];f.setActive(C);},[t,c]),react.useEffect(()=>()=>{v.current?.destroy(),v.current=null;},[]),react.useEffect(()=>V(()=>v.current?.captureActive()??Promise.resolve(null)),[]);let u=react.useMemo(()=>t.flatMap(l=>l.panels.filter(f=>f.activeOnly===false||l.module.id===c).map(f=>{let C=f.component;return {key:`${l.module.id}:${f.id}`,slot:f.slot,order:f.order??0,moduleId:l.module.id,component:jsxRuntime.jsx(C,{})}})).sort((l,f)=>l.order-f.order),[t,c]),m=l=>u.filter(f=>f.slot===l),S=t.length>0,y=m("hud").length,x=g.length>1,b=!o?.account,R=react.useRef(null),M=react.useRef(null),[k,Re]=react.useState({top:0,bottom:0});react.useLayoutEffect(()=>{let l=()=>{let C=y>0&&R.current?Math.ceil(R.current.getBoundingClientRect().height):0,T=x&&M.current?Math.ceil(M.current.getBoundingClientRect().height)+me:0;Re(O=>O.top===C&&O.bottom===T?O:{top:C,bottom:T});};if(l(),typeof ResizeObserver>"u")return;let f=new ResizeObserver(l);return R.current&&f.observe(R.current),M.current&&f.observe(M.current),()=>f.disconnect()},[y,x]);let Ee={...Be,"--idos-safe-top":`${k.top}px`,"--idos-safe-bottom":`${k.bottom}px`};return jsxRuntime.jsxs("div",{style:Ee,children:[jsxRuntime.jsx("div",{ref:d,style:ze}),jsxRuntime.jsx("div",{style:{...Ne,top:k.top,bottom:k.bottom},children:m("overlay").map(l=>jsxRuntime.jsx("div",{style:Y,children:l.component},l.key))}),jsxRuntime.jsx("div",{ref:R,style:_e,children:m("hud").map(l=>jsxRuntime.jsx("div",{style:Ge,children:l.component},l.key))}),jsxRuntime.jsx("div",{style:{...je,top:k.top,bottom:k.bottom},children:m("sidebar").map(l=>jsxRuntime.jsx("div",{style:Y,children:l.component},l.key))}),x&&jsxRuntime.jsx("nav",{ref:M,style:We,children:g.map(l=>jsxRuntime.jsxs("button",{type:"button",onClick:()=>r(l.id),style:l.id===i?qe:he,children:[l.icon?`${l.icon} `:"",l.label]},l.id))}),b&&(n||s)&&jsxRuntime.jsxs("div",{style:Fe,children:[n&&jsxRuntime.jsx("button",{type:"button",style:ve,onClick:n,title:"Log out",children:"\u{1F6AA} Log out"}),s&&jsxRuntime.jsx(Oe,{userID:s})]}),m("modal").length>0&&jsxRuntime.jsx("div",{style:Ke,children:m("modal").map(l=>jsxRuntime.jsx("div",{style:Y,children:l.component},l.key))}),!S&&jsxRuntime.jsx(De,{})]})}function Oe({userID:t}){let[o,e]=react.useState(false),n=()=>{(async()=>{try{await navigator.clipboard.writeText(t);}catch{let a=document.createElement("textarea");a.value=t,document.body.appendChild(a),a.select(),document.execCommand("copy"),a.remove();}e(true),window.setTimeout(()=>e(false),1500);})();},s=t.length>12?`${t.slice(0,5)}\u2026${t.slice(-5)}`:t;return jsxRuntime.jsx("button",{type:"button",style:Ve,onClick:n,title:`Copy your player ID: ${t}`,children:o?"\u2713 Copied":`ID: ${s} \u29C9`})}function De(){return jsxRuntime.jsxs("div",{style:Ye,children:[jsxRuntime.jsx("style",{children:`
2
2
  @keyframes idos-empty-float {
3
3
  0%, 100% { transform: translateY(0) rotate(-6deg); }
4
4
  50% { transform: translateY(-16px) rotate(6deg); }
@@ -7,5 +7,5 @@
7
7
  0% { transform: scale(0.55); opacity: 0.55; }
8
8
  100% { transform: scale(1.7); opacity: 0; }
9
9
  }
10
- `}),jsxRuntime.jsxs("div",{style:Ve,children:[jsxRuntime.jsx("span",{style:{...pe,animationDelay:"0s"}}),jsxRuntime.jsx("span",{style:{...pe,animationDelay:"1.1s"}}),jsxRuntime.jsx("span",{style:Fe,children:"\u{1F9E9}"})]}),jsxRuntime.jsx("div",{style:{fontWeight:700,fontSize:18,marginBottom:6},children:"No modules installed"}),jsxRuntime.jsxs("div",{style:{opacity:.85,maxWidth:380,lineHeight:1.5},children:["Add a module under ",jsxRuntime.jsx("code",{children:"src/modules/"})," and register it in"," ",jsxRuntime.jsx("code",{children:"src/modules.ts"}),". The host shell will pick it up here."]})]})}var Ue={position:"absolute",inset:0,overflow:"hidden",background:"#0d66fe",color:"#fff",fontFamily:"system-ui, sans-serif"},Te={position:"absolute",inset:0,zIndex:0},fe=16,Pe={position:"absolute",top:0,right:0,bottom:0,left:0,zIndex:1,pointerEvents:"none"},Oe={display:"contents",pointerEvents:"auto"},De={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},Be={position:"absolute",top:0,right:0,bottom:0,width:340,maxWidth:"40vw",zIndex:2,display:"flex",flexDirection:"column",gap:12,padding:16,overflowY:"auto",pointerEvents:"none"},Ne={position:"absolute",bottom:fe,left:"50%",transform:"translateX(-50%)",zIndex:3,display:"flex",gap:8,padding:6,borderRadius:14,background:"rgba(4,32,90,0.72)",backdropFilter:"blur(6px)",pointerEvents:"auto"},ge={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfe0ff",background:"transparent",cursor:"pointer"},ze={...ge,color:"#0d66fe",background:"#fff"},Ge={position:"absolute",bottom:16,left:16,zIndex:3,display:"flex",gap:8,alignItems:"center",pointerEvents:"auto"},me={border:"none",borderRadius:12,padding:"8px 14px",fontWeight:700,fontSize:13,color:"#cfe0ff",background:"rgba(4,32,90,0.72)",backdropFilter:"blur(6px)",cursor:"pointer"},_e={...me,fontWeight:600,fontFamily:"ui-monospace, Consolas, monospace"},je={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},K={pointerEvents:"auto"},We={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24},Ve={position:"relative",width:110,height:110,marginBottom:16,display:"grid",placeItems:"center"},pe={position:"absolute",inset:0,borderRadius:"50%",border:"2px solid rgba(255,255,255,0.55)",animation:"idos-empty-ripple 2.2s ease-out infinite"},Fe={fontSize:46,animation:"idos-empty-float 3s ease-in-out infinite",filter:"drop-shadow(0 8px 12px rgba(0,0,0,0.25))"};function Q(e){let{client:o,modules:t,events:s,sharedUi:i,surface:l,renderLogin:d}=e,[y]=react.useState(V),[g,r]=react.useState(true),[n,c]=react.useState(null),p=react.useRef(null),u=()=>{for(let b of p.current??[])b.dispose();p.current=null;},m=()=>{u();let b=F(t,{client:o,events:s,surface:l,sharedUi:i,navigator:y});p.current=b,c(b);};react.useEffect(()=>()=>u(),[]);let S=react.useRef(false);react.useEffect(()=>{if(S.current)return;S.current=true;let b=core.readSsoCodeFromUrl();if(b){(async()=>((await o.auth.loginWithSsoCode(b.code)).ok&&m(),r(false)))();return}if(o.auth.lastAuthType===core.AuthType.None){r(false);return}(async()=>((await o.auth.autoLogin()).ok&&m(),r(false)))();},[o]),react.useEffect(()=>{let b=()=>{u(),c(null);},R=o.on("auth:unauthorized",b),k=o.on("auth:loggedOut",b);return ()=>{R(),k();}},[o]);let v=n?"game":g?"loading":"login";return react.useEffect(()=>{G({screen:v,loggedIn:n!==null,userId:o.auth.context?.userID??null,titleId:o.titleID??null,modules:t.map(b=>b.id),sharedUi:i});},[v,n,o,t,i]),n?jsxRuntime.jsx(X,{registrations:n,sharedUi:i,events:s,navigator:y,onLogout:()=>o.auth.logout(),userID:o.auth.context?.userID??null}):g?null:jsxRuntime.jsx(d,{client:o,onAuthenticated:m})}var Ye='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 860 690" fill="#fff"><g transform="translate(243 -2)"><path d="M147.333 12.333c-13.6 2.534-12.533 1.2-12.933 15.067l-.4 12.267-4.533-11.067c-2.534-6-5.067-10.933-5.734-10.933-2.666 0-27.866 8.666-36.533 12.666-11.733 5.334-26.667 14.8-36.133 22.934l-6.934 5.866L51.6 69.267c8.133 11.066 7.333 11.466-5.067 2.933-7.6-5.067-8.4-5.333-11.466-3.733-3.467 1.866-18.4 17.333-20.4 21.2-.8 1.6 7.066 8.8 33.733 30.933l34.667 28.933 8.8-8.266c14.666-13.867 28.666-22 48.133-28.267 9.067-2.933 14.8-3.733 28.533-4.4 34.267-1.333 60 7.467 81.6 28.133 21.6 20.4 34.934 49.6 37.467 81.734l.8 11.2 14.8 4.533c8.133 2.533 23.733 7.333 34.667 10.8 10.933 3.333 20.4 5.6 21.066 4.933 1.6-1.6 6.134-20.533 7.734-32.666.8-6 1.333-17.6 1.066-25.6l-.4-14.667-8-1.067c-4.4-.533-10.133-1.466-12.666-1.866l-4.667-.8 4.667-1.2c16.933-4.534 18.666-5.2 18.666-8 0-5.467-9.6-31.334-16.666-44.8-4-7.6-10.667-18.667-14.934-24.667-9.866-13.867-31.333-35.467-45.2-45.2-10.4-7.467-34.4-20.933-37.2-21.067-.8 0-4 4-7.333 8.8-3.2 4.8-6.133 8.134-6.4 7.334s.4-5.6 1.6-10.667c1.2-5.2 2.133-9.6 2.133-9.867 0-.933-19.866-6.133-34.4-9.066-14.8-2.934-49.333-4.4-59.6-2.534"/><path d="M157.867 125.533c-21.067 3.334-42.134 14.8-57.467 31.334-13.333 14.133-13.733 12.8 5.6 22 9.2 4.4 16.667 8.266 16.667 8.533s-1.334.4-2.934.133c-13.866-2.133-41.6-5.866-41.733-5.6-.267.267-7.467 28.534-16.267 63.067l-16 62.667 7.334.4c4 .266 7.466.266 7.6 0 .266-.267 3.866-13.867 8.133-30.4 4.267-16.534 8.267-30.8 8.933-31.734.934-1.2 11.067-1.6 42.4-1.6 32.134 0 41.2.4 41.2 1.6 0 .934-1.733 4.667-3.866 8.4L153.733 261l-35.066 6.933c-19.334 3.867-35.2 7.2-35.467 7.467-.667.667-29.867 113.467-29.467 113.867.267.133 23.734-3.6 52.4-8.534l52-8.8 20.4-39.866c11.2-22 20.667-39.734 20.934-39.467.4.533-1.334 26.8-2.8 40.8l-.667 6.933 6.267-3.2c21.2-10.666 52.4-13.466 86.933-8l5.867.934-5.6-7.334C286.4 318.6 281.2 310.6 278 304.867c-5.867-10.134-6-10.8-6-21.867 0-6.267 1.467-20 3.333-30.667 1.867-10.666 3.334-19.466 3.334-19.466 0-.134-9.067-4.267-20.134-9.334s-19.466-9.333-18.8-9.6c.8-.266 7.734.8 15.6 2.267 7.734 1.6 14.4 2.8 14.8 2.8 1.2 0 .4-10.533-1.466-18-7.2-27.733-28-53.467-53.734-66-16.4-8-40.8-12-57.066-9.467"/><path d="M235.6 346.333c-24 4.534-44.133 13.867-68.267 31.467-14 10.267-28.533 18.133-47.733 25.867-23.467 9.466-52.8 32.666-64.4 50.666l-2.533 4L58 454.2c9.333-7.333 30.133-19.467 49.333-28.667C173.733 393.667 246.4 382.2 312.8 393c11.2 1.733 39.2 8.533 45.067 10.8 2.266.8 2.266.667.8-2.267-4-7.6-15.6-21.866-25.867-31.466-12-11.467-24.667-18.934-37.6-22.4-11.467-3.067-46.267-3.867-59.6-1.334"/></g><g transform="translate(-460 467)"><path d="M721.533 34.467c-14.933 5.466-22 17.466-22.933 38.666-.933 24.134 3.467 32.8 30.267 59.867 19.6 19.867 22.933 25.2 22.933 37.867.133 13.466-6.133 20.133-16.933 18.4-9.067-1.467-12.534-7.867-12.534-22.667V159H696.6l.667 13.333c.533 11.467 1.2 14.4 4.933 22 7.067 14.267 16.8 19.6 36.4 19.734 10.667.133 12.267-.134 20.667-4.4 7.6-3.867 9.733-5.867 13.2-11.734 7.6-12.533 9.066-32 3.733-47.6-3.733-11.066-10.667-20.4-27.867-37.2-19.866-19.6-22.533-24.133-22.666-38.4 0-8.933.4-10.533 3.2-13.6 6.266-6.666 18.266-5.6 22.133 2 1.067 2 2 7.067 2 11.2v7.334h27.067l-.934-9.2c-1.6-18.267-8.266-30.267-20-36.4-7.2-3.867-29.2-4.8-37.6-1.6M630.067 34.867c-11.734 4.666-18 11.6-21.734 24.4-1.866 6.4-2 15.333-1.733 67.2l.4 59.866 3.733 7.6c6.8 13.867 18.534 20.267 36.934 20.267 13.733 0 22.933-3.333 30.666-11.067 10.934-11.066 11.2-12.533 11.734-74.666.266-35.734-.134-56.934-1.067-62.8-2.667-16.134-11.6-27.467-24.8-31.467-8.933-2.667-26.4-2.267-34.133.667m28.666 26.8 3.6 4v56.666c0 40.934-.4 57.467-1.6 60-3.6 8-15.6 9.734-22.666 3.467l-4.4-3.867-.4-56.533c-.267-51.733-.134-56.8 2-61.067 3.066-5.866 7.6-8.266 14.4-7.466 3.733.4 6.4 1.866 9.066 4.8M511.667 123.133v89.334l29.066-.4c28.8-.4 28.934-.4 36.667-4.267 9.467-4.533 14.4-10.933 17.467-22.4 2-7.333 2.266-15.467 1.866-65.733l-.4-57.334-4.266-8.8c-8.267-16.666-17.2-19.866-55.334-19.866h-25.066zm53.6-60.266 4.4 3.866.4 52.8c.266 35.067-.134 54.4-1.067 58-2 7.467-5.733 9.6-18.667 10.4l-10.666.8V59h10.666c9.867 0 10.934.267 14.934 3.867M471.667 145v67.333h26.666V77.667h-26.666zM471.667 48.333V63h26.666V33.667h-26.666z"/></g><g transform="translate(-106 244)"><path d="M893.4 259.733c-6.8 3.467-9.2 5.6-12.667 11.467-10.666 17.733-9.2 42.933 3.467 62.267 2.8 4.266 12.267 14.8 20.933 23.333 9.867 9.467 17.067 17.733 18.934 21.6 5.6 11.333 5.2 25.333-.934 30.8-3.466 3.067-11.333 4.133-16.133 2.133-5.867-2.4-8-7.466-8-19.333v-10h-27.067l.8 11.6c1.2 15.867 3.867 24.133 10.267 31.333 7.467 8.534 16.4 12.134 30 12.267 19.067.133 30.133-5.733 37.333-19.867 3.734-7.466 4-8.666 4-24 0-16 0-16.133-5.2-26.666-4.4-9.2-7.733-13.2-23.066-28.534-21.067-21.066-24.8-27.066-24.934-40.4-.133-10.4 2.8-15.6 9.734-17.6 10.133-2.933 17.2 3.334 18.4 16.267l.8 8.267H955.4l-.8-10.8c-.533-8.4-1.6-12.667-4.8-19.2-7.067-14.134-16.667-19.334-36.133-19.334-10.667 0-12.534.4-20.267 4.4M791 346v89.333h76v-24h-48v-54.666h37.333v-24H819V282h48v-25.333h-76zM661.667 346v89.333h22.666l.134-63.066c0-34.534.533-61.734 1.066-60.267.534 1.467 5.467 29.867 10.8 62.933l9.867 60.4h13.067c7.2 0 13.066-.4 13.066-1.066 0-3.067 18.8-124.8 19.334-125.334.4-.4.666 27.867.666 62.8v63.6h25.334V256.667h-38l-9.2 61.6c-5.067 34-9.6 62.133-10 62.666-.534.534-5.334-26.4-10.667-60-5.467-33.466-10.133-61.733-10.533-62.666-.4-1.2-5.467-1.6-19.067-1.6h-18.533zM586.467 258.267c-.8 2.666-27.467 172.4-27.467 174.933 0 1.867 1.733 2.133 12 2.133h11.867l.8-4.4c.533-2.266 1.6-9.333 2.4-15.6l1.6-11.333 17.6-.4 17.466-.4 1.467 8.4c.8 4.667 1.733 11.867 2.267 16l.933 7.733h13.733c7.6 0 13.867-.266 13.867-.666 0-.8-26.533-168.134-27.467-173.734l-.8-4.266h-19.866c-14.8 0-20.134.4-20.4 1.6M613 336.533c3.333 23.067 5.867 42.134 5.6 42.4-.4.267-6.533.267-13.867.134l-13.2-.4 4.934-33.334c2.8-18.4 5.733-38.4 6.666-44.666C604.2 292.533 605 290.133 605.8 292c.533 1.467 3.867 21.467 7.2 44.533M497.267 257.2c-10.134 3.733-15.2 8.267-19.867 17.733L473 284l-.4 59.067c-.4 51.2-.133 60.133 1.733 66.533 5.6 19.333 17.067 27.333 39.467 27.467 10.267.133 12.267-.267 20.133-4.134 9.334-4.533 13.867-9.733 17.867-20.266 2-4.934 2.4-12 2.933-41.067l.534-34.933h-38.934v23.866l6.4.4 6.267.4v19.334c0 13.466-.533 20.666-1.867 23.733-5.066 12-23.333 10.4-26.8-2.4-.933-3.6-1.333-23.2-1.066-59.067.4-48.533.666-54.133 2.666-57.333 3.334-4.8 11.2-7.067 17.6-4.933 6.934 2.266 9.067 7.2 9.867 22.933l.667 13.067H555.4l-.8-15.734c-.8-18-3.067-25.6-9.867-33.466-7.466-8.8-13.466-11.2-29.066-11.734-9.067-.266-14.934.134-18.4 1.467"/></g></svg>',ye=`data:image/svg+xml;utf8,${encodeURIComponent(Ye)}`;var Je=["https://cloud.idosgames.com","https://idosgames.com","https://www.idosgames.com"],Qe=/^https:\/\/[a-z0-9]{8}(-dev)?\.idos\.games$/;function Se(){if(typeof window>"u")return false;let{origin:e}=window.location;return Je.includes(e)||Qe.test(e)?true:typeof document<"u"&&document.querySelector('meta[name="idos-game-host"]')!==null}function ee({client:e,onAuthenticated:o}){let[t,s]=react.useState(false),[i,l]=react.useState(null),[d,y]=react.useState(true),g=async()=>{s(true),l(null),e.auth.setRememberSession(d);let r=await e.auth.loginWithDeviceID();if(r.ok){o();return}l(r.error),s(false);};return jsxRuntime.jsx("div",{style:w.root,children:jsxRuntime.jsxs("div",{style:w.card,children:[jsxRuntime.jsx("img",{src:ye,alt:"iDos Games",style:w.logo}),jsxRuntime.jsx("h1",{style:w.title,children:"Sign in"}),Se()&&jsxRuntime.jsx("button",{type:"button",onClick:()=>core.beginSsoRedirect({titleID:e.titleID}),disabled:t,style:{...w.primary,opacity:t?.6:1,cursor:t?"default":"pointer"},children:"Continue with iDos Games"}),jsxRuntime.jsx("button",{type:"button",onClick:()=>{g();},disabled:t,style:{...Se()?w.ghost:w.primary,opacity:t?.6:1,cursor:t?"default":"pointer"},children:t?"Signing in\u2026":"Play as guest"}),jsxRuntime.jsxs("label",{style:{...w.remember,opacity:t?.6:1},children:[jsxRuntime.jsx("input",{type:"checkbox",checked:d,disabled:t,onChange:r=>y(r.target.checked),style:w.switchInput}),jsxRuntime.jsx("span",{style:{...w.switchTrack,background:d?"#fff":"rgba(255, 255, 255, 0.3)"},children:jsxRuntime.jsx("span",{style:{...w.switchKnob,left:d?"21px":"3px",background:d?"#0d66fe":"#fff"}})}),"Remember me"]}),i&&jsxRuntime.jsx("span",{style:w.error,children:i})]})})}var w={root:{position:"absolute",inset:0,display:"grid",placeItems:"center",background:"#0d66fe",color:"#fff",font:"14px system-ui, sans-serif"},card:{width:"min(340px, 88vw)",display:"grid",gap:"18px",justifyItems:"center"},logo:{width:"180px",userSelect:"none",pointerEvents:"none"},title:{margin:0,fontSize:"22px",fontWeight:600,textAlign:"center"},primary:{width:"100%",padding:"11px 16px",borderRadius:"8px",border:"none",background:"#fff",color:"#0d66fe",fontWeight:600,font:"inherit"},ghost:{width:"100%",padding:"11px 16px",borderRadius:"8px",border:"1px solid rgba(255, 255, 255, 0.45)",background:"transparent",color:"#fff",fontWeight:600,font:"inherit"},remember:{display:"flex",alignItems:"center",gap:"10px",cursor:"pointer",color:"rgba(255, 255, 255, 0.85)"},switchInput:{position:"absolute",opacity:0,width:0,height:0},switchTrack:{position:"relative",width:"42px",height:"24px",borderRadius:"12px",transition:"background 0.15s",flexShrink:0},switchKnob:{position:"absolute",top:"3px",width:"18px",height:"18px",borderRadius:"50%",transition:"left 0.15s, background 0.15s"},error:{color:"#ffd7d7",textAlign:"center"}};function ot(e){let{container:o,client:t,modules:s,renderLogin:i}=e;o.style.position="relative";let l=document.createElement("div");Object.assign(l.style,{position:"absolute",inset:"0",zIndex:"0",pointerEvents:"none"});let d=document.createElement("div");Object.assign(d.style,{position:"absolute",inset:"0",zIndex:"1"}),o.append(l,d);let y=D(),g=N(l);_(()=>y.describe());let r=A(s);for(let c of r.warnings)console.warn(`[idos shared-ui] ${c}`);let n=client.createRoot(d);return n.render(jsxRuntime.jsx(react$1.IDosGamesProvider,{client:t,children:jsxRuntime.jsx(react$1.StatusProvider,{children:jsxRuntime.jsx(Q,{client:t,modules:s,events:y,sharedUi:r.owners,surface:g,renderLogin:i??ee})})})),{unmount(){n.unmount(),l.remove(),d.remove();}}}
11
- exports.AuthGate=Q;exports.DefaultLoginScreen=ee;exports.HostShell=X;exports.SceneStage=I;exports.createContentRegistry=W;exports.createHostEventBus=D;exports.createHostNavigator=V;exports.createSharedEventBus=ke;exports.createSurfaceAllocator=N;exports.emptySharedUiOwners=le;exports.mountHost=ot;exports.publishEventsProvider=_;exports.publishHostState=G;exports.registerAgentApi=z;exports.resolveSharedUi=A;exports.runModules=F;exports.sharedUiFor=B;
10
+ `}),jsxRuntime.jsxs("div",{style:Qe,children:[jsxRuntime.jsx("span",{style:{...ge,animationDelay:"0s"}}),jsxRuntime.jsx("span",{style:{...ge,animationDelay:"1.1s"}}),jsxRuntime.jsx("span",{style:Xe,children:"\u{1F9E9}"})]}),jsxRuntime.jsx("div",{style:{fontWeight:700,fontSize:18,marginBottom:6},children:"No modules installed"}),jsxRuntime.jsxs("div",{style:{opacity:.85,maxWidth:380,lineHeight:1.5},children:["Add a module under ",jsxRuntime.jsx("code",{children:"src/modules/"})," and register it in"," ",jsxRuntime.jsx("code",{children:"src/modules.ts"}),". The host shell will pick it up here."]})]})}var Be={position:"absolute",inset:0,overflow:"hidden",background:"#0d66fe",color:"#fff",fontFamily:"system-ui, sans-serif"},ze={position:"absolute",inset:0,zIndex:0},me=16,Ne={position:"absolute",top:0,right:0,bottom:0,left:0,zIndex:1,pointerEvents:"none"},Ge={display:"contents",pointerEvents:"auto"},_e={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},je={position:"absolute",top:0,right:0,bottom:0,width:340,maxWidth:"40vw",zIndex:2,display:"flex",flexDirection:"column",gap:12,padding:16,overflowY:"auto",pointerEvents:"none"},We={position:"absolute",bottom:me,left:"50%",transform:"translateX(-50%)",zIndex:3,display:"flex",gap:8,padding:6,borderRadius:14,background:"rgba(4,32,90,0.72)",backdropFilter:"blur(6px)",pointerEvents:"auto"},he={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfe0ff",background:"transparent",cursor:"pointer"},qe={...he,color:"#0d66fe",background:"#fff"},Fe={position:"absolute",bottom:16,left:16,zIndex:3,display:"flex",gap:8,alignItems:"center",pointerEvents:"auto"},ve={border:"none",borderRadius:12,padding:"8px 14px",fontWeight:700,fontSize:13,color:"#cfe0ff",background:"rgba(4,32,90,0.72)",backdropFilter:"blur(6px)",cursor:"pointer"},Ve={...ve,fontWeight:600,fontFamily:"ui-monospace, Consolas, monospace"},Ke={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},Y={pointerEvents:"auto"},Ye={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24},Qe={position:"relative",width:110,height:110,marginBottom:16,display:"grid",placeItems:"center"},ge={position:"absolute",inset:0,borderRadius:"50%",border:"2px solid rgba(255,255,255,0.55)",animation:"idos-empty-ripple 2.2s ease-out infinite"},Xe={fontSize:46,animation:"idos-empty-float 3s ease-in-out infinite",filter:"drop-shadow(0 8px 12px rgba(0,0,0,0.25))"};function Z(t){let{client:o,modules:e,events:n,sharedUi:s,surface:a,renderLogin:d}=t,[v]=react.useState(q),[g,i]=react.useState(true),[r,c]=react.useState(null),p=react.useRef(null),u=()=>{for(let b of p.current??[])b.dispose();p.current=null;},m=()=>{u();let b=F(e,{client:o,events:n,surface:a,sharedUi:s,navigator:v});p.current=b,c(b);};react.useEffect(()=>()=>u(),[]);let S=react.useRef(false);react.useEffect(()=>{if(S.current)return;S.current=true;let b=core.readSsoCodeFromUrl();if(b){(async()=>((await o.auth.loginWithSsoCode(b.code)).ok&&m(),i(false)))();return}if(o.auth.lastAuthType===core.AuthType.None){i(false);return}(async()=>((await o.auth.autoLogin()).ok&&m(),i(false)))();},[o]),react.useEffect(()=>{let b=()=>{u(),c(null);},R=o.on("auth:unauthorized",b),M=o.on("auth:loggedOut",b);return ()=>{R(),M();}},[o]);let y=r?"game":g?"loading":"login";return react.useEffect(()=>{G({screen:y,loggedIn:r!==null,userId:o.auth.context?.userID??null,titleId:o.titleID??null,modules:e.map(b=>b.id),sharedUi:s});},[y,r,o,e,s]),r?jsxRuntime.jsx(X,{registrations:r,sharedUi:s,events:n,navigator:v,onLogout:()=>o.auth.logout(),userID:o.auth.context?.userID??null}):g?null:jsxRuntime.jsx(d,{client:o,onAuthenticated:m})}var et='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 860 690" fill="#fff"><g transform="translate(243 -2)"><path d="M147.333 12.333c-13.6 2.534-12.533 1.2-12.933 15.067l-.4 12.267-4.533-11.067c-2.534-6-5.067-10.933-5.734-10.933-2.666 0-27.866 8.666-36.533 12.666-11.733 5.334-26.667 14.8-36.133 22.934l-6.934 5.866L51.6 69.267c8.133 11.066 7.333 11.466-5.067 2.933-7.6-5.067-8.4-5.333-11.466-3.733-3.467 1.866-18.4 17.333-20.4 21.2-.8 1.6 7.066 8.8 33.733 30.933l34.667 28.933 8.8-8.266c14.666-13.867 28.666-22 48.133-28.267 9.067-2.933 14.8-3.733 28.533-4.4 34.267-1.333 60 7.467 81.6 28.133 21.6 20.4 34.934 49.6 37.467 81.734l.8 11.2 14.8 4.533c8.133 2.533 23.733 7.333 34.667 10.8 10.933 3.333 20.4 5.6 21.066 4.933 1.6-1.6 6.134-20.533 7.734-32.666.8-6 1.333-17.6 1.066-25.6l-.4-14.667-8-1.067c-4.4-.533-10.133-1.466-12.666-1.866l-4.667-.8 4.667-1.2c16.933-4.534 18.666-5.2 18.666-8 0-5.467-9.6-31.334-16.666-44.8-4-7.6-10.667-18.667-14.934-24.667-9.866-13.867-31.333-35.467-45.2-45.2-10.4-7.467-34.4-20.933-37.2-21.067-.8 0-4 4-7.333 8.8-3.2 4.8-6.133 8.134-6.4 7.334s.4-5.6 1.6-10.667c1.2-5.2 2.133-9.6 2.133-9.867 0-.933-19.866-6.133-34.4-9.066-14.8-2.934-49.333-4.4-59.6-2.534"/><path d="M157.867 125.533c-21.067 3.334-42.134 14.8-57.467 31.334-13.333 14.133-13.733 12.8 5.6 22 9.2 4.4 16.667 8.266 16.667 8.533s-1.334.4-2.934.133c-13.866-2.133-41.6-5.866-41.733-5.6-.267.267-7.467 28.534-16.267 63.067l-16 62.667 7.334.4c4 .266 7.466.266 7.6 0 .266-.267 3.866-13.867 8.133-30.4 4.267-16.534 8.267-30.8 8.933-31.734.934-1.2 11.067-1.6 42.4-1.6 32.134 0 41.2.4 41.2 1.6 0 .934-1.733 4.667-3.866 8.4L153.733 261l-35.066 6.933c-19.334 3.867-35.2 7.2-35.467 7.467-.667.667-29.867 113.467-29.467 113.867.267.133 23.734-3.6 52.4-8.534l52-8.8 20.4-39.866c11.2-22 20.667-39.734 20.934-39.467.4.533-1.334 26.8-2.8 40.8l-.667 6.933 6.267-3.2c21.2-10.666 52.4-13.466 86.933-8l5.867.934-5.6-7.334C286.4 318.6 281.2 310.6 278 304.867c-5.867-10.134-6-10.8-6-21.867 0-6.267 1.467-20 3.333-30.667 1.867-10.666 3.334-19.466 3.334-19.466 0-.134-9.067-4.267-20.134-9.334s-19.466-9.333-18.8-9.6c.8-.266 7.734.8 15.6 2.267 7.734 1.6 14.4 2.8 14.8 2.8 1.2 0 .4-10.533-1.466-18-7.2-27.733-28-53.467-53.734-66-16.4-8-40.8-12-57.066-9.467"/><path d="M235.6 346.333c-24 4.534-44.133 13.867-68.267 31.467-14 10.267-28.533 18.133-47.733 25.867-23.467 9.466-52.8 32.666-64.4 50.666l-2.533 4L58 454.2c9.333-7.333 30.133-19.467 49.333-28.667C173.733 393.667 246.4 382.2 312.8 393c11.2 1.733 39.2 8.533 45.067 10.8 2.266.8 2.266.667.8-2.267-4-7.6-15.6-21.866-25.867-31.466-12-11.467-24.667-18.934-37.6-22.4-11.467-3.067-46.267-3.867-59.6-1.334"/></g><g transform="translate(-460 467)"><path d="M721.533 34.467c-14.933 5.466-22 17.466-22.933 38.666-.933 24.134 3.467 32.8 30.267 59.867 19.6 19.867 22.933 25.2 22.933 37.867.133 13.466-6.133 20.133-16.933 18.4-9.067-1.467-12.534-7.867-12.534-22.667V159H696.6l.667 13.333c.533 11.467 1.2 14.4 4.933 22 7.067 14.267 16.8 19.6 36.4 19.734 10.667.133 12.267-.134 20.667-4.4 7.6-3.867 9.733-5.867 13.2-11.734 7.6-12.533 9.066-32 3.733-47.6-3.733-11.066-10.667-20.4-27.867-37.2-19.866-19.6-22.533-24.133-22.666-38.4 0-8.933.4-10.533 3.2-13.6 6.266-6.666 18.266-5.6 22.133 2 1.067 2 2 7.067 2 11.2v7.334h27.067l-.934-9.2c-1.6-18.267-8.266-30.267-20-36.4-7.2-3.867-29.2-4.8-37.6-1.6M630.067 34.867c-11.734 4.666-18 11.6-21.734 24.4-1.866 6.4-2 15.333-1.733 67.2l.4 59.866 3.733 7.6c6.8 13.867 18.534 20.267 36.934 20.267 13.733 0 22.933-3.333 30.666-11.067 10.934-11.066 11.2-12.533 11.734-74.666.266-35.734-.134-56.934-1.067-62.8-2.667-16.134-11.6-27.467-24.8-31.467-8.933-2.667-26.4-2.267-34.133.667m28.666 26.8 3.6 4v56.666c0 40.934-.4 57.467-1.6 60-3.6 8-15.6 9.734-22.666 3.467l-4.4-3.867-.4-56.533c-.267-51.733-.134-56.8 2-61.067 3.066-5.866 7.6-8.266 14.4-7.466 3.733.4 6.4 1.866 9.066 4.8M511.667 123.133v89.334l29.066-.4c28.8-.4 28.934-.4 36.667-4.267 9.467-4.533 14.4-10.933 17.467-22.4 2-7.333 2.266-15.467 1.866-65.733l-.4-57.334-4.266-8.8c-8.267-16.666-17.2-19.866-55.334-19.866h-25.066zm53.6-60.266 4.4 3.866.4 52.8c.266 35.067-.134 54.4-1.067 58-2 7.467-5.733 9.6-18.667 10.4l-10.666.8V59h10.666c9.867 0 10.934.267 14.934 3.867M471.667 145v67.333h26.666V77.667h-26.666zM471.667 48.333V63h26.666V33.667h-26.666z"/></g><g transform="translate(-106 244)"><path d="M893.4 259.733c-6.8 3.467-9.2 5.6-12.667 11.467-10.666 17.733-9.2 42.933 3.467 62.267 2.8 4.266 12.267 14.8 20.933 23.333 9.867 9.467 17.067 17.733 18.934 21.6 5.6 11.333 5.2 25.333-.934 30.8-3.466 3.067-11.333 4.133-16.133 2.133-5.867-2.4-8-7.466-8-19.333v-10h-27.067l.8 11.6c1.2 15.867 3.867 24.133 10.267 31.333 7.467 8.534 16.4 12.134 30 12.267 19.067.133 30.133-5.733 37.333-19.867 3.734-7.466 4-8.666 4-24 0-16 0-16.133-5.2-26.666-4.4-9.2-7.733-13.2-23.066-28.534-21.067-21.066-24.8-27.066-24.934-40.4-.133-10.4 2.8-15.6 9.734-17.6 10.133-2.933 17.2 3.334 18.4 16.267l.8 8.267H955.4l-.8-10.8c-.533-8.4-1.6-12.667-4.8-19.2-7.067-14.134-16.667-19.334-36.133-19.334-10.667 0-12.534.4-20.267 4.4M791 346v89.333h76v-24h-48v-54.666h37.333v-24H819V282h48v-25.333h-76zM661.667 346v89.333h22.666l.134-63.066c0-34.534.533-61.734 1.066-60.267.534 1.467 5.467 29.867 10.8 62.933l9.867 60.4h13.067c7.2 0 13.066-.4 13.066-1.066 0-3.067 18.8-124.8 19.334-125.334.4-.4.666 27.867.666 62.8v63.6h25.334V256.667h-38l-9.2 61.6c-5.067 34-9.6 62.133-10 62.666-.534.534-5.334-26.4-10.667-60-5.467-33.466-10.133-61.733-10.533-62.666-.4-1.2-5.467-1.6-19.067-1.6h-18.533zM586.467 258.267c-.8 2.666-27.467 172.4-27.467 174.933 0 1.867 1.733 2.133 12 2.133h11.867l.8-4.4c.533-2.266 1.6-9.333 2.4-15.6l1.6-11.333 17.6-.4 17.466-.4 1.467 8.4c.8 4.667 1.733 11.867 2.267 16l.933 7.733h13.733c7.6 0 13.867-.266 13.867-.666 0-.8-26.533-168.134-27.467-173.734l-.8-4.266h-19.866c-14.8 0-20.134.4-20.4 1.6M613 336.533c3.333 23.067 5.867 42.134 5.6 42.4-.4.267-6.533.267-13.867.134l-13.2-.4 4.934-33.334c2.8-18.4 5.733-38.4 6.666-44.666C604.2 292.533 605 290.133 605.8 292c.533 1.467 3.867 21.467 7.2 44.533M497.267 257.2c-10.134 3.733-15.2 8.267-19.867 17.733L473 284l-.4 59.067c-.4 51.2-.133 60.133 1.733 66.533 5.6 19.333 17.067 27.333 39.467 27.467 10.267.133 12.267-.267 20.133-4.134 9.334-4.533 13.867-9.733 17.867-20.266 2-4.934 2.4-12 2.933-41.067l.534-34.933h-38.934v23.866l6.4.4 6.267.4v19.334c0 13.466-.533 20.666-1.867 23.733-5.066 12-23.333 10.4-26.8-2.4-.933-3.6-1.333-23.2-1.066-59.067.4-48.533.666-54.133 2.666-57.333 3.334-4.8 11.2-7.067 17.6-4.933 6.934 2.266 9.067 7.2 9.867 22.933l.667 13.067H555.4l-.8-15.734c-.8-18-3.067-25.6-9.867-33.466-7.466-8.8-13.466-11.2-29.066-11.734-9.067-.266-14.934.134-18.4 1.467"/></g></svg>',be=`data:image/svg+xml;utf8,${encodeURIComponent(et)}`;var ot=["https://cloud.idosgames.com","https://idosgames.com","https://www.idosgames.com"],nt=/^https:\/\/[a-z0-9]{8}(-dev)?\.idos\.games$/;function we(){if(typeof window>"u")return false;let{origin:t}=window.location;return ot.includes(t)||nt.test(t)?true:typeof document<"u"&&document.querySelector('meta[name="idos-game-host"]')!==null}function te({client:t,onAuthenticated:o}){let[e,n]=react.useState(false),[s,a]=react.useState(null),[d,v]=react.useState(true),g=async()=>{n(true),a(null),t.auth.setRememberSession(d);let i=await t.auth.loginWithDeviceID();if(i.ok){o();return}a(i.error),n(false);};return jsxRuntime.jsx("div",{style:w.root,children:jsxRuntime.jsxs("div",{style:w.card,children:[jsxRuntime.jsx("img",{src:be,alt:"iDos Games",style:w.logo}),jsxRuntime.jsx("h1",{style:w.title,children:"Sign in"}),we()&&jsxRuntime.jsx("button",{type:"button",onClick:()=>core.beginSsoRedirect({titleID:t.titleID}),disabled:e,style:{...w.primary,opacity:e?.6:1,cursor:e?"default":"pointer"},children:"Continue with iDos Games"}),jsxRuntime.jsx("button",{type:"button",onClick:()=>{g();},disabled:e,style:{...we()?w.ghost:w.primary,opacity:e?.6:1,cursor:e?"default":"pointer"},children:e?"Signing in\u2026":"Play as guest"}),jsxRuntime.jsxs("label",{style:{...w.remember,opacity:e?.6:1},children:[jsxRuntime.jsx("input",{type:"checkbox",checked:d,disabled:e,onChange:i=>v(i.target.checked),style:w.switchInput}),jsxRuntime.jsx("span",{style:{...w.switchTrack,background:d?"#fff":"rgba(255, 255, 255, 0.3)"},children:jsxRuntime.jsx("span",{style:{...w.switchKnob,left:d?"21px":"3px",background:d?"#0d66fe":"#fff"}})}),"Remember me"]}),s&&jsxRuntime.jsx("span",{style:w.error,children:s})]})})}var w={root:{position:"absolute",inset:0,display:"grid",placeItems:"center",background:"#0d66fe",color:"#fff",font:"14px system-ui, sans-serif"},card:{width:"min(340px, 88vw)",display:"grid",gap:"18px",justifyItems:"center"},logo:{width:"180px",userSelect:"none",pointerEvents:"none"},title:{margin:0,fontSize:"22px",fontWeight:600,textAlign:"center"},primary:{width:"100%",padding:"11px 16px",borderRadius:"8px",border:"none",background:"#fff",color:"#0d66fe",fontWeight:600,font:"inherit"},ghost:{width:"100%",padding:"11px 16px",borderRadius:"8px",border:"1px solid rgba(255, 255, 255, 0.45)",background:"transparent",color:"#fff",fontWeight:600,font:"inherit"},remember:{display:"flex",alignItems:"center",gap:"10px",cursor:"pointer",color:"rgba(255, 255, 255, 0.85)"},switchInput:{position:"absolute",opacity:0,width:0,height:0},switchTrack:{position:"relative",width:"42px",height:"24px",borderRadius:"12px",transition:"background 0.15s",flexShrink:0},switchKnob:{position:"absolute",top:"3px",width:"18px",height:"18px",borderRadius:"50%",transition:"left 0.15s, background 0.15s"},error:{color:"#ffd7d7",textAlign:"center"}};function at(t){let{container:o,client:e,modules:n,renderLogin:s}=t;o.style.position="relative";let a=document.createElement("div");Object.assign(a.style,{position:"absolute",inset:"0",zIndex:"0",pointerEvents:"none"});let d=document.createElement("div");Object.assign(d.style,{position:"absolute",inset:"0",zIndex:"1"}),o.append(a,d);let v=D(),g=z(a);_(()=>v.describe());let i=I(n);for(let c of i.warnings)console.warn(`[idos shared-ui] ${c}`);let r=client.createRoot(d);return r.render(jsxRuntime.jsx(react$1.IDosGamesProvider,{client:e,children:jsxRuntime.jsx(react$1.StatusProvider,{children:jsxRuntime.jsx(Z,{client:e,modules:n,events:v,sharedUi:i.owners,surface:g,renderLogin:s??te})})})),{unmount(){r.unmount(),a.remove(),d.remove();}}}
11
+ exports.AuthGate=Z;exports.DefaultLoginScreen=te;exports.HostShell=X;exports.SceneStage=P;exports.createContentRegistry=W;exports.createHostEventBus=D;exports.createHostNavigator=q;exports.createSharedEventBus=Ce;exports.createSurfaceAllocator=z;exports.emptySharedUiOwners=de;exports.mountHost=at;exports.publishEventsProvider=_;exports.publishHostState=G;exports.registerAgentApi=N;exports.resolveSharedUi=I;exports.runModules=F;exports.servePlatformShots=V;exports.sharedUiFor=B;
package/dist/index.d.cts CHANGED
@@ -234,11 +234,32 @@ declare class SceneStage {
234
234
  /** Make exactly `scenes` the active set: suspend/hide the ones leaving, mount+activate the ones
235
235
  * entering. Idempotent — calling with the current set is a no-op. */
236
236
  setActive(scenes: readonly EngineScene[]): void;
237
+ /**
238
+ * A still frame of what the player is looking at, for the platform's screenshot bridge.
239
+ *
240
+ * Asks the active scene first (`EngineScene.capture`) — only the scene can render and read its
241
+ * WebGL canvas in one turn; see the contract's note on `preserveDrawingBuffer`. A scene without
242
+ * `capture` still works when it draws into a plain 2D canvas, so as a fallback we read the last
243
+ * canvas under its host element. Everything else (a DOM-only mode, nothing mounted, a cleared
244
+ * WebGL buffer that yields a blank frame) resolves `null` and the caller decides what to show —
245
+ * an empty image is worse than an honest "could not".
246
+ */
247
+ captureActive(): Promise<Blob | null>;
237
248
  /** Permanent teardown: destroy every mounted scene and remove its host element. */
238
249
  destroy(): void;
239
250
  }
240
251
 
252
+ /**
253
+ * Answer the platform page's requests for a still frame, for as long as the host is mounted.
254
+ *
255
+ * A no-op outside the browser and outside an iframe — the platform page is the only caller, and
256
+ * there is nobody to answer when the game is the top-level document.
257
+ *
258
+ * Returns an unsubscribe function.
259
+ */
260
+ declare function servePlatformShots(capture: () => Promise<Blob | null>): () => void;
261
+
241
262
  /** Creates an allocator whose surfaces are appended to `layer`. */
242
263
  declare function createSurfaceAllocator(layer: HTMLElement): SurfaceAllocator;
243
264
 
244
- export { type AgentBridgeGlobal, type AgentHostState, AuthGate, DefaultLoginScreen, type EventLogEntry, type HostEventBus, type HostEventBusDescription, type HostHandle, type HostNavigator, HostShell, type LoginScreenProps, type ModuleEventHandle, type ModuleRegistration, type RenderLogin, SceneStage, type SharedServices, type SharedUiOwners, type SharedUiResolution, createContentRegistry, createHostEventBus, createHostNavigator, createSharedEventBus, createSurfaceAllocator, emptySharedUiOwners, mountHost, publishEventsProvider, publishHostState, registerAgentApi, resolveSharedUi, runModules, sharedUiFor };
265
+ export { type AgentBridgeGlobal, type AgentHostState, AuthGate, DefaultLoginScreen, type EventLogEntry, type HostEventBus, type HostEventBusDescription, type HostHandle, type HostNavigator, HostShell, type LoginScreenProps, type ModuleEventHandle, type ModuleRegistration, type RenderLogin, SceneStage, type SharedServices, type SharedUiOwners, type SharedUiResolution, createContentRegistry, createHostEventBus, createHostNavigator, createSharedEventBus, createSurfaceAllocator, emptySharedUiOwners, mountHost, publishEventsProvider, publishHostState, registerAgentApi, resolveSharedUi, runModules, servePlatformShots, sharedUiFor };
package/dist/index.d.ts CHANGED
@@ -234,11 +234,32 @@ declare class SceneStage {
234
234
  /** Make exactly `scenes` the active set: suspend/hide the ones leaving, mount+activate the ones
235
235
  * entering. Idempotent — calling with the current set is a no-op. */
236
236
  setActive(scenes: readonly EngineScene[]): void;
237
+ /**
238
+ * A still frame of what the player is looking at, for the platform's screenshot bridge.
239
+ *
240
+ * Asks the active scene first (`EngineScene.capture`) — only the scene can render and read its
241
+ * WebGL canvas in one turn; see the contract's note on `preserveDrawingBuffer`. A scene without
242
+ * `capture` still works when it draws into a plain 2D canvas, so as a fallback we read the last
243
+ * canvas under its host element. Everything else (a DOM-only mode, nothing mounted, a cleared
244
+ * WebGL buffer that yields a blank frame) resolves `null` and the caller decides what to show —
245
+ * an empty image is worse than an honest "could not".
246
+ */
247
+ captureActive(): Promise<Blob | null>;
237
248
  /** Permanent teardown: destroy every mounted scene and remove its host element. */
238
249
  destroy(): void;
239
250
  }
240
251
 
252
+ /**
253
+ * Answer the platform page's requests for a still frame, for as long as the host is mounted.
254
+ *
255
+ * A no-op outside the browser and outside an iframe — the platform page is the only caller, and
256
+ * there is nobody to answer when the game is the top-level document.
257
+ *
258
+ * Returns an unsubscribe function.
259
+ */
260
+ declare function servePlatformShots(capture: () => Promise<Blob | null>): () => void;
261
+
241
262
  /** Creates an allocator whose surfaces are appended to `layer`. */
242
263
  declare function createSurfaceAllocator(layer: HTMLElement): SurfaceAllocator;
243
264
 
244
- export { type AgentBridgeGlobal, type AgentHostState, AuthGate, DefaultLoginScreen, type EventLogEntry, type HostEventBus, type HostEventBusDescription, type HostHandle, type HostNavigator, HostShell, type LoginScreenProps, type ModuleEventHandle, type ModuleRegistration, type RenderLogin, SceneStage, type SharedServices, type SharedUiOwners, type SharedUiResolution, createContentRegistry, createHostEventBus, createHostNavigator, createSharedEventBus, createSurfaceAllocator, emptySharedUiOwners, mountHost, publishEventsProvider, publishHostState, registerAgentApi, resolveSharedUi, runModules, sharedUiFor };
265
+ export { type AgentBridgeGlobal, type AgentHostState, AuthGate, DefaultLoginScreen, type EventLogEntry, type HostEventBus, type HostEventBusDescription, type HostHandle, type HostNavigator, HostShell, type LoginScreenProps, type ModuleEventHandle, type ModuleRegistration, type RenderLogin, SceneStage, type SharedServices, type SharedUiOwners, type SharedUiResolution, createContentRegistry, createHostEventBus, createHostNavigator, createSharedEventBus, createSurfaceAllocator, emptySharedUiOwners, mountHost, publishEventsProvider, publishHostState, registerAgentApi, resolveSharedUi, runModules, servePlatformShots, sharedUiFor };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import {createRoot}from'react-dom/client';import {IDosGamesProvider,StatusProvider}from'@idosgames/react';import {isTopicName,SHARED_UI_ROLES,isSharedUiRole,hostTopics,topicNamespace}from'@idosgames/module-sdk';import {useRef,useMemo,useState,useEffect,useLayoutEffect}from'react';import {readSsoCodeFromUrl,AuthType,beginSsoRedirect}from'@idosgames/core';import {jsx,jsxs}from'react/jsx-runtime';var Ee=50,T="host",ne=e=>typeof e=="string"?e:e.name,re=e=>typeof e=="string"?null:e.shape,se=e=>e.replace(/@\d+$/,"");function D(){let e=new Map,o=new Map,t=[],s=new Set,i=r=>{t.push(r),t.length>Ee&&t.shift();},l=(r,n)=>{s.has(r)||(s.add(r),console.warn(n));},d=(r,n,c)=>{console.error(`[idos events] ${c}`),i({topic:n,from:r,at:Date.now(),delivered:0,rejected:c});},y=(r,n,c,p)=>{if(!isTopicName(n)){d(r,n,`"${r}" emitted "${n}", which is not a topic name \u2014 use defineTopic("<module-id>:<event>@<major>", shape({\u2026})). Not delivered.`);return}let u=topicNamespace(n);if(r!==T&&u===T){d(r,n,`"${r}" emitted "${n}", but the "host:" namespace belongs to the host. Not delivered.`);return}if(r!==T&&u!==r){d(r,n,`"${r}" emitted "${n}" into the "${u}" namespace \u2014 a module may only emit its own topics ("${r}:\u2026"). Not delivered.`);return}if(c){let v=c.check(p);v&&l(`emit|${r}|${n}`,`[idos events] "${r}" emitted "${n}" with a payload that does not match its own shape: ${v}. Fix the emit or the topic's shape (and module.meta.json).`);}let m=o.get(n);m||o.set(n,m=new Set),m.add(r);let S=0;for(let v of [...e.get(n)??[]]){if(v.shape){let x=v.shape.check(p);if(x){l(`on|${v.moduleId}|${n}`,`[idos events] "${v.moduleId}" skipped "${n}" from "${r}": ${x}. Its copy of the topic's shape no longer matches the emitter \u2014 re-copy it from the catalog.`);continue}}try{v.handler(p),S+=1;}catch(x){console.error(`[idos events] a "${n}" handler in "${v.moduleId}" threw \u2014 other listeners still received the event.`,x);}}i({topic:n,from:r,at:Date.now(),delivered:S});},g=(r,n,c)=>{let p=e.get(n);return p||e.set(n,p=new Set),p.add(c),()=>{let u=e.get(n);u&&(u.delete(c),u.size===0&&e.delete(n));}};return {forModule(r){let n=new Set,c=false;return {emit(u,m){c||y(r,ne(u),re(u),m);},on(u,m){if(c)return ()=>{};let S=ne(u);isTopicName(S)||console.warn(`[idos events] "${r}" subscribed to "${S}", which is not a topic name \u2014 nothing can ever be emitted to it.`);let v=g(r,S,{moduleId:r,shape:re(u),handler:m});return n.add(v),()=>{v(),n.delete(v);}},dispose(){c=true;for(let u of n)u();n.clear();}}},emitAsHost(r,n){y(T,r.name,r.shape,n);},describe(){let r={};for(let[p,u]of e)r[p]=[...new Set([...u].map(m=>m.moduleId))];let n={};for(let[p,u]of o)n[p]=[...u];let c=[];for(let[p,u]of Object.entries(r)){if(o.has(p))continue;let m=[...o.keys()].filter(S=>S!==p&&se(S)===se(p));m.length>0&&c.push(`${u.join(", ")} listen${u.length===1?"s":""} to "${p}", but only ${m.map(S=>`"${S}"`).join(", ")} ${m.length===1?"has":"have"} been emitted \u2014 the major versions differ, so these never meet.`);}return {log:t.slice(),listeners:r,emitted:n,mismatches:c}}}}function ke(){let e=new Map;return {emit(o,t){let s=e.get(o);if(s)for(let i of [...s])i(t);},on(o,t){let s=t,i=e.get(o);return i||(i=new Set,e.set(o,i)),i.add(s),()=>{i.delete(s),i.size===0&&e.delete(o);}}}}function le(){return Object.fromEntries(SHARED_UI_ROLES.map(e=>[e,null]))}function A(e){let o=le(),t=[],s=SHARED_UI_ROLES.join(", ");for(let i of e)for(let l of i.sharedUi?.provides??[]){if(!isSharedUiRole(l)){t.push(`module "${i.id}" provides unknown shared UI role "${String(l)}" (known: ${s}) \u2014 ignored.`);continue}let d=o[l];d===null?o[l]=i.id:d!==i.id&&t.push(`shared UI role "${l}" is provided by both "${d}" and "${i.id}" \u2014 "${d}" wins (it comes first in src/modules.ts), "${i.id}" hides its copy.`);}for(let i of e)for(let l of i.sharedUi?.requires??[]){if(!isSharedUiRole(l)){t.push(`module "${i.id}" requires unknown shared UI role "${String(l)}" (known: ${s}).`);continue}o[l]===null&&t.push(`module "${i.id}" requires shared UI role "${l}", but no installed module provides it \u2014 install game-hud (or another module that provides "${l}").`);}return {owners:o,warnings:t}}function B(e,o){let t=s=>e[s]??null;return {ownerOf:t,shouldDraw:s=>{let i=t(s);return i===null||i===o}}}var Me={position:"absolute",inset:"0"};function N(e){return {request(o){let t=document.createElement("div");return t.dataset.surface=o,Object.assign(t.style,Me),t.style.pointerEvents=o==="fullbleed-canvas"?"auto":"none",e.appendChild(t),{host:t,release(){t.remove();}}}}}var Ce="__IDOS_AGENT__",de={},ce,ue;function He(){try{return typeof window<"u"&&window.self!==window.top}catch{return true}}function z(e,o){de[e]=o,j();}function G(e){ce=e,j();}function _(e){ue=e,j();}function j(){if(!He())return;let e={version:1,modules:de,host:ce,events:ue};globalThis[Ce]=e;}function W(){let e=new Map,o=new Set,t=()=>{for(let s of o)s();};return {registerType(s){if(!s?.type)throw new Error("ctx.content.registerType(): handler.type is required");return e.set(s.type,s),t(),()=>{e.get(s.type)===s&&(e.delete(s.type),t());}},getType:s=>e.get(s),listTypes:()=>[...e.values()],subscribe(s){return o.add(s),()=>{o.delete(s);}}}}function V(){let e=null,o=null;return {navigate(t){t&&(e?e(t):o=t);},bind(t){if(e=t,o!==null){let s=o;o=null,t(s);}return ()=>{e===t&&(e=null);}}}}function F(e,o){let t=o.sharedUi??A(e).owners,s=o.content??W(),i=[];try{for(let l of e){let d=o.events.forModule(l.id),y=[],g={module:l,scenes:[],panels:[],routes:[],dispose:()=>{d.dispose();for(let n of y.splice(0))n();}};i.push(g);let r={client:o.client,titleId:o.client.titleID,events:d,sharedUi:B(t,l.id),surface:o.surface,registerScene:n=>g.scenes.push(n),registerPanel:n=>g.panels.push(n),registerRoute:n=>g.routes.push(n),content:{registerType:n=>{let c=s.registerType(n);return y.push(c),c},getType:n=>s.getType(n),listTypes:()=>s.listTypes(),subscribe:n=>s.subscribe(n)},navigate:n=>o.navigator?.navigate(n),exposeToAgent:n=>z(l.id,n)};l.setup(r);}}catch(l){for(let d of i)d.dispose();throw l}return i}var I=class{constructor(o){this.container=o;}container;hosts=new Map;active=new Set;ensureMounted(o){let t=this.hosts.get(o);return t||(t=document.createElement("div"),Object.assign(t.style,{position:"absolute",inset:"0"}),this.container.appendChild(t),this.hosts.set(o,t),o.mount({host:t})),t}setActive(o){let t=new Set(o);for(let s of this.active){if(t.has(s))continue;s.suspend?.();let i=this.hosts.get(s);i&&(i.style.display="none");}for(let s of t){if(this.active.has(s))continue;let i=this.ensureMounted(s);i.style.display="block",s.activate?.();}this.active=t;}destroy(){for(let[o,t]of this.hosts)o.destroy(),t.remove();this.hosts.clear(),this.active.clear();}};function X({registrations:e,sharedUi:o,events:t,onLogout:s,userID:i,navigator:l}){let d=useRef(null),y=useRef(null),g=useMemo(()=>e.flatMap(a=>a.routes.map(f=>({id:f.id,label:f.label,icon:f.icon,order:f.order??0,moduleId:a.module.id}))).sort((a,f)=>a.order-f.order),[e]),[r,n]=useState(()=>g[0]?.id??null);useEffect(()=>{r!==null&&g.some(a=>a.id===r)||n(g[0]?.id??null);},[g,r]),useEffect(()=>l?.bind(a=>{g.some(f=>f.id===a)&&n(a);}),[l,g]);let c=useMemo(()=>g.find(a=>a.id===r)?.moduleId??null,[g,r]),p=useRef(null);useEffect(()=>{if(r===null||r===p.current)return;let a=p.current;p.current=r,t?.emitAsHost(hostTopics.modeChanged,a===null?{to:r}:{from:a,to:r});},[r,t]),useEffect(()=>{let a=d.current;if(!a)return;let f=y.current??=new I(a),C=e.find(U=>U.module.id===c)?.scenes??[];f.setActive(C);},[e,c]),useEffect(()=>()=>{y.current?.destroy(),y.current=null;},[]);let u=useMemo(()=>e.flatMap(a=>a.panels.filter(f=>f.activeOnly===false||a.module.id===c).map(f=>{let C=f.component;return {key:`${a.module.id}:${f.id}`,slot:f.slot,order:f.order??0,moduleId:a.module.id,component:jsx(C,{})}})).sort((a,f)=>a.order-f.order),[e,c]),m=a=>u.filter(f=>f.slot===a),S=e.length>0,v=m("hud").length,x=g.length>1,b=!o?.account,R=useRef(null),k=useRef(null),[M,we]=useState({top:0,bottom:0});useLayoutEffect(()=>{let a=()=>{let C=v>0&&R.current?Math.ceil(R.current.getBoundingClientRect().height):0,U=x&&k.current?Math.ceil(k.current.getBoundingClientRect().height)+fe:0;we(O=>O.top===C&&O.bottom===U?O:{top:C,bottom:U});};if(a(),typeof ResizeObserver>"u")return;let f=new ResizeObserver(a);return R.current&&f.observe(R.current),k.current&&f.observe(k.current),()=>f.disconnect()},[v,x]);let xe={...Ue,"--idos-safe-top":`${M.top}px`,"--idos-safe-bottom":`${M.bottom}px`};return jsxs("div",{style:xe,children:[jsx("div",{ref:d,style:Te}),jsx("div",{style:{...Pe,top:M.top,bottom:M.bottom},children:m("overlay").map(a=>jsx("div",{style:K,children:a.component},a.key))}),jsx("div",{ref:R,style:De,children:m("hud").map(a=>jsx("div",{style:Oe,children:a.component},a.key))}),jsx("div",{style:{...Be,top:M.top,bottom:M.bottom},children:m("sidebar").map(a=>jsx("div",{style:K,children:a.component},a.key))}),x&&jsx("nav",{ref:k,style:Ne,children:g.map(a=>jsxs("button",{type:"button",onClick:()=>n(a.id),style:a.id===r?ze:ge,children:[a.icon?`${a.icon} `:"",a.label]},a.id))}),b&&(s||i)&&jsxs("div",{style:Ge,children:[s&&jsx("button",{type:"button",style:me,onClick:s,title:"Log out",children:"\u{1F6AA} Log out"}),i&&jsx(Le,{userID:i})]}),m("modal").length>0&&jsx("div",{style:je,children:m("modal").map(a=>jsx("div",{style:K,children:a.component},a.key))}),!S&&jsx($e,{})]})}function Le({userID:e}){let[o,t]=useState(false),s=()=>{(async()=>{try{await navigator.clipboard.writeText(e);}catch{let l=document.createElement("textarea");l.value=e,document.body.appendChild(l),l.select(),document.execCommand("copy"),l.remove();}t(true),window.setTimeout(()=>t(false),1500);})();},i=e.length>12?`${e.slice(0,5)}\u2026${e.slice(-5)}`:e;return jsx("button",{type:"button",style:_e,onClick:s,title:`Copy your player ID: ${e}`,children:o?"\u2713 Copied":`ID: ${i} \u29C9`})}function $e(){return jsxs("div",{style:We,children:[jsx("style",{children:`
1
+ import {createRoot}from'react-dom/client';import {IDosGamesProvider,StatusProvider}from'@idosgames/react';import {isTopicName,SHARED_UI_ROLES,isSharedUiRole,hostTopics,topicNamespace}from'@idosgames/module-sdk';import {useRef,useMemo,useState,useEffect,useLayoutEffect}from'react';import {readSsoCodeFromUrl,AuthType,beginSsoRedirect,isPlatformParentOrigin}from'@idosgames/core';import {jsx,jsxs}from'react/jsx-runtime';var ke=50,U="host",re=t=>typeof t=="string"?t:t.name,se=t=>typeof t=="string"?null:t.shape,ie=t=>t.replace(/@\d+$/,"");function D(){let t=new Map,o=new Map,e=[],n=new Set,s=i=>{e.push(i),e.length>ke&&e.shift();},a=(i,r)=>{n.has(i)||(n.add(i),console.warn(r));},d=(i,r,c)=>{console.error(`[idos events] ${c}`),s({topic:r,from:i,at:Date.now(),delivered:0,rejected:c});},v=(i,r,c,p)=>{if(!isTopicName(r)){d(i,r,`"${i}" emitted "${r}", which is not a topic name \u2014 use defineTopic("<module-id>:<event>@<major>", shape({\u2026})). Not delivered.`);return}let u=topicNamespace(r);if(i!==U&&u===U){d(i,r,`"${i}" emitted "${r}", but the "host:" namespace belongs to the host. Not delivered.`);return}if(i!==U&&u!==i){d(i,r,`"${i}" emitted "${r}" into the "${u}" namespace \u2014 a module may only emit its own topics ("${i}:\u2026"). Not delivered.`);return}if(c){let y=c.check(p);y&&a(`emit|${i}|${r}`,`[idos events] "${i}" emitted "${r}" with a payload that does not match its own shape: ${y}. Fix the emit or the topic's shape (and module.meta.json).`);}let m=o.get(r);m||o.set(r,m=new Set),m.add(i);let S=0;for(let y of [...t.get(r)??[]]){if(y.shape){let x=y.shape.check(p);if(x){a(`on|${y.moduleId}|${r}`,`[idos events] "${y.moduleId}" skipped "${r}" from "${i}": ${x}. Its copy of the topic's shape no longer matches the emitter \u2014 re-copy it from the catalog.`);continue}}try{y.handler(p),S+=1;}catch(x){console.error(`[idos events] a "${r}" handler in "${y.moduleId}" threw \u2014 other listeners still received the event.`,x);}}s({topic:r,from:i,at:Date.now(),delivered:S});},g=(i,r,c)=>{let p=t.get(r);return p||t.set(r,p=new Set),p.add(c),()=>{let u=t.get(r);u&&(u.delete(c),u.size===0&&t.delete(r));}};return {forModule(i){let r=new Set,c=false;return {emit(u,m){c||v(i,re(u),se(u),m);},on(u,m){if(c)return ()=>{};let S=re(u);isTopicName(S)||console.warn(`[idos events] "${i}" subscribed to "${S}", which is not a topic name \u2014 nothing can ever be emitted to it.`);let y=g(i,S,{moduleId:i,shape:se(u),handler:m});return r.add(y),()=>{y(),r.delete(y);}},dispose(){c=true;for(let u of r)u();r.clear();}}},emitAsHost(i,r){v(U,i.name,i.shape,r);},describe(){let i={};for(let[p,u]of t)i[p]=[...new Set([...u].map(m=>m.moduleId))];let r={};for(let[p,u]of o)r[p]=[...u];let c=[];for(let[p,u]of Object.entries(i)){if(o.has(p))continue;let m=[...o.keys()].filter(S=>S!==p&&ie(S)===ie(p));m.length>0&&c.push(`${u.join(", ")} listen${u.length===1?"s":""} to "${p}", but only ${m.map(S=>`"${S}"`).join(", ")} ${m.length===1?"has":"have"} been emitted \u2014 the major versions differ, so these never meet.`);}return {log:e.slice(),listeners:i,emitted:r,mismatches:c}}}}function Ce(){let t=new Map;return {emit(o,e){let n=t.get(o);if(n)for(let s of [...n])s(e);},on(o,e){let n=e,s=t.get(o);return s||(s=new Set,t.set(o,s)),s.add(n),()=>{s.delete(n),s.size===0&&t.delete(o);}}}}function de(){return Object.fromEntries(SHARED_UI_ROLES.map(t=>[t,null]))}function I(t){let o=de(),e=[],n=SHARED_UI_ROLES.join(", ");for(let s of t)for(let a of s.sharedUi?.provides??[]){if(!isSharedUiRole(a)){e.push(`module "${s.id}" provides unknown shared UI role "${String(a)}" (known: ${n}) \u2014 ignored.`);continue}let d=o[a];d===null?o[a]=s.id:d!==s.id&&e.push(`shared UI role "${a}" is provided by both "${d}" and "${s.id}" \u2014 "${d}" wins (it comes first in src/modules.ts), "${s.id}" hides its copy.`);}for(let s of t)for(let a of s.sharedUi?.requires??[]){if(!isSharedUiRole(a)){e.push(`module "${s.id}" requires unknown shared UI role "${String(a)}" (known: ${n}).`);continue}o[a]===null&&e.push(`module "${s.id}" requires shared UI role "${a}", but no installed module provides it \u2014 install game-hud (or another module that provides "${a}").`);}return {owners:o,warnings:e}}function B(t,o){let e=n=>t[n]??null;return {ownerOf:e,shouldDraw:n=>{let s=e(n);return s===null||s===o}}}var Ae={position:"absolute",inset:"0"};function z(t){return {request(o){let e=document.createElement("div");return e.dataset.surface=o,Object.assign(e.style,Ae),e.style.pointerEvents=o==="fullbleed-canvas"?"auto":"none",t.appendChild(e),{host:e,release(){e.remove();}}}}}var He="__IDOS_AGENT__",ce={},ue,pe;function Ie(){try{return typeof window<"u"&&window.self!==window.top}catch{return true}}function N(t,o){ce[t]=o,j();}function G(t){ue=t,j();}function _(t){pe=t,j();}function j(){if(!Ie())return;let t={version:1,modules:ce,host:ue,events:pe};globalThis[He]=t;}function W(){let t=new Map,o=new Set,e=()=>{for(let n of o)n();};return {registerType(n){if(!n?.type)throw new Error("ctx.content.registerType(): handler.type is required");return t.set(n.type,n),e(),()=>{t.get(n.type)===n&&(t.delete(n.type),e());}},getType:n=>t.get(n),listTypes:()=>[...t.values()],subscribe(n){return o.add(n),()=>{o.delete(n);}}}}function q(){let t=null,o=null;return {navigate(e){e&&(t?t(e):o=e);},bind(e){if(t=e,o!==null){let n=o;o=null,e(n);}return ()=>{t===e&&(t=null);}}}}function F(t,o){let e=o.sharedUi??I(t).owners,n=o.content??W(),s=[];try{for(let a of t){let d=o.events.forModule(a.id),v=[],g={module:a,scenes:[],panels:[],routes:[],dispose:()=>{d.dispose();for(let r of v.splice(0))r();}};s.push(g);let i={client:o.client,titleId:o.client.titleID,events:d,sharedUi:B(e,a.id),surface:o.surface,registerScene:r=>g.scenes.push(r),registerPanel:r=>g.panels.push(r),registerRoute:r=>g.routes.push(r),content:{registerType:r=>{let c=n.registerType(r);return v.push(c),c},getType:r=>n.getType(r),listTypes:()=>n.listTypes(),subscribe:r=>n.subscribe(r)},navigate:r=>o.navigator?.navigate(r),exposeToAgent:r=>N(a.id,r)};a.setup(i);}}catch(a){for(let d of s)d.dispose();throw a}return s}async function Pe(t){try{let o=await createImageBitmap(t,{resizeWidth:32,resizeHeight:32,resizeQuality:"low"}),e=document.createElement("canvas");e.width=o.width,e.height=o.height;let n=e.getContext("2d");if(!n)return !0;n.drawImage(o,0,0),o.close?.();let{data:s}=n.getImageData(0,0,e.width,e.height);for(let a=4;a<s.length;a+=4)if(s[a]!==s[0]||s[a+1]!==s[1]||s[a+2]!==s[2]||s[a+3]!==s[3])return !0;return !1}catch{return true}}var P=class{constructor(o){this.container=o;}container;hosts=new Map;active=new Set;ensureMounted(o){let e=this.hosts.get(o);return e||(e=document.createElement("div"),Object.assign(e.style,{position:"absolute",inset:"0"}),this.container.appendChild(e),this.hosts.set(o,e),o.mount({host:e})),e}setActive(o){let e=new Set(o);for(let n of this.active){if(e.has(n))continue;n.suspend?.();let s=this.hosts.get(n);s&&(s.style.display="none");}for(let n of e){if(this.active.has(n))continue;let s=this.ensureMounted(n);s.style.display="block",n.activate?.();}this.active=e;}async captureActive(){for(let o of this.active){let e=await o.capture?.().catch(()=>null);if(e)return e;let s=this.hosts.get(o)?.querySelectorAll("canvas"),a=s?.[s.length-1];if(!a)continue;let d=await new Promise(v=>{try{a.toBlob(v,"image/png");}catch{v(null);}});if(d&&await Pe(d))return d}return null}destroy(){for(let[o,e]of this.hosts)o.destroy(),e.remove();this.hosts.clear(),this.active.clear();}};var Te="IDOS_PLATFORM_SHOT_REQUEST",fe="IDOS_PLATFORM_SHOT_RESPONSE";function V(t){if(typeof window>"u"||window.self===window.top)return ()=>{};let o=e=>{let n=e?.data;if(!n||n.type!==Te||typeof n.requestId!="string"||!isPlatformParentOrigin(e.origin))return;let s=e.source;if(!s)return;let a=n.requestId;t().catch(()=>null).then(d=>{try{s.postMessage(d?{type:fe,requestId:a,image:d}:{type:fe,requestId:a},e.origin);}catch{}});};return window.addEventListener("message",o),()=>window.removeEventListener("message",o)}function X({registrations:t,sharedUi:o,events:e,onLogout:n,userID:s,navigator:a}){let d=useRef(null),v=useRef(null),g=useMemo(()=>t.flatMap(l=>l.routes.map(f=>({id:f.id,label:f.label,icon:f.icon,order:f.order??0,moduleId:l.module.id}))).sort((l,f)=>l.order-f.order),[t]),[i,r]=useState(()=>g[0]?.id??null);useEffect(()=>{i!==null&&g.some(l=>l.id===i)||r(g[0]?.id??null);},[g,i]),useEffect(()=>a?.bind(l=>{g.some(f=>f.id===l)&&r(l);}),[a,g]);let c=useMemo(()=>g.find(l=>l.id===i)?.moduleId??null,[g,i]),p=useRef(null);useEffect(()=>{if(i===null||i===p.current)return;let l=p.current;p.current=i,e?.emitAsHost(hostTopics.modeChanged,l===null?{to:i}:{from:l,to:i});},[i,e]),useEffect(()=>{let l=d.current;if(!l)return;let f=v.current??=new P(l),C=t.find(T=>T.module.id===c)?.scenes??[];f.setActive(C);},[t,c]),useEffect(()=>()=>{v.current?.destroy(),v.current=null;},[]),useEffect(()=>V(()=>v.current?.captureActive()??Promise.resolve(null)),[]);let u=useMemo(()=>t.flatMap(l=>l.panels.filter(f=>f.activeOnly===false||l.module.id===c).map(f=>{let C=f.component;return {key:`${l.module.id}:${f.id}`,slot:f.slot,order:f.order??0,moduleId:l.module.id,component:jsx(C,{})}})).sort((l,f)=>l.order-f.order),[t,c]),m=l=>u.filter(f=>f.slot===l),S=t.length>0,y=m("hud").length,x=g.length>1,b=!o?.account,R=useRef(null),M=useRef(null),[k,Re]=useState({top:0,bottom:0});useLayoutEffect(()=>{let l=()=>{let C=y>0&&R.current?Math.ceil(R.current.getBoundingClientRect().height):0,T=x&&M.current?Math.ceil(M.current.getBoundingClientRect().height)+me:0;Re(O=>O.top===C&&O.bottom===T?O:{top:C,bottom:T});};if(l(),typeof ResizeObserver>"u")return;let f=new ResizeObserver(l);return R.current&&f.observe(R.current),M.current&&f.observe(M.current),()=>f.disconnect()},[y,x]);let Ee={...Be,"--idos-safe-top":`${k.top}px`,"--idos-safe-bottom":`${k.bottom}px`};return jsxs("div",{style:Ee,children:[jsx("div",{ref:d,style:ze}),jsx("div",{style:{...Ne,top:k.top,bottom:k.bottom},children:m("overlay").map(l=>jsx("div",{style:Y,children:l.component},l.key))}),jsx("div",{ref:R,style:_e,children:m("hud").map(l=>jsx("div",{style:Ge,children:l.component},l.key))}),jsx("div",{style:{...je,top:k.top,bottom:k.bottom},children:m("sidebar").map(l=>jsx("div",{style:Y,children:l.component},l.key))}),x&&jsx("nav",{ref:M,style:We,children:g.map(l=>jsxs("button",{type:"button",onClick:()=>r(l.id),style:l.id===i?qe:he,children:[l.icon?`${l.icon} `:"",l.label]},l.id))}),b&&(n||s)&&jsxs("div",{style:Fe,children:[n&&jsx("button",{type:"button",style:ve,onClick:n,title:"Log out",children:"\u{1F6AA} Log out"}),s&&jsx(Oe,{userID:s})]}),m("modal").length>0&&jsx("div",{style:Ke,children:m("modal").map(l=>jsx("div",{style:Y,children:l.component},l.key))}),!S&&jsx(De,{})]})}function Oe({userID:t}){let[o,e]=useState(false),n=()=>{(async()=>{try{await navigator.clipboard.writeText(t);}catch{let a=document.createElement("textarea");a.value=t,document.body.appendChild(a),a.select(),document.execCommand("copy"),a.remove();}e(true),window.setTimeout(()=>e(false),1500);})();},s=t.length>12?`${t.slice(0,5)}\u2026${t.slice(-5)}`:t;return jsx("button",{type:"button",style:Ve,onClick:n,title:`Copy your player ID: ${t}`,children:o?"\u2713 Copied":`ID: ${s} \u29C9`})}function De(){return jsxs("div",{style:Ye,children:[jsx("style",{children:`
2
2
  @keyframes idos-empty-float {
3
3
  0%, 100% { transform: translateY(0) rotate(-6deg); }
4
4
  50% { transform: translateY(-16px) rotate(6deg); }
@@ -7,5 +7,5 @@ import {createRoot}from'react-dom/client';import {IDosGamesProvider,StatusProvid
7
7
  0% { transform: scale(0.55); opacity: 0.55; }
8
8
  100% { transform: scale(1.7); opacity: 0; }
9
9
  }
10
- `}),jsxs("div",{style:Ve,children:[jsx("span",{style:{...pe,animationDelay:"0s"}}),jsx("span",{style:{...pe,animationDelay:"1.1s"}}),jsx("span",{style:Fe,children:"\u{1F9E9}"})]}),jsx("div",{style:{fontWeight:700,fontSize:18,marginBottom:6},children:"No modules installed"}),jsxs("div",{style:{opacity:.85,maxWidth:380,lineHeight:1.5},children:["Add a module under ",jsx("code",{children:"src/modules/"})," and register it in"," ",jsx("code",{children:"src/modules.ts"}),". The host shell will pick it up here."]})]})}var Ue={position:"absolute",inset:0,overflow:"hidden",background:"#0d66fe",color:"#fff",fontFamily:"system-ui, sans-serif"},Te={position:"absolute",inset:0,zIndex:0},fe=16,Pe={position:"absolute",top:0,right:0,bottom:0,left:0,zIndex:1,pointerEvents:"none"},Oe={display:"contents",pointerEvents:"auto"},De={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},Be={position:"absolute",top:0,right:0,bottom:0,width:340,maxWidth:"40vw",zIndex:2,display:"flex",flexDirection:"column",gap:12,padding:16,overflowY:"auto",pointerEvents:"none"},Ne={position:"absolute",bottom:fe,left:"50%",transform:"translateX(-50%)",zIndex:3,display:"flex",gap:8,padding:6,borderRadius:14,background:"rgba(4,32,90,0.72)",backdropFilter:"blur(6px)",pointerEvents:"auto"},ge={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfe0ff",background:"transparent",cursor:"pointer"},ze={...ge,color:"#0d66fe",background:"#fff"},Ge={position:"absolute",bottom:16,left:16,zIndex:3,display:"flex",gap:8,alignItems:"center",pointerEvents:"auto"},me={border:"none",borderRadius:12,padding:"8px 14px",fontWeight:700,fontSize:13,color:"#cfe0ff",background:"rgba(4,32,90,0.72)",backdropFilter:"blur(6px)",cursor:"pointer"},_e={...me,fontWeight:600,fontFamily:"ui-monospace, Consolas, monospace"},je={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},K={pointerEvents:"auto"},We={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24},Ve={position:"relative",width:110,height:110,marginBottom:16,display:"grid",placeItems:"center"},pe={position:"absolute",inset:0,borderRadius:"50%",border:"2px solid rgba(255,255,255,0.55)",animation:"idos-empty-ripple 2.2s ease-out infinite"},Fe={fontSize:46,animation:"idos-empty-float 3s ease-in-out infinite",filter:"drop-shadow(0 8px 12px rgba(0,0,0,0.25))"};function Q(e){let{client:o,modules:t,events:s,sharedUi:i,surface:l,renderLogin:d}=e,[y]=useState(V),[g,r]=useState(true),[n,c]=useState(null),p=useRef(null),u=()=>{for(let b of p.current??[])b.dispose();p.current=null;},m=()=>{u();let b=F(t,{client:o,events:s,surface:l,sharedUi:i,navigator:y});p.current=b,c(b);};useEffect(()=>()=>u(),[]);let S=useRef(false);useEffect(()=>{if(S.current)return;S.current=true;let b=readSsoCodeFromUrl();if(b){(async()=>((await o.auth.loginWithSsoCode(b.code)).ok&&m(),r(false)))();return}if(o.auth.lastAuthType===AuthType.None){r(false);return}(async()=>((await o.auth.autoLogin()).ok&&m(),r(false)))();},[o]),useEffect(()=>{let b=()=>{u(),c(null);},R=o.on("auth:unauthorized",b),k=o.on("auth:loggedOut",b);return ()=>{R(),k();}},[o]);let v=n?"game":g?"loading":"login";return useEffect(()=>{G({screen:v,loggedIn:n!==null,userId:o.auth.context?.userID??null,titleId:o.titleID??null,modules:t.map(b=>b.id),sharedUi:i});},[v,n,o,t,i]),n?jsx(X,{registrations:n,sharedUi:i,events:s,navigator:y,onLogout:()=>o.auth.logout(),userID:o.auth.context?.userID??null}):g?null:jsx(d,{client:o,onAuthenticated:m})}var Ye='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 860 690" fill="#fff"><g transform="translate(243 -2)"><path d="M147.333 12.333c-13.6 2.534-12.533 1.2-12.933 15.067l-.4 12.267-4.533-11.067c-2.534-6-5.067-10.933-5.734-10.933-2.666 0-27.866 8.666-36.533 12.666-11.733 5.334-26.667 14.8-36.133 22.934l-6.934 5.866L51.6 69.267c8.133 11.066 7.333 11.466-5.067 2.933-7.6-5.067-8.4-5.333-11.466-3.733-3.467 1.866-18.4 17.333-20.4 21.2-.8 1.6 7.066 8.8 33.733 30.933l34.667 28.933 8.8-8.266c14.666-13.867 28.666-22 48.133-28.267 9.067-2.933 14.8-3.733 28.533-4.4 34.267-1.333 60 7.467 81.6 28.133 21.6 20.4 34.934 49.6 37.467 81.734l.8 11.2 14.8 4.533c8.133 2.533 23.733 7.333 34.667 10.8 10.933 3.333 20.4 5.6 21.066 4.933 1.6-1.6 6.134-20.533 7.734-32.666.8-6 1.333-17.6 1.066-25.6l-.4-14.667-8-1.067c-4.4-.533-10.133-1.466-12.666-1.866l-4.667-.8 4.667-1.2c16.933-4.534 18.666-5.2 18.666-8 0-5.467-9.6-31.334-16.666-44.8-4-7.6-10.667-18.667-14.934-24.667-9.866-13.867-31.333-35.467-45.2-45.2-10.4-7.467-34.4-20.933-37.2-21.067-.8 0-4 4-7.333 8.8-3.2 4.8-6.133 8.134-6.4 7.334s.4-5.6 1.6-10.667c1.2-5.2 2.133-9.6 2.133-9.867 0-.933-19.866-6.133-34.4-9.066-14.8-2.934-49.333-4.4-59.6-2.534"/><path d="M157.867 125.533c-21.067 3.334-42.134 14.8-57.467 31.334-13.333 14.133-13.733 12.8 5.6 22 9.2 4.4 16.667 8.266 16.667 8.533s-1.334.4-2.934.133c-13.866-2.133-41.6-5.866-41.733-5.6-.267.267-7.467 28.534-16.267 63.067l-16 62.667 7.334.4c4 .266 7.466.266 7.6 0 .266-.267 3.866-13.867 8.133-30.4 4.267-16.534 8.267-30.8 8.933-31.734.934-1.2 11.067-1.6 42.4-1.6 32.134 0 41.2.4 41.2 1.6 0 .934-1.733 4.667-3.866 8.4L153.733 261l-35.066 6.933c-19.334 3.867-35.2 7.2-35.467 7.467-.667.667-29.867 113.467-29.467 113.867.267.133 23.734-3.6 52.4-8.534l52-8.8 20.4-39.866c11.2-22 20.667-39.734 20.934-39.467.4.533-1.334 26.8-2.8 40.8l-.667 6.933 6.267-3.2c21.2-10.666 52.4-13.466 86.933-8l5.867.934-5.6-7.334C286.4 318.6 281.2 310.6 278 304.867c-5.867-10.134-6-10.8-6-21.867 0-6.267 1.467-20 3.333-30.667 1.867-10.666 3.334-19.466 3.334-19.466 0-.134-9.067-4.267-20.134-9.334s-19.466-9.333-18.8-9.6c.8-.266 7.734.8 15.6 2.267 7.734 1.6 14.4 2.8 14.8 2.8 1.2 0 .4-10.533-1.466-18-7.2-27.733-28-53.467-53.734-66-16.4-8-40.8-12-57.066-9.467"/><path d="M235.6 346.333c-24 4.534-44.133 13.867-68.267 31.467-14 10.267-28.533 18.133-47.733 25.867-23.467 9.466-52.8 32.666-64.4 50.666l-2.533 4L58 454.2c9.333-7.333 30.133-19.467 49.333-28.667C173.733 393.667 246.4 382.2 312.8 393c11.2 1.733 39.2 8.533 45.067 10.8 2.266.8 2.266.667.8-2.267-4-7.6-15.6-21.866-25.867-31.466-12-11.467-24.667-18.934-37.6-22.4-11.467-3.067-46.267-3.867-59.6-1.334"/></g><g transform="translate(-460 467)"><path d="M721.533 34.467c-14.933 5.466-22 17.466-22.933 38.666-.933 24.134 3.467 32.8 30.267 59.867 19.6 19.867 22.933 25.2 22.933 37.867.133 13.466-6.133 20.133-16.933 18.4-9.067-1.467-12.534-7.867-12.534-22.667V159H696.6l.667 13.333c.533 11.467 1.2 14.4 4.933 22 7.067 14.267 16.8 19.6 36.4 19.734 10.667.133 12.267-.134 20.667-4.4 7.6-3.867 9.733-5.867 13.2-11.734 7.6-12.533 9.066-32 3.733-47.6-3.733-11.066-10.667-20.4-27.867-37.2-19.866-19.6-22.533-24.133-22.666-38.4 0-8.933.4-10.533 3.2-13.6 6.266-6.666 18.266-5.6 22.133 2 1.067 2 2 7.067 2 11.2v7.334h27.067l-.934-9.2c-1.6-18.267-8.266-30.267-20-36.4-7.2-3.867-29.2-4.8-37.6-1.6M630.067 34.867c-11.734 4.666-18 11.6-21.734 24.4-1.866 6.4-2 15.333-1.733 67.2l.4 59.866 3.733 7.6c6.8 13.867 18.534 20.267 36.934 20.267 13.733 0 22.933-3.333 30.666-11.067 10.934-11.066 11.2-12.533 11.734-74.666.266-35.734-.134-56.934-1.067-62.8-2.667-16.134-11.6-27.467-24.8-31.467-8.933-2.667-26.4-2.267-34.133.667m28.666 26.8 3.6 4v56.666c0 40.934-.4 57.467-1.6 60-3.6 8-15.6 9.734-22.666 3.467l-4.4-3.867-.4-56.533c-.267-51.733-.134-56.8 2-61.067 3.066-5.866 7.6-8.266 14.4-7.466 3.733.4 6.4 1.866 9.066 4.8M511.667 123.133v89.334l29.066-.4c28.8-.4 28.934-.4 36.667-4.267 9.467-4.533 14.4-10.933 17.467-22.4 2-7.333 2.266-15.467 1.866-65.733l-.4-57.334-4.266-8.8c-8.267-16.666-17.2-19.866-55.334-19.866h-25.066zm53.6-60.266 4.4 3.866.4 52.8c.266 35.067-.134 54.4-1.067 58-2 7.467-5.733 9.6-18.667 10.4l-10.666.8V59h10.666c9.867 0 10.934.267 14.934 3.867M471.667 145v67.333h26.666V77.667h-26.666zM471.667 48.333V63h26.666V33.667h-26.666z"/></g><g transform="translate(-106 244)"><path d="M893.4 259.733c-6.8 3.467-9.2 5.6-12.667 11.467-10.666 17.733-9.2 42.933 3.467 62.267 2.8 4.266 12.267 14.8 20.933 23.333 9.867 9.467 17.067 17.733 18.934 21.6 5.6 11.333 5.2 25.333-.934 30.8-3.466 3.067-11.333 4.133-16.133 2.133-5.867-2.4-8-7.466-8-19.333v-10h-27.067l.8 11.6c1.2 15.867 3.867 24.133 10.267 31.333 7.467 8.534 16.4 12.134 30 12.267 19.067.133 30.133-5.733 37.333-19.867 3.734-7.466 4-8.666 4-24 0-16 0-16.133-5.2-26.666-4.4-9.2-7.733-13.2-23.066-28.534-21.067-21.066-24.8-27.066-24.934-40.4-.133-10.4 2.8-15.6 9.734-17.6 10.133-2.933 17.2 3.334 18.4 16.267l.8 8.267H955.4l-.8-10.8c-.533-8.4-1.6-12.667-4.8-19.2-7.067-14.134-16.667-19.334-36.133-19.334-10.667 0-12.534.4-20.267 4.4M791 346v89.333h76v-24h-48v-54.666h37.333v-24H819V282h48v-25.333h-76zM661.667 346v89.333h22.666l.134-63.066c0-34.534.533-61.734 1.066-60.267.534 1.467 5.467 29.867 10.8 62.933l9.867 60.4h13.067c7.2 0 13.066-.4 13.066-1.066 0-3.067 18.8-124.8 19.334-125.334.4-.4.666 27.867.666 62.8v63.6h25.334V256.667h-38l-9.2 61.6c-5.067 34-9.6 62.133-10 62.666-.534.534-5.334-26.4-10.667-60-5.467-33.466-10.133-61.733-10.533-62.666-.4-1.2-5.467-1.6-19.067-1.6h-18.533zM586.467 258.267c-.8 2.666-27.467 172.4-27.467 174.933 0 1.867 1.733 2.133 12 2.133h11.867l.8-4.4c.533-2.266 1.6-9.333 2.4-15.6l1.6-11.333 17.6-.4 17.466-.4 1.467 8.4c.8 4.667 1.733 11.867 2.267 16l.933 7.733h13.733c7.6 0 13.867-.266 13.867-.666 0-.8-26.533-168.134-27.467-173.734l-.8-4.266h-19.866c-14.8 0-20.134.4-20.4 1.6M613 336.533c3.333 23.067 5.867 42.134 5.6 42.4-.4.267-6.533.267-13.867.134l-13.2-.4 4.934-33.334c2.8-18.4 5.733-38.4 6.666-44.666C604.2 292.533 605 290.133 605.8 292c.533 1.467 3.867 21.467 7.2 44.533M497.267 257.2c-10.134 3.733-15.2 8.267-19.867 17.733L473 284l-.4 59.067c-.4 51.2-.133 60.133 1.733 66.533 5.6 19.333 17.067 27.333 39.467 27.467 10.267.133 12.267-.267 20.133-4.134 9.334-4.533 13.867-9.733 17.867-20.266 2-4.934 2.4-12 2.933-41.067l.534-34.933h-38.934v23.866l6.4.4 6.267.4v19.334c0 13.466-.533 20.666-1.867 23.733-5.066 12-23.333 10.4-26.8-2.4-.933-3.6-1.333-23.2-1.066-59.067.4-48.533.666-54.133 2.666-57.333 3.334-4.8 11.2-7.067 17.6-4.933 6.934 2.266 9.067 7.2 9.867 22.933l.667 13.067H555.4l-.8-15.734c-.8-18-3.067-25.6-9.867-33.466-7.466-8.8-13.466-11.2-29.066-11.734-9.067-.266-14.934.134-18.4 1.467"/></g></svg>',ye=`data:image/svg+xml;utf8,${encodeURIComponent(Ye)}`;var Je=["https://cloud.idosgames.com","https://idosgames.com","https://www.idosgames.com"],Qe=/^https:\/\/[a-z0-9]{8}(-dev)?\.idos\.games$/;function Se(){if(typeof window>"u")return false;let{origin:e}=window.location;return Je.includes(e)||Qe.test(e)?true:typeof document<"u"&&document.querySelector('meta[name="idos-game-host"]')!==null}function ee({client:e,onAuthenticated:o}){let[t,s]=useState(false),[i,l]=useState(null),[d,y]=useState(true),g=async()=>{s(true),l(null),e.auth.setRememberSession(d);let r=await e.auth.loginWithDeviceID();if(r.ok){o();return}l(r.error),s(false);};return jsx("div",{style:w.root,children:jsxs("div",{style:w.card,children:[jsx("img",{src:ye,alt:"iDos Games",style:w.logo}),jsx("h1",{style:w.title,children:"Sign in"}),Se()&&jsx("button",{type:"button",onClick:()=>beginSsoRedirect({titleID:e.titleID}),disabled:t,style:{...w.primary,opacity:t?.6:1,cursor:t?"default":"pointer"},children:"Continue with iDos Games"}),jsx("button",{type:"button",onClick:()=>{g();},disabled:t,style:{...Se()?w.ghost:w.primary,opacity:t?.6:1,cursor:t?"default":"pointer"},children:t?"Signing in\u2026":"Play as guest"}),jsxs("label",{style:{...w.remember,opacity:t?.6:1},children:[jsx("input",{type:"checkbox",checked:d,disabled:t,onChange:r=>y(r.target.checked),style:w.switchInput}),jsx("span",{style:{...w.switchTrack,background:d?"#fff":"rgba(255, 255, 255, 0.3)"},children:jsx("span",{style:{...w.switchKnob,left:d?"21px":"3px",background:d?"#0d66fe":"#fff"}})}),"Remember me"]}),i&&jsx("span",{style:w.error,children:i})]})})}var w={root:{position:"absolute",inset:0,display:"grid",placeItems:"center",background:"#0d66fe",color:"#fff",font:"14px system-ui, sans-serif"},card:{width:"min(340px, 88vw)",display:"grid",gap:"18px",justifyItems:"center"},logo:{width:"180px",userSelect:"none",pointerEvents:"none"},title:{margin:0,fontSize:"22px",fontWeight:600,textAlign:"center"},primary:{width:"100%",padding:"11px 16px",borderRadius:"8px",border:"none",background:"#fff",color:"#0d66fe",fontWeight:600,font:"inherit"},ghost:{width:"100%",padding:"11px 16px",borderRadius:"8px",border:"1px solid rgba(255, 255, 255, 0.45)",background:"transparent",color:"#fff",fontWeight:600,font:"inherit"},remember:{display:"flex",alignItems:"center",gap:"10px",cursor:"pointer",color:"rgba(255, 255, 255, 0.85)"},switchInput:{position:"absolute",opacity:0,width:0,height:0},switchTrack:{position:"relative",width:"42px",height:"24px",borderRadius:"12px",transition:"background 0.15s",flexShrink:0},switchKnob:{position:"absolute",top:"3px",width:"18px",height:"18px",borderRadius:"50%",transition:"left 0.15s, background 0.15s"},error:{color:"#ffd7d7",textAlign:"center"}};function ot(e){let{container:o,client:t,modules:s,renderLogin:i}=e;o.style.position="relative";let l=document.createElement("div");Object.assign(l.style,{position:"absolute",inset:"0",zIndex:"0",pointerEvents:"none"});let d=document.createElement("div");Object.assign(d.style,{position:"absolute",inset:"0",zIndex:"1"}),o.append(l,d);let y=D(),g=N(l);_(()=>y.describe());let r=A(s);for(let c of r.warnings)console.warn(`[idos shared-ui] ${c}`);let n=createRoot(d);return n.render(jsx(IDosGamesProvider,{client:t,children:jsx(StatusProvider,{children:jsx(Q,{client:t,modules:s,events:y,sharedUi:r.owners,surface:g,renderLogin:i??ee})})})),{unmount(){n.unmount(),l.remove(),d.remove();}}}
11
- export{Q as AuthGate,ee as DefaultLoginScreen,X as HostShell,I as SceneStage,W as createContentRegistry,D as createHostEventBus,V as createHostNavigator,ke as createSharedEventBus,N as createSurfaceAllocator,le as emptySharedUiOwners,ot as mountHost,_ as publishEventsProvider,G as publishHostState,z as registerAgentApi,A as resolveSharedUi,F as runModules,B as sharedUiFor};
10
+ `}),jsxs("div",{style:Qe,children:[jsx("span",{style:{...ge,animationDelay:"0s"}}),jsx("span",{style:{...ge,animationDelay:"1.1s"}}),jsx("span",{style:Xe,children:"\u{1F9E9}"})]}),jsx("div",{style:{fontWeight:700,fontSize:18,marginBottom:6},children:"No modules installed"}),jsxs("div",{style:{opacity:.85,maxWidth:380,lineHeight:1.5},children:["Add a module under ",jsx("code",{children:"src/modules/"})," and register it in"," ",jsx("code",{children:"src/modules.ts"}),". The host shell will pick it up here."]})]})}var Be={position:"absolute",inset:0,overflow:"hidden",background:"#0d66fe",color:"#fff",fontFamily:"system-ui, sans-serif"},ze={position:"absolute",inset:0,zIndex:0},me=16,Ne={position:"absolute",top:0,right:0,bottom:0,left:0,zIndex:1,pointerEvents:"none"},Ge={display:"contents",pointerEvents:"auto"},_e={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},je={position:"absolute",top:0,right:0,bottom:0,width:340,maxWidth:"40vw",zIndex:2,display:"flex",flexDirection:"column",gap:12,padding:16,overflowY:"auto",pointerEvents:"none"},We={position:"absolute",bottom:me,left:"50%",transform:"translateX(-50%)",zIndex:3,display:"flex",gap:8,padding:6,borderRadius:14,background:"rgba(4,32,90,0.72)",backdropFilter:"blur(6px)",pointerEvents:"auto"},he={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfe0ff",background:"transparent",cursor:"pointer"},qe={...he,color:"#0d66fe",background:"#fff"},Fe={position:"absolute",bottom:16,left:16,zIndex:3,display:"flex",gap:8,alignItems:"center",pointerEvents:"auto"},ve={border:"none",borderRadius:12,padding:"8px 14px",fontWeight:700,fontSize:13,color:"#cfe0ff",background:"rgba(4,32,90,0.72)",backdropFilter:"blur(6px)",cursor:"pointer"},Ve={...ve,fontWeight:600,fontFamily:"ui-monospace, Consolas, monospace"},Ke={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},Y={pointerEvents:"auto"},Ye={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24},Qe={position:"relative",width:110,height:110,marginBottom:16,display:"grid",placeItems:"center"},ge={position:"absolute",inset:0,borderRadius:"50%",border:"2px solid rgba(255,255,255,0.55)",animation:"idos-empty-ripple 2.2s ease-out infinite"},Xe={fontSize:46,animation:"idos-empty-float 3s ease-in-out infinite",filter:"drop-shadow(0 8px 12px rgba(0,0,0,0.25))"};function Z(t){let{client:o,modules:e,events:n,sharedUi:s,surface:a,renderLogin:d}=t,[v]=useState(q),[g,i]=useState(true),[r,c]=useState(null),p=useRef(null),u=()=>{for(let b of p.current??[])b.dispose();p.current=null;},m=()=>{u();let b=F(e,{client:o,events:n,surface:a,sharedUi:s,navigator:v});p.current=b,c(b);};useEffect(()=>()=>u(),[]);let S=useRef(false);useEffect(()=>{if(S.current)return;S.current=true;let b=readSsoCodeFromUrl();if(b){(async()=>((await o.auth.loginWithSsoCode(b.code)).ok&&m(),i(false)))();return}if(o.auth.lastAuthType===AuthType.None){i(false);return}(async()=>((await o.auth.autoLogin()).ok&&m(),i(false)))();},[o]),useEffect(()=>{let b=()=>{u(),c(null);},R=o.on("auth:unauthorized",b),M=o.on("auth:loggedOut",b);return ()=>{R(),M();}},[o]);let y=r?"game":g?"loading":"login";return useEffect(()=>{G({screen:y,loggedIn:r!==null,userId:o.auth.context?.userID??null,titleId:o.titleID??null,modules:e.map(b=>b.id),sharedUi:s});},[y,r,o,e,s]),r?jsx(X,{registrations:r,sharedUi:s,events:n,navigator:v,onLogout:()=>o.auth.logout(),userID:o.auth.context?.userID??null}):g?null:jsx(d,{client:o,onAuthenticated:m})}var et='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 860 690" fill="#fff"><g transform="translate(243 -2)"><path d="M147.333 12.333c-13.6 2.534-12.533 1.2-12.933 15.067l-.4 12.267-4.533-11.067c-2.534-6-5.067-10.933-5.734-10.933-2.666 0-27.866 8.666-36.533 12.666-11.733 5.334-26.667 14.8-36.133 22.934l-6.934 5.866L51.6 69.267c8.133 11.066 7.333 11.466-5.067 2.933-7.6-5.067-8.4-5.333-11.466-3.733-3.467 1.866-18.4 17.333-20.4 21.2-.8 1.6 7.066 8.8 33.733 30.933l34.667 28.933 8.8-8.266c14.666-13.867 28.666-22 48.133-28.267 9.067-2.933 14.8-3.733 28.533-4.4 34.267-1.333 60 7.467 81.6 28.133 21.6 20.4 34.934 49.6 37.467 81.734l.8 11.2 14.8 4.533c8.133 2.533 23.733 7.333 34.667 10.8 10.933 3.333 20.4 5.6 21.066 4.933 1.6-1.6 6.134-20.533 7.734-32.666.8-6 1.333-17.6 1.066-25.6l-.4-14.667-8-1.067c-4.4-.533-10.133-1.466-12.666-1.866l-4.667-.8 4.667-1.2c16.933-4.534 18.666-5.2 18.666-8 0-5.467-9.6-31.334-16.666-44.8-4-7.6-10.667-18.667-14.934-24.667-9.866-13.867-31.333-35.467-45.2-45.2-10.4-7.467-34.4-20.933-37.2-21.067-.8 0-4 4-7.333 8.8-3.2 4.8-6.133 8.134-6.4 7.334s.4-5.6 1.6-10.667c1.2-5.2 2.133-9.6 2.133-9.867 0-.933-19.866-6.133-34.4-9.066-14.8-2.934-49.333-4.4-59.6-2.534"/><path d="M157.867 125.533c-21.067 3.334-42.134 14.8-57.467 31.334-13.333 14.133-13.733 12.8 5.6 22 9.2 4.4 16.667 8.266 16.667 8.533s-1.334.4-2.934.133c-13.866-2.133-41.6-5.866-41.733-5.6-.267.267-7.467 28.534-16.267 63.067l-16 62.667 7.334.4c4 .266 7.466.266 7.6 0 .266-.267 3.866-13.867 8.133-30.4 4.267-16.534 8.267-30.8 8.933-31.734.934-1.2 11.067-1.6 42.4-1.6 32.134 0 41.2.4 41.2 1.6 0 .934-1.733 4.667-3.866 8.4L153.733 261l-35.066 6.933c-19.334 3.867-35.2 7.2-35.467 7.467-.667.667-29.867 113.467-29.467 113.867.267.133 23.734-3.6 52.4-8.534l52-8.8 20.4-39.866c11.2-22 20.667-39.734 20.934-39.467.4.533-1.334 26.8-2.8 40.8l-.667 6.933 6.267-3.2c21.2-10.666 52.4-13.466 86.933-8l5.867.934-5.6-7.334C286.4 318.6 281.2 310.6 278 304.867c-5.867-10.134-6-10.8-6-21.867 0-6.267 1.467-20 3.333-30.667 1.867-10.666 3.334-19.466 3.334-19.466 0-.134-9.067-4.267-20.134-9.334s-19.466-9.333-18.8-9.6c.8-.266 7.734.8 15.6 2.267 7.734 1.6 14.4 2.8 14.8 2.8 1.2 0 .4-10.533-1.466-18-7.2-27.733-28-53.467-53.734-66-16.4-8-40.8-12-57.066-9.467"/><path d="M235.6 346.333c-24 4.534-44.133 13.867-68.267 31.467-14 10.267-28.533 18.133-47.733 25.867-23.467 9.466-52.8 32.666-64.4 50.666l-2.533 4L58 454.2c9.333-7.333 30.133-19.467 49.333-28.667C173.733 393.667 246.4 382.2 312.8 393c11.2 1.733 39.2 8.533 45.067 10.8 2.266.8 2.266.667.8-2.267-4-7.6-15.6-21.866-25.867-31.466-12-11.467-24.667-18.934-37.6-22.4-11.467-3.067-46.267-3.867-59.6-1.334"/></g><g transform="translate(-460 467)"><path d="M721.533 34.467c-14.933 5.466-22 17.466-22.933 38.666-.933 24.134 3.467 32.8 30.267 59.867 19.6 19.867 22.933 25.2 22.933 37.867.133 13.466-6.133 20.133-16.933 18.4-9.067-1.467-12.534-7.867-12.534-22.667V159H696.6l.667 13.333c.533 11.467 1.2 14.4 4.933 22 7.067 14.267 16.8 19.6 36.4 19.734 10.667.133 12.267-.134 20.667-4.4 7.6-3.867 9.733-5.867 13.2-11.734 7.6-12.533 9.066-32 3.733-47.6-3.733-11.066-10.667-20.4-27.867-37.2-19.866-19.6-22.533-24.133-22.666-38.4 0-8.933.4-10.533 3.2-13.6 6.266-6.666 18.266-5.6 22.133 2 1.067 2 2 7.067 2 11.2v7.334h27.067l-.934-9.2c-1.6-18.267-8.266-30.267-20-36.4-7.2-3.867-29.2-4.8-37.6-1.6M630.067 34.867c-11.734 4.666-18 11.6-21.734 24.4-1.866 6.4-2 15.333-1.733 67.2l.4 59.866 3.733 7.6c6.8 13.867 18.534 20.267 36.934 20.267 13.733 0 22.933-3.333 30.666-11.067 10.934-11.066 11.2-12.533 11.734-74.666.266-35.734-.134-56.934-1.067-62.8-2.667-16.134-11.6-27.467-24.8-31.467-8.933-2.667-26.4-2.267-34.133.667m28.666 26.8 3.6 4v56.666c0 40.934-.4 57.467-1.6 60-3.6 8-15.6 9.734-22.666 3.467l-4.4-3.867-.4-56.533c-.267-51.733-.134-56.8 2-61.067 3.066-5.866 7.6-8.266 14.4-7.466 3.733.4 6.4 1.866 9.066 4.8M511.667 123.133v89.334l29.066-.4c28.8-.4 28.934-.4 36.667-4.267 9.467-4.533 14.4-10.933 17.467-22.4 2-7.333 2.266-15.467 1.866-65.733l-.4-57.334-4.266-8.8c-8.267-16.666-17.2-19.866-55.334-19.866h-25.066zm53.6-60.266 4.4 3.866.4 52.8c.266 35.067-.134 54.4-1.067 58-2 7.467-5.733 9.6-18.667 10.4l-10.666.8V59h10.666c9.867 0 10.934.267 14.934 3.867M471.667 145v67.333h26.666V77.667h-26.666zM471.667 48.333V63h26.666V33.667h-26.666z"/></g><g transform="translate(-106 244)"><path d="M893.4 259.733c-6.8 3.467-9.2 5.6-12.667 11.467-10.666 17.733-9.2 42.933 3.467 62.267 2.8 4.266 12.267 14.8 20.933 23.333 9.867 9.467 17.067 17.733 18.934 21.6 5.6 11.333 5.2 25.333-.934 30.8-3.466 3.067-11.333 4.133-16.133 2.133-5.867-2.4-8-7.466-8-19.333v-10h-27.067l.8 11.6c1.2 15.867 3.867 24.133 10.267 31.333 7.467 8.534 16.4 12.134 30 12.267 19.067.133 30.133-5.733 37.333-19.867 3.734-7.466 4-8.666 4-24 0-16 0-16.133-5.2-26.666-4.4-9.2-7.733-13.2-23.066-28.534-21.067-21.066-24.8-27.066-24.934-40.4-.133-10.4 2.8-15.6 9.734-17.6 10.133-2.933 17.2 3.334 18.4 16.267l.8 8.267H955.4l-.8-10.8c-.533-8.4-1.6-12.667-4.8-19.2-7.067-14.134-16.667-19.334-36.133-19.334-10.667 0-12.534.4-20.267 4.4M791 346v89.333h76v-24h-48v-54.666h37.333v-24H819V282h48v-25.333h-76zM661.667 346v89.333h22.666l.134-63.066c0-34.534.533-61.734 1.066-60.267.534 1.467 5.467 29.867 10.8 62.933l9.867 60.4h13.067c7.2 0 13.066-.4 13.066-1.066 0-3.067 18.8-124.8 19.334-125.334.4-.4.666 27.867.666 62.8v63.6h25.334V256.667h-38l-9.2 61.6c-5.067 34-9.6 62.133-10 62.666-.534.534-5.334-26.4-10.667-60-5.467-33.466-10.133-61.733-10.533-62.666-.4-1.2-5.467-1.6-19.067-1.6h-18.533zM586.467 258.267c-.8 2.666-27.467 172.4-27.467 174.933 0 1.867 1.733 2.133 12 2.133h11.867l.8-4.4c.533-2.266 1.6-9.333 2.4-15.6l1.6-11.333 17.6-.4 17.466-.4 1.467 8.4c.8 4.667 1.733 11.867 2.267 16l.933 7.733h13.733c7.6 0 13.867-.266 13.867-.666 0-.8-26.533-168.134-27.467-173.734l-.8-4.266h-19.866c-14.8 0-20.134.4-20.4 1.6M613 336.533c3.333 23.067 5.867 42.134 5.6 42.4-.4.267-6.533.267-13.867.134l-13.2-.4 4.934-33.334c2.8-18.4 5.733-38.4 6.666-44.666C604.2 292.533 605 290.133 605.8 292c.533 1.467 3.867 21.467 7.2 44.533M497.267 257.2c-10.134 3.733-15.2 8.267-19.867 17.733L473 284l-.4 59.067c-.4 51.2-.133 60.133 1.733 66.533 5.6 19.333 17.067 27.333 39.467 27.467 10.267.133 12.267-.267 20.133-4.134 9.334-4.533 13.867-9.733 17.867-20.266 2-4.934 2.4-12 2.933-41.067l.534-34.933h-38.934v23.866l6.4.4 6.267.4v19.334c0 13.466-.533 20.666-1.867 23.733-5.066 12-23.333 10.4-26.8-2.4-.933-3.6-1.333-23.2-1.066-59.067.4-48.533.666-54.133 2.666-57.333 3.334-4.8 11.2-7.067 17.6-4.933 6.934 2.266 9.067 7.2 9.867 22.933l.667 13.067H555.4l-.8-15.734c-.8-18-3.067-25.6-9.867-33.466-7.466-8.8-13.466-11.2-29.066-11.734-9.067-.266-14.934.134-18.4 1.467"/></g></svg>',be=`data:image/svg+xml;utf8,${encodeURIComponent(et)}`;var ot=["https://cloud.idosgames.com","https://idosgames.com","https://www.idosgames.com"],nt=/^https:\/\/[a-z0-9]{8}(-dev)?\.idos\.games$/;function we(){if(typeof window>"u")return false;let{origin:t}=window.location;return ot.includes(t)||nt.test(t)?true:typeof document<"u"&&document.querySelector('meta[name="idos-game-host"]')!==null}function te({client:t,onAuthenticated:o}){let[e,n]=useState(false),[s,a]=useState(null),[d,v]=useState(true),g=async()=>{n(true),a(null),t.auth.setRememberSession(d);let i=await t.auth.loginWithDeviceID();if(i.ok){o();return}a(i.error),n(false);};return jsx("div",{style:w.root,children:jsxs("div",{style:w.card,children:[jsx("img",{src:be,alt:"iDos Games",style:w.logo}),jsx("h1",{style:w.title,children:"Sign in"}),we()&&jsx("button",{type:"button",onClick:()=>beginSsoRedirect({titleID:t.titleID}),disabled:e,style:{...w.primary,opacity:e?.6:1,cursor:e?"default":"pointer"},children:"Continue with iDos Games"}),jsx("button",{type:"button",onClick:()=>{g();},disabled:e,style:{...we()?w.ghost:w.primary,opacity:e?.6:1,cursor:e?"default":"pointer"},children:e?"Signing in\u2026":"Play as guest"}),jsxs("label",{style:{...w.remember,opacity:e?.6:1},children:[jsx("input",{type:"checkbox",checked:d,disabled:e,onChange:i=>v(i.target.checked),style:w.switchInput}),jsx("span",{style:{...w.switchTrack,background:d?"#fff":"rgba(255, 255, 255, 0.3)"},children:jsx("span",{style:{...w.switchKnob,left:d?"21px":"3px",background:d?"#0d66fe":"#fff"}})}),"Remember me"]}),s&&jsx("span",{style:w.error,children:s})]})})}var w={root:{position:"absolute",inset:0,display:"grid",placeItems:"center",background:"#0d66fe",color:"#fff",font:"14px system-ui, sans-serif"},card:{width:"min(340px, 88vw)",display:"grid",gap:"18px",justifyItems:"center"},logo:{width:"180px",userSelect:"none",pointerEvents:"none"},title:{margin:0,fontSize:"22px",fontWeight:600,textAlign:"center"},primary:{width:"100%",padding:"11px 16px",borderRadius:"8px",border:"none",background:"#fff",color:"#0d66fe",fontWeight:600,font:"inherit"},ghost:{width:"100%",padding:"11px 16px",borderRadius:"8px",border:"1px solid rgba(255, 255, 255, 0.45)",background:"transparent",color:"#fff",fontWeight:600,font:"inherit"},remember:{display:"flex",alignItems:"center",gap:"10px",cursor:"pointer",color:"rgba(255, 255, 255, 0.85)"},switchInput:{position:"absolute",opacity:0,width:0,height:0},switchTrack:{position:"relative",width:"42px",height:"24px",borderRadius:"12px",transition:"background 0.15s",flexShrink:0},switchKnob:{position:"absolute",top:"3px",width:"18px",height:"18px",borderRadius:"50%",transition:"left 0.15s, background 0.15s"},error:{color:"#ffd7d7",textAlign:"center"}};function at(t){let{container:o,client:e,modules:n,renderLogin:s}=t;o.style.position="relative";let a=document.createElement("div");Object.assign(a.style,{position:"absolute",inset:"0",zIndex:"0",pointerEvents:"none"});let d=document.createElement("div");Object.assign(d.style,{position:"absolute",inset:"0",zIndex:"1"}),o.append(a,d);let v=D(),g=z(a);_(()=>v.describe());let i=I(n);for(let c of i.warnings)console.warn(`[idos shared-ui] ${c}`);let r=createRoot(d);return r.render(jsx(IDosGamesProvider,{client:e,children:jsx(StatusProvider,{children:jsx(Z,{client:e,modules:n,events:v,sharedUi:i.owners,surface:g,renderLogin:s??te})})})),{unmount(){r.unmount(),a.remove(),d.remove();}}}
11
+ export{Z as AuthGate,te as DefaultLoginScreen,X as HostShell,P as SceneStage,W as createContentRegistry,D as createHostEventBus,q as createHostNavigator,Ce as createSharedEventBus,z as createSurfaceAllocator,de as emptySharedUiOwners,at as mountHost,_ as publishEventsProvider,G as publishHostState,N as registerAgentApi,I as resolveSharedUi,F as runModules,V as servePlatformShots,B as sharedUiFor};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idosgames/app-shell",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "description": "The host runtime for composable modules: module registry, shared event bus, surface allocator, scene stage, and the React Mode Router shell. A project seeds one host shell and plugs N modules into it.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -47,9 +47,9 @@
47
47
  },
48
48
  "//": "react/react-dom are consumer-provided peers. @idosgames/* are real ranges pinned in step with those packages.",
49
49
  "dependencies": {
50
- "@idosgames/core": "^0.16.0",
51
- "@idosgames/module-sdk": "^0.3.3",
52
- "@idosgames/react": "^0.2.9"
50
+ "@idosgames/core": "^0.17.0",
51
+ "@idosgames/module-sdk": "^0.4.0",
52
+ "@idosgames/react": "^0.2.10"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "react": "^18.3.1 || ^19.0.0",