@idosgames/app-shell 0.1.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/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +61 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +1 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 iDos Games
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# @idosgames/app-shell
|
|
2
|
+
|
|
3
|
+
The **host runtime** for iDosGames composable modules. A project is one host shell plus N feature
|
|
4
|
+
modules; this package is the shell — it owns the module registry, a shared event bus, a surface
|
|
5
|
+
allocator, the imperative scene stage, and the React **Mode Router** that switches between modules.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { createIDosGamesClient } from "@idosgames/core";
|
|
9
|
+
import { mountHost } from "@idosgames/app-shell";
|
|
10
|
+
import { modules } from "./modules";
|
|
11
|
+
|
|
12
|
+
const client = createIDosGamesClient({ titleID, buildKey });
|
|
13
|
+
await client.auth.loginWithDeviceID();
|
|
14
|
+
mountHost({ container: document.getElementById("app")!, client, modules });
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`mountHost` renders a nav-bar when ≥2 modules register a route and mode-switches between them (only
|
|
18
|
+
the active mode's scene is mounted and ticking). Panels registered with `activeOnly: false` stay
|
|
19
|
+
visible across every mode (e.g. a shared HUD).
|
|
20
|
+
|
|
21
|
+
Modules are authored against [`@idosgames/module-sdk`](https://www.npmjs.com/package/@idosgames/module-sdk);
|
|
22
|
+
shared React glue is [`@idosgames/react`](https://www.npmjs.com/package/@idosgames/react). React and
|
|
23
|
+
ReactDOM are peer dependencies. See `docs/composable-modules-architecture.md` for the full design.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var client=require('react-dom/client'),react$1=require('@idosgames/react'),react=require('react'),jsxRuntime=require('react/jsx-runtime');function S(){let r=new Map;return {emit(n,t){let o=r.get(n);if(o)for(let s of [...o])s(t);},on(n,t){let o=t,s=r.get(n);return s||(s=new Set,r.set(n,s)),s.add(o),()=>{s.delete(o),s.size===0&&r.delete(n);}}}}var k={position:"absolute",inset:"0"};function g(r){return {request(n){let t=document.createElement("div");return t.dataset.surface=n,Object.assign(t.style,k),t.style.pointerEvents=n==="fullbleed-canvas"?"auto":"none",r.appendChild(t),{host:t,release(){t.remove();}}}}}function h(r,n){return r.map(t=>{let o={module:t,scenes:[],panels:[],routes:[]},s={client:n.client,events:n.events,surface:n.surface,registerScene:a=>o.scenes.push(a),registerPanel:a=>o.panels.push(a),registerRoute:a=>o.routes.push(a)};return t.setup(s),o})}var u=class{constructor(n){this.container=n;}container;hosts=new Map;active=new Set;ensureMounted(n){let t=this.hosts.get(n);return t||(t=document.createElement("div"),Object.assign(t.style,{position:"absolute",inset:"0"}),this.container.appendChild(t),this.hosts.set(n,t),n.mount({host:t})),t}setActive(n){let t=new Set(n);for(let o of this.active){if(t.has(o))continue;o.suspend?.();let s=this.hosts.get(o);s&&(s.style.display="none");}for(let o of t){if(this.active.has(o))continue;let s=this.ensureMounted(o);s.style.display="block",o.activate?.();}this.active=t;}destroy(){for(let[n,t]of this.hosts)n.destroy(),t.remove();this.hosts.clear(),this.active.clear();}};function E({registrations:r}){let n=react.useRef(null),t=react.useRef(null),o=react.useMemo(()=>r.flatMap(e=>e.routes.map(i=>({id:i.id,label:i.label,icon:i.icon,order:i.order??0,moduleId:e.module.id}))).sort((e,i)=>e.order-i.order),[r]),[s,a]=react.useState(()=>o[0]?.id??null);react.useEffect(()=>{s!==null&&o.some(e=>e.id===s)||a(o[0]?.id??null);},[o,s]);let c=react.useMemo(()=>o.find(e=>e.id===s)?.moduleId??null,[o,s]);react.useEffect(()=>{let e=n.current;if(!e)return;let i=t.current??=new u(e),y=r.find(R=>R.module.id===c)?.scenes??[];i.setActive(y);},[r,c]),react.useEffect(()=>()=>{t.current?.destroy(),t.current=null;},[]);let v=react.useMemo(()=>r.flatMap(e=>e.panels.filter(i=>i.activeOnly===false||e.module.id===c).map(i=>{let y=i.component;return {key:`${e.module.id}:${i.id}`,slot:i.slot,order:i.order??0,moduleId:e.module.id,component:jsxRuntime.jsx(y,{})}})).sort((e,i)=>e.order-i.order),[r,c]),d=e=>v.filter(i=>i.slot===e),p=r.length>0;return jsxRuntime.jsxs("div",{style:w,children:[jsxRuntime.jsx("div",{ref:n,style:z}),jsxRuntime.jsx("div",{style:A,children:d("overlay").map(e=>jsxRuntime.jsx("div",{style:m,children:e.component},e.key))}),jsxRuntime.jsx("div",{style:B,children:d("hud").map(e=>jsxRuntime.jsx("div",{style:m,children:e.component},e.key))}),jsxRuntime.jsx("div",{style:L,children:d("sidebar").map(e=>jsxRuntime.jsx("div",{style:m,children:e.component},e.key))}),o.length>1&&jsxRuntime.jsx("nav",{style:D,children:o.map(e=>jsxRuntime.jsxs("button",{type:"button",onClick:()=>a(e.id),style:e.id===s?T:P,children:[e.icon?`${e.icon} `:"",e.label]},e.id))}),d("modal").length>0&&jsxRuntime.jsx("div",{style:G,children:d("modal").map(e=>jsxRuntime.jsx("div",{style:m,children:e.component},e.key))}),!p&&jsxRuntime.jsx(H,{})]})}function H(){return jsxRuntime.jsxs("div",{style:N,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 w={position:"absolute",inset:0,overflow:"hidden",color:"#fff",fontFamily:"system-ui, sans-serif"},z={position:"absolute",inset:0,zIndex:0},A={position:"absolute",inset:0,zIndex:1,pointerEvents:"none"},B={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},L={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"},D={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"},P={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfc9ee",background:"transparent",cursor:"pointer"},T={...P,color:"#fff",background:"#6c5ce7"},G={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},m={pointerEvents:"auto"},N={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24};function $(r){let{container:n,client:t,modules:o}=r;n.style.position="relative";let s=document.createElement("div");Object.assign(s.style,{position:"absolute",inset:"0",zIndex:"0",pointerEvents:"none"});let a=document.createElement("div");Object.assign(a.style,{position:"absolute",inset:"0",zIndex:"1"}),n.append(s,a);let c=S(),v=g(s),d=h(o,{client:t,events:c,surface:v}),p=client.createRoot(a);return p.render(jsxRuntime.jsx(react$1.IDosGamesProvider,{client:t,children:jsxRuntime.jsx(react$1.StatusProvider,{children:jsxRuntime.jsx(E,{registrations:d})})})),{unmount(){p.unmount(),s.remove(),a.remove();}}}exports.HostShell=E;exports.SceneStage=u;exports.createSharedEventBus=S;exports.createSurfaceAllocator=g;exports.mountHost=$;exports.runModules=h;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { IDosGamesClient, Module, EngineScene, UiPanel, RouteEntry, SharedEventBus, SurfaceAllocator } from '@idosgames/module-sdk';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface HostHandle {
|
|
5
|
+
unmount(): void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Mounts the host shell into `container` with the given modules, all driven by one shared,
|
|
9
|
+
* already-authenticated SDK client. This is the composable-module analog of the old per-template
|
|
10
|
+
* `mountBoardGame` — except the app owns it and the games are plugged in as modules.
|
|
11
|
+
*
|
|
12
|
+
* DOM layout inside `container`:
|
|
13
|
+
* container (position: relative)
|
|
14
|
+
* ├── surfaceLayer — ad-hoc module surfaces, behind everything
|
|
15
|
+
* └── reactHost — the React tree (scenes render here, UI panels on top)
|
|
16
|
+
*/
|
|
17
|
+
declare function mountHost(options: {
|
|
18
|
+
container: HTMLElement;
|
|
19
|
+
client: IDosGamesClient;
|
|
20
|
+
modules: readonly Module[];
|
|
21
|
+
}): HostHandle;
|
|
22
|
+
|
|
23
|
+
interface ModuleRegistration {
|
|
24
|
+
module: Module;
|
|
25
|
+
scenes: EngineScene[];
|
|
26
|
+
panels: UiPanel[];
|
|
27
|
+
routes: RouteEntry[];
|
|
28
|
+
}
|
|
29
|
+
/** Shared services every module receives — created once per host session. */
|
|
30
|
+
interface SharedServices {
|
|
31
|
+
client: IDosGamesClient;
|
|
32
|
+
events: SharedEventBus;
|
|
33
|
+
surface: SurfaceAllocator;
|
|
34
|
+
}
|
|
35
|
+
/** Install every module and return their collected registrations, in declaration order. */
|
|
36
|
+
declare function runModules(modules: readonly Module[], shared: SharedServices): ModuleRegistration[];
|
|
37
|
+
|
|
38
|
+
declare function HostShell({ registrations, }: {
|
|
39
|
+
registrations: readonly ModuleRegistration[];
|
|
40
|
+
}): ReactNode;
|
|
41
|
+
|
|
42
|
+
declare class SceneStage {
|
|
43
|
+
private readonly container;
|
|
44
|
+
private readonly hosts;
|
|
45
|
+
private active;
|
|
46
|
+
constructor(container: HTMLElement);
|
|
47
|
+
private ensureMounted;
|
|
48
|
+
/** Make exactly `scenes` the active set: suspend/hide the ones leaving, mount+activate the ones
|
|
49
|
+
* entering. Idempotent — calling with the current set is a no-op. */
|
|
50
|
+
setActive(scenes: readonly EngineScene[]): void;
|
|
51
|
+
/** Permanent teardown: destroy every mounted scene and remove its host element. */
|
|
52
|
+
destroy(): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** In-memory pub/sub shared by all modules for a host session. */
|
|
56
|
+
declare function createSharedEventBus(): SharedEventBus;
|
|
57
|
+
|
|
58
|
+
/** Creates an allocator whose surfaces are appended to `layer`. */
|
|
59
|
+
declare function createSurfaceAllocator(layer: HTMLElement): SurfaceAllocator;
|
|
60
|
+
|
|
61
|
+
export { type HostHandle, HostShell, type ModuleRegistration, SceneStage, type SharedServices, createSharedEventBus, createSurfaceAllocator, mountHost, runModules };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { IDosGamesClient, Module, EngineScene, UiPanel, RouteEntry, SharedEventBus, SurfaceAllocator } from '@idosgames/module-sdk';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
interface HostHandle {
|
|
5
|
+
unmount(): void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Mounts the host shell into `container` with the given modules, all driven by one shared,
|
|
9
|
+
* already-authenticated SDK client. This is the composable-module analog of the old per-template
|
|
10
|
+
* `mountBoardGame` — except the app owns it and the games are plugged in as modules.
|
|
11
|
+
*
|
|
12
|
+
* DOM layout inside `container`:
|
|
13
|
+
* container (position: relative)
|
|
14
|
+
* ├── surfaceLayer — ad-hoc module surfaces, behind everything
|
|
15
|
+
* └── reactHost — the React tree (scenes render here, UI panels on top)
|
|
16
|
+
*/
|
|
17
|
+
declare function mountHost(options: {
|
|
18
|
+
container: HTMLElement;
|
|
19
|
+
client: IDosGamesClient;
|
|
20
|
+
modules: readonly Module[];
|
|
21
|
+
}): HostHandle;
|
|
22
|
+
|
|
23
|
+
interface ModuleRegistration {
|
|
24
|
+
module: Module;
|
|
25
|
+
scenes: EngineScene[];
|
|
26
|
+
panels: UiPanel[];
|
|
27
|
+
routes: RouteEntry[];
|
|
28
|
+
}
|
|
29
|
+
/** Shared services every module receives — created once per host session. */
|
|
30
|
+
interface SharedServices {
|
|
31
|
+
client: IDosGamesClient;
|
|
32
|
+
events: SharedEventBus;
|
|
33
|
+
surface: SurfaceAllocator;
|
|
34
|
+
}
|
|
35
|
+
/** Install every module and return their collected registrations, in declaration order. */
|
|
36
|
+
declare function runModules(modules: readonly Module[], shared: SharedServices): ModuleRegistration[];
|
|
37
|
+
|
|
38
|
+
declare function HostShell({ registrations, }: {
|
|
39
|
+
registrations: readonly ModuleRegistration[];
|
|
40
|
+
}): ReactNode;
|
|
41
|
+
|
|
42
|
+
declare class SceneStage {
|
|
43
|
+
private readonly container;
|
|
44
|
+
private readonly hosts;
|
|
45
|
+
private active;
|
|
46
|
+
constructor(container: HTMLElement);
|
|
47
|
+
private ensureMounted;
|
|
48
|
+
/** Make exactly `scenes` the active set: suspend/hide the ones leaving, mount+activate the ones
|
|
49
|
+
* entering. Idempotent — calling with the current set is a no-op. */
|
|
50
|
+
setActive(scenes: readonly EngineScene[]): void;
|
|
51
|
+
/** Permanent teardown: destroy every mounted scene and remove its host element. */
|
|
52
|
+
destroy(): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** In-memory pub/sub shared by all modules for a host session. */
|
|
56
|
+
declare function createSharedEventBus(): SharedEventBus;
|
|
57
|
+
|
|
58
|
+
/** Creates an allocator whose surfaces are appended to `layer`. */
|
|
59
|
+
declare function createSurfaceAllocator(layer: HTMLElement): SurfaceAllocator;
|
|
60
|
+
|
|
61
|
+
export { type HostHandle, HostShell, type ModuleRegistration, SceneStage, type SharedServices, createSharedEventBus, createSurfaceAllocator, mountHost, runModules };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {createRoot}from'react-dom/client';import {IDosGamesProvider,StatusProvider}from'@idosgames/react';import {useRef,useMemo,useState,useEffect}from'react';import {jsx,jsxs}from'react/jsx-runtime';function S(){let r=new Map;return {emit(n,t){let o=r.get(n);if(o)for(let s of [...o])s(t);},on(n,t){let o=t,s=r.get(n);return s||(s=new Set,r.set(n,s)),s.add(o),()=>{s.delete(o),s.size===0&&r.delete(n);}}}}var k={position:"absolute",inset:"0"};function g(r){return {request(n){let t=document.createElement("div");return t.dataset.surface=n,Object.assign(t.style,k),t.style.pointerEvents=n==="fullbleed-canvas"?"auto":"none",r.appendChild(t),{host:t,release(){t.remove();}}}}}function h(r,n){return r.map(t=>{let o={module:t,scenes:[],panels:[],routes:[]},s={client:n.client,events:n.events,surface:n.surface,registerScene:a=>o.scenes.push(a),registerPanel:a=>o.panels.push(a),registerRoute:a=>o.routes.push(a)};return t.setup(s),o})}var u=class{constructor(n){this.container=n;}container;hosts=new Map;active=new Set;ensureMounted(n){let t=this.hosts.get(n);return t||(t=document.createElement("div"),Object.assign(t.style,{position:"absolute",inset:"0"}),this.container.appendChild(t),this.hosts.set(n,t),n.mount({host:t})),t}setActive(n){let t=new Set(n);for(let o of this.active){if(t.has(o))continue;o.suspend?.();let s=this.hosts.get(o);s&&(s.style.display="none");}for(let o of t){if(this.active.has(o))continue;let s=this.ensureMounted(o);s.style.display="block",o.activate?.();}this.active=t;}destroy(){for(let[n,t]of this.hosts)n.destroy(),t.remove();this.hosts.clear(),this.active.clear();}};function E({registrations:r}){let n=useRef(null),t=useRef(null),o=useMemo(()=>r.flatMap(e=>e.routes.map(i=>({id:i.id,label:i.label,icon:i.icon,order:i.order??0,moduleId:e.module.id}))).sort((e,i)=>e.order-i.order),[r]),[s,a]=useState(()=>o[0]?.id??null);useEffect(()=>{s!==null&&o.some(e=>e.id===s)||a(o[0]?.id??null);},[o,s]);let c=useMemo(()=>o.find(e=>e.id===s)?.moduleId??null,[o,s]);useEffect(()=>{let e=n.current;if(!e)return;let i=t.current??=new u(e),y=r.find(R=>R.module.id===c)?.scenes??[];i.setActive(y);},[r,c]),useEffect(()=>()=>{t.current?.destroy(),t.current=null;},[]);let v=useMemo(()=>r.flatMap(e=>e.panels.filter(i=>i.activeOnly===false||e.module.id===c).map(i=>{let y=i.component;return {key:`${e.module.id}:${i.id}`,slot:i.slot,order:i.order??0,moduleId:e.module.id,component:jsx(y,{})}})).sort((e,i)=>e.order-i.order),[r,c]),d=e=>v.filter(i=>i.slot===e),p=r.length>0;return jsxs("div",{style:w,children:[jsx("div",{ref:n,style:z}),jsx("div",{style:A,children:d("overlay").map(e=>jsx("div",{style:m,children:e.component},e.key))}),jsx("div",{style:B,children:d("hud").map(e=>jsx("div",{style:m,children:e.component},e.key))}),jsx("div",{style:L,children:d("sidebar").map(e=>jsx("div",{style:m,children:e.component},e.key))}),o.length>1&&jsx("nav",{style:D,children:o.map(e=>jsxs("button",{type:"button",onClick:()=>a(e.id),style:e.id===s?T:P,children:[e.icon?`${e.icon} `:"",e.label]},e.id))}),d("modal").length>0&&jsx("div",{style:G,children:d("modal").map(e=>jsx("div",{style:m,children:e.component},e.key))}),!p&&jsx(H,{})]})}function H(){return jsxs("div",{style:N,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 w={position:"absolute",inset:0,overflow:"hidden",color:"#fff",fontFamily:"system-ui, sans-serif"},z={position:"absolute",inset:0,zIndex:0},A={position:"absolute",inset:0,zIndex:1,pointerEvents:"none"},B={position:"absolute",top:0,left:0,right:0,zIndex:2,display:"flex",gap:12,padding:16,pointerEvents:"none"},L={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"},D={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"},P={border:"none",borderRadius:10,padding:"8px 16px",fontWeight:700,fontSize:14,color:"#cfc9ee",background:"transparent",cursor:"pointer"},T={...P,color:"#fff",background:"#6c5ce7"},G={position:"absolute",inset:0,zIndex:4,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(0,0,0,0.5)",pointerEvents:"none"},m={pointerEvents:"auto"},N={position:"absolute",inset:0,zIndex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",padding:24};function $(r){let{container:n,client:t,modules:o}=r;n.style.position="relative";let s=document.createElement("div");Object.assign(s.style,{position:"absolute",inset:"0",zIndex:"0",pointerEvents:"none"});let a=document.createElement("div");Object.assign(a.style,{position:"absolute",inset:"0",zIndex:"1"}),n.append(s,a);let c=S(),v=g(s),d=h(o,{client:t,events:c,surface:v}),p=createRoot(a);return p.render(jsx(IDosGamesProvider,{client:t,children:jsx(StatusProvider,{children:jsx(E,{registrations:d})})})),{unmount(){p.unmount(),s.remove(),a.remove();}}}export{E as HostShell,u as SceneStage,S as createSharedEventBus,g as createSurfaceAllocator,$ as mountHost,h as runModules};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@idosgames/app-shell",
|
|
3
|
+
"version": "0.1.0",
|
|
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
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "iDos Games",
|
|
8
|
+
"homepage": "https://github.com/iDos-Games/iDosGamesSDK_TS#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/iDos-Games/iDosGamesSDK_TS.git",
|
|
12
|
+
"directory": "packages/app-shell"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/iDos-Games/iDosGamesSDK_TS/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"idosgames",
|
|
19
|
+
"sdk",
|
|
20
|
+
"host",
|
|
21
|
+
"shell",
|
|
22
|
+
"modules",
|
|
23
|
+
"plugin"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"sideEffects": false,
|
|
29
|
+
"main": "./dist/index.cjs",
|
|
30
|
+
"module": "./dist/index.js",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"exports": {
|
|
33
|
+
".": {
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"import": "./dist/index.js",
|
|
36
|
+
"require": "./dist/index.cjs"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"README.md",
|
|
42
|
+
"LICENSE"
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
47
|
+
},
|
|
48
|
+
"//": "react/react-dom are consumer-provided peers. @idosgames/* are real ranges pinned in step with those packages.",
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@idosgames/core": "^0.1.1",
|
|
51
|
+
"@idosgames/module-sdk": "^0.1.0",
|
|
52
|
+
"@idosgames/react": "^0.1.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"react": "^18.3.1 || ^19.0.0",
|
|
56
|
+
"react-dom": "^18.3.1 || ^19.0.0"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/react": "^19.2.17",
|
|
60
|
+
"@types/react-dom": "^19.2.3",
|
|
61
|
+
"react": "^19.2.7",
|
|
62
|
+
"react-dom": "^19.2.7"
|
|
63
|
+
}
|
|
64
|
+
}
|