@idosgames/app-shell 0.1.2 → 0.1.3

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 +1,11 @@
1
- 'use strict';var client=require('react-dom/client'),react$1=require('@idosgames/react'),react=require('react'),core=require('@idosgames/core'),jsxRuntime=require('react/jsx-runtime');function h(){let s=new Map;return {emit(o,e){let n=s.get(o);if(n)for(let r of [...n])r(e);},on(o,e){let n=e,r=s.get(o);return r||(r=new Set,s.set(o,r)),r.add(n),()=>{r.delete(n),r.size===0&&s.delete(o);}}}}var B={position:"absolute",inset:"0"};function b(s){return {request(o){let e=document.createElement("div");return e.dataset.surface=o,Object.assign(e.style,B),e.style.pointerEvents=o==="fullbleed-canvas"?"auto":"none",s.appendChild(e),{host:e,release(){e.remove();}}}}}function x(s,o){return s.map(e=>{let n={module:e,scenes:[],panels:[],routes:[]},r={client:o.client,titleId:o.client.titleID,events:o.events,surface:o.surface,registerScene:l=>n.scenes.push(l),registerPanel:l=>n.panels.push(l),registerRoute:l=>n.routes.push(l)};return e.setup(r),n})}var f=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 r=this.hosts.get(n);r&&(r.style.display="none");}for(let n of e){if(this.active.has(n))continue;let r=this.ensureMounted(n);r.style.display="block",n.activate?.();}this.active=e;}destroy(){for(let[o,e]of this.hosts)o.destroy(),e.remove();this.hosts.clear(),this.active.clear();}};function k({registrations:s}){let o=react.useRef(null),e=react.useRef(null),n=react.useMemo(()=>s.flatMap(t=>t.routes.map(i=>({id:i.id,label:i.label,icon:i.icon,order:i.order??0,moduleId:t.module.id}))).sort((t,i)=>t.order-i.order),[s]),[r,l]=react.useState(()=>n[0]?.id??null);react.useEffect(()=>{r!==null&&n.some(t=>t.id===r)||l(n[0]?.id??null);},[n,r]);let d=react.useMemo(()=>n.find(t=>t.id===r)?.moduleId??null,[n,r]);react.useEffect(()=>{let t=o.current;if(!t)return;let i=e.current??=new f(t),m=s.find(S=>S.module.id===d)?.scenes??[];i.setActive(m);},[s,d]),react.useEffect(()=>()=>{e.current?.destroy(),e.current=null;},[]);let p=react.useMemo(()=>s.flatMap(t=>t.panels.filter(i=>i.activeOnly===false||t.module.id===d).map(i=>{let m=i.component;return {key:`${t.module.id}:${i.id}`,slot:i.slot,order:i.order??0,moduleId:t.module.id,component:jsxRuntime.jsx(m,{})}})).sort((t,i)=>t.order-i.order),[s,d]),c=t=>p.filter(i=>i.slot===t),u=s.length>0;return jsxRuntime.jsxs("div",{style:T,children:[jsxRuntime.jsx("div",{ref:o,style:O}),jsxRuntime.jsx("div",{style:W,children:c("overlay").map(t=>jsxRuntime.jsx("div",{style:y,children:t.component},t.key))}),jsxRuntime.jsx("div",{style:j,children:c("hud").map(t=>jsxRuntime.jsx("div",{style:y,children:t.component},t.key))}),jsxRuntime.jsx("div",{style:U,children:c("sidebar").map(t=>jsxRuntime.jsx("div",{style:y,children:t.component},t.key))}),n.length>1&&jsxRuntime.jsx("nav",{style:$,children:n.map(t=>jsxRuntime.jsxs("button",{type:"button",onClick:()=>l(t.id),style:t.id===r?F:A,children:[t.icon?`${t.icon} `:"",t.label]},t.id))}),c("modal").length>0&&jsxRuntime.jsx("div",{style:K,children:c("modal").map(t=>jsxRuntime.jsx("div",{style:y,children:t.component},t.key))}),!u&&jsxRuntime.jsx(N,{})]})}function N(){return jsxRuntime.jsxs("div",{style:q,children:[jsxRuntime.jsx("div",{style:{fontSize:40,marginBottom:12},children:"\u{1F9E9}"}),jsxRuntime.jsx("div",{style:{fontWeight:700,fontSize:18,marginBottom:6},children:"No modules installed"}),jsxRuntime.jsxs("div",{style:{opacity:.7,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 T={position:"absolute",inset:0,overflow:"hidden",color:"#fff",fontFamily:"system-ui, sans-serif"},O={position:"absolute",inset:0,zIndex:0},W={position:"absolute",inset:0,zIndex:1,pointerEvents:"none"},j={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},U={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"},$={position:"absolute",bottom:16,left:"50%",transform:"translateX(-50%)",zIndex:3,display:"flex",gap:8,padding:6,borderRadius:14,background:"rgba(20,18,40,0.72)",backdropFilter:"blur(6px)",pointerEvents:"auto"},A={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfc9ee",background:"transparent",cursor:"pointer"},F={...A,color:"#fff",background:"#6c5ce7"},K={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},y={pointerEvents:"auto"},q={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24};function M(s){let{client:o,modules:e,events:n,surface:r,renderLogin:l}=s,[d,p]=react.useState(true),[c,u]=react.useState(null),t=()=>{u(x(e,{client:o,events:n,surface:r}));},i=react.useRef(false);return react.useEffect(()=>{if(!i.current){if(i.current=true,o.auth.lastAuthType===core.AuthType.None){p(false);return}(async()=>((await o.auth.autoLogin()).ok&&t(),p(false)))();}},[o]),react.useEffect(()=>{let m=()=>u(null),S=o.on("auth:unauthorized",m),z=o.on("auth:loggedOut",m);return ()=>{S(),z();}},[o]),c?jsxRuntime.jsx(k,{registrations:c}):d?null:l({client:o,onAuthenticated:t})}function C({client:s,onAuthenticated:o}){let[e,n]=react.useState(false),[r,l]=react.useState(null),[d,p]=react.useState(true),c=async()=>{n(true),l(null),s.auth.setRememberSession(d);let u=await s.auth.loginWithDeviceID();if(u.ok){o();return}l(u.error),n(false);};return jsxRuntime.jsx("div",{style:{position:"absolute",inset:0,display:"grid",placeItems:"center",gap:"12px",color:"#e8e6f3",font:"14px system-ui, sans-serif"},children:jsxRuntime.jsxs("div",{style:{display:"grid",gap:"12px",justifyItems:"center"},children:[jsxRuntime.jsx("button",{type:"button",onClick:()=>{c();},disabled:e,style:{padding:"10px 20px",borderRadius:"8px",border:"1px solid #4c4470",background:e?"#2a2545":"#3b3363",color:"inherit",cursor:e?"default":"pointer",font:"inherit"},children:e?"Signing in\u2026":"Play as guest"}),jsxRuntime.jsxs("label",{style:{display:"flex",alignItems:"center",gap:"6px",cursor:e?"default":"pointer",opacity:e?.6:1},children:[jsxRuntime.jsx("input",{type:"checkbox",checked:d,disabled:e,onChange:u=>p(u.target.checked)}),"Remember me"]}),r&&jsxRuntime.jsx("span",{style:{color:"#ff9b9b"},children:r})]})})}function _(s){let{container:o,client:e,modules:n,renderLogin:r}=s;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 p=h(),c=b(l),u=client.createRoot(d);return u.render(jsxRuntime.jsx(react$1.IDosGamesProvider,{client:e,children:jsxRuntime.jsx(react$1.StatusProvider,{children:jsxRuntime.jsx(M,{client:e,modules:n,events:p,surface:c,renderLogin:r??C})})})),{unmount(){u.unmount(),l.remove(),d.remove();}}}exports.AuthGate=M;exports.DefaultLoginScreen=C;exports.HostShell=k;exports.SceneStage=f;exports.createSharedEventBus=h;exports.createSurfaceAllocator=b;exports.mountHost=_;exports.runModules=x;
1
+ 'use strict';var client=require('react-dom/client'),react$1=require('@idosgames/react'),react=require('react'),core=require('@idosgames/core'),jsxRuntime=require('react/jsx-runtime');function x(){let s=new Map;return {emit(o,e){let r=s.get(o);if(r)for(let n of [...r])n(e);},on(o,e){let r=e,n=s.get(o);return n||(n=new Set,s.set(o,n)),n.add(r),()=>{n.delete(r),n.size===0&&s.delete(o);}}}}var V={position:"absolute",inset:"0"};function R(s){return {request(o){let e=document.createElement("div");return e.dataset.surface=o,Object.assign(e.style,V),e.style.pointerEvents=o==="fullbleed-canvas"?"auto":"none",s.appendChild(e),{host:e,release(){e.remove();}}}}}function k(s,o){return s.map(e=>{let r={module:e,scenes:[],panels:[],routes:[]},n={client:o.client,titleId:o.client.titleID,events:o.events,surface:o.surface,registerScene:i=>r.scenes.push(i),registerPanel:i=>r.panels.push(i),registerRoute:i=>r.routes.push(i)};return e.setup(n),r})}var y=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 r of this.active){if(e.has(r))continue;r.suspend?.();let n=this.hosts.get(r);n&&(n.style.display="none");}for(let r of e){if(this.active.has(r))continue;let n=this.ensureMounted(r);n.style.display="block",r.activate?.();}this.active=e;}destroy(){for(let[o,e]of this.hosts)o.destroy(),e.remove();this.hosts.clear(),this.active.clear();}};function C({registrations:s,onLogout:o}){let e=react.useRef(null),r=react.useRef(null),n=react.useMemo(()=>s.flatMap(t=>t.routes.map(l=>({id:l.id,label:l.label,icon:l.icon,order:l.order??0,moduleId:t.module.id}))).sort((t,l)=>t.order-l.order),[s]),[i,c]=react.useState(()=>n[0]?.id??null);react.useEffect(()=>{i!==null&&n.some(t=>t.id===i)||c(n[0]?.id??null);},[n,i]);let u=react.useMemo(()=>n.find(t=>t.id===i)?.moduleId??null,[n,i]);react.useEffect(()=>{let t=e.current;if(!t)return;let l=r.current??=new y(t),g=s.find(b=>b.module.id===u)?.scenes??[];l.setActive(g);},[s,u]),react.useEffect(()=>()=>{r.current?.destroy(),r.current=null;},[]);let m=react.useMemo(()=>s.flatMap(t=>t.panels.filter(l=>l.activeOnly===false||t.module.id===u).map(l=>{let g=l.component;return {key:`${t.module.id}:${l.id}`,slot:l.slot,order:l.order??0,moduleId:t.module.id,component:jsxRuntime.jsx(g,{})}})).sort((t,l)=>t.order-l.order),[s,u]),d=t=>m.filter(l=>l.slot===t),v=s.length>0;return jsxRuntime.jsxs("div",{style:_,children:[jsxRuntime.jsx("div",{ref:e,style:K}),jsxRuntime.jsx("div",{style:$,children:d("overlay").map(t=>jsxRuntime.jsx("div",{style:S,children:t.component},t.key))}),jsxRuntime.jsx("div",{style:j,children:d("hud").map(t=>jsxRuntime.jsx("div",{style:S,children:t.component},t.key))}),jsxRuntime.jsx("div",{style:F,children:d("sidebar").map(t=>jsxRuntime.jsx("div",{style:S,children:t.component},t.key))}),n.length>1&&jsxRuntime.jsx("nav",{style:Y,children:n.map(t=>jsxRuntime.jsxs("button",{type:"button",onClick:()=>c(t.id),style:t.id===i?q:H,children:[t.icon?`${t.icon} `:"",t.label]},t.id))}),o&&jsxRuntime.jsx("button",{type:"button",style:X,onClick:o,title:"Log out",children:"\u{1F6AA} Log out"}),d("modal").length>0&&jsxRuntime.jsx("div",{style:J,children:d("modal").map(t=>jsxRuntime.jsx("div",{style:S,children:t.component},t.key))}),!v&&jsxRuntime.jsx(U,{})]})}function U(){return jsxRuntime.jsxs("div",{style:Q,children:[jsxRuntime.jsx("style",{children:`
2
+ @keyframes idos-empty-float {
3
+ 0%, 100% { transform: translateY(0) rotate(-6deg); }
4
+ 50% { transform: translateY(-16px) rotate(6deg); }
5
+ }
6
+ @keyframes idos-empty-ripple {
7
+ 0% { transform: scale(0.55); opacity: 0.55; }
8
+ 100% { transform: scale(1.7); opacity: 0; }
9
+ }
10
+ `}),jsxRuntime.jsxs("div",{style:Z,children:[jsxRuntime.jsx("span",{style:{...z,animationDelay:"0s"}}),jsxRuntime.jsx("span",{style:{...z,animationDelay:"1.1s"}}),jsxRuntime.jsx("span",{style:ee,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 _={position:"absolute",inset:0,overflow:"hidden",background:"#0d66fe",color:"#fff",fontFamily:"system-ui, sans-serif"},K={position:"absolute",inset:0,zIndex:0},$={position:"absolute",inset:0,zIndex:1,pointerEvents:"none"},j={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},F={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"},Y={position:"absolute",bottom:16,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"},H={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfe0ff",background:"transparent",cursor:"pointer"},q={...H,color:"#0d66fe",background:"#fff"},X={position:"absolute",bottom:16,left:16,zIndex:3,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",pointerEvents:"auto"},J={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},S={pointerEvents:"auto"},Q={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24},Z={position:"relative",width:110,height:110,marginBottom:16,display:"grid",placeItems:"center"},z={position:"absolute",inset:0,borderRadius:"50%",border:"2px solid rgba(255,255,255,0.55)",animation:"idos-empty-ripple 2.2s ease-out infinite"},ee={fontSize:46,animation:"idos-empty-float 3s ease-in-out infinite",filter:"drop-shadow(0 8px 12px rgba(0,0,0,0.25))"};function E(s){let{client:o,modules:e,events:r,surface:n,renderLogin:i}=s,[c,u]=react.useState(true),[m,d]=react.useState(null),v=()=>{d(k(e,{client:o,events:r,surface:n}));},t=react.useRef(false);return react.useEffect(()=>{if(!t.current){if(t.current=true,o.auth.lastAuthType===core.AuthType.None){u(false);return}(async()=>((await o.auth.autoLogin()).ok&&v(),u(false)))();}},[o]),react.useEffect(()=>{let g=()=>d(null),b=o.on("auth:unauthorized",g),N=o.on("auth:loggedOut",g);return ()=>{b(),N();}},[o]),m?jsxRuntime.jsx(C,{registrations:m,onLogout:()=>o.auth.logout()}):c?null:jsxRuntime.jsx(i,{client:o,onAuthenticated:v})}var ne='<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>',O=`data:image/svg+xml;utf8,${encodeURIComponent(ne)}`;function I({client:s,onAuthenticated:o}){let[e,r]=react.useState(false),[n,i]=react.useState(null),[c,u]=react.useState(true),m=async()=>{r(true),i(null),s.auth.setRememberSession(c);let d=await s.auth.loginWithDeviceID();if(d.ok){o();return}i(d.error),r(false);};return jsxRuntime.jsx("div",{style:p.root,children:jsxRuntime.jsxs("div",{style:p.card,children:[jsxRuntime.jsx("img",{src:O,alt:"iDos Games",style:p.logo}),jsxRuntime.jsx("h1",{style:p.title,children:"Sign in"}),jsxRuntime.jsx("button",{type:"button",onClick:()=>{m();},disabled:e,style:{...p.primary,opacity:e?.6:1,cursor:e?"default":"pointer"},children:e?"Signing in\u2026":"Play as guest"}),jsxRuntime.jsxs("label",{style:{...p.remember,opacity:e?.6:1},children:[jsxRuntime.jsx("input",{type:"checkbox",checked:c,disabled:e,onChange:d=>u(d.target.checked),style:p.switchInput}),jsxRuntime.jsx("span",{style:{...p.switchTrack,background:c?"#fff":"rgba(255, 255, 255, 0.3)"},children:jsxRuntime.jsx("span",{style:{...p.switchKnob,left:c?"21px":"3px",background:c?"#0d66fe":"#fff"}})}),"Remember me"]}),n&&jsxRuntime.jsx("span",{style:p.error,children:n})]})})}var p={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"},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 le(s){let{container:o,client:e,modules:r,renderLogin:n}=s;o.style.position="relative";let i=document.createElement("div");Object.assign(i.style,{position:"absolute",inset:"0",zIndex:"0",pointerEvents:"none"});let c=document.createElement("div");Object.assign(c.style,{position:"absolute",inset:"0",zIndex:"1"}),o.append(i,c);let u=x(),m=R(i),d=client.createRoot(c);return d.render(jsxRuntime.jsx(react$1.IDosGamesProvider,{client:e,children:jsxRuntime.jsx(react$1.StatusProvider,{children:jsxRuntime.jsx(E,{client:e,modules:r,events:u,surface:m,renderLogin:n??I})})})),{unmount(){d.unmount(),i.remove(),c.remove();}}}
11
+ exports.AuthGate=E;exports.DefaultLoginScreen=I;exports.HostShell=C;exports.SceneStage=y;exports.createSharedEventBus=x;exports.createSurfaceAllocator=R;exports.mountHost=le;exports.runModules=k;
package/dist/index.d.cts CHANGED
@@ -59,10 +59,11 @@ declare function mountHost(options: {
59
59
  /**
60
60
  * Last-resort login screen, used only when the host was mounted without a `renderLogin`.
61
61
  *
62
- * Deliberately plain and guest-only: a game's real login screen belongs in the project (branding,
63
- * which providers it offers, art), and lives in the host template as `src/LoginScreen.tsx`. This
64
- * one exists so a project that deleted or broke its screen still boots into something a player can
65
- * get past, instead of a blank page.
62
+ * Guest-only on purpose: a game's real login screen belongs in the project (which providers it
63
+ * offers, art, copy) and lives in the host template as `src/LoginScreen.tsx`. This one exists so a
64
+ * project that deleted or broke its screen still boots into something a player can get past —
65
+ * but it carries the same brand look as the template screen, so even the fallback never looks
66
+ * broken or unstyled.
66
67
  */
67
68
  declare function DefaultLoginScreen({ client, onAuthenticated, }: LoginScreenProps): ReactNode;
68
69
 
@@ -81,8 +82,10 @@ interface SharedServices {
81
82
  /** Install every module and return their collected registrations, in declaration order. */
82
83
  declare function runModules(modules: readonly Module[], shared: SharedServices): ModuleRegistration[];
83
84
 
84
- declare function HostShell({ registrations, }: {
85
+ declare function HostShell({ registrations, onLogout, }: {
85
86
  registrations: readonly ModuleRegistration[];
87
+ /** Renders a "Log out" control in the host chrome (bottom-left) when provided. */
88
+ onLogout?: () => void;
86
89
  }): ReactNode;
87
90
 
88
91
  declare class SceneStage {
package/dist/index.d.ts CHANGED
@@ -59,10 +59,11 @@ declare function mountHost(options: {
59
59
  /**
60
60
  * Last-resort login screen, used only when the host was mounted without a `renderLogin`.
61
61
  *
62
- * Deliberately plain and guest-only: a game's real login screen belongs in the project (branding,
63
- * which providers it offers, art), and lives in the host template as `src/LoginScreen.tsx`. This
64
- * one exists so a project that deleted or broke its screen still boots into something a player can
65
- * get past, instead of a blank page.
62
+ * Guest-only on purpose: a game's real login screen belongs in the project (which providers it
63
+ * offers, art, copy) and lives in the host template as `src/LoginScreen.tsx`. This one exists so a
64
+ * project that deleted or broke its screen still boots into something a player can get past —
65
+ * but it carries the same brand look as the template screen, so even the fallback never looks
66
+ * broken or unstyled.
66
67
  */
67
68
  declare function DefaultLoginScreen({ client, onAuthenticated, }: LoginScreenProps): ReactNode;
68
69
 
@@ -81,8 +82,10 @@ interface SharedServices {
81
82
  /** Install every module and return their collected registrations, in declaration order. */
82
83
  declare function runModules(modules: readonly Module[], shared: SharedServices): ModuleRegistration[];
83
84
 
84
- declare function HostShell({ registrations, }: {
85
+ declare function HostShell({ registrations, onLogout, }: {
85
86
  registrations: readonly ModuleRegistration[];
87
+ /** Renders a "Log out" control in the host chrome (bottom-left) when provided. */
88
+ onLogout?: () => void;
86
89
  }): ReactNode;
87
90
 
88
91
  declare class SceneStage {
package/dist/index.js CHANGED
@@ -1 +1,11 @@
1
- import {createRoot}from'react-dom/client';import {IDosGamesProvider,StatusProvider}from'@idosgames/react';import {useRef,useMemo,useState,useEffect}from'react';import {AuthType}from'@idosgames/core';import {jsx,jsxs}from'react/jsx-runtime';function h(){let s=new Map;return {emit(o,e){let n=s.get(o);if(n)for(let r of [...n])r(e);},on(o,e){let n=e,r=s.get(o);return r||(r=new Set,s.set(o,r)),r.add(n),()=>{r.delete(n),r.size===0&&s.delete(o);}}}}var B={position:"absolute",inset:"0"};function b(s){return {request(o){let e=document.createElement("div");return e.dataset.surface=o,Object.assign(e.style,B),e.style.pointerEvents=o==="fullbleed-canvas"?"auto":"none",s.appendChild(e),{host:e,release(){e.remove();}}}}}function x(s,o){return s.map(e=>{let n={module:e,scenes:[],panels:[],routes:[]},r={client:o.client,titleId:o.client.titleID,events:o.events,surface:o.surface,registerScene:l=>n.scenes.push(l),registerPanel:l=>n.panels.push(l),registerRoute:l=>n.routes.push(l)};return e.setup(r),n})}var f=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 r=this.hosts.get(n);r&&(r.style.display="none");}for(let n of e){if(this.active.has(n))continue;let r=this.ensureMounted(n);r.style.display="block",n.activate?.();}this.active=e;}destroy(){for(let[o,e]of this.hosts)o.destroy(),e.remove();this.hosts.clear(),this.active.clear();}};function k({registrations:s}){let o=useRef(null),e=useRef(null),n=useMemo(()=>s.flatMap(t=>t.routes.map(i=>({id:i.id,label:i.label,icon:i.icon,order:i.order??0,moduleId:t.module.id}))).sort((t,i)=>t.order-i.order),[s]),[r,l]=useState(()=>n[0]?.id??null);useEffect(()=>{r!==null&&n.some(t=>t.id===r)||l(n[0]?.id??null);},[n,r]);let d=useMemo(()=>n.find(t=>t.id===r)?.moduleId??null,[n,r]);useEffect(()=>{let t=o.current;if(!t)return;let i=e.current??=new f(t),m=s.find(S=>S.module.id===d)?.scenes??[];i.setActive(m);},[s,d]),useEffect(()=>()=>{e.current?.destroy(),e.current=null;},[]);let p=useMemo(()=>s.flatMap(t=>t.panels.filter(i=>i.activeOnly===false||t.module.id===d).map(i=>{let m=i.component;return {key:`${t.module.id}:${i.id}`,slot:i.slot,order:i.order??0,moduleId:t.module.id,component:jsx(m,{})}})).sort((t,i)=>t.order-i.order),[s,d]),c=t=>p.filter(i=>i.slot===t),u=s.length>0;return jsxs("div",{style:T,children:[jsx("div",{ref:o,style:O}),jsx("div",{style:W,children:c("overlay").map(t=>jsx("div",{style:y,children:t.component},t.key))}),jsx("div",{style:j,children:c("hud").map(t=>jsx("div",{style:y,children:t.component},t.key))}),jsx("div",{style:U,children:c("sidebar").map(t=>jsx("div",{style:y,children:t.component},t.key))}),n.length>1&&jsx("nav",{style:$,children:n.map(t=>jsxs("button",{type:"button",onClick:()=>l(t.id),style:t.id===r?F:A,children:[t.icon?`${t.icon} `:"",t.label]},t.id))}),c("modal").length>0&&jsx("div",{style:K,children:c("modal").map(t=>jsx("div",{style:y,children:t.component},t.key))}),!u&&jsx(N,{})]})}function N(){return jsxs("div",{style:q,children:[jsx("div",{style:{fontSize:40,marginBottom:12},children:"\u{1F9E9}"}),jsx("div",{style:{fontWeight:700,fontSize:18,marginBottom:6},children:"No modules installed"}),jsxs("div",{style:{opacity:.7,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 T={position:"absolute",inset:0,overflow:"hidden",color:"#fff",fontFamily:"system-ui, sans-serif"},O={position:"absolute",inset:0,zIndex:0},W={position:"absolute",inset:0,zIndex:1,pointerEvents:"none"},j={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},U={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"},$={position:"absolute",bottom:16,left:"50%",transform:"translateX(-50%)",zIndex:3,display:"flex",gap:8,padding:6,borderRadius:14,background:"rgba(20,18,40,0.72)",backdropFilter:"blur(6px)",pointerEvents:"auto"},A={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfc9ee",background:"transparent",cursor:"pointer"},F={...A,color:"#fff",background:"#6c5ce7"},K={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},y={pointerEvents:"auto"},q={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24};function M(s){let{client:o,modules:e,events:n,surface:r,renderLogin:l}=s,[d,p]=useState(true),[c,u]=useState(null),t=()=>{u(x(e,{client:o,events:n,surface:r}));},i=useRef(false);return useEffect(()=>{if(!i.current){if(i.current=true,o.auth.lastAuthType===AuthType.None){p(false);return}(async()=>((await o.auth.autoLogin()).ok&&t(),p(false)))();}},[o]),useEffect(()=>{let m=()=>u(null),S=o.on("auth:unauthorized",m),z=o.on("auth:loggedOut",m);return ()=>{S(),z();}},[o]),c?jsx(k,{registrations:c}):d?null:l({client:o,onAuthenticated:t})}function C({client:s,onAuthenticated:o}){let[e,n]=useState(false),[r,l]=useState(null),[d,p]=useState(true),c=async()=>{n(true),l(null),s.auth.setRememberSession(d);let u=await s.auth.loginWithDeviceID();if(u.ok){o();return}l(u.error),n(false);};return jsx("div",{style:{position:"absolute",inset:0,display:"grid",placeItems:"center",gap:"12px",color:"#e8e6f3",font:"14px system-ui, sans-serif"},children:jsxs("div",{style:{display:"grid",gap:"12px",justifyItems:"center"},children:[jsx("button",{type:"button",onClick:()=>{c();},disabled:e,style:{padding:"10px 20px",borderRadius:"8px",border:"1px solid #4c4470",background:e?"#2a2545":"#3b3363",color:"inherit",cursor:e?"default":"pointer",font:"inherit"},children:e?"Signing in\u2026":"Play as guest"}),jsxs("label",{style:{display:"flex",alignItems:"center",gap:"6px",cursor:e?"default":"pointer",opacity:e?.6:1},children:[jsx("input",{type:"checkbox",checked:d,disabled:e,onChange:u=>p(u.target.checked)}),"Remember me"]}),r&&jsx("span",{style:{color:"#ff9b9b"},children:r})]})})}function _(s){let{container:o,client:e,modules:n,renderLogin:r}=s;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 p=h(),c=b(l),u=createRoot(d);return u.render(jsx(IDosGamesProvider,{client:e,children:jsx(StatusProvider,{children:jsx(M,{client:e,modules:n,events:p,surface:c,renderLogin:r??C})})})),{unmount(){u.unmount(),l.remove(),d.remove();}}}export{M as AuthGate,C as DefaultLoginScreen,k as HostShell,f as SceneStage,h as createSharedEventBus,b as createSurfaceAllocator,_ as mountHost,x as runModules};
1
+ import {createRoot}from'react-dom/client';import {IDosGamesProvider,StatusProvider}from'@idosgames/react';import {useRef,useMemo,useState,useEffect}from'react';import {AuthType}from'@idosgames/core';import {jsx,jsxs}from'react/jsx-runtime';function x(){let s=new Map;return {emit(o,e){let r=s.get(o);if(r)for(let n of [...r])n(e);},on(o,e){let r=e,n=s.get(o);return n||(n=new Set,s.set(o,n)),n.add(r),()=>{n.delete(r),n.size===0&&s.delete(o);}}}}var V={position:"absolute",inset:"0"};function R(s){return {request(o){let e=document.createElement("div");return e.dataset.surface=o,Object.assign(e.style,V),e.style.pointerEvents=o==="fullbleed-canvas"?"auto":"none",s.appendChild(e),{host:e,release(){e.remove();}}}}}function k(s,o){return s.map(e=>{let r={module:e,scenes:[],panels:[],routes:[]},n={client:o.client,titleId:o.client.titleID,events:o.events,surface:o.surface,registerScene:i=>r.scenes.push(i),registerPanel:i=>r.panels.push(i),registerRoute:i=>r.routes.push(i)};return e.setup(n),r})}var y=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 r of this.active){if(e.has(r))continue;r.suspend?.();let n=this.hosts.get(r);n&&(n.style.display="none");}for(let r of e){if(this.active.has(r))continue;let n=this.ensureMounted(r);n.style.display="block",r.activate?.();}this.active=e;}destroy(){for(let[o,e]of this.hosts)o.destroy(),e.remove();this.hosts.clear(),this.active.clear();}};function C({registrations:s,onLogout:o}){let e=useRef(null),r=useRef(null),n=useMemo(()=>s.flatMap(t=>t.routes.map(l=>({id:l.id,label:l.label,icon:l.icon,order:l.order??0,moduleId:t.module.id}))).sort((t,l)=>t.order-l.order),[s]),[i,c]=useState(()=>n[0]?.id??null);useEffect(()=>{i!==null&&n.some(t=>t.id===i)||c(n[0]?.id??null);},[n,i]);let u=useMemo(()=>n.find(t=>t.id===i)?.moduleId??null,[n,i]);useEffect(()=>{let t=e.current;if(!t)return;let l=r.current??=new y(t),g=s.find(b=>b.module.id===u)?.scenes??[];l.setActive(g);},[s,u]),useEffect(()=>()=>{r.current?.destroy(),r.current=null;},[]);let m=useMemo(()=>s.flatMap(t=>t.panels.filter(l=>l.activeOnly===false||t.module.id===u).map(l=>{let g=l.component;return {key:`${t.module.id}:${l.id}`,slot:l.slot,order:l.order??0,moduleId:t.module.id,component:jsx(g,{})}})).sort((t,l)=>t.order-l.order),[s,u]),d=t=>m.filter(l=>l.slot===t),v=s.length>0;return jsxs("div",{style:_,children:[jsx("div",{ref:e,style:K}),jsx("div",{style:$,children:d("overlay").map(t=>jsx("div",{style:S,children:t.component},t.key))}),jsx("div",{style:j,children:d("hud").map(t=>jsx("div",{style:S,children:t.component},t.key))}),jsx("div",{style:F,children:d("sidebar").map(t=>jsx("div",{style:S,children:t.component},t.key))}),n.length>1&&jsx("nav",{style:Y,children:n.map(t=>jsxs("button",{type:"button",onClick:()=>c(t.id),style:t.id===i?q:H,children:[t.icon?`${t.icon} `:"",t.label]},t.id))}),o&&jsx("button",{type:"button",style:X,onClick:o,title:"Log out",children:"\u{1F6AA} Log out"}),d("modal").length>0&&jsx("div",{style:J,children:d("modal").map(t=>jsx("div",{style:S,children:t.component},t.key))}),!v&&jsx(U,{})]})}function U(){return jsxs("div",{style:Q,children:[jsx("style",{children:`
2
+ @keyframes idos-empty-float {
3
+ 0%, 100% { transform: translateY(0) rotate(-6deg); }
4
+ 50% { transform: translateY(-16px) rotate(6deg); }
5
+ }
6
+ @keyframes idos-empty-ripple {
7
+ 0% { transform: scale(0.55); opacity: 0.55; }
8
+ 100% { transform: scale(1.7); opacity: 0; }
9
+ }
10
+ `}),jsxs("div",{style:Z,children:[jsx("span",{style:{...z,animationDelay:"0s"}}),jsx("span",{style:{...z,animationDelay:"1.1s"}}),jsx("span",{style:ee,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 _={position:"absolute",inset:0,overflow:"hidden",background:"#0d66fe",color:"#fff",fontFamily:"system-ui, sans-serif"},K={position:"absolute",inset:0,zIndex:0},$={position:"absolute",inset:0,zIndex:1,pointerEvents:"none"},j={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},F={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"},Y={position:"absolute",bottom:16,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"},H={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfe0ff",background:"transparent",cursor:"pointer"},q={...H,color:"#0d66fe",background:"#fff"},X={position:"absolute",bottom:16,left:16,zIndex:3,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",pointerEvents:"auto"},J={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},S={pointerEvents:"auto"},Q={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24},Z={position:"relative",width:110,height:110,marginBottom:16,display:"grid",placeItems:"center"},z={position:"absolute",inset:0,borderRadius:"50%",border:"2px solid rgba(255,255,255,0.55)",animation:"idos-empty-ripple 2.2s ease-out infinite"},ee={fontSize:46,animation:"idos-empty-float 3s ease-in-out infinite",filter:"drop-shadow(0 8px 12px rgba(0,0,0,0.25))"};function E(s){let{client:o,modules:e,events:r,surface:n,renderLogin:i}=s,[c,u]=useState(true),[m,d]=useState(null),v=()=>{d(k(e,{client:o,events:r,surface:n}));},t=useRef(false);return useEffect(()=>{if(!t.current){if(t.current=true,o.auth.lastAuthType===AuthType.None){u(false);return}(async()=>((await o.auth.autoLogin()).ok&&v(),u(false)))();}},[o]),useEffect(()=>{let g=()=>d(null),b=o.on("auth:unauthorized",g),N=o.on("auth:loggedOut",g);return ()=>{b(),N();}},[o]),m?jsx(C,{registrations:m,onLogout:()=>o.auth.logout()}):c?null:jsx(i,{client:o,onAuthenticated:v})}var ne='<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>',O=`data:image/svg+xml;utf8,${encodeURIComponent(ne)}`;function I({client:s,onAuthenticated:o}){let[e,r]=useState(false),[n,i]=useState(null),[c,u]=useState(true),m=async()=>{r(true),i(null),s.auth.setRememberSession(c);let d=await s.auth.loginWithDeviceID();if(d.ok){o();return}i(d.error),r(false);};return jsx("div",{style:p.root,children:jsxs("div",{style:p.card,children:[jsx("img",{src:O,alt:"iDos Games",style:p.logo}),jsx("h1",{style:p.title,children:"Sign in"}),jsx("button",{type:"button",onClick:()=>{m();},disabled:e,style:{...p.primary,opacity:e?.6:1,cursor:e?"default":"pointer"},children:e?"Signing in\u2026":"Play as guest"}),jsxs("label",{style:{...p.remember,opacity:e?.6:1},children:[jsx("input",{type:"checkbox",checked:c,disabled:e,onChange:d=>u(d.target.checked),style:p.switchInput}),jsx("span",{style:{...p.switchTrack,background:c?"#fff":"rgba(255, 255, 255, 0.3)"},children:jsx("span",{style:{...p.switchKnob,left:c?"21px":"3px",background:c?"#0d66fe":"#fff"}})}),"Remember me"]}),n&&jsx("span",{style:p.error,children:n})]})})}var p={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"},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 le(s){let{container:o,client:e,modules:r,renderLogin:n}=s;o.style.position="relative";let i=document.createElement("div");Object.assign(i.style,{position:"absolute",inset:"0",zIndex:"0",pointerEvents:"none"});let c=document.createElement("div");Object.assign(c.style,{position:"absolute",inset:"0",zIndex:"1"}),o.append(i,c);let u=x(),m=R(i),d=createRoot(c);return d.render(jsx(IDosGamesProvider,{client:e,children:jsx(StatusProvider,{children:jsx(E,{client:e,modules:r,events:u,surface:m,renderLogin:n??I})})})),{unmount(){d.unmount(),i.remove(),c.remove();}}}
11
+ export{E as AuthGate,I as DefaultLoginScreen,C as HostShell,y as SceneStage,x as createSharedEventBus,R as createSurfaceAllocator,le as mountHost,k as runModules};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idosgames/app-shell",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
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",