@dloizides/game-shell 0.1.0 → 0.1.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1
4
+
5
+ - Desktop install card sits 60px from the bottom by default, set by `--gs-card-bottom` (clears a bottom-right HUD badge).
6
+
3
7
  ## 0.1.0
4
8
 
5
9
  - Initial release: fit, install, crash, lifecycle, versionPoll, initGameShell, game-shell.css, IIFE bundle.
package/README.md CHANGED
@@ -31,4 +31,4 @@ Unity / Godot / vanilla pages: load `dist/game-shell.iife.js` (global `GameShell
31
31
  ## Theme
32
32
 
33
33
  Every overlay reads only these CSS variables; defaults are a neutral dark theme. Set them on `:root` in the game:
34
- `--gs-font-display --gs-font-text --gs-surface --gs-surface-solid --gs-edge --gs-ink --gs-ink-dim --gs-accent --gs-on-accent --gs-scrim --gs-radius --gs-radius-pill --gs-focus`.
34
+ `--gs-font-display --gs-font-text --gs-surface --gs-surface-solid --gs-edge --gs-ink --gs-ink-dim --gs-accent --gs-on-accent --gs-scrim --gs-radius --gs-radius-pill --gs-focus`, plus `--gs-card-bottom` (desktop card offset from the bottom, default 60px).
@@ -1,4 +1,4 @@
1
- :where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}
1
+ :where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-card-bottom:60px;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}
2
2
  .gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}
3
3
  .gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}
4
4
  .gs *{box-sizing:border-box}
@@ -14,7 +14,7 @@
14
14
  .gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}
15
15
  .gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}
16
16
  .gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}
17
- .gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(24px + var(--gs-safe-bottom))}
17
+ .gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(var(--gs-card-bottom,60px) + var(--gs-safe-bottom))}
18
18
  .gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}
19
19
  .gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}
20
20
  .gs-chip svg{color:var(--gs-accent)}
@@ -1,5 +1,5 @@
1
1
  "use strict";var GameShell=(()=>{var N=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var J=Object.prototype.hasOwnProperty;var X=(e,t)=>{for(var n in t)N(e,n,{get:t[n],enumerable:!0})},ee=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Q(t))!J.call(e,o)&&o!==n&&N(e,o,{get:()=>t[o],enumerable:!(r=Z(t,o))||r.enumerable});return e};var te=e=>ee(N({},"__esModule",{value:!0}),e);var be={};X(be,{CRASH_KIND:()=>m,DEFAULT_SNOOZE_DAYS:()=>P,DESKTOP_MIN_WIDTH:()=>W,GAME_SHELL_CSS:()=>R,GS_RESIZE_EVENT:()=>O,GS_VH_VAR:()=>y,initGameShell:()=>q,injectStyles:()=>D,isDesktop:()=>v,isIosSafari:()=>I,isStandalone:()=>L,prefersReducedMotion:()=>$,startCrash:()=>b,startFit:()=>E,startInstall:()=>w,startLifecycle:()=>C,startVersionPoll:()=>k,unlockAudio:()=>U});var m={Error:"error",Rejection:"rejection"};function a(e,t,n="",r=""){let o=e.createElement(t);return n!==""&&(o.className=n),r!==""&&(o.textContent=r),o}function x(e,t){let n=a(e,"span","gs-ico");return n.innerHTML=t,n}function f(e,t){let n=a(e,"button",t.className);return n.type="button",t.icon!==void 0&&n.append(x(e,t.icon)),t.text!==void 0&&n.append(e.createTextNode(t.text)),t.ariaLabel!==void 0&&n.setAttribute("aria-label",t.ariaLabel),n.addEventListener("click",()=>t.onClick()),n}var _="gs-crash-title",A="gs-crash-body";function H(e){let t=a(e.doc,"div","gs gs-crash");t.setAttribute("role","alertdialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-labelledby",_),t.setAttribute("aria-describedby",A);let n=a(e.doc,"div","gs-panel"),r=a(e.doc,"h2","gs-h",e.labels.crashTitle);r.id=_;let o=a(e.doc,"p","",e.labels.crashBody);o.id=A;let i=a(e.doc,"div","gs-acts"),l=f(e.doc,{className:"gs-btn gs-primary",text:e.labels.reload,onClick:e.onReload});return i.append(l,f(e.doc,{className:"gs-btn gs-ghost",text:e.labels.copyDetails,onClick:e.onCopy})),n.append(r,o,i),e.reference!==void 0&&e.reference!==""&&n.append(a(e.doc,"p","gs-ref",`${e.labels.errorReported} ${e.reference}`)),t.append(n),{root:t,reload:l}}function ne(e){let t=e.error,n=t instanceof Error?t.stack:void 0,r=e.filename!==""?`${e.filename}:${e.lineno}:${e.colno}`:void 0,o=e.message!==""?e.message:String(t);return{kind:m.Error,message:o,source:n!=null?n:r}}function oe(e){let t=e.reason;return t instanceof Error?{kind:m.Rejection,message:t.message,source:t.stack}:{kind:m.Rejection,message:String(t)}}function re(e,t){var n,r;try{return(r=(n=e.report)==null?void 0:n.call(e,t))!=null?r:void 0}catch(o){return}}function se(e,t,n){let r=[t.message,t.source,n].filter(o=>o!==void 0&&o!=="").join(`
2
- `);try{e.navigator.clipboard.writeText(r).catch(()=>{})}catch(o){}}function b(e){var d,c;let t=(d=e.win)!=null?d:window,n=(c=e.reload)!=null?c:(()=>t.location.reload()),r=null,o=s=>{let g=re(e,s);if(r)return;let p=H({doc:t.document,labels:e.labels,reference:g,onReload:n,onCopy:()=>se(t,s,e.appVersion)});r=p.root,t.document.body.append(r),p.reload.focus()},i=s=>{s instanceof ErrorEvent&&o(ne(s))},l=s=>o(oe(s));return t.addEventListener("error",i),t.addEventListener("unhandledrejection",l),{dispose:()=>{t.removeEventListener("error",i),t.removeEventListener("unhandledrejection",l),r==null||r.remove(),r=null}}}var O="gs:resize",y="--gs-vh";function V(e){let t=e.visualViewport;return t?{width:t.width,height:t.height}:{width:e.innerWidth,height:e.innerHeight}}function ie(e){return typeof e.requestAnimationFrame=="function"?t=>{e.requestAnimationFrame(()=>t())}:t=>{e.setTimeout(t,0)}}function E(e=window){let t=e.document.documentElement,n=ie(e),r=V(e),o=!1,i=!1;t.style.setProperty(y,`${r.height}px`);let l=()=>{o=!1;let s=V(e),g=s.width===r.width&&s.height===r.height;i||g||(r=s,t.style.setProperty(y,`${s.height}px`),e.dispatchEvent(new CustomEvent(O,{detail:s})))},d=()=>{o||(o=!0,n(l))},c=e.visualViewport;return c==null||c.addEventListener("resize",d),e.addEventListener("resize",d),e.addEventListener("orientationchange",d),{dispose:()=>{i=!0,c==null||c.removeEventListener("resize",d),e.removeEventListener("resize",d),e.removeEventListener("orientationchange",d)}}}var S=e=>`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${e}</svg>`,u={download:S('<path d="M12 4v11M7 10l5 5 5-5M5 20h14"/>'),add:S('<path d="M12 5v14M5 12h14"/>'),close:S('<path d="M6 6l12 12M18 6L6 18"/>'),share:S('<path d="M12 15V4M8 8l4-4 4 4M6 12v8h12v-8"/>')};var z="gs-install-steps";function B(e){let t=a(e.doc,"ol","gs-steps");t.id=z;let n=a(e.doc,"li");n.append(x(e.doc,u.share),e.doc.createTextNode(e.labels.tapShare));let r=a(e.doc,"li");return r.append(x(e.doc,u.add),e.doc.createTextNode(e.labels.tapAdd)),t.append(n,r),t}function M(e){return f(e.doc,{className:"gs-x",ariaLabel:e.labels.notNow,icon:u.close,onClick:e.onDismiss})}function ae(e){let t=a(e.doc,"div","gs-seal");if(e.variant==="prompt")return t.append(f(e.doc,{className:"gs-chip",text:e.labels.install,icon:u.download,onClick:e.onInstall})),t.append(M(e)),[t];let n=B(e);n.hidden=!0;let r=f(e.doc,{className:"gs-chip",text:e.labels.addToHome,icon:u.add,onClick:()=>{n.hidden=!n.hidden,r.setAttribute("aria-expanded",String(!n.hidden))}});return r.setAttribute("aria-expanded","false"),r.setAttribute("aria-controls",z),t.append(r,M(e)),[t,n]}function le(e){let t=a(e.doc,"div","gs-card"),n=a(e.doc,"div","gs-app");n.append(a(e.doc,"i"));let r=a(e.doc,"div","gs-txt");r.append(a(e.doc,"b","",e.appName),a(e.doc,"span","",e.labels.installBody));let o=a(e.doc,"div","gs-acts");return e.variant==="prompt"&&o.append(f(e.doc,{className:"gs-btn gs-primary",text:e.labels.install,icon:u.download,onClick:e.onInstall})),o.append(f(e.doc,{className:"gs-btn gs-ghost",text:e.labels.notNow,onClick:e.onDismiss})),t.append(M(e),n,r),e.variant==="ios"&&t.append(B(e)),t.append(o),[t]}function K(e){let t=a(e.doc,"div","gs gs-install");return t.dataset.layout=e.layout,t.dataset.variant=e.variant,t.setAttribute("role","region"),t.setAttribute("aria-label",e.variant==="prompt"?e.labels.install:e.labels.addToHome),t.addEventListener("keydown",n=>{n.key==="Escape"&&e.onDismiss()}),t.append(...e.layout==="card"?le(e):ae(e)),t}var W=1024,de=/iPad|iPhone|iPod/,ce=/CriOS|FxiOS|EdgiOS|OPiOS/;function L(e){return typeof e.matchMedia=="function"&&e.matchMedia("(display-mode: standalone)").matches||e.navigator.standalone===!0}function I(e){let t=e.navigator.userAgent,n=t.includes("Macintosh")&&e.navigator.maxTouchPoints>1;return(de.test(t)||n)&&!ce.test(t)}function v(e){return e.innerWidth>=1024}function T(e,t){return t!=null?t:`gs-install-snooze:${e}`}function G(e,t,n,r){try{let o=e.localStorage.getItem(t);if(o===null)return!1;let i=Number(o);return Number.isFinite(i)&&r-i<n*864e5}catch(o){return!1}}function j(e,t,n){try{e.localStorage.setItem(t,String(n))}catch(r){}}var P=14,pe="accepted";function ge(e,t,n){let r=T(e.appName,e.storageKey),o={deferred:null,variant:null,node:null},i=()=>{var s;(s=o.node)==null||s.remove(),o.node=null},l=()=>{j(t,r,n()),i()},d=async()=>{let s=o.deferred;if(o.deferred=null,!!s)try{if(await s.prompt(),(await s.userChoice).outcome===pe){i();return}l()}catch(g){i()}};return{state:o,mount:()=>{o.variant!==null&&(i(),o.node=K({doc:t.document,layout:v(t)?"card":"chip",variant:o.variant,appName:e.appName,labels:e.labels,onInstall:()=>{d()},onDismiss:l}),t.document.body.append(o.node))},unmount:i}}function w(e){var c,s,g;let t=(c=e.win)!=null?c:window,n=(s=e.now)!=null?s:(()=>Date.now()),r=T(e.appName,e.storageKey);if(L(t)||G(t,r,(g=e.snoozeDays)!=null?g:P,n()))return{dispose:()=>{}};let o=ge(e,t,n),i=p=>{p.preventDefault(),o.state.deferred=p,o.state.variant="prompt",o.mount()},l=()=>{o.state.variant=null,o.unmount()},d=()=>{let p=o.state.node;p&&p.dataset.layout==="card"!==v(t)&&o.mount()};return t.addEventListener("beforeinstallprompt",i),t.addEventListener("appinstalled",l),t.addEventListener("resize",d),I(t)&&(o.state.variant="ios",o.mount()),{dispose:()=>{t.removeEventListener("beforeinstallprompt",i),t.removeEventListener("appinstalled",l),t.removeEventListener("resize",d),o.unmount()}}}var fe="(prefers-reduced-motion: reduce)",F=["pointerdown","keydown"];function C(e,t=document){let n=()=>{var r,o;if(t.visibilityState==="hidden"){(r=e.onHidden)==null||r.call(e);return}(o=e.onVisible)==null||o.call(e)};return t.addEventListener("visibilitychange",n),{dispose:()=>t.removeEventListener("visibilitychange",n)}}function U(e,t=window){let n=()=>{F.forEach(o=>t.removeEventListener(o,r,!0))};function r(){n();try{Promise.resolve(e.resume()).catch(()=>{})}catch(o){}}return F.forEach(o=>t.addEventListener(o,r,!0)),{dispose:n}}function $(e=window){return new URLSearchParams(e.location.search).get("reducedMotion")==="1"?!0:typeof e.matchMedia=="function"&&e.matchMedia(fe).matches}var Y="gs-styles",ue=":where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}",me=".gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}",ve=`.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}
2
+ `);try{e.navigator.clipboard.writeText(r).catch(()=>{})}catch(o){}}function b(e){var d,c;let t=(d=e.win)!=null?d:window,n=(c=e.reload)!=null?c:(()=>t.location.reload()),r=null,o=s=>{let g=re(e,s);if(r)return;let p=H({doc:t.document,labels:e.labels,reference:g,onReload:n,onCopy:()=>se(t,s,e.appVersion)});r=p.root,t.document.body.append(r),p.reload.focus()},i=s=>{s instanceof ErrorEvent&&o(ne(s))},l=s=>o(oe(s));return t.addEventListener("error",i),t.addEventListener("unhandledrejection",l),{dispose:()=>{t.removeEventListener("error",i),t.removeEventListener("unhandledrejection",l),r==null||r.remove(),r=null}}}var O="gs:resize",y="--gs-vh";function V(e){let t=e.visualViewport;return t?{width:t.width,height:t.height}:{width:e.innerWidth,height:e.innerHeight}}function ie(e){return typeof e.requestAnimationFrame=="function"?t=>{e.requestAnimationFrame(()=>t())}:t=>{e.setTimeout(t,0)}}function E(e=window){let t=e.document.documentElement,n=ie(e),r=V(e),o=!1,i=!1;t.style.setProperty(y,`${r.height}px`);let l=()=>{o=!1;let s=V(e),g=s.width===r.width&&s.height===r.height;i||g||(r=s,t.style.setProperty(y,`${s.height}px`),e.dispatchEvent(new CustomEvent(O,{detail:s})))},d=()=>{o||(o=!0,n(l))},c=e.visualViewport;return c==null||c.addEventListener("resize",d),e.addEventListener("resize",d),e.addEventListener("orientationchange",d),{dispose:()=>{i=!0,c==null||c.removeEventListener("resize",d),e.removeEventListener("resize",d),e.removeEventListener("orientationchange",d)}}}var S=e=>`<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${e}</svg>`,u={download:S('<path d="M12 4v11M7 10l5 5 5-5M5 20h14"/>'),add:S('<path d="M12 5v14M5 12h14"/>'),close:S('<path d="M6 6l12 12M18 6L6 18"/>'),share:S('<path d="M12 15V4M8 8l4-4 4 4M6 12v8h12v-8"/>')};var z="gs-install-steps";function B(e){let t=a(e.doc,"ol","gs-steps");t.id=z;let n=a(e.doc,"li");n.append(x(e.doc,u.share),e.doc.createTextNode(e.labels.tapShare));let r=a(e.doc,"li");return r.append(x(e.doc,u.add),e.doc.createTextNode(e.labels.tapAdd)),t.append(n,r),t}function M(e){return f(e.doc,{className:"gs-x",ariaLabel:e.labels.notNow,icon:u.close,onClick:e.onDismiss})}function ae(e){let t=a(e.doc,"div","gs-seal");if(e.variant==="prompt")return t.append(f(e.doc,{className:"gs-chip",text:e.labels.install,icon:u.download,onClick:e.onInstall})),t.append(M(e)),[t];let n=B(e);n.hidden=!0;let r=f(e.doc,{className:"gs-chip",text:e.labels.addToHome,icon:u.add,onClick:()=>{n.hidden=!n.hidden,r.setAttribute("aria-expanded",String(!n.hidden))}});return r.setAttribute("aria-expanded","false"),r.setAttribute("aria-controls",z),t.append(r,M(e)),[t,n]}function le(e){let t=a(e.doc,"div","gs-card"),n=a(e.doc,"div","gs-app");n.append(a(e.doc,"i"));let r=a(e.doc,"div","gs-txt");r.append(a(e.doc,"b","",e.appName),a(e.doc,"span","",e.labels.installBody));let o=a(e.doc,"div","gs-acts");return e.variant==="prompt"&&o.append(f(e.doc,{className:"gs-btn gs-primary",text:e.labels.install,icon:u.download,onClick:e.onInstall})),o.append(f(e.doc,{className:"gs-btn gs-ghost",text:e.labels.notNow,onClick:e.onDismiss})),t.append(M(e),n,r),e.variant==="ios"&&t.append(B(e)),t.append(o),[t]}function K(e){let t=a(e.doc,"div","gs gs-install");return t.dataset.layout=e.layout,t.dataset.variant=e.variant,t.setAttribute("role","region"),t.setAttribute("aria-label",e.variant==="prompt"?e.labels.install:e.labels.addToHome),t.addEventListener("keydown",n=>{n.key==="Escape"&&e.onDismiss()}),t.append(...e.layout==="card"?le(e):ae(e)),t}var W=1024,de=/iPad|iPhone|iPod/,ce=/CriOS|FxiOS|EdgiOS|OPiOS/;function L(e){return typeof e.matchMedia=="function"&&e.matchMedia("(display-mode: standalone)").matches||e.navigator.standalone===!0}function I(e){let t=e.navigator.userAgent,n=t.includes("Macintosh")&&e.navigator.maxTouchPoints>1;return(de.test(t)||n)&&!ce.test(t)}function v(e){return e.innerWidth>=1024}function T(e,t){return t!=null?t:`gs-install-snooze:${e}`}function G(e,t,n,r){try{let o=e.localStorage.getItem(t);if(o===null)return!1;let i=Number(o);return Number.isFinite(i)&&r-i<n*864e5}catch(o){return!1}}function j(e,t,n){try{e.localStorage.setItem(t,String(n))}catch(r){}}var P=14,pe="accepted";function ge(e,t,n){let r=T(e.appName,e.storageKey),o={deferred:null,variant:null,node:null},i=()=>{var s;(s=o.node)==null||s.remove(),o.node=null},l=()=>{j(t,r,n()),i()},d=async()=>{let s=o.deferred;if(o.deferred=null,!!s)try{if(await s.prompt(),(await s.userChoice).outcome===pe){i();return}l()}catch(g){i()}};return{state:o,mount:()=>{o.variant!==null&&(i(),o.node=K({doc:t.document,layout:v(t)?"card":"chip",variant:o.variant,appName:e.appName,labels:e.labels,onInstall:()=>{d()},onDismiss:l}),t.document.body.append(o.node))},unmount:i}}function w(e){var c,s,g;let t=(c=e.win)!=null?c:window,n=(s=e.now)!=null?s:(()=>Date.now()),r=T(e.appName,e.storageKey);if(L(t)||G(t,r,(g=e.snoozeDays)!=null?g:P,n()))return{dispose:()=>{}};let o=ge(e,t,n),i=p=>{p.preventDefault(),o.state.deferred=p,o.state.variant="prompt",o.mount()},l=()=>{o.state.variant=null,o.unmount()},d=()=>{let p=o.state.node;p&&p.dataset.layout==="card"!==v(t)&&o.mount()};return t.addEventListener("beforeinstallprompt",i),t.addEventListener("appinstalled",l),t.addEventListener("resize",d),I(t)&&(o.state.variant="ios",o.mount()),{dispose:()=>{t.removeEventListener("beforeinstallprompt",i),t.removeEventListener("appinstalled",l),t.removeEventListener("resize",d),o.unmount()}}}var fe="(prefers-reduced-motion: reduce)",F=["pointerdown","keydown"];function C(e,t=document){let n=()=>{var r,o;if(t.visibilityState==="hidden"){(r=e.onHidden)==null||r.call(e);return}(o=e.onVisible)==null||o.call(e)};return t.addEventListener("visibilitychange",n),{dispose:()=>t.removeEventListener("visibilitychange",n)}}function U(e,t=window){let n=()=>{F.forEach(o=>t.removeEventListener(o,r,!0))};function r(){n();try{Promise.resolve(e.resume()).catch(()=>{})}catch(o){}}return F.forEach(o=>t.addEventListener(o,r,!0)),{dispose:n}}function $(e=window){return new URLSearchParams(e.location.search).get("reducedMotion")==="1"?!0:typeof e.matchMedia=="function"&&e.matchMedia(fe).matches}var Y="gs-styles",ue=":where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-card-bottom:60px;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}",me=".gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}",ve=`.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}
3
3
  .gs *{box-sizing:border-box}
4
4
  .gs button{min-width:44px;min-height:44px;margin:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}
5
5
  .gs button:focus-visible{outline:2px solid var(--gs-focus);outline-offset:2px}
@@ -12,7 +12,7 @@
12
12
  .gs-txt{min-width:0}
13
13
  .gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}
14
14
  .gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`,he=`.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}
15
- .gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(24px + var(--gs-safe-bottom))}
15
+ .gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(var(--gs-card-bottom,60px) + var(--gs-safe-bottom))}
16
16
  .gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}
17
17
  .gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}
18
18
  .gs-chip svg{color:var(--gs-accent)}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/crash/crashKind.ts","../src/dom.ts","../src/crash/crashOverlay.ts","../src/crash/crash.ts","../src/fit/fit.ts","../src/icons.ts","../src/install/banner.ts","../src/install/platform.ts","../src/install/snooze.ts","../src/install/install.ts","../src/lifecycle/lifecycle.ts","../src/styles.ts","../src/version/versionPoll.ts","../src/initGameShell.ts"],"sourcesContent":["export { initGameShell } from './initGameShell';\nexport type { GameShellOptions } from './initGameShell';\nexport { startFit, GS_RESIZE_EVENT, GS_VH_VAR } from './fit/fit';\nexport type { GsResizeDetail } from './fit/fit';\nexport { startInstall, DEFAULT_SNOOZE_DAYS } from './install/install';\nexport type { InstallOptions, BeforeInstallPromptEvent } from './install/install';\nexport { isStandalone, isIosSafari, isDesktop, DESKTOP_MIN_WIDTH } from './install/platform';\nexport { startCrash } from './crash/crash';\nexport type { CrashOptions } from './crash/crash';\nexport { CRASH_KIND } from './crash/crashKind';\nexport type { CrashInfo, CrashKind } from './crash/crashKind';\nexport { startLifecycle, unlockAudio, prefersReducedMotion } from './lifecycle/lifecycle';\nexport type { LifecycleOptions, ResumableAudio } from './lifecycle/lifecycle';\nexport { startVersionPoll } from './version/versionPoll';\nexport type { VersionPollOptions } from './version/versionPoll';\nexport { GAME_SHELL_CSS, injectStyles } from './styles';\nexport type { Disposable, GameShellLabels, InstallLabels, CrashLabels } from './types';\n","export const CRASH_KIND = {\n Error: 'error',\n Rejection: 'rejection',\n} as const;\n\nexport type CrashKind = (typeof CRASH_KIND)[keyof typeof CRASH_KIND];\n\nexport interface CrashInfo {\n kind: CrashKind;\n message: string;\n source?: string;\n}\n","export function el<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n className = '',\n text = '',\n): HTMLElementTagNameMap[K] {\n const node = doc.createElement(tag);\n if (className !== '') {\n node.className = className;\n }\n if (text !== '') {\n node.textContent = text;\n }\n return node;\n}\n\nexport function iconSpan(doc: Document, svg: string): HTMLSpanElement {\n const span = el(doc, 'span', 'gs-ico');\n span.innerHTML = svg;\n return span;\n}\n\nexport interface ButtonSpec {\n className: string;\n text?: string;\n ariaLabel?: string;\n icon?: string;\n onClick(): void;\n}\n\nexport function button(doc: Document, spec: ButtonSpec): HTMLButtonElement {\n const btn = el(doc, 'button', spec.className);\n btn.type = 'button';\n if (spec.icon !== undefined) {\n btn.append(iconSpan(doc, spec.icon));\n }\n if (spec.text !== undefined) {\n btn.append(doc.createTextNode(spec.text));\n }\n if (spec.ariaLabel !== undefined) {\n btn.setAttribute('aria-label', spec.ariaLabel);\n }\n btn.addEventListener('click', () => spec.onClick());\n return btn;\n}\n","import { button, el } from '../dom';\nimport type { CrashLabels } from '../types';\n\nexport const CRASH_TITLE_ID = 'gs-crash-title';\nconst CRASH_BODY_ID = 'gs-crash-body';\n\nexport interface CrashOverlayProps {\n doc: Document;\n labels: CrashLabels;\n reference?: string;\n onReload(): void;\n onCopy(): void;\n}\n\nexport interface CrashOverlayView {\n root: HTMLElement;\n reload: HTMLButtonElement;\n}\n\nexport function renderCrashOverlay(p: CrashOverlayProps): CrashOverlayView {\n const root = el(p.doc, 'div', 'gs gs-crash');\n root.setAttribute('role', 'alertdialog');\n root.setAttribute('aria-modal', 'true');\n root.setAttribute('aria-labelledby', CRASH_TITLE_ID);\n root.setAttribute('aria-describedby', CRASH_BODY_ID);\n const panel = el(p.doc, 'div', 'gs-panel');\n const title = el(p.doc, 'h2', 'gs-h', p.labels.crashTitle);\n title.id = CRASH_TITLE_ID;\n const body = el(p.doc, 'p', '', p.labels.crashBody);\n body.id = CRASH_BODY_ID;\n const acts = el(p.doc, 'div', 'gs-acts');\n const reload = button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.reload, onClick: p.onReload });\n acts.append(reload, button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.copyDetails, onClick: p.onCopy }));\n panel.append(title, body, acts);\n if (p.reference !== undefined && p.reference !== '') {\n panel.append(el(p.doc, 'p', 'gs-ref', `${p.labels.errorReported} ${p.reference}`));\n }\n root.append(panel);\n return { root, reload };\n}\n","import type { CrashLabels, Disposable } from '../types';\nimport { CRASH_KIND, type CrashInfo } from './crashKind';\nimport { renderCrashOverlay } from './crashOverlay';\n\nexport interface CrashOptions {\n labels: CrashLabels;\n report?: (info: CrashInfo) => string | void;\n appVersion?: string;\n win?: Window;\n reload?: () => void;\n}\n\nfunction fromErrorEvent(e: ErrorEvent): CrashInfo {\n const err: unknown = e.error;\n const stack = err instanceof Error ? err.stack : undefined;\n const location = e.filename !== '' ? `${e.filename}:${e.lineno}:${e.colno}` : undefined;\n const message = e.message !== '' ? e.message : String(err);\n return { kind: CRASH_KIND.Error, message, source: stack ?? location };\n}\n\nfunction fromRejection(e: Event): CrashInfo {\n const reason: unknown = (e as PromiseRejectionEvent).reason;\n if (reason instanceof Error) {\n return { kind: CRASH_KIND.Rejection, message: reason.message, source: reason.stack };\n }\n return { kind: CRASH_KIND.Rejection, message: String(reason) };\n}\n\nfunction safeReport(opts: CrashOptions, info: CrashInfo): string | undefined {\n try {\n return opts.report?.(info) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction copyDetails(win: Window, info: CrashInfo, appVersion?: string): void {\n const text = [info.message, info.source, appVersion]\n .filter((part): part is string => part !== undefined && part !== '')\n .join('\\n');\n try {\n win.navigator.clipboard.writeText(text).catch(() => undefined);\n } catch {\n // No clipboard API (insecure context): nothing to copy into.\n }\n}\n\nexport function startCrash(opts: CrashOptions): Disposable {\n const win = opts.win ?? window;\n const reload = opts.reload ?? ((): void => win.location.reload());\n let overlay: HTMLElement | null = null;\n\n const handle = (info: CrashInfo): void => {\n const reference = safeReport(opts, info);\n if (overlay) {\n return;\n }\n const view = renderCrashOverlay({\n doc: win.document,\n labels: opts.labels,\n reference,\n onReload: reload,\n onCopy: () => copyDetails(win, info, opts.appVersion),\n });\n overlay = view.root;\n win.document.body.append(overlay);\n view.reload.focus();\n };\n const onError = (e: Event): void => {\n if (e instanceof ErrorEvent) {\n handle(fromErrorEvent(e));\n }\n };\n const onRejection = (e: Event): void => handle(fromRejection(e));\n\n win.addEventListener('error', onError);\n win.addEventListener('unhandledrejection', onRejection);\n return {\n dispose: (): void => {\n win.removeEventListener('error', onError);\n win.removeEventListener('unhandledrejection', onRejection);\n overlay?.remove();\n overlay = null;\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport const GS_RESIZE_EVENT = 'gs:resize';\nexport const GS_VH_VAR = '--gs-vh';\n\nexport interface GsResizeDetail {\n width: number;\n height: number;\n}\n\nfunction measure(win: Window): GsResizeDetail {\n const vv = win.visualViewport;\n if (vv) {\n return { width: vv.width, height: vv.height };\n }\n return { width: win.innerWidth, height: win.innerHeight };\n}\n\nfunction scheduler(win: Window): (cb: () => void) => void {\n if (typeof win.requestAnimationFrame === 'function') {\n return (cb) => {\n win.requestAnimationFrame(() => cb());\n };\n }\n return (cb) => {\n win.setTimeout(cb, 0);\n };\n}\n\nexport function startFit(win: Window = window): Disposable {\n const root = win.document.documentElement;\n const schedule = scheduler(win);\n let last = measure(win);\n let pending = false;\n let disposed = false;\n root.style.setProperty(GS_VH_VAR, `${last.height}px`);\n\n const apply = (): void => {\n pending = false;\n const next = measure(win);\n const unchanged = next.width === last.width && next.height === last.height;\n if (disposed || unchanged) {\n return;\n }\n last = next;\n root.style.setProperty(GS_VH_VAR, `${next.height}px`);\n win.dispatchEvent(new CustomEvent<GsResizeDetail>(GS_RESIZE_EVENT, { detail: next }));\n };\n const onChange = (): void => {\n if (pending) {\n return;\n }\n pending = true;\n schedule(apply);\n };\n\n const vv = win.visualViewport;\n vv?.addEventListener('resize', onChange);\n win.addEventListener('resize', onChange);\n win.addEventListener('orientationchange', onChange);\n return {\n dispose: (): void => {\n disposed = true;\n vv?.removeEventListener('resize', onChange);\n win.removeEventListener('resize', onChange);\n win.removeEventListener('orientationchange', onChange);\n },\n };\n}\n","const svg = (paths: string): string =>\n `<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n\nexport const ICONS = {\n download: svg('<path d=\"M12 4v11M7 10l5 5 5-5M5 20h14\"/>'),\n add: svg('<path d=\"M12 5v14M5 12h14\"/>'),\n close: svg('<path d=\"M6 6l12 12M18 6L6 18\"/>'),\n share: svg('<path d=\"M12 15V4M8 8l4-4 4 4M6 12v8h12v-8\"/>'),\n} as const;\n","import { button, el, iconSpan } from '../dom';\nimport { ICONS } from '../icons';\nimport type { InstallLabels } from '../types';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\n\nexport const STEPS_ID = 'gs-install-steps';\n\nexport interface BannerProps {\n doc: Document;\n layout: BannerLayout;\n variant: InstallVariant;\n appName: string;\n labels: InstallLabels;\n onInstall(): void;\n onDismiss(): void;\n}\n\nfunction renderSteps(p: BannerProps): HTMLOListElement {\n const list = el(p.doc, 'ol', 'gs-steps');\n list.id = STEPS_ID;\n const share = el(p.doc, 'li');\n share.append(iconSpan(p.doc, ICONS.share), p.doc.createTextNode(p.labels.tapShare));\n const add = el(p.doc, 'li');\n add.append(iconSpan(p.doc, ICONS.add), p.doc.createTextNode(p.labels.tapAdd));\n list.append(share, add);\n return list;\n}\n\nfunction closeButton(p: BannerProps): HTMLButtonElement {\n return button(p.doc, { className: 'gs-x', ariaLabel: p.labels.notNow, icon: ICONS.close, onClick: p.onDismiss });\n}\n\nfunction renderChip(p: BannerProps): HTMLElement[] {\n const seal = el(p.doc, 'div', 'gs-seal');\n if (p.variant === InstallVariant.Prompt) {\n seal.append(button(p.doc, { className: 'gs-chip', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n seal.append(closeButton(p));\n return [seal];\n }\n const steps = renderSteps(p);\n steps.hidden = true;\n const chip = button(p.doc, {\n className: 'gs-chip',\n text: p.labels.addToHome,\n icon: ICONS.add,\n onClick: () => {\n steps.hidden = !steps.hidden;\n chip.setAttribute('aria-expanded', String(!steps.hidden));\n },\n });\n chip.setAttribute('aria-expanded', 'false');\n chip.setAttribute('aria-controls', STEPS_ID);\n seal.append(chip, closeButton(p));\n return [seal, steps];\n}\n\nfunction renderCard(p: BannerProps): HTMLElement[] {\n const card = el(p.doc, 'div', 'gs-card');\n const app = el(p.doc, 'div', 'gs-app');\n app.append(el(p.doc, 'i'));\n const txt = el(p.doc, 'div', 'gs-txt');\n txt.append(el(p.doc, 'b', '', p.appName), el(p.doc, 'span', '', p.labels.installBody));\n const acts = el(p.doc, 'div', 'gs-acts');\n if (p.variant === InstallVariant.Prompt) {\n acts.append(button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n }\n acts.append(button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.notNow, onClick: p.onDismiss }));\n card.append(closeButton(p), app, txt);\n if (p.variant === InstallVariant.Ios) {\n card.append(renderSteps(p));\n }\n card.append(acts);\n return [card];\n}\n\nexport function renderBanner(p: BannerProps): HTMLElement {\n const wrap = el(p.doc, 'div', 'gs gs-install');\n wrap.dataset.layout = p.layout;\n wrap.dataset.variant = p.variant;\n wrap.setAttribute('role', 'region');\n wrap.setAttribute('aria-label', p.variant === InstallVariant.Prompt ? p.labels.install : p.labels.addToHome);\n wrap.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n p.onDismiss();\n }\n });\n wrap.append(...(p.layout === BannerLayout.Card ? renderCard(p) : renderChip(p)));\n return wrap;\n}\n","export const DESKTOP_MIN_WIDTH = 1024;\nconst IOS_DEVICE_RE = /iPad|iPhone|iPod/;\nconst IOS_OTHER_BROWSER_RE = /CriOS|FxiOS|EdgiOS|OPiOS/;\n\ninterface IosNavigator extends Navigator {\n standalone?: boolean;\n}\n\nexport function isStandalone(win: Window): boolean {\n const media = typeof win.matchMedia === 'function' && win.matchMedia('(display-mode: standalone)').matches;\n return media || (win.navigator as IosNavigator).standalone === true;\n}\n\nexport function isIosSafari(win: Window): boolean {\n const ua = win.navigator.userAgent;\n const iPadAsMac = ua.includes('Macintosh') && win.navigator.maxTouchPoints > 1;\n const iosDevice = IOS_DEVICE_RE.test(ua) || iPadAsMac;\n return iosDevice && !IOS_OTHER_BROWSER_RE.test(ua);\n}\n\nexport function isDesktop(win: Window): boolean {\n return win.innerWidth >= DESKTOP_MIN_WIDTH;\n}\n","const DAY_MS = 86_400_000;\n\nexport function snoozeKey(appName: string, override?: string): string {\n return override ?? `gs-install-snooze:${appName}`;\n}\n\nexport function isSnoozed(win: Window, key: string, days: number, now: number): boolean {\n try {\n const raw = win.localStorage.getItem(key);\n if (raw === null) {\n return false;\n }\n const at = Number(raw);\n return Number.isFinite(at) && now - at < days * DAY_MS;\n } catch {\n return false;\n }\n}\n\nexport function writeSnooze(win: Window, key: string, now: number): void {\n try {\n win.localStorage.setItem(key, String(now));\n } catch {\n // Storage blocked (private mode, quota): the banner simply shows again next load.\n }\n}\n","import type { Disposable, InstallLabels } from '../types';\nimport { renderBanner } from './banner';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\nimport { isDesktop, isIosSafari, isStandalone } from './platform';\nimport { isSnoozed, snoozeKey, writeSnooze } from './snooze';\n\nexport const DEFAULT_SNOOZE_DAYS = 14;\nconst ACCEPTED = 'accepted';\n\nexport interface BeforeInstallPromptEvent extends Event {\n prompt(): Promise<void>;\n userChoice: Promise<{ outcome: string }>;\n}\n\nexport interface InstallOptions {\n appName: string;\n labels: InstallLabels;\n snoozeDays?: number;\n storageKey?: string;\n win?: Window;\n now?: () => number;\n}\n\ninterface InstallState {\n deferred: BeforeInstallPromptEvent | null;\n variant: InstallVariant | null;\n node: HTMLElement | null;\n}\n\nfunction createController(opts: InstallOptions, win: Window, now: () => number): {\n state: InstallState;\n mount(): void;\n unmount(): void;\n} {\n const key = snoozeKey(opts.appName, opts.storageKey);\n const state: InstallState = { deferred: null, variant: null, node: null };\n const unmount = (): void => {\n state.node?.remove();\n state.node = null;\n };\n const dismiss = (): void => {\n writeSnooze(win, key, now());\n unmount();\n };\n const install = async (): Promise<void> => {\n const evt = state.deferred;\n state.deferred = null;\n if (!evt) {\n return;\n }\n try {\n await evt.prompt();\n const choice = await evt.userChoice;\n if (choice.outcome === ACCEPTED) {\n unmount();\n return;\n }\n dismiss();\n } catch {\n unmount();\n }\n };\n const mount = (): void => {\n if (state.variant === null) {\n return;\n }\n unmount();\n state.node = renderBanner({\n doc: win.document,\n layout: isDesktop(win) ? BannerLayout.Card : BannerLayout.Chip,\n variant: state.variant,\n appName: opts.appName,\n labels: opts.labels,\n onInstall: () => void install(),\n onDismiss: dismiss,\n });\n win.document.body.append(state.node);\n };\n return { state, mount, unmount };\n}\n\nexport function startInstall(opts: InstallOptions): Disposable {\n const win = opts.win ?? window;\n const now = opts.now ?? ((): number => Date.now());\n const key = snoozeKey(opts.appName, opts.storageKey);\n if (isStandalone(win) || isSnoozed(win, key, opts.snoozeDays ?? DEFAULT_SNOOZE_DAYS, now())) {\n return { dispose: (): void => undefined };\n }\n const ctl = createController(opts, win, now);\n const onPrompt = (e: Event): void => {\n e.preventDefault();\n ctl.state.deferred = e as BeforeInstallPromptEvent;\n ctl.state.variant = InstallVariant.Prompt;\n ctl.mount();\n };\n const onInstalled = (): void => {\n ctl.state.variant = null;\n ctl.unmount();\n };\n const onResize = (): void => {\n const node = ctl.state.node;\n if (node && (node.dataset.layout === BannerLayout.Card) !== isDesktop(win)) {\n ctl.mount();\n }\n };\n win.addEventListener('beforeinstallprompt', onPrompt);\n win.addEventListener('appinstalled', onInstalled);\n win.addEventListener('resize', onResize);\n if (isIosSafari(win)) {\n ctl.state.variant = InstallVariant.Ios;\n ctl.mount();\n }\n return {\n dispose: (): void => {\n win.removeEventListener('beforeinstallprompt', onPrompt);\n win.removeEventListener('appinstalled', onInstalled);\n win.removeEventListener('resize', onResize);\n ctl.unmount();\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport interface LifecycleOptions {\n onHidden?(): void;\n onVisible?(): void;\n}\n\nexport interface ResumableAudio {\n resume(): Promise<void> | void;\n}\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\nconst UNLOCK_EVENTS = ['pointerdown', 'keydown'] as const;\n\nexport function startLifecycle(opts: LifecycleOptions, doc: Document = document): Disposable {\n const onChange = (): void => {\n if (doc.visibilityState === 'hidden') {\n opts.onHidden?.();\n return;\n }\n opts.onVisible?.();\n };\n doc.addEventListener('visibilitychange', onChange);\n return { dispose: (): void => doc.removeEventListener('visibilitychange', onChange) };\n}\n\nexport function unlockAudio(ctx: ResumableAudio, win: Window = window): Disposable {\n const detach = (): void => {\n UNLOCK_EVENTS.forEach((type) => win.removeEventListener(type, onFirst, true));\n };\n function onFirst(): void {\n detach();\n try {\n Promise.resolve(ctx.resume()).catch(() => undefined);\n } catch {\n // A browser that refuses resume() leaves the game silent, never crashed.\n }\n }\n UNLOCK_EVENTS.forEach((type) => win.addEventListener(type, onFirst, true));\n return { dispose: detach };\n}\n\nexport function prefersReducedMotion(win: Window = window): boolean {\n if (new URLSearchParams(win.location.search).get('reducedMotion') === '1') {\n return true;\n }\n return typeof win.matchMedia === 'function' && win.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n","const STYLE_ID = 'gs-styles';\n\nconst THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;\n\nconst ROOT = `.gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}`;\n\nconst BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}\n.gs *{box-sizing:border-box}\n.gs button{min-width:44px;min-height:44px;margin:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}\n.gs button:focus-visible{outline:2px solid var(--gs-focus);outline-offset:2px}\n.gs svg{width:20px;height:20px;flex:none}\n.gs-ico{display:inline-flex}\n.gs-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 18px;border-radius:var(--gs-radius);font:700 16px/1 var(--gs-font-text);white-space:nowrap}\n.gs-primary{background:var(--gs-accent);color:var(--gs-on-accent)}\n.gs .gs-ghost{color:var(--gs-ink);border:1px solid var(--gs-edge)}\n.gs-x{width:44px;height:44px;display:grid;place-items:center;color:var(--gs-ink-dim);flex:none}\n.gs-txt{min-width:0}\n.gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}\n.gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`;\n\nconst INSTALL = `.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}\n.gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(24px + var(--gs-safe-bottom))}\n.gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}\n.gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}\n.gs-chip svg{color:var(--gs-accent)}\n.gs-seal .gs-x{border-left:1px solid var(--gs-edge)}\n.gs-steps{margin:8px 0 0;width:262px;padding:10px 14px;list-style:none;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);display:grid;gap:2px;counter-reset:s}\n.gs-steps[hidden]{display:none}\n.gs-steps li{display:flex;align-items:center;gap:10px;min-height:36px;font-size:15px;color:var(--gs-ink);counter-increment:s}\n.gs-steps li::before{content:counter(s);font:400 15px var(--gs-font-display);color:var(--gs-ink-dim);width:12px}\n.gs-steps svg{width:17px;height:17px;color:var(--gs-accent)}\n.gs-card{position:relative;width:344px;max-width:calc(100vw - 48px);padding:18px;border-radius:var(--gs-radius);background:var(--gs-surface);border:1px solid var(--gs-edge);display:grid;gap:12px}\n.gs-card .gs-x{position:absolute;top:4px;right:4px}\n.gs-card .gs-txt{padding-right:36px}\n.gs-card .gs-acts{display:flex;gap:8px}\n.gs-card .gs-steps{width:auto;margin:0;border:0;padding:0;background:none}\n.gs-app{width:40px;height:40px;border-radius:var(--gs-radius);background:var(--gs-surface-solid);border:1px solid var(--gs-edge);display:grid;place-items:center}\n.gs-app i{width:13px;height:13px;border-radius:50%;background:var(--gs-accent);box-shadow:0 0 10px var(--gs-accent)}`;\n\nconst CRASH = `.gs-crash{position:fixed;inset:0;z-index:2147483001;background:var(--gs-scrim);display:grid;place-items:center;padding:20px}\n.gs-panel{max-width:340px;background:var(--gs-surface-solid);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);padding:24px}\n.gs-h{margin:0;font:400 28px/1.15 var(--gs-font-display);color:var(--gs-ink)}\n.gs-panel p{font-size:16px;line-height:1.5;color:var(--gs-ink-dim);margin:10px 0 0}\n.gs-panel .gs-acts{display:flex;flex-direction:column;gap:8px;margin-top:20px}\n.gs-panel .gs-ref{font:13px ui-monospace,monospace}\n@media (min-width:1024px){.gs-panel{max-width:460px;padding:32px}.gs-panel .gs-acts{flex-direction:row}}`;\n\nexport const GAME_SHELL_CSS = [THEME, ROOT, BASE, INSTALL, CRASH].join('\\n');\n\nexport function injectStyles(doc: Document = document): void {\n if (doc.getElementById(STYLE_ID)) {\n return;\n }\n const style = doc.createElement('style');\n style.id = STYLE_ID;\n style.textContent = GAME_SHELL_CSS;\n doc.head.append(style);\n}\n","import type { Disposable } from '../types';\n\nexport interface VersionPollOptions {\n url: string;\n intervalMs: number;\n onNewVersion(): void;\n fetchFn?: typeof fetch;\n win?: Window;\n}\n\nexport function startVersionPoll(opts: VersionPollOptions): Disposable {\n const win = opts.win ?? window;\n const fetchFn = opts.fetchFn ?? ((input: RequestInfo | URL, init?: RequestInit): Promise<Response> => win.fetch(input, init));\n let baseline: string | null = null;\n let fired = false;\n let busy = false;\n\n const check = async (): Promise<void> => {\n if (fired || busy) {\n return;\n }\n busy = true;\n try {\n const res = await fetchFn(opts.url, { cache: 'no-store' });\n if (!res.ok) {\n return;\n }\n const value = (await res.text()).trim();\n if (baseline === null) {\n baseline = value;\n } else if (value !== baseline) {\n fired = true;\n opts.onNewVersion();\n }\n } catch {\n // Offline or a deploy mid-flight: the next tick tries again.\n } finally {\n busy = false;\n }\n };\n const onVisibility = (): void => {\n if (win.document.visibilityState === 'visible') {\n void check();\n }\n };\n\n void check();\n const timer = win.setInterval(() => void check(), opts.intervalMs);\n win.document.addEventListener('visibilitychange', onVisibility);\n return {\n dispose: (): void => {\n win.clearInterval(timer);\n win.document.removeEventListener('visibilitychange', onVisibility);\n },\n };\n}\n","import { startCrash } from './crash/crash';\nimport type { CrashInfo } from './crash/crashKind';\nimport { startFit } from './fit/fit';\nimport { startInstall } from './install/install';\nimport { startLifecycle, type LifecycleOptions } from './lifecycle/lifecycle';\nimport { injectStyles } from './styles';\nimport type { Disposable, GameShellLabels } from './types';\nimport { startVersionPoll } from './version/versionPoll';\n\nexport interface GameShellOptions {\n root: HTMLElement;\n appName: string;\n labels: GameShellLabels;\n appVersion?: string;\n install?: { snoozeDays?: number; storageKey?: string } | false;\n version?: { url: string; intervalMs: number; onNewVersion(): void };\n crash?: { report?(info: CrashInfo): string | void } | false;\n lifecycle?: LifecycleOptions;\n}\n\nexport function initGameShell(opts: GameShellOptions): Disposable {\n const doc = opts.root.ownerDocument;\n injectStyles(doc);\n opts.root.classList.add('gs-root');\n const parts: Disposable[] = [startFit()];\n if (opts.install !== false) {\n parts.push(startInstall({ appName: opts.appName, labels: opts.labels, ...opts.install }));\n }\n if (opts.crash !== false) {\n parts.push(startCrash({ labels: opts.labels, report: opts.crash?.report, appVersion: opts.appVersion }));\n }\n if (opts.lifecycle) {\n parts.push(startLifecycle(opts.lifecycle, doc));\n }\n if (opts.version) {\n parts.push(startVersionPoll(opts.version));\n }\n return {\n dispose: (): void => {\n parts.forEach((part) => part.dispose());\n opts.root.classList.remove('gs-root');\n },\n };\n}\n"],"mappings":"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","names":["src_exports","__export","CRASH_KIND","DEFAULT_SNOOZE_DAYS","DESKTOP_MIN_WIDTH","GAME_SHELL_CSS","GS_RESIZE_EVENT","GS_VH_VAR","initGameShell","injectStyles","isDesktop","isIosSafari","isStandalone","prefersReducedMotion","startCrash","startFit","startInstall","startLifecycle","startVersionPoll","unlockAudio","CRASH_KIND","el","doc","tag","className","text","node","iconSpan","svg","span","button","spec","btn","CRASH_TITLE_ID","CRASH_BODY_ID","renderCrashOverlay","p","root","el","panel","title","body","acts","reload","button","fromErrorEvent","err","stack","location","message","CRASH_KIND","fromRejection","reason","safeReport","opts","info","_a","_b","e","copyDetails","win","appVersion","text","part","startCrash","reload","overlay","handle","reference","view","renderCrashOverlay","onError","onRejection","GS_RESIZE_EVENT","GS_VH_VAR","measure","win","vv","scheduler","cb","startFit","root","schedule","last","pending","disposed","apply","next","unchanged","onChange","svg","paths","ICONS","STEPS_ID","renderSteps","p","list","el","share","iconSpan","ICONS","add","closeButton","button","renderChip","seal","steps","chip","renderCard","card","app","txt","acts","renderBanner","wrap","e","DESKTOP_MIN_WIDTH","IOS_DEVICE_RE","IOS_OTHER_BROWSER_RE","isStandalone","win","isIosSafari","ua","iPadAsMac","isDesktop","snoozeKey","appName","override","isSnoozed","win","key","days","now","raw","at","e","writeSnooze","DEFAULT_SNOOZE_DAYS","ACCEPTED","createController","opts","win","now","key","snoozeKey","state","unmount","_a","dismiss","writeSnooze","install","evt","e","renderBanner","isDesktop","startInstall","_b","_c","isStandalone","isSnoozed","ctl","onPrompt","onInstalled","onResize","node","isIosSafari","REDUCED_MOTION_QUERY","UNLOCK_EVENTS","startLifecycle","opts","doc","onChange","_a","_b","unlockAudio","ctx","win","detach","type","onFirst","e","prefersReducedMotion","STYLE_ID","THEME","ROOT","BASE","INSTALL","CRASH","GAME_SHELL_CSS","injectStyles","doc","style","startVersionPoll","opts","_a","_b","win","fetchFn","input","init","baseline","fired","busy","check","res","value","e","onVisibility","timer","initGameShell","opts","_a","doc","injectStyles","parts","startFit","startInstall","startCrash","startLifecycle","startVersionPoll","part"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/crash/crashKind.ts","../src/dom.ts","../src/crash/crashOverlay.ts","../src/crash/crash.ts","../src/fit/fit.ts","../src/icons.ts","../src/install/banner.ts","../src/install/platform.ts","../src/install/snooze.ts","../src/install/install.ts","../src/lifecycle/lifecycle.ts","../src/styles.ts","../src/version/versionPoll.ts","../src/initGameShell.ts"],"sourcesContent":["export { initGameShell } from './initGameShell';\nexport type { GameShellOptions } from './initGameShell';\nexport { startFit, GS_RESIZE_EVENT, GS_VH_VAR } from './fit/fit';\nexport type { GsResizeDetail } from './fit/fit';\nexport { startInstall, DEFAULT_SNOOZE_DAYS } from './install/install';\nexport type { InstallOptions, BeforeInstallPromptEvent } from './install/install';\nexport { isStandalone, isIosSafari, isDesktop, DESKTOP_MIN_WIDTH } from './install/platform';\nexport { startCrash } from './crash/crash';\nexport type { CrashOptions } from './crash/crash';\nexport { CRASH_KIND } from './crash/crashKind';\nexport type { CrashInfo, CrashKind } from './crash/crashKind';\nexport { startLifecycle, unlockAudio, prefersReducedMotion } from './lifecycle/lifecycle';\nexport type { LifecycleOptions, ResumableAudio } from './lifecycle/lifecycle';\nexport { startVersionPoll } from './version/versionPoll';\nexport type { VersionPollOptions } from './version/versionPoll';\nexport { GAME_SHELL_CSS, injectStyles } from './styles';\nexport type { Disposable, GameShellLabels, InstallLabels, CrashLabels } from './types';\n","export const CRASH_KIND = {\n Error: 'error',\n Rejection: 'rejection',\n} as const;\n\nexport type CrashKind = (typeof CRASH_KIND)[keyof typeof CRASH_KIND];\n\nexport interface CrashInfo {\n kind: CrashKind;\n message: string;\n source?: string;\n}\n","export function el<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n className = '',\n text = '',\n): HTMLElementTagNameMap[K] {\n const node = doc.createElement(tag);\n if (className !== '') {\n node.className = className;\n }\n if (text !== '') {\n node.textContent = text;\n }\n return node;\n}\n\nexport function iconSpan(doc: Document, svg: string): HTMLSpanElement {\n const span = el(doc, 'span', 'gs-ico');\n span.innerHTML = svg;\n return span;\n}\n\nexport interface ButtonSpec {\n className: string;\n text?: string;\n ariaLabel?: string;\n icon?: string;\n onClick(): void;\n}\n\nexport function button(doc: Document, spec: ButtonSpec): HTMLButtonElement {\n const btn = el(doc, 'button', spec.className);\n btn.type = 'button';\n if (spec.icon !== undefined) {\n btn.append(iconSpan(doc, spec.icon));\n }\n if (spec.text !== undefined) {\n btn.append(doc.createTextNode(spec.text));\n }\n if (spec.ariaLabel !== undefined) {\n btn.setAttribute('aria-label', spec.ariaLabel);\n }\n btn.addEventListener('click', () => spec.onClick());\n return btn;\n}\n","import { button, el } from '../dom';\nimport type { CrashLabels } from '../types';\n\nexport const CRASH_TITLE_ID = 'gs-crash-title';\nconst CRASH_BODY_ID = 'gs-crash-body';\n\nexport interface CrashOverlayProps {\n doc: Document;\n labels: CrashLabels;\n reference?: string;\n onReload(): void;\n onCopy(): void;\n}\n\nexport interface CrashOverlayView {\n root: HTMLElement;\n reload: HTMLButtonElement;\n}\n\nexport function renderCrashOverlay(p: CrashOverlayProps): CrashOverlayView {\n const root = el(p.doc, 'div', 'gs gs-crash');\n root.setAttribute('role', 'alertdialog');\n root.setAttribute('aria-modal', 'true');\n root.setAttribute('aria-labelledby', CRASH_TITLE_ID);\n root.setAttribute('aria-describedby', CRASH_BODY_ID);\n const panel = el(p.doc, 'div', 'gs-panel');\n const title = el(p.doc, 'h2', 'gs-h', p.labels.crashTitle);\n title.id = CRASH_TITLE_ID;\n const body = el(p.doc, 'p', '', p.labels.crashBody);\n body.id = CRASH_BODY_ID;\n const acts = el(p.doc, 'div', 'gs-acts');\n const reload = button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.reload, onClick: p.onReload });\n acts.append(reload, button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.copyDetails, onClick: p.onCopy }));\n panel.append(title, body, acts);\n if (p.reference !== undefined && p.reference !== '') {\n panel.append(el(p.doc, 'p', 'gs-ref', `${p.labels.errorReported} ${p.reference}`));\n }\n root.append(panel);\n return { root, reload };\n}\n","import type { CrashLabels, Disposable } from '../types';\nimport { CRASH_KIND, type CrashInfo } from './crashKind';\nimport { renderCrashOverlay } from './crashOverlay';\n\nexport interface CrashOptions {\n labels: CrashLabels;\n report?: (info: CrashInfo) => string | void;\n appVersion?: string;\n win?: Window;\n reload?: () => void;\n}\n\nfunction fromErrorEvent(e: ErrorEvent): CrashInfo {\n const err: unknown = e.error;\n const stack = err instanceof Error ? err.stack : undefined;\n const location = e.filename !== '' ? `${e.filename}:${e.lineno}:${e.colno}` : undefined;\n const message = e.message !== '' ? e.message : String(err);\n return { kind: CRASH_KIND.Error, message, source: stack ?? location };\n}\n\nfunction fromRejection(e: Event): CrashInfo {\n const reason: unknown = (e as PromiseRejectionEvent).reason;\n if (reason instanceof Error) {\n return { kind: CRASH_KIND.Rejection, message: reason.message, source: reason.stack };\n }\n return { kind: CRASH_KIND.Rejection, message: String(reason) };\n}\n\nfunction safeReport(opts: CrashOptions, info: CrashInfo): string | undefined {\n try {\n return opts.report?.(info) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction copyDetails(win: Window, info: CrashInfo, appVersion?: string): void {\n const text = [info.message, info.source, appVersion]\n .filter((part): part is string => part !== undefined && part !== '')\n .join('\\n');\n try {\n win.navigator.clipboard.writeText(text).catch(() => undefined);\n } catch {\n // No clipboard API (insecure context): nothing to copy into.\n }\n}\n\nexport function startCrash(opts: CrashOptions): Disposable {\n const win = opts.win ?? window;\n const reload = opts.reload ?? ((): void => win.location.reload());\n let overlay: HTMLElement | null = null;\n\n const handle = (info: CrashInfo): void => {\n const reference = safeReport(opts, info);\n if (overlay) {\n return;\n }\n const view = renderCrashOverlay({\n doc: win.document,\n labels: opts.labels,\n reference,\n onReload: reload,\n onCopy: () => copyDetails(win, info, opts.appVersion),\n });\n overlay = view.root;\n win.document.body.append(overlay);\n view.reload.focus();\n };\n const onError = (e: Event): void => {\n if (e instanceof ErrorEvent) {\n handle(fromErrorEvent(e));\n }\n };\n const onRejection = (e: Event): void => handle(fromRejection(e));\n\n win.addEventListener('error', onError);\n win.addEventListener('unhandledrejection', onRejection);\n return {\n dispose: (): void => {\n win.removeEventListener('error', onError);\n win.removeEventListener('unhandledrejection', onRejection);\n overlay?.remove();\n overlay = null;\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport const GS_RESIZE_EVENT = 'gs:resize';\nexport const GS_VH_VAR = '--gs-vh';\n\nexport interface GsResizeDetail {\n width: number;\n height: number;\n}\n\nfunction measure(win: Window): GsResizeDetail {\n const vv = win.visualViewport;\n if (vv) {\n return { width: vv.width, height: vv.height };\n }\n return { width: win.innerWidth, height: win.innerHeight };\n}\n\nfunction scheduler(win: Window): (cb: () => void) => void {\n if (typeof win.requestAnimationFrame === 'function') {\n return (cb) => {\n win.requestAnimationFrame(() => cb());\n };\n }\n return (cb) => {\n win.setTimeout(cb, 0);\n };\n}\n\nexport function startFit(win: Window = window): Disposable {\n const root = win.document.documentElement;\n const schedule = scheduler(win);\n let last = measure(win);\n let pending = false;\n let disposed = false;\n root.style.setProperty(GS_VH_VAR, `${last.height}px`);\n\n const apply = (): void => {\n pending = false;\n const next = measure(win);\n const unchanged = next.width === last.width && next.height === last.height;\n if (disposed || unchanged) {\n return;\n }\n last = next;\n root.style.setProperty(GS_VH_VAR, `${next.height}px`);\n win.dispatchEvent(new CustomEvent<GsResizeDetail>(GS_RESIZE_EVENT, { detail: next }));\n };\n const onChange = (): void => {\n if (pending) {\n return;\n }\n pending = true;\n schedule(apply);\n };\n\n const vv = win.visualViewport;\n vv?.addEventListener('resize', onChange);\n win.addEventListener('resize', onChange);\n win.addEventListener('orientationchange', onChange);\n return {\n dispose: (): void => {\n disposed = true;\n vv?.removeEventListener('resize', onChange);\n win.removeEventListener('resize', onChange);\n win.removeEventListener('orientationchange', onChange);\n },\n };\n}\n","const svg = (paths: string): string =>\n `<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n\nexport const ICONS = {\n download: svg('<path d=\"M12 4v11M7 10l5 5 5-5M5 20h14\"/>'),\n add: svg('<path d=\"M12 5v14M5 12h14\"/>'),\n close: svg('<path d=\"M6 6l12 12M18 6L6 18\"/>'),\n share: svg('<path d=\"M12 15V4M8 8l4-4 4 4M6 12v8h12v-8\"/>'),\n} as const;\n","import { button, el, iconSpan } from '../dom';\nimport { ICONS } from '../icons';\nimport type { InstallLabels } from '../types';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\n\nexport const STEPS_ID = 'gs-install-steps';\n\nexport interface BannerProps {\n doc: Document;\n layout: BannerLayout;\n variant: InstallVariant;\n appName: string;\n labels: InstallLabels;\n onInstall(): void;\n onDismiss(): void;\n}\n\nfunction renderSteps(p: BannerProps): HTMLOListElement {\n const list = el(p.doc, 'ol', 'gs-steps');\n list.id = STEPS_ID;\n const share = el(p.doc, 'li');\n share.append(iconSpan(p.doc, ICONS.share), p.doc.createTextNode(p.labels.tapShare));\n const add = el(p.doc, 'li');\n add.append(iconSpan(p.doc, ICONS.add), p.doc.createTextNode(p.labels.tapAdd));\n list.append(share, add);\n return list;\n}\n\nfunction closeButton(p: BannerProps): HTMLButtonElement {\n return button(p.doc, { className: 'gs-x', ariaLabel: p.labels.notNow, icon: ICONS.close, onClick: p.onDismiss });\n}\n\nfunction renderChip(p: BannerProps): HTMLElement[] {\n const seal = el(p.doc, 'div', 'gs-seal');\n if (p.variant === InstallVariant.Prompt) {\n seal.append(button(p.doc, { className: 'gs-chip', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n seal.append(closeButton(p));\n return [seal];\n }\n const steps = renderSteps(p);\n steps.hidden = true;\n const chip = button(p.doc, {\n className: 'gs-chip',\n text: p.labels.addToHome,\n icon: ICONS.add,\n onClick: () => {\n steps.hidden = !steps.hidden;\n chip.setAttribute('aria-expanded', String(!steps.hidden));\n },\n });\n chip.setAttribute('aria-expanded', 'false');\n chip.setAttribute('aria-controls', STEPS_ID);\n seal.append(chip, closeButton(p));\n return [seal, steps];\n}\n\nfunction renderCard(p: BannerProps): HTMLElement[] {\n const card = el(p.doc, 'div', 'gs-card');\n const app = el(p.doc, 'div', 'gs-app');\n app.append(el(p.doc, 'i'));\n const txt = el(p.doc, 'div', 'gs-txt');\n txt.append(el(p.doc, 'b', '', p.appName), el(p.doc, 'span', '', p.labels.installBody));\n const acts = el(p.doc, 'div', 'gs-acts');\n if (p.variant === InstallVariant.Prompt) {\n acts.append(button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n }\n acts.append(button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.notNow, onClick: p.onDismiss }));\n card.append(closeButton(p), app, txt);\n if (p.variant === InstallVariant.Ios) {\n card.append(renderSteps(p));\n }\n card.append(acts);\n return [card];\n}\n\nexport function renderBanner(p: BannerProps): HTMLElement {\n const wrap = el(p.doc, 'div', 'gs gs-install');\n wrap.dataset.layout = p.layout;\n wrap.dataset.variant = p.variant;\n wrap.setAttribute('role', 'region');\n wrap.setAttribute('aria-label', p.variant === InstallVariant.Prompt ? p.labels.install : p.labels.addToHome);\n wrap.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n p.onDismiss();\n }\n });\n wrap.append(...(p.layout === BannerLayout.Card ? renderCard(p) : renderChip(p)));\n return wrap;\n}\n","export const DESKTOP_MIN_WIDTH = 1024;\nconst IOS_DEVICE_RE = /iPad|iPhone|iPod/;\nconst IOS_OTHER_BROWSER_RE = /CriOS|FxiOS|EdgiOS|OPiOS/;\n\ninterface IosNavigator extends Navigator {\n standalone?: boolean;\n}\n\nexport function isStandalone(win: Window): boolean {\n const media = typeof win.matchMedia === 'function' && win.matchMedia('(display-mode: standalone)').matches;\n return media || (win.navigator as IosNavigator).standalone === true;\n}\n\nexport function isIosSafari(win: Window): boolean {\n const ua = win.navigator.userAgent;\n const iPadAsMac = ua.includes('Macintosh') && win.navigator.maxTouchPoints > 1;\n const iosDevice = IOS_DEVICE_RE.test(ua) || iPadAsMac;\n return iosDevice && !IOS_OTHER_BROWSER_RE.test(ua);\n}\n\nexport function isDesktop(win: Window): boolean {\n return win.innerWidth >= DESKTOP_MIN_WIDTH;\n}\n","const DAY_MS = 86_400_000;\n\nexport function snoozeKey(appName: string, override?: string): string {\n return override ?? `gs-install-snooze:${appName}`;\n}\n\nexport function isSnoozed(win: Window, key: string, days: number, now: number): boolean {\n try {\n const raw = win.localStorage.getItem(key);\n if (raw === null) {\n return false;\n }\n const at = Number(raw);\n return Number.isFinite(at) && now - at < days * DAY_MS;\n } catch {\n return false;\n }\n}\n\nexport function writeSnooze(win: Window, key: string, now: number): void {\n try {\n win.localStorage.setItem(key, String(now));\n } catch {\n // Storage blocked (private mode, quota): the banner simply shows again next load.\n }\n}\n","import type { Disposable, InstallLabels } from '../types';\nimport { renderBanner } from './banner';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\nimport { isDesktop, isIosSafari, isStandalone } from './platform';\nimport { isSnoozed, snoozeKey, writeSnooze } from './snooze';\n\nexport const DEFAULT_SNOOZE_DAYS = 14;\nconst ACCEPTED = 'accepted';\n\nexport interface BeforeInstallPromptEvent extends Event {\n prompt(): Promise<void>;\n userChoice: Promise<{ outcome: string }>;\n}\n\nexport interface InstallOptions {\n appName: string;\n labels: InstallLabels;\n snoozeDays?: number;\n storageKey?: string;\n win?: Window;\n now?: () => number;\n}\n\ninterface InstallState {\n deferred: BeforeInstallPromptEvent | null;\n variant: InstallVariant | null;\n node: HTMLElement | null;\n}\n\nfunction createController(opts: InstallOptions, win: Window, now: () => number): {\n state: InstallState;\n mount(): void;\n unmount(): void;\n} {\n const key = snoozeKey(opts.appName, opts.storageKey);\n const state: InstallState = { deferred: null, variant: null, node: null };\n const unmount = (): void => {\n state.node?.remove();\n state.node = null;\n };\n const dismiss = (): void => {\n writeSnooze(win, key, now());\n unmount();\n };\n const install = async (): Promise<void> => {\n const evt = state.deferred;\n state.deferred = null;\n if (!evt) {\n return;\n }\n try {\n await evt.prompt();\n const choice = await evt.userChoice;\n if (choice.outcome === ACCEPTED) {\n unmount();\n return;\n }\n dismiss();\n } catch {\n unmount();\n }\n };\n const mount = (): void => {\n if (state.variant === null) {\n return;\n }\n unmount();\n state.node = renderBanner({\n doc: win.document,\n layout: isDesktop(win) ? BannerLayout.Card : BannerLayout.Chip,\n variant: state.variant,\n appName: opts.appName,\n labels: opts.labels,\n onInstall: () => void install(),\n onDismiss: dismiss,\n });\n win.document.body.append(state.node);\n };\n return { state, mount, unmount };\n}\n\nexport function startInstall(opts: InstallOptions): Disposable {\n const win = opts.win ?? window;\n const now = opts.now ?? ((): number => Date.now());\n const key = snoozeKey(opts.appName, opts.storageKey);\n if (isStandalone(win) || isSnoozed(win, key, opts.snoozeDays ?? DEFAULT_SNOOZE_DAYS, now())) {\n return { dispose: (): void => undefined };\n }\n const ctl = createController(opts, win, now);\n const onPrompt = (e: Event): void => {\n e.preventDefault();\n ctl.state.deferred = e as BeforeInstallPromptEvent;\n ctl.state.variant = InstallVariant.Prompt;\n ctl.mount();\n };\n const onInstalled = (): void => {\n ctl.state.variant = null;\n ctl.unmount();\n };\n const onResize = (): void => {\n const node = ctl.state.node;\n if (node && (node.dataset.layout === BannerLayout.Card) !== isDesktop(win)) {\n ctl.mount();\n }\n };\n win.addEventListener('beforeinstallprompt', onPrompt);\n win.addEventListener('appinstalled', onInstalled);\n win.addEventListener('resize', onResize);\n if (isIosSafari(win)) {\n ctl.state.variant = InstallVariant.Ios;\n ctl.mount();\n }\n return {\n dispose: (): void => {\n win.removeEventListener('beforeinstallprompt', onPrompt);\n win.removeEventListener('appinstalled', onInstalled);\n win.removeEventListener('resize', onResize);\n ctl.unmount();\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport interface LifecycleOptions {\n onHidden?(): void;\n onVisible?(): void;\n}\n\nexport interface ResumableAudio {\n resume(): Promise<void> | void;\n}\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\nconst UNLOCK_EVENTS = ['pointerdown', 'keydown'] as const;\n\nexport function startLifecycle(opts: LifecycleOptions, doc: Document = document): Disposable {\n const onChange = (): void => {\n if (doc.visibilityState === 'hidden') {\n opts.onHidden?.();\n return;\n }\n opts.onVisible?.();\n };\n doc.addEventListener('visibilitychange', onChange);\n return { dispose: (): void => doc.removeEventListener('visibilitychange', onChange) };\n}\n\nexport function unlockAudio(ctx: ResumableAudio, win: Window = window): Disposable {\n const detach = (): void => {\n UNLOCK_EVENTS.forEach((type) => win.removeEventListener(type, onFirst, true));\n };\n function onFirst(): void {\n detach();\n try {\n Promise.resolve(ctx.resume()).catch(() => undefined);\n } catch {\n // A browser that refuses resume() leaves the game silent, never crashed.\n }\n }\n UNLOCK_EVENTS.forEach((type) => win.addEventListener(type, onFirst, true));\n return { dispose: detach };\n}\n\nexport function prefersReducedMotion(win: Window = window): boolean {\n if (new URLSearchParams(win.location.search).get('reducedMotion') === '1') {\n return true;\n }\n return typeof win.matchMedia === 'function' && win.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n","const STYLE_ID = 'gs-styles';\n\nconst THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-card-bottom:60px;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;\n\nconst ROOT = `.gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}`;\n\nconst BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}\n.gs *{box-sizing:border-box}\n.gs button{min-width:44px;min-height:44px;margin:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}\n.gs button:focus-visible{outline:2px solid var(--gs-focus);outline-offset:2px}\n.gs svg{width:20px;height:20px;flex:none}\n.gs-ico{display:inline-flex}\n.gs-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 18px;border-radius:var(--gs-radius);font:700 16px/1 var(--gs-font-text);white-space:nowrap}\n.gs-primary{background:var(--gs-accent);color:var(--gs-on-accent)}\n.gs .gs-ghost{color:var(--gs-ink);border:1px solid var(--gs-edge)}\n.gs-x{width:44px;height:44px;display:grid;place-items:center;color:var(--gs-ink-dim);flex:none}\n.gs-txt{min-width:0}\n.gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}\n.gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`;\n\nconst INSTALL = `.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}\n.gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(var(--gs-card-bottom,60px) + var(--gs-safe-bottom))}\n.gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}\n.gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}\n.gs-chip svg{color:var(--gs-accent)}\n.gs-seal .gs-x{border-left:1px solid var(--gs-edge)}\n.gs-steps{margin:8px 0 0;width:262px;padding:10px 14px;list-style:none;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);display:grid;gap:2px;counter-reset:s}\n.gs-steps[hidden]{display:none}\n.gs-steps li{display:flex;align-items:center;gap:10px;min-height:36px;font-size:15px;color:var(--gs-ink);counter-increment:s}\n.gs-steps li::before{content:counter(s);font:400 15px var(--gs-font-display);color:var(--gs-ink-dim);width:12px}\n.gs-steps svg{width:17px;height:17px;color:var(--gs-accent)}\n.gs-card{position:relative;width:344px;max-width:calc(100vw - 48px);padding:18px;border-radius:var(--gs-radius);background:var(--gs-surface);border:1px solid var(--gs-edge);display:grid;gap:12px}\n.gs-card .gs-x{position:absolute;top:4px;right:4px}\n.gs-card .gs-txt{padding-right:36px}\n.gs-card .gs-acts{display:flex;gap:8px}\n.gs-card .gs-steps{width:auto;margin:0;border:0;padding:0;background:none}\n.gs-app{width:40px;height:40px;border-radius:var(--gs-radius);background:var(--gs-surface-solid);border:1px solid var(--gs-edge);display:grid;place-items:center}\n.gs-app i{width:13px;height:13px;border-radius:50%;background:var(--gs-accent);box-shadow:0 0 10px var(--gs-accent)}`;\n\nconst CRASH = `.gs-crash{position:fixed;inset:0;z-index:2147483001;background:var(--gs-scrim);display:grid;place-items:center;padding:20px}\n.gs-panel{max-width:340px;background:var(--gs-surface-solid);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);padding:24px}\n.gs-h{margin:0;font:400 28px/1.15 var(--gs-font-display);color:var(--gs-ink)}\n.gs-panel p{font-size:16px;line-height:1.5;color:var(--gs-ink-dim);margin:10px 0 0}\n.gs-panel .gs-acts{display:flex;flex-direction:column;gap:8px;margin-top:20px}\n.gs-panel .gs-ref{font:13px ui-monospace,monospace}\n@media (min-width:1024px){.gs-panel{max-width:460px;padding:32px}.gs-panel .gs-acts{flex-direction:row}}`;\n\nexport const GAME_SHELL_CSS = [THEME, ROOT, BASE, INSTALL, CRASH].join('\\n');\n\nexport function injectStyles(doc: Document = document): void {\n if (doc.getElementById(STYLE_ID)) {\n return;\n }\n const style = doc.createElement('style');\n style.id = STYLE_ID;\n style.textContent = GAME_SHELL_CSS;\n doc.head.append(style);\n}\n","import type { Disposable } from '../types';\n\nexport interface VersionPollOptions {\n url: string;\n intervalMs: number;\n onNewVersion(): void;\n fetchFn?: typeof fetch;\n win?: Window;\n}\n\nexport function startVersionPoll(opts: VersionPollOptions): Disposable {\n const win = opts.win ?? window;\n const fetchFn = opts.fetchFn ?? ((input: RequestInfo | URL, init?: RequestInit): Promise<Response> => win.fetch(input, init));\n let baseline: string | null = null;\n let fired = false;\n let busy = false;\n\n const check = async (): Promise<void> => {\n if (fired || busy) {\n return;\n }\n busy = true;\n try {\n const res = await fetchFn(opts.url, { cache: 'no-store' });\n if (!res.ok) {\n return;\n }\n const value = (await res.text()).trim();\n if (baseline === null) {\n baseline = value;\n } else if (value !== baseline) {\n fired = true;\n opts.onNewVersion();\n }\n } catch {\n // Offline or a deploy mid-flight: the next tick tries again.\n } finally {\n busy = false;\n }\n };\n const onVisibility = (): void => {\n if (win.document.visibilityState === 'visible') {\n void check();\n }\n };\n\n void check();\n const timer = win.setInterval(() => void check(), opts.intervalMs);\n win.document.addEventListener('visibilitychange', onVisibility);\n return {\n dispose: (): void => {\n win.clearInterval(timer);\n win.document.removeEventListener('visibilitychange', onVisibility);\n },\n };\n}\n","import { startCrash } from './crash/crash';\nimport type { CrashInfo } from './crash/crashKind';\nimport { startFit } from './fit/fit';\nimport { startInstall } from './install/install';\nimport { startLifecycle, type LifecycleOptions } from './lifecycle/lifecycle';\nimport { injectStyles } from './styles';\nimport type { Disposable, GameShellLabels } from './types';\nimport { startVersionPoll } from './version/versionPoll';\n\nexport interface GameShellOptions {\n root: HTMLElement;\n appName: string;\n labels: GameShellLabels;\n appVersion?: string;\n install?: { snoozeDays?: number; storageKey?: string } | false;\n version?: { url: string; intervalMs: number; onNewVersion(): void };\n crash?: { report?(info: CrashInfo): string | void } | false;\n lifecycle?: LifecycleOptions;\n}\n\nexport function initGameShell(opts: GameShellOptions): Disposable {\n const doc = opts.root.ownerDocument;\n injectStyles(doc);\n opts.root.classList.add('gs-root');\n const parts: Disposable[] = [startFit()];\n if (opts.install !== false) {\n parts.push(startInstall({ appName: opts.appName, labels: opts.labels, ...opts.install }));\n }\n if (opts.crash !== false) {\n parts.push(startCrash({ labels: opts.labels, report: opts.crash?.report, appVersion: opts.appVersion }));\n }\n if (opts.lifecycle) {\n parts.push(startLifecycle(opts.lifecycle, doc));\n }\n if (opts.version) {\n parts.push(startVersionPoll(opts.version));\n }\n return {\n dispose: (): void => {\n parts.forEach((part) => part.dispose());\n opts.root.classList.remove('gs-root');\n },\n };\n}\n"],"mappings":"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","names":["src_exports","__export","CRASH_KIND","DEFAULT_SNOOZE_DAYS","DESKTOP_MIN_WIDTH","GAME_SHELL_CSS","GS_RESIZE_EVENT","GS_VH_VAR","initGameShell","injectStyles","isDesktop","isIosSafari","isStandalone","prefersReducedMotion","startCrash","startFit","startInstall","startLifecycle","startVersionPoll","unlockAudio","CRASH_KIND","el","doc","tag","className","text","node","iconSpan","svg","span","button","spec","btn","CRASH_TITLE_ID","CRASH_BODY_ID","renderCrashOverlay","p","root","el","panel","title","body","acts","reload","button","fromErrorEvent","err","stack","location","message","CRASH_KIND","fromRejection","reason","safeReport","opts","info","_a","_b","e","copyDetails","win","appVersion","text","part","startCrash","reload","overlay","handle","reference","view","renderCrashOverlay","onError","onRejection","GS_RESIZE_EVENT","GS_VH_VAR","measure","win","vv","scheduler","cb","startFit","root","schedule","last","pending","disposed","apply","next","unchanged","onChange","svg","paths","ICONS","STEPS_ID","renderSteps","p","list","el","share","iconSpan","ICONS","add","closeButton","button","renderChip","seal","steps","chip","renderCard","card","app","txt","acts","renderBanner","wrap","e","DESKTOP_MIN_WIDTH","IOS_DEVICE_RE","IOS_OTHER_BROWSER_RE","isStandalone","win","isIosSafari","ua","iPadAsMac","isDesktop","snoozeKey","appName","override","isSnoozed","win","key","days","now","raw","at","e","writeSnooze","DEFAULT_SNOOZE_DAYS","ACCEPTED","createController","opts","win","now","key","snoozeKey","state","unmount","_a","dismiss","writeSnooze","install","evt","e","renderBanner","isDesktop","startInstall","_b","_c","isStandalone","isSnoozed","ctl","onPrompt","onInstalled","onResize","node","isIosSafari","REDUCED_MOTION_QUERY","UNLOCK_EVENTS","startLifecycle","opts","doc","onChange","_a","_b","unlockAudio","ctx","win","detach","type","onFirst","e","prefersReducedMotion","STYLE_ID","THEME","ROOT","BASE","INSTALL","CRASH","GAME_SHELL_CSS","injectStyles","doc","style","startVersionPoll","opts","_a","_b","win","fetchFn","input","init","baseline","fired","busy","check","res","value","e","onVisibility","timer","initGameShell","opts","_a","doc","injectStyles","parts","startFit","startInstall","startCrash","startLifecycle","startVersionPoll","part"]}
package/dist/index.js CHANGED
@@ -439,7 +439,7 @@ function prefersReducedMotion(win = window) {
439
439
 
440
440
  // src/styles.ts
441
441
  var STYLE_ID = "gs-styles";
442
- var THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;
442
+ var THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-card-bottom:60px;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;
443
443
  var ROOT = `.gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}`;
444
444
  var BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}
445
445
  .gs *{box-sizing:border-box}
@@ -455,7 +455,7 @@ var BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:b
455
455
  .gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}
456
456
  .gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`;
457
457
  var INSTALL = `.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}
458
- .gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(24px + var(--gs-safe-bottom))}
458
+ .gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(var(--gs-card-bottom,60px) + var(--gs-safe-bottom))}
459
459
  .gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}
460
460
  .gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}
461
461
  .gs-chip svg{color:var(--gs-accent)}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/crash/crashKind.ts","../src/dom.ts","../src/crash/crashOverlay.ts","../src/crash/crash.ts","../src/fit/fit.ts","../src/icons.ts","../src/install/banner.ts","../src/install/platform.ts","../src/install/snooze.ts","../src/install/install.ts","../src/lifecycle/lifecycle.ts","../src/styles.ts","../src/version/versionPoll.ts","../src/initGameShell.ts"],"names":["svg"],"mappings":"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","file":"index.js","sourcesContent":["export const CRASH_KIND = {\n Error: 'error',\n Rejection: 'rejection',\n} as const;\n\nexport type CrashKind = (typeof CRASH_KIND)[keyof typeof CRASH_KIND];\n\nexport interface CrashInfo {\n kind: CrashKind;\n message: string;\n source?: string;\n}\n","export function el<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n className = '',\n text = '',\n): HTMLElementTagNameMap[K] {\n const node = doc.createElement(tag);\n if (className !== '') {\n node.className = className;\n }\n if (text !== '') {\n node.textContent = text;\n }\n return node;\n}\n\nexport function iconSpan(doc: Document, svg: string): HTMLSpanElement {\n const span = el(doc, 'span', 'gs-ico');\n span.innerHTML = svg;\n return span;\n}\n\nexport interface ButtonSpec {\n className: string;\n text?: string;\n ariaLabel?: string;\n icon?: string;\n onClick(): void;\n}\n\nexport function button(doc: Document, spec: ButtonSpec): HTMLButtonElement {\n const btn = el(doc, 'button', spec.className);\n btn.type = 'button';\n if (spec.icon !== undefined) {\n btn.append(iconSpan(doc, spec.icon));\n }\n if (spec.text !== undefined) {\n btn.append(doc.createTextNode(spec.text));\n }\n if (spec.ariaLabel !== undefined) {\n btn.setAttribute('aria-label', spec.ariaLabel);\n }\n btn.addEventListener('click', () => spec.onClick());\n return btn;\n}\n","import { button, el } from '../dom';\nimport type { CrashLabels } from '../types';\n\nexport const CRASH_TITLE_ID = 'gs-crash-title';\nconst CRASH_BODY_ID = 'gs-crash-body';\n\nexport interface CrashOverlayProps {\n doc: Document;\n labels: CrashLabels;\n reference?: string;\n onReload(): void;\n onCopy(): void;\n}\n\nexport interface CrashOverlayView {\n root: HTMLElement;\n reload: HTMLButtonElement;\n}\n\nexport function renderCrashOverlay(p: CrashOverlayProps): CrashOverlayView {\n const root = el(p.doc, 'div', 'gs gs-crash');\n root.setAttribute('role', 'alertdialog');\n root.setAttribute('aria-modal', 'true');\n root.setAttribute('aria-labelledby', CRASH_TITLE_ID);\n root.setAttribute('aria-describedby', CRASH_BODY_ID);\n const panel = el(p.doc, 'div', 'gs-panel');\n const title = el(p.doc, 'h2', 'gs-h', p.labels.crashTitle);\n title.id = CRASH_TITLE_ID;\n const body = el(p.doc, 'p', '', p.labels.crashBody);\n body.id = CRASH_BODY_ID;\n const acts = el(p.doc, 'div', 'gs-acts');\n const reload = button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.reload, onClick: p.onReload });\n acts.append(reload, button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.copyDetails, onClick: p.onCopy }));\n panel.append(title, body, acts);\n if (p.reference !== undefined && p.reference !== '') {\n panel.append(el(p.doc, 'p', 'gs-ref', `${p.labels.errorReported} ${p.reference}`));\n }\n root.append(panel);\n return { root, reload };\n}\n","import type { CrashLabels, Disposable } from '../types';\nimport { CRASH_KIND, type CrashInfo } from './crashKind';\nimport { renderCrashOverlay } from './crashOverlay';\n\nexport interface CrashOptions {\n labels: CrashLabels;\n report?: (info: CrashInfo) => string | void;\n appVersion?: string;\n win?: Window;\n reload?: () => void;\n}\n\nfunction fromErrorEvent(e: ErrorEvent): CrashInfo {\n const err: unknown = e.error;\n const stack = err instanceof Error ? err.stack : undefined;\n const location = e.filename !== '' ? `${e.filename}:${e.lineno}:${e.colno}` : undefined;\n const message = e.message !== '' ? e.message : String(err);\n return { kind: CRASH_KIND.Error, message, source: stack ?? location };\n}\n\nfunction fromRejection(e: Event): CrashInfo {\n const reason: unknown = (e as PromiseRejectionEvent).reason;\n if (reason instanceof Error) {\n return { kind: CRASH_KIND.Rejection, message: reason.message, source: reason.stack };\n }\n return { kind: CRASH_KIND.Rejection, message: String(reason) };\n}\n\nfunction safeReport(opts: CrashOptions, info: CrashInfo): string | undefined {\n try {\n return opts.report?.(info) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction copyDetails(win: Window, info: CrashInfo, appVersion?: string): void {\n const text = [info.message, info.source, appVersion]\n .filter((part): part is string => part !== undefined && part !== '')\n .join('\\n');\n try {\n win.navigator.clipboard.writeText(text).catch(() => undefined);\n } catch {\n // No clipboard API (insecure context): nothing to copy into.\n }\n}\n\nexport function startCrash(opts: CrashOptions): Disposable {\n const win = opts.win ?? window;\n const reload = opts.reload ?? ((): void => win.location.reload());\n let overlay: HTMLElement | null = null;\n\n const handle = (info: CrashInfo): void => {\n const reference = safeReport(opts, info);\n if (overlay) {\n return;\n }\n const view = renderCrashOverlay({\n doc: win.document,\n labels: opts.labels,\n reference,\n onReload: reload,\n onCopy: () => copyDetails(win, info, opts.appVersion),\n });\n overlay = view.root;\n win.document.body.append(overlay);\n view.reload.focus();\n };\n const onError = (e: Event): void => {\n if (e instanceof ErrorEvent) {\n handle(fromErrorEvent(e));\n }\n };\n const onRejection = (e: Event): void => handle(fromRejection(e));\n\n win.addEventListener('error', onError);\n win.addEventListener('unhandledrejection', onRejection);\n return {\n dispose: (): void => {\n win.removeEventListener('error', onError);\n win.removeEventListener('unhandledrejection', onRejection);\n overlay?.remove();\n overlay = null;\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport const GS_RESIZE_EVENT = 'gs:resize';\nexport const GS_VH_VAR = '--gs-vh';\n\nexport interface GsResizeDetail {\n width: number;\n height: number;\n}\n\nfunction measure(win: Window): GsResizeDetail {\n const vv = win.visualViewport;\n if (vv) {\n return { width: vv.width, height: vv.height };\n }\n return { width: win.innerWidth, height: win.innerHeight };\n}\n\nfunction scheduler(win: Window): (cb: () => void) => void {\n if (typeof win.requestAnimationFrame === 'function') {\n return (cb) => {\n win.requestAnimationFrame(() => cb());\n };\n }\n return (cb) => {\n win.setTimeout(cb, 0);\n };\n}\n\nexport function startFit(win: Window = window): Disposable {\n const root = win.document.documentElement;\n const schedule = scheduler(win);\n let last = measure(win);\n let pending = false;\n let disposed = false;\n root.style.setProperty(GS_VH_VAR, `${last.height}px`);\n\n const apply = (): void => {\n pending = false;\n const next = measure(win);\n const unchanged = next.width === last.width && next.height === last.height;\n if (disposed || unchanged) {\n return;\n }\n last = next;\n root.style.setProperty(GS_VH_VAR, `${next.height}px`);\n win.dispatchEvent(new CustomEvent<GsResizeDetail>(GS_RESIZE_EVENT, { detail: next }));\n };\n const onChange = (): void => {\n if (pending) {\n return;\n }\n pending = true;\n schedule(apply);\n };\n\n const vv = win.visualViewport;\n vv?.addEventListener('resize', onChange);\n win.addEventListener('resize', onChange);\n win.addEventListener('orientationchange', onChange);\n return {\n dispose: (): void => {\n disposed = true;\n vv?.removeEventListener('resize', onChange);\n win.removeEventListener('resize', onChange);\n win.removeEventListener('orientationchange', onChange);\n },\n };\n}\n","const svg = (paths: string): string =>\n `<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n\nexport const ICONS = {\n download: svg('<path d=\"M12 4v11M7 10l5 5 5-5M5 20h14\"/>'),\n add: svg('<path d=\"M12 5v14M5 12h14\"/>'),\n close: svg('<path d=\"M6 6l12 12M18 6L6 18\"/>'),\n share: svg('<path d=\"M12 15V4M8 8l4-4 4 4M6 12v8h12v-8\"/>'),\n} as const;\n","import { button, el, iconSpan } from '../dom';\nimport { ICONS } from '../icons';\nimport type { InstallLabels } from '../types';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\n\nexport const STEPS_ID = 'gs-install-steps';\n\nexport interface BannerProps {\n doc: Document;\n layout: BannerLayout;\n variant: InstallVariant;\n appName: string;\n labels: InstallLabels;\n onInstall(): void;\n onDismiss(): void;\n}\n\nfunction renderSteps(p: BannerProps): HTMLOListElement {\n const list = el(p.doc, 'ol', 'gs-steps');\n list.id = STEPS_ID;\n const share = el(p.doc, 'li');\n share.append(iconSpan(p.doc, ICONS.share), p.doc.createTextNode(p.labels.tapShare));\n const add = el(p.doc, 'li');\n add.append(iconSpan(p.doc, ICONS.add), p.doc.createTextNode(p.labels.tapAdd));\n list.append(share, add);\n return list;\n}\n\nfunction closeButton(p: BannerProps): HTMLButtonElement {\n return button(p.doc, { className: 'gs-x', ariaLabel: p.labels.notNow, icon: ICONS.close, onClick: p.onDismiss });\n}\n\nfunction renderChip(p: BannerProps): HTMLElement[] {\n const seal = el(p.doc, 'div', 'gs-seal');\n if (p.variant === InstallVariant.Prompt) {\n seal.append(button(p.doc, { className: 'gs-chip', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n seal.append(closeButton(p));\n return [seal];\n }\n const steps = renderSteps(p);\n steps.hidden = true;\n const chip = button(p.doc, {\n className: 'gs-chip',\n text: p.labels.addToHome,\n icon: ICONS.add,\n onClick: () => {\n steps.hidden = !steps.hidden;\n chip.setAttribute('aria-expanded', String(!steps.hidden));\n },\n });\n chip.setAttribute('aria-expanded', 'false');\n chip.setAttribute('aria-controls', STEPS_ID);\n seal.append(chip, closeButton(p));\n return [seal, steps];\n}\n\nfunction renderCard(p: BannerProps): HTMLElement[] {\n const card = el(p.doc, 'div', 'gs-card');\n const app = el(p.doc, 'div', 'gs-app');\n app.append(el(p.doc, 'i'));\n const txt = el(p.doc, 'div', 'gs-txt');\n txt.append(el(p.doc, 'b', '', p.appName), el(p.doc, 'span', '', p.labels.installBody));\n const acts = el(p.doc, 'div', 'gs-acts');\n if (p.variant === InstallVariant.Prompt) {\n acts.append(button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n }\n acts.append(button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.notNow, onClick: p.onDismiss }));\n card.append(closeButton(p), app, txt);\n if (p.variant === InstallVariant.Ios) {\n card.append(renderSteps(p));\n }\n card.append(acts);\n return [card];\n}\n\nexport function renderBanner(p: BannerProps): HTMLElement {\n const wrap = el(p.doc, 'div', 'gs gs-install');\n wrap.dataset.layout = p.layout;\n wrap.dataset.variant = p.variant;\n wrap.setAttribute('role', 'region');\n wrap.setAttribute('aria-label', p.variant === InstallVariant.Prompt ? p.labels.install : p.labels.addToHome);\n wrap.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n p.onDismiss();\n }\n });\n wrap.append(...(p.layout === BannerLayout.Card ? renderCard(p) : renderChip(p)));\n return wrap;\n}\n","export const DESKTOP_MIN_WIDTH = 1024;\nconst IOS_DEVICE_RE = /iPad|iPhone|iPod/;\nconst IOS_OTHER_BROWSER_RE = /CriOS|FxiOS|EdgiOS|OPiOS/;\n\ninterface IosNavigator extends Navigator {\n standalone?: boolean;\n}\n\nexport function isStandalone(win: Window): boolean {\n const media = typeof win.matchMedia === 'function' && win.matchMedia('(display-mode: standalone)').matches;\n return media || (win.navigator as IosNavigator).standalone === true;\n}\n\nexport function isIosSafari(win: Window): boolean {\n const ua = win.navigator.userAgent;\n const iPadAsMac = ua.includes('Macintosh') && win.navigator.maxTouchPoints > 1;\n const iosDevice = IOS_DEVICE_RE.test(ua) || iPadAsMac;\n return iosDevice && !IOS_OTHER_BROWSER_RE.test(ua);\n}\n\nexport function isDesktop(win: Window): boolean {\n return win.innerWidth >= DESKTOP_MIN_WIDTH;\n}\n","const DAY_MS = 86_400_000;\n\nexport function snoozeKey(appName: string, override?: string): string {\n return override ?? `gs-install-snooze:${appName}`;\n}\n\nexport function isSnoozed(win: Window, key: string, days: number, now: number): boolean {\n try {\n const raw = win.localStorage.getItem(key);\n if (raw === null) {\n return false;\n }\n const at = Number(raw);\n return Number.isFinite(at) && now - at < days * DAY_MS;\n } catch {\n return false;\n }\n}\n\nexport function writeSnooze(win: Window, key: string, now: number): void {\n try {\n win.localStorage.setItem(key, String(now));\n } catch {\n // Storage blocked (private mode, quota): the banner simply shows again next load.\n }\n}\n","import type { Disposable, InstallLabels } from '../types';\nimport { renderBanner } from './banner';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\nimport { isDesktop, isIosSafari, isStandalone } from './platform';\nimport { isSnoozed, snoozeKey, writeSnooze } from './snooze';\n\nexport const DEFAULT_SNOOZE_DAYS = 14;\nconst ACCEPTED = 'accepted';\n\nexport interface BeforeInstallPromptEvent extends Event {\n prompt(): Promise<void>;\n userChoice: Promise<{ outcome: string }>;\n}\n\nexport interface InstallOptions {\n appName: string;\n labels: InstallLabels;\n snoozeDays?: number;\n storageKey?: string;\n win?: Window;\n now?: () => number;\n}\n\ninterface InstallState {\n deferred: BeforeInstallPromptEvent | null;\n variant: InstallVariant | null;\n node: HTMLElement | null;\n}\n\nfunction createController(opts: InstallOptions, win: Window, now: () => number): {\n state: InstallState;\n mount(): void;\n unmount(): void;\n} {\n const key = snoozeKey(opts.appName, opts.storageKey);\n const state: InstallState = { deferred: null, variant: null, node: null };\n const unmount = (): void => {\n state.node?.remove();\n state.node = null;\n };\n const dismiss = (): void => {\n writeSnooze(win, key, now());\n unmount();\n };\n const install = async (): Promise<void> => {\n const evt = state.deferred;\n state.deferred = null;\n if (!evt) {\n return;\n }\n try {\n await evt.prompt();\n const choice = await evt.userChoice;\n if (choice.outcome === ACCEPTED) {\n unmount();\n return;\n }\n dismiss();\n } catch {\n unmount();\n }\n };\n const mount = (): void => {\n if (state.variant === null) {\n return;\n }\n unmount();\n state.node = renderBanner({\n doc: win.document,\n layout: isDesktop(win) ? BannerLayout.Card : BannerLayout.Chip,\n variant: state.variant,\n appName: opts.appName,\n labels: opts.labels,\n onInstall: () => void install(),\n onDismiss: dismiss,\n });\n win.document.body.append(state.node);\n };\n return { state, mount, unmount };\n}\n\nexport function startInstall(opts: InstallOptions): Disposable {\n const win = opts.win ?? window;\n const now = opts.now ?? ((): number => Date.now());\n const key = snoozeKey(opts.appName, opts.storageKey);\n if (isStandalone(win) || isSnoozed(win, key, opts.snoozeDays ?? DEFAULT_SNOOZE_DAYS, now())) {\n return { dispose: (): void => undefined };\n }\n const ctl = createController(opts, win, now);\n const onPrompt = (e: Event): void => {\n e.preventDefault();\n ctl.state.deferred = e as BeforeInstallPromptEvent;\n ctl.state.variant = InstallVariant.Prompt;\n ctl.mount();\n };\n const onInstalled = (): void => {\n ctl.state.variant = null;\n ctl.unmount();\n };\n const onResize = (): void => {\n const node = ctl.state.node;\n if (node && (node.dataset.layout === BannerLayout.Card) !== isDesktop(win)) {\n ctl.mount();\n }\n };\n win.addEventListener('beforeinstallprompt', onPrompt);\n win.addEventListener('appinstalled', onInstalled);\n win.addEventListener('resize', onResize);\n if (isIosSafari(win)) {\n ctl.state.variant = InstallVariant.Ios;\n ctl.mount();\n }\n return {\n dispose: (): void => {\n win.removeEventListener('beforeinstallprompt', onPrompt);\n win.removeEventListener('appinstalled', onInstalled);\n win.removeEventListener('resize', onResize);\n ctl.unmount();\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport interface LifecycleOptions {\n onHidden?(): void;\n onVisible?(): void;\n}\n\nexport interface ResumableAudio {\n resume(): Promise<void> | void;\n}\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\nconst UNLOCK_EVENTS = ['pointerdown', 'keydown'] as const;\n\nexport function startLifecycle(opts: LifecycleOptions, doc: Document = document): Disposable {\n const onChange = (): void => {\n if (doc.visibilityState === 'hidden') {\n opts.onHidden?.();\n return;\n }\n opts.onVisible?.();\n };\n doc.addEventListener('visibilitychange', onChange);\n return { dispose: (): void => doc.removeEventListener('visibilitychange', onChange) };\n}\n\nexport function unlockAudio(ctx: ResumableAudio, win: Window = window): Disposable {\n const detach = (): void => {\n UNLOCK_EVENTS.forEach((type) => win.removeEventListener(type, onFirst, true));\n };\n function onFirst(): void {\n detach();\n try {\n Promise.resolve(ctx.resume()).catch(() => undefined);\n } catch {\n // A browser that refuses resume() leaves the game silent, never crashed.\n }\n }\n UNLOCK_EVENTS.forEach((type) => win.addEventListener(type, onFirst, true));\n return { dispose: detach };\n}\n\nexport function prefersReducedMotion(win: Window = window): boolean {\n if (new URLSearchParams(win.location.search).get('reducedMotion') === '1') {\n return true;\n }\n return typeof win.matchMedia === 'function' && win.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n","const STYLE_ID = 'gs-styles';\n\nconst THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;\n\nconst ROOT = `.gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}`;\n\nconst BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}\n.gs *{box-sizing:border-box}\n.gs button{min-width:44px;min-height:44px;margin:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}\n.gs button:focus-visible{outline:2px solid var(--gs-focus);outline-offset:2px}\n.gs svg{width:20px;height:20px;flex:none}\n.gs-ico{display:inline-flex}\n.gs-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 18px;border-radius:var(--gs-radius);font:700 16px/1 var(--gs-font-text);white-space:nowrap}\n.gs-primary{background:var(--gs-accent);color:var(--gs-on-accent)}\n.gs .gs-ghost{color:var(--gs-ink);border:1px solid var(--gs-edge)}\n.gs-x{width:44px;height:44px;display:grid;place-items:center;color:var(--gs-ink-dim);flex:none}\n.gs-txt{min-width:0}\n.gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}\n.gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`;\n\nconst INSTALL = `.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}\n.gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(24px + var(--gs-safe-bottom))}\n.gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}\n.gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}\n.gs-chip svg{color:var(--gs-accent)}\n.gs-seal .gs-x{border-left:1px solid var(--gs-edge)}\n.gs-steps{margin:8px 0 0;width:262px;padding:10px 14px;list-style:none;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);display:grid;gap:2px;counter-reset:s}\n.gs-steps[hidden]{display:none}\n.gs-steps li{display:flex;align-items:center;gap:10px;min-height:36px;font-size:15px;color:var(--gs-ink);counter-increment:s}\n.gs-steps li::before{content:counter(s);font:400 15px var(--gs-font-display);color:var(--gs-ink-dim);width:12px}\n.gs-steps svg{width:17px;height:17px;color:var(--gs-accent)}\n.gs-card{position:relative;width:344px;max-width:calc(100vw - 48px);padding:18px;border-radius:var(--gs-radius);background:var(--gs-surface);border:1px solid var(--gs-edge);display:grid;gap:12px}\n.gs-card .gs-x{position:absolute;top:4px;right:4px}\n.gs-card .gs-txt{padding-right:36px}\n.gs-card .gs-acts{display:flex;gap:8px}\n.gs-card .gs-steps{width:auto;margin:0;border:0;padding:0;background:none}\n.gs-app{width:40px;height:40px;border-radius:var(--gs-radius);background:var(--gs-surface-solid);border:1px solid var(--gs-edge);display:grid;place-items:center}\n.gs-app i{width:13px;height:13px;border-radius:50%;background:var(--gs-accent);box-shadow:0 0 10px var(--gs-accent)}`;\n\nconst CRASH = `.gs-crash{position:fixed;inset:0;z-index:2147483001;background:var(--gs-scrim);display:grid;place-items:center;padding:20px}\n.gs-panel{max-width:340px;background:var(--gs-surface-solid);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);padding:24px}\n.gs-h{margin:0;font:400 28px/1.15 var(--gs-font-display);color:var(--gs-ink)}\n.gs-panel p{font-size:16px;line-height:1.5;color:var(--gs-ink-dim);margin:10px 0 0}\n.gs-panel .gs-acts{display:flex;flex-direction:column;gap:8px;margin-top:20px}\n.gs-panel .gs-ref{font:13px ui-monospace,monospace}\n@media (min-width:1024px){.gs-panel{max-width:460px;padding:32px}.gs-panel .gs-acts{flex-direction:row}}`;\n\nexport const GAME_SHELL_CSS = [THEME, ROOT, BASE, INSTALL, CRASH].join('\\n');\n\nexport function injectStyles(doc: Document = document): void {\n if (doc.getElementById(STYLE_ID)) {\n return;\n }\n const style = doc.createElement('style');\n style.id = STYLE_ID;\n style.textContent = GAME_SHELL_CSS;\n doc.head.append(style);\n}\n","import type { Disposable } from '../types';\n\nexport interface VersionPollOptions {\n url: string;\n intervalMs: number;\n onNewVersion(): void;\n fetchFn?: typeof fetch;\n win?: Window;\n}\n\nexport function startVersionPoll(opts: VersionPollOptions): Disposable {\n const win = opts.win ?? window;\n const fetchFn = opts.fetchFn ?? ((input: RequestInfo | URL, init?: RequestInit): Promise<Response> => win.fetch(input, init));\n let baseline: string | null = null;\n let fired = false;\n let busy = false;\n\n const check = async (): Promise<void> => {\n if (fired || busy) {\n return;\n }\n busy = true;\n try {\n const res = await fetchFn(opts.url, { cache: 'no-store' });\n if (!res.ok) {\n return;\n }\n const value = (await res.text()).trim();\n if (baseline === null) {\n baseline = value;\n } else if (value !== baseline) {\n fired = true;\n opts.onNewVersion();\n }\n } catch {\n // Offline or a deploy mid-flight: the next tick tries again.\n } finally {\n busy = false;\n }\n };\n const onVisibility = (): void => {\n if (win.document.visibilityState === 'visible') {\n void check();\n }\n };\n\n void check();\n const timer = win.setInterval(() => void check(), opts.intervalMs);\n win.document.addEventListener('visibilitychange', onVisibility);\n return {\n dispose: (): void => {\n win.clearInterval(timer);\n win.document.removeEventListener('visibilitychange', onVisibility);\n },\n };\n}\n","import { startCrash } from './crash/crash';\nimport type { CrashInfo } from './crash/crashKind';\nimport { startFit } from './fit/fit';\nimport { startInstall } from './install/install';\nimport { startLifecycle, type LifecycleOptions } from './lifecycle/lifecycle';\nimport { injectStyles } from './styles';\nimport type { Disposable, GameShellLabels } from './types';\nimport { startVersionPoll } from './version/versionPoll';\n\nexport interface GameShellOptions {\n root: HTMLElement;\n appName: string;\n labels: GameShellLabels;\n appVersion?: string;\n install?: { snoozeDays?: number; storageKey?: string } | false;\n version?: { url: string; intervalMs: number; onNewVersion(): void };\n crash?: { report?(info: CrashInfo): string | void } | false;\n lifecycle?: LifecycleOptions;\n}\n\nexport function initGameShell(opts: GameShellOptions): Disposable {\n const doc = opts.root.ownerDocument;\n injectStyles(doc);\n opts.root.classList.add('gs-root');\n const parts: Disposable[] = [startFit()];\n if (opts.install !== false) {\n parts.push(startInstall({ appName: opts.appName, labels: opts.labels, ...opts.install }));\n }\n if (opts.crash !== false) {\n parts.push(startCrash({ labels: opts.labels, report: opts.crash?.report, appVersion: opts.appVersion }));\n }\n if (opts.lifecycle) {\n parts.push(startLifecycle(opts.lifecycle, doc));\n }\n if (opts.version) {\n parts.push(startVersionPoll(opts.version));\n }\n return {\n dispose: (): void => {\n parts.forEach((part) => part.dispose());\n opts.root.classList.remove('gs-root');\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/crash/crashKind.ts","../src/dom.ts","../src/crash/crashOverlay.ts","../src/crash/crash.ts","../src/fit/fit.ts","../src/icons.ts","../src/install/banner.ts","../src/install/platform.ts","../src/install/snooze.ts","../src/install/install.ts","../src/lifecycle/lifecycle.ts","../src/styles.ts","../src/version/versionPoll.ts","../src/initGameShell.ts"],"names":["svg"],"mappings":"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","file":"index.js","sourcesContent":["export const CRASH_KIND = {\n Error: 'error',\n Rejection: 'rejection',\n} as const;\n\nexport type CrashKind = (typeof CRASH_KIND)[keyof typeof CRASH_KIND];\n\nexport interface CrashInfo {\n kind: CrashKind;\n message: string;\n source?: string;\n}\n","export function el<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n className = '',\n text = '',\n): HTMLElementTagNameMap[K] {\n const node = doc.createElement(tag);\n if (className !== '') {\n node.className = className;\n }\n if (text !== '') {\n node.textContent = text;\n }\n return node;\n}\n\nexport function iconSpan(doc: Document, svg: string): HTMLSpanElement {\n const span = el(doc, 'span', 'gs-ico');\n span.innerHTML = svg;\n return span;\n}\n\nexport interface ButtonSpec {\n className: string;\n text?: string;\n ariaLabel?: string;\n icon?: string;\n onClick(): void;\n}\n\nexport function button(doc: Document, spec: ButtonSpec): HTMLButtonElement {\n const btn = el(doc, 'button', spec.className);\n btn.type = 'button';\n if (spec.icon !== undefined) {\n btn.append(iconSpan(doc, spec.icon));\n }\n if (spec.text !== undefined) {\n btn.append(doc.createTextNode(spec.text));\n }\n if (spec.ariaLabel !== undefined) {\n btn.setAttribute('aria-label', spec.ariaLabel);\n }\n btn.addEventListener('click', () => spec.onClick());\n return btn;\n}\n","import { button, el } from '../dom';\nimport type { CrashLabels } from '../types';\n\nexport const CRASH_TITLE_ID = 'gs-crash-title';\nconst CRASH_BODY_ID = 'gs-crash-body';\n\nexport interface CrashOverlayProps {\n doc: Document;\n labels: CrashLabels;\n reference?: string;\n onReload(): void;\n onCopy(): void;\n}\n\nexport interface CrashOverlayView {\n root: HTMLElement;\n reload: HTMLButtonElement;\n}\n\nexport function renderCrashOverlay(p: CrashOverlayProps): CrashOverlayView {\n const root = el(p.doc, 'div', 'gs gs-crash');\n root.setAttribute('role', 'alertdialog');\n root.setAttribute('aria-modal', 'true');\n root.setAttribute('aria-labelledby', CRASH_TITLE_ID);\n root.setAttribute('aria-describedby', CRASH_BODY_ID);\n const panel = el(p.doc, 'div', 'gs-panel');\n const title = el(p.doc, 'h2', 'gs-h', p.labels.crashTitle);\n title.id = CRASH_TITLE_ID;\n const body = el(p.doc, 'p', '', p.labels.crashBody);\n body.id = CRASH_BODY_ID;\n const acts = el(p.doc, 'div', 'gs-acts');\n const reload = button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.reload, onClick: p.onReload });\n acts.append(reload, button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.copyDetails, onClick: p.onCopy }));\n panel.append(title, body, acts);\n if (p.reference !== undefined && p.reference !== '') {\n panel.append(el(p.doc, 'p', 'gs-ref', `${p.labels.errorReported} ${p.reference}`));\n }\n root.append(panel);\n return { root, reload };\n}\n","import type { CrashLabels, Disposable } from '../types';\nimport { CRASH_KIND, type CrashInfo } from './crashKind';\nimport { renderCrashOverlay } from './crashOverlay';\n\nexport interface CrashOptions {\n labels: CrashLabels;\n report?: (info: CrashInfo) => string | void;\n appVersion?: string;\n win?: Window;\n reload?: () => void;\n}\n\nfunction fromErrorEvent(e: ErrorEvent): CrashInfo {\n const err: unknown = e.error;\n const stack = err instanceof Error ? err.stack : undefined;\n const location = e.filename !== '' ? `${e.filename}:${e.lineno}:${e.colno}` : undefined;\n const message = e.message !== '' ? e.message : String(err);\n return { kind: CRASH_KIND.Error, message, source: stack ?? location };\n}\n\nfunction fromRejection(e: Event): CrashInfo {\n const reason: unknown = (e as PromiseRejectionEvent).reason;\n if (reason instanceof Error) {\n return { kind: CRASH_KIND.Rejection, message: reason.message, source: reason.stack };\n }\n return { kind: CRASH_KIND.Rejection, message: String(reason) };\n}\n\nfunction safeReport(opts: CrashOptions, info: CrashInfo): string | undefined {\n try {\n return opts.report?.(info) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction copyDetails(win: Window, info: CrashInfo, appVersion?: string): void {\n const text = [info.message, info.source, appVersion]\n .filter((part): part is string => part !== undefined && part !== '')\n .join('\\n');\n try {\n win.navigator.clipboard.writeText(text).catch(() => undefined);\n } catch {\n // No clipboard API (insecure context): nothing to copy into.\n }\n}\n\nexport function startCrash(opts: CrashOptions): Disposable {\n const win = opts.win ?? window;\n const reload = opts.reload ?? ((): void => win.location.reload());\n let overlay: HTMLElement | null = null;\n\n const handle = (info: CrashInfo): void => {\n const reference = safeReport(opts, info);\n if (overlay) {\n return;\n }\n const view = renderCrashOverlay({\n doc: win.document,\n labels: opts.labels,\n reference,\n onReload: reload,\n onCopy: () => copyDetails(win, info, opts.appVersion),\n });\n overlay = view.root;\n win.document.body.append(overlay);\n view.reload.focus();\n };\n const onError = (e: Event): void => {\n if (e instanceof ErrorEvent) {\n handle(fromErrorEvent(e));\n }\n };\n const onRejection = (e: Event): void => handle(fromRejection(e));\n\n win.addEventListener('error', onError);\n win.addEventListener('unhandledrejection', onRejection);\n return {\n dispose: (): void => {\n win.removeEventListener('error', onError);\n win.removeEventListener('unhandledrejection', onRejection);\n overlay?.remove();\n overlay = null;\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport const GS_RESIZE_EVENT = 'gs:resize';\nexport const GS_VH_VAR = '--gs-vh';\n\nexport interface GsResizeDetail {\n width: number;\n height: number;\n}\n\nfunction measure(win: Window): GsResizeDetail {\n const vv = win.visualViewport;\n if (vv) {\n return { width: vv.width, height: vv.height };\n }\n return { width: win.innerWidth, height: win.innerHeight };\n}\n\nfunction scheduler(win: Window): (cb: () => void) => void {\n if (typeof win.requestAnimationFrame === 'function') {\n return (cb) => {\n win.requestAnimationFrame(() => cb());\n };\n }\n return (cb) => {\n win.setTimeout(cb, 0);\n };\n}\n\nexport function startFit(win: Window = window): Disposable {\n const root = win.document.documentElement;\n const schedule = scheduler(win);\n let last = measure(win);\n let pending = false;\n let disposed = false;\n root.style.setProperty(GS_VH_VAR, `${last.height}px`);\n\n const apply = (): void => {\n pending = false;\n const next = measure(win);\n const unchanged = next.width === last.width && next.height === last.height;\n if (disposed || unchanged) {\n return;\n }\n last = next;\n root.style.setProperty(GS_VH_VAR, `${next.height}px`);\n win.dispatchEvent(new CustomEvent<GsResizeDetail>(GS_RESIZE_EVENT, { detail: next }));\n };\n const onChange = (): void => {\n if (pending) {\n return;\n }\n pending = true;\n schedule(apply);\n };\n\n const vv = win.visualViewport;\n vv?.addEventListener('resize', onChange);\n win.addEventListener('resize', onChange);\n win.addEventListener('orientationchange', onChange);\n return {\n dispose: (): void => {\n disposed = true;\n vv?.removeEventListener('resize', onChange);\n win.removeEventListener('resize', onChange);\n win.removeEventListener('orientationchange', onChange);\n },\n };\n}\n","const svg = (paths: string): string =>\n `<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n\nexport const ICONS = {\n download: svg('<path d=\"M12 4v11M7 10l5 5 5-5M5 20h14\"/>'),\n add: svg('<path d=\"M12 5v14M5 12h14\"/>'),\n close: svg('<path d=\"M6 6l12 12M18 6L6 18\"/>'),\n share: svg('<path d=\"M12 15V4M8 8l4-4 4 4M6 12v8h12v-8\"/>'),\n} as const;\n","import { button, el, iconSpan } from '../dom';\nimport { ICONS } from '../icons';\nimport type { InstallLabels } from '../types';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\n\nexport const STEPS_ID = 'gs-install-steps';\n\nexport interface BannerProps {\n doc: Document;\n layout: BannerLayout;\n variant: InstallVariant;\n appName: string;\n labels: InstallLabels;\n onInstall(): void;\n onDismiss(): void;\n}\n\nfunction renderSteps(p: BannerProps): HTMLOListElement {\n const list = el(p.doc, 'ol', 'gs-steps');\n list.id = STEPS_ID;\n const share = el(p.doc, 'li');\n share.append(iconSpan(p.doc, ICONS.share), p.doc.createTextNode(p.labels.tapShare));\n const add = el(p.doc, 'li');\n add.append(iconSpan(p.doc, ICONS.add), p.doc.createTextNode(p.labels.tapAdd));\n list.append(share, add);\n return list;\n}\n\nfunction closeButton(p: BannerProps): HTMLButtonElement {\n return button(p.doc, { className: 'gs-x', ariaLabel: p.labels.notNow, icon: ICONS.close, onClick: p.onDismiss });\n}\n\nfunction renderChip(p: BannerProps): HTMLElement[] {\n const seal = el(p.doc, 'div', 'gs-seal');\n if (p.variant === InstallVariant.Prompt) {\n seal.append(button(p.doc, { className: 'gs-chip', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n seal.append(closeButton(p));\n return [seal];\n }\n const steps = renderSteps(p);\n steps.hidden = true;\n const chip = button(p.doc, {\n className: 'gs-chip',\n text: p.labels.addToHome,\n icon: ICONS.add,\n onClick: () => {\n steps.hidden = !steps.hidden;\n chip.setAttribute('aria-expanded', String(!steps.hidden));\n },\n });\n chip.setAttribute('aria-expanded', 'false');\n chip.setAttribute('aria-controls', STEPS_ID);\n seal.append(chip, closeButton(p));\n return [seal, steps];\n}\n\nfunction renderCard(p: BannerProps): HTMLElement[] {\n const card = el(p.doc, 'div', 'gs-card');\n const app = el(p.doc, 'div', 'gs-app');\n app.append(el(p.doc, 'i'));\n const txt = el(p.doc, 'div', 'gs-txt');\n txt.append(el(p.doc, 'b', '', p.appName), el(p.doc, 'span', '', p.labels.installBody));\n const acts = el(p.doc, 'div', 'gs-acts');\n if (p.variant === InstallVariant.Prompt) {\n acts.append(button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n }\n acts.append(button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.notNow, onClick: p.onDismiss }));\n card.append(closeButton(p), app, txt);\n if (p.variant === InstallVariant.Ios) {\n card.append(renderSteps(p));\n }\n card.append(acts);\n return [card];\n}\n\nexport function renderBanner(p: BannerProps): HTMLElement {\n const wrap = el(p.doc, 'div', 'gs gs-install');\n wrap.dataset.layout = p.layout;\n wrap.dataset.variant = p.variant;\n wrap.setAttribute('role', 'region');\n wrap.setAttribute('aria-label', p.variant === InstallVariant.Prompt ? p.labels.install : p.labels.addToHome);\n wrap.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n p.onDismiss();\n }\n });\n wrap.append(...(p.layout === BannerLayout.Card ? renderCard(p) : renderChip(p)));\n return wrap;\n}\n","export const DESKTOP_MIN_WIDTH = 1024;\nconst IOS_DEVICE_RE = /iPad|iPhone|iPod/;\nconst IOS_OTHER_BROWSER_RE = /CriOS|FxiOS|EdgiOS|OPiOS/;\n\ninterface IosNavigator extends Navigator {\n standalone?: boolean;\n}\n\nexport function isStandalone(win: Window): boolean {\n const media = typeof win.matchMedia === 'function' && win.matchMedia('(display-mode: standalone)').matches;\n return media || (win.navigator as IosNavigator).standalone === true;\n}\n\nexport function isIosSafari(win: Window): boolean {\n const ua = win.navigator.userAgent;\n const iPadAsMac = ua.includes('Macintosh') && win.navigator.maxTouchPoints > 1;\n const iosDevice = IOS_DEVICE_RE.test(ua) || iPadAsMac;\n return iosDevice && !IOS_OTHER_BROWSER_RE.test(ua);\n}\n\nexport function isDesktop(win: Window): boolean {\n return win.innerWidth >= DESKTOP_MIN_WIDTH;\n}\n","const DAY_MS = 86_400_000;\n\nexport function snoozeKey(appName: string, override?: string): string {\n return override ?? `gs-install-snooze:${appName}`;\n}\n\nexport function isSnoozed(win: Window, key: string, days: number, now: number): boolean {\n try {\n const raw = win.localStorage.getItem(key);\n if (raw === null) {\n return false;\n }\n const at = Number(raw);\n return Number.isFinite(at) && now - at < days * DAY_MS;\n } catch {\n return false;\n }\n}\n\nexport function writeSnooze(win: Window, key: string, now: number): void {\n try {\n win.localStorage.setItem(key, String(now));\n } catch {\n // Storage blocked (private mode, quota): the banner simply shows again next load.\n }\n}\n","import type { Disposable, InstallLabels } from '../types';\nimport { renderBanner } from './banner';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\nimport { isDesktop, isIosSafari, isStandalone } from './platform';\nimport { isSnoozed, snoozeKey, writeSnooze } from './snooze';\n\nexport const DEFAULT_SNOOZE_DAYS = 14;\nconst ACCEPTED = 'accepted';\n\nexport interface BeforeInstallPromptEvent extends Event {\n prompt(): Promise<void>;\n userChoice: Promise<{ outcome: string }>;\n}\n\nexport interface InstallOptions {\n appName: string;\n labels: InstallLabels;\n snoozeDays?: number;\n storageKey?: string;\n win?: Window;\n now?: () => number;\n}\n\ninterface InstallState {\n deferred: BeforeInstallPromptEvent | null;\n variant: InstallVariant | null;\n node: HTMLElement | null;\n}\n\nfunction createController(opts: InstallOptions, win: Window, now: () => number): {\n state: InstallState;\n mount(): void;\n unmount(): void;\n} {\n const key = snoozeKey(opts.appName, opts.storageKey);\n const state: InstallState = { deferred: null, variant: null, node: null };\n const unmount = (): void => {\n state.node?.remove();\n state.node = null;\n };\n const dismiss = (): void => {\n writeSnooze(win, key, now());\n unmount();\n };\n const install = async (): Promise<void> => {\n const evt = state.deferred;\n state.deferred = null;\n if (!evt) {\n return;\n }\n try {\n await evt.prompt();\n const choice = await evt.userChoice;\n if (choice.outcome === ACCEPTED) {\n unmount();\n return;\n }\n dismiss();\n } catch {\n unmount();\n }\n };\n const mount = (): void => {\n if (state.variant === null) {\n return;\n }\n unmount();\n state.node = renderBanner({\n doc: win.document,\n layout: isDesktop(win) ? BannerLayout.Card : BannerLayout.Chip,\n variant: state.variant,\n appName: opts.appName,\n labels: opts.labels,\n onInstall: () => void install(),\n onDismiss: dismiss,\n });\n win.document.body.append(state.node);\n };\n return { state, mount, unmount };\n}\n\nexport function startInstall(opts: InstallOptions): Disposable {\n const win = opts.win ?? window;\n const now = opts.now ?? ((): number => Date.now());\n const key = snoozeKey(opts.appName, opts.storageKey);\n if (isStandalone(win) || isSnoozed(win, key, opts.snoozeDays ?? DEFAULT_SNOOZE_DAYS, now())) {\n return { dispose: (): void => undefined };\n }\n const ctl = createController(opts, win, now);\n const onPrompt = (e: Event): void => {\n e.preventDefault();\n ctl.state.deferred = e as BeforeInstallPromptEvent;\n ctl.state.variant = InstallVariant.Prompt;\n ctl.mount();\n };\n const onInstalled = (): void => {\n ctl.state.variant = null;\n ctl.unmount();\n };\n const onResize = (): void => {\n const node = ctl.state.node;\n if (node && (node.dataset.layout === BannerLayout.Card) !== isDesktop(win)) {\n ctl.mount();\n }\n };\n win.addEventListener('beforeinstallprompt', onPrompt);\n win.addEventListener('appinstalled', onInstalled);\n win.addEventListener('resize', onResize);\n if (isIosSafari(win)) {\n ctl.state.variant = InstallVariant.Ios;\n ctl.mount();\n }\n return {\n dispose: (): void => {\n win.removeEventListener('beforeinstallprompt', onPrompt);\n win.removeEventListener('appinstalled', onInstalled);\n win.removeEventListener('resize', onResize);\n ctl.unmount();\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport interface LifecycleOptions {\n onHidden?(): void;\n onVisible?(): void;\n}\n\nexport interface ResumableAudio {\n resume(): Promise<void> | void;\n}\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\nconst UNLOCK_EVENTS = ['pointerdown', 'keydown'] as const;\n\nexport function startLifecycle(opts: LifecycleOptions, doc: Document = document): Disposable {\n const onChange = (): void => {\n if (doc.visibilityState === 'hidden') {\n opts.onHidden?.();\n return;\n }\n opts.onVisible?.();\n };\n doc.addEventListener('visibilitychange', onChange);\n return { dispose: (): void => doc.removeEventListener('visibilitychange', onChange) };\n}\n\nexport function unlockAudio(ctx: ResumableAudio, win: Window = window): Disposable {\n const detach = (): void => {\n UNLOCK_EVENTS.forEach((type) => win.removeEventListener(type, onFirst, true));\n };\n function onFirst(): void {\n detach();\n try {\n Promise.resolve(ctx.resume()).catch(() => undefined);\n } catch {\n // A browser that refuses resume() leaves the game silent, never crashed.\n }\n }\n UNLOCK_EVENTS.forEach((type) => win.addEventListener(type, onFirst, true));\n return { dispose: detach };\n}\n\nexport function prefersReducedMotion(win: Window = window): boolean {\n if (new URLSearchParams(win.location.search).get('reducedMotion') === '1') {\n return true;\n }\n return typeof win.matchMedia === 'function' && win.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n","const STYLE_ID = 'gs-styles';\n\nconst THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-card-bottom:60px;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;\n\nconst ROOT = `.gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}`;\n\nconst BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}\n.gs *{box-sizing:border-box}\n.gs button{min-width:44px;min-height:44px;margin:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}\n.gs button:focus-visible{outline:2px solid var(--gs-focus);outline-offset:2px}\n.gs svg{width:20px;height:20px;flex:none}\n.gs-ico{display:inline-flex}\n.gs-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 18px;border-radius:var(--gs-radius);font:700 16px/1 var(--gs-font-text);white-space:nowrap}\n.gs-primary{background:var(--gs-accent);color:var(--gs-on-accent)}\n.gs .gs-ghost{color:var(--gs-ink);border:1px solid var(--gs-edge)}\n.gs-x{width:44px;height:44px;display:grid;place-items:center;color:var(--gs-ink-dim);flex:none}\n.gs-txt{min-width:0}\n.gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}\n.gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`;\n\nconst INSTALL = `.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}\n.gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(var(--gs-card-bottom,60px) + var(--gs-safe-bottom))}\n.gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}\n.gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}\n.gs-chip svg{color:var(--gs-accent)}\n.gs-seal .gs-x{border-left:1px solid var(--gs-edge)}\n.gs-steps{margin:8px 0 0;width:262px;padding:10px 14px;list-style:none;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);display:grid;gap:2px;counter-reset:s}\n.gs-steps[hidden]{display:none}\n.gs-steps li{display:flex;align-items:center;gap:10px;min-height:36px;font-size:15px;color:var(--gs-ink);counter-increment:s}\n.gs-steps li::before{content:counter(s);font:400 15px var(--gs-font-display);color:var(--gs-ink-dim);width:12px}\n.gs-steps svg{width:17px;height:17px;color:var(--gs-accent)}\n.gs-card{position:relative;width:344px;max-width:calc(100vw - 48px);padding:18px;border-radius:var(--gs-radius);background:var(--gs-surface);border:1px solid var(--gs-edge);display:grid;gap:12px}\n.gs-card .gs-x{position:absolute;top:4px;right:4px}\n.gs-card .gs-txt{padding-right:36px}\n.gs-card .gs-acts{display:flex;gap:8px}\n.gs-card .gs-steps{width:auto;margin:0;border:0;padding:0;background:none}\n.gs-app{width:40px;height:40px;border-radius:var(--gs-radius);background:var(--gs-surface-solid);border:1px solid var(--gs-edge);display:grid;place-items:center}\n.gs-app i{width:13px;height:13px;border-radius:50%;background:var(--gs-accent);box-shadow:0 0 10px var(--gs-accent)}`;\n\nconst CRASH = `.gs-crash{position:fixed;inset:0;z-index:2147483001;background:var(--gs-scrim);display:grid;place-items:center;padding:20px}\n.gs-panel{max-width:340px;background:var(--gs-surface-solid);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);padding:24px}\n.gs-h{margin:0;font:400 28px/1.15 var(--gs-font-display);color:var(--gs-ink)}\n.gs-panel p{font-size:16px;line-height:1.5;color:var(--gs-ink-dim);margin:10px 0 0}\n.gs-panel .gs-acts{display:flex;flex-direction:column;gap:8px;margin-top:20px}\n.gs-panel .gs-ref{font:13px ui-monospace,monospace}\n@media (min-width:1024px){.gs-panel{max-width:460px;padding:32px}.gs-panel .gs-acts{flex-direction:row}}`;\n\nexport const GAME_SHELL_CSS = [THEME, ROOT, BASE, INSTALL, CRASH].join('\\n');\n\nexport function injectStyles(doc: Document = document): void {\n if (doc.getElementById(STYLE_ID)) {\n return;\n }\n const style = doc.createElement('style');\n style.id = STYLE_ID;\n style.textContent = GAME_SHELL_CSS;\n doc.head.append(style);\n}\n","import type { Disposable } from '../types';\n\nexport interface VersionPollOptions {\n url: string;\n intervalMs: number;\n onNewVersion(): void;\n fetchFn?: typeof fetch;\n win?: Window;\n}\n\nexport function startVersionPoll(opts: VersionPollOptions): Disposable {\n const win = opts.win ?? window;\n const fetchFn = opts.fetchFn ?? ((input: RequestInfo | URL, init?: RequestInit): Promise<Response> => win.fetch(input, init));\n let baseline: string | null = null;\n let fired = false;\n let busy = false;\n\n const check = async (): Promise<void> => {\n if (fired || busy) {\n return;\n }\n busy = true;\n try {\n const res = await fetchFn(opts.url, { cache: 'no-store' });\n if (!res.ok) {\n return;\n }\n const value = (await res.text()).trim();\n if (baseline === null) {\n baseline = value;\n } else if (value !== baseline) {\n fired = true;\n opts.onNewVersion();\n }\n } catch {\n // Offline or a deploy mid-flight: the next tick tries again.\n } finally {\n busy = false;\n }\n };\n const onVisibility = (): void => {\n if (win.document.visibilityState === 'visible') {\n void check();\n }\n };\n\n void check();\n const timer = win.setInterval(() => void check(), opts.intervalMs);\n win.document.addEventListener('visibilitychange', onVisibility);\n return {\n dispose: (): void => {\n win.clearInterval(timer);\n win.document.removeEventListener('visibilitychange', onVisibility);\n },\n };\n}\n","import { startCrash } from './crash/crash';\nimport type { CrashInfo } from './crash/crashKind';\nimport { startFit } from './fit/fit';\nimport { startInstall } from './install/install';\nimport { startLifecycle, type LifecycleOptions } from './lifecycle/lifecycle';\nimport { injectStyles } from './styles';\nimport type { Disposable, GameShellLabels } from './types';\nimport { startVersionPoll } from './version/versionPoll';\n\nexport interface GameShellOptions {\n root: HTMLElement;\n appName: string;\n labels: GameShellLabels;\n appVersion?: string;\n install?: { snoozeDays?: number; storageKey?: string } | false;\n version?: { url: string; intervalMs: number; onNewVersion(): void };\n crash?: { report?(info: CrashInfo): string | void } | false;\n lifecycle?: LifecycleOptions;\n}\n\nexport function initGameShell(opts: GameShellOptions): Disposable {\n const doc = opts.root.ownerDocument;\n injectStyles(doc);\n opts.root.classList.add('gs-root');\n const parts: Disposable[] = [startFit()];\n if (opts.install !== false) {\n parts.push(startInstall({ appName: opts.appName, labels: opts.labels, ...opts.install }));\n }\n if (opts.crash !== false) {\n parts.push(startCrash({ labels: opts.labels, report: opts.crash?.report, appVersion: opts.appVersion }));\n }\n if (opts.lifecycle) {\n parts.push(startLifecycle(opts.lifecycle, doc));\n }\n if (opts.version) {\n parts.push(startVersionPoll(opts.version));\n }\n return {\n dispose: (): void => {\n parts.forEach((part) => part.dispose());\n opts.root.classList.remove('gs-root');\n },\n };\n}\n"]}
package/dist/index.mjs CHANGED
@@ -437,7 +437,7 @@ function prefersReducedMotion(win = window) {
437
437
 
438
438
  // src/styles.ts
439
439
  var STYLE_ID = "gs-styles";
440
- var THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;
440
+ var THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-card-bottom:60px;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;
441
441
  var ROOT = `.gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}`;
442
442
  var BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}
443
443
  .gs *{box-sizing:border-box}
@@ -453,7 +453,7 @@ var BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:b
453
453
  .gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}
454
454
  .gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`;
455
455
  var INSTALL = `.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}
456
- .gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(24px + var(--gs-safe-bottom))}
456
+ .gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(var(--gs-card-bottom,60px) + var(--gs-safe-bottom))}
457
457
  .gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}
458
458
  .gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}
459
459
  .gs-chip svg{color:var(--gs-accent)}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/crash/crashKind.ts","../src/dom.ts","../src/crash/crashOverlay.ts","../src/crash/crash.ts","../src/fit/fit.ts","../src/icons.ts","../src/install/banner.ts","../src/install/platform.ts","../src/install/snooze.ts","../src/install/install.ts","../src/lifecycle/lifecycle.ts","../src/styles.ts","../src/version/versionPoll.ts","../src/initGameShell.ts"],"names":["svg"],"mappings":"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","file":"index.mjs","sourcesContent":["export const CRASH_KIND = {\n Error: 'error',\n Rejection: 'rejection',\n} as const;\n\nexport type CrashKind = (typeof CRASH_KIND)[keyof typeof CRASH_KIND];\n\nexport interface CrashInfo {\n kind: CrashKind;\n message: string;\n source?: string;\n}\n","export function el<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n className = '',\n text = '',\n): HTMLElementTagNameMap[K] {\n const node = doc.createElement(tag);\n if (className !== '') {\n node.className = className;\n }\n if (text !== '') {\n node.textContent = text;\n }\n return node;\n}\n\nexport function iconSpan(doc: Document, svg: string): HTMLSpanElement {\n const span = el(doc, 'span', 'gs-ico');\n span.innerHTML = svg;\n return span;\n}\n\nexport interface ButtonSpec {\n className: string;\n text?: string;\n ariaLabel?: string;\n icon?: string;\n onClick(): void;\n}\n\nexport function button(doc: Document, spec: ButtonSpec): HTMLButtonElement {\n const btn = el(doc, 'button', spec.className);\n btn.type = 'button';\n if (spec.icon !== undefined) {\n btn.append(iconSpan(doc, spec.icon));\n }\n if (spec.text !== undefined) {\n btn.append(doc.createTextNode(spec.text));\n }\n if (spec.ariaLabel !== undefined) {\n btn.setAttribute('aria-label', spec.ariaLabel);\n }\n btn.addEventListener('click', () => spec.onClick());\n return btn;\n}\n","import { button, el } from '../dom';\nimport type { CrashLabels } from '../types';\n\nexport const CRASH_TITLE_ID = 'gs-crash-title';\nconst CRASH_BODY_ID = 'gs-crash-body';\n\nexport interface CrashOverlayProps {\n doc: Document;\n labels: CrashLabels;\n reference?: string;\n onReload(): void;\n onCopy(): void;\n}\n\nexport interface CrashOverlayView {\n root: HTMLElement;\n reload: HTMLButtonElement;\n}\n\nexport function renderCrashOverlay(p: CrashOverlayProps): CrashOverlayView {\n const root = el(p.doc, 'div', 'gs gs-crash');\n root.setAttribute('role', 'alertdialog');\n root.setAttribute('aria-modal', 'true');\n root.setAttribute('aria-labelledby', CRASH_TITLE_ID);\n root.setAttribute('aria-describedby', CRASH_BODY_ID);\n const panel = el(p.doc, 'div', 'gs-panel');\n const title = el(p.doc, 'h2', 'gs-h', p.labels.crashTitle);\n title.id = CRASH_TITLE_ID;\n const body = el(p.doc, 'p', '', p.labels.crashBody);\n body.id = CRASH_BODY_ID;\n const acts = el(p.doc, 'div', 'gs-acts');\n const reload = button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.reload, onClick: p.onReload });\n acts.append(reload, button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.copyDetails, onClick: p.onCopy }));\n panel.append(title, body, acts);\n if (p.reference !== undefined && p.reference !== '') {\n panel.append(el(p.doc, 'p', 'gs-ref', `${p.labels.errorReported} ${p.reference}`));\n }\n root.append(panel);\n return { root, reload };\n}\n","import type { CrashLabels, Disposable } from '../types';\nimport { CRASH_KIND, type CrashInfo } from './crashKind';\nimport { renderCrashOverlay } from './crashOverlay';\n\nexport interface CrashOptions {\n labels: CrashLabels;\n report?: (info: CrashInfo) => string | void;\n appVersion?: string;\n win?: Window;\n reload?: () => void;\n}\n\nfunction fromErrorEvent(e: ErrorEvent): CrashInfo {\n const err: unknown = e.error;\n const stack = err instanceof Error ? err.stack : undefined;\n const location = e.filename !== '' ? `${e.filename}:${e.lineno}:${e.colno}` : undefined;\n const message = e.message !== '' ? e.message : String(err);\n return { kind: CRASH_KIND.Error, message, source: stack ?? location };\n}\n\nfunction fromRejection(e: Event): CrashInfo {\n const reason: unknown = (e as PromiseRejectionEvent).reason;\n if (reason instanceof Error) {\n return { kind: CRASH_KIND.Rejection, message: reason.message, source: reason.stack };\n }\n return { kind: CRASH_KIND.Rejection, message: String(reason) };\n}\n\nfunction safeReport(opts: CrashOptions, info: CrashInfo): string | undefined {\n try {\n return opts.report?.(info) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction copyDetails(win: Window, info: CrashInfo, appVersion?: string): void {\n const text = [info.message, info.source, appVersion]\n .filter((part): part is string => part !== undefined && part !== '')\n .join('\\n');\n try {\n win.navigator.clipboard.writeText(text).catch(() => undefined);\n } catch {\n // No clipboard API (insecure context): nothing to copy into.\n }\n}\n\nexport function startCrash(opts: CrashOptions): Disposable {\n const win = opts.win ?? window;\n const reload = opts.reload ?? ((): void => win.location.reload());\n let overlay: HTMLElement | null = null;\n\n const handle = (info: CrashInfo): void => {\n const reference = safeReport(opts, info);\n if (overlay) {\n return;\n }\n const view = renderCrashOverlay({\n doc: win.document,\n labels: opts.labels,\n reference,\n onReload: reload,\n onCopy: () => copyDetails(win, info, opts.appVersion),\n });\n overlay = view.root;\n win.document.body.append(overlay);\n view.reload.focus();\n };\n const onError = (e: Event): void => {\n if (e instanceof ErrorEvent) {\n handle(fromErrorEvent(e));\n }\n };\n const onRejection = (e: Event): void => handle(fromRejection(e));\n\n win.addEventListener('error', onError);\n win.addEventListener('unhandledrejection', onRejection);\n return {\n dispose: (): void => {\n win.removeEventListener('error', onError);\n win.removeEventListener('unhandledrejection', onRejection);\n overlay?.remove();\n overlay = null;\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport const GS_RESIZE_EVENT = 'gs:resize';\nexport const GS_VH_VAR = '--gs-vh';\n\nexport interface GsResizeDetail {\n width: number;\n height: number;\n}\n\nfunction measure(win: Window): GsResizeDetail {\n const vv = win.visualViewport;\n if (vv) {\n return { width: vv.width, height: vv.height };\n }\n return { width: win.innerWidth, height: win.innerHeight };\n}\n\nfunction scheduler(win: Window): (cb: () => void) => void {\n if (typeof win.requestAnimationFrame === 'function') {\n return (cb) => {\n win.requestAnimationFrame(() => cb());\n };\n }\n return (cb) => {\n win.setTimeout(cb, 0);\n };\n}\n\nexport function startFit(win: Window = window): Disposable {\n const root = win.document.documentElement;\n const schedule = scheduler(win);\n let last = measure(win);\n let pending = false;\n let disposed = false;\n root.style.setProperty(GS_VH_VAR, `${last.height}px`);\n\n const apply = (): void => {\n pending = false;\n const next = measure(win);\n const unchanged = next.width === last.width && next.height === last.height;\n if (disposed || unchanged) {\n return;\n }\n last = next;\n root.style.setProperty(GS_VH_VAR, `${next.height}px`);\n win.dispatchEvent(new CustomEvent<GsResizeDetail>(GS_RESIZE_EVENT, { detail: next }));\n };\n const onChange = (): void => {\n if (pending) {\n return;\n }\n pending = true;\n schedule(apply);\n };\n\n const vv = win.visualViewport;\n vv?.addEventListener('resize', onChange);\n win.addEventListener('resize', onChange);\n win.addEventListener('orientationchange', onChange);\n return {\n dispose: (): void => {\n disposed = true;\n vv?.removeEventListener('resize', onChange);\n win.removeEventListener('resize', onChange);\n win.removeEventListener('orientationchange', onChange);\n },\n };\n}\n","const svg = (paths: string): string =>\n `<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n\nexport const ICONS = {\n download: svg('<path d=\"M12 4v11M7 10l5 5 5-5M5 20h14\"/>'),\n add: svg('<path d=\"M12 5v14M5 12h14\"/>'),\n close: svg('<path d=\"M6 6l12 12M18 6L6 18\"/>'),\n share: svg('<path d=\"M12 15V4M8 8l4-4 4 4M6 12v8h12v-8\"/>'),\n} as const;\n","import { button, el, iconSpan } from '../dom';\nimport { ICONS } from '../icons';\nimport type { InstallLabels } from '../types';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\n\nexport const STEPS_ID = 'gs-install-steps';\n\nexport interface BannerProps {\n doc: Document;\n layout: BannerLayout;\n variant: InstallVariant;\n appName: string;\n labels: InstallLabels;\n onInstall(): void;\n onDismiss(): void;\n}\n\nfunction renderSteps(p: BannerProps): HTMLOListElement {\n const list = el(p.doc, 'ol', 'gs-steps');\n list.id = STEPS_ID;\n const share = el(p.doc, 'li');\n share.append(iconSpan(p.doc, ICONS.share), p.doc.createTextNode(p.labels.tapShare));\n const add = el(p.doc, 'li');\n add.append(iconSpan(p.doc, ICONS.add), p.doc.createTextNode(p.labels.tapAdd));\n list.append(share, add);\n return list;\n}\n\nfunction closeButton(p: BannerProps): HTMLButtonElement {\n return button(p.doc, { className: 'gs-x', ariaLabel: p.labels.notNow, icon: ICONS.close, onClick: p.onDismiss });\n}\n\nfunction renderChip(p: BannerProps): HTMLElement[] {\n const seal = el(p.doc, 'div', 'gs-seal');\n if (p.variant === InstallVariant.Prompt) {\n seal.append(button(p.doc, { className: 'gs-chip', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n seal.append(closeButton(p));\n return [seal];\n }\n const steps = renderSteps(p);\n steps.hidden = true;\n const chip = button(p.doc, {\n className: 'gs-chip',\n text: p.labels.addToHome,\n icon: ICONS.add,\n onClick: () => {\n steps.hidden = !steps.hidden;\n chip.setAttribute('aria-expanded', String(!steps.hidden));\n },\n });\n chip.setAttribute('aria-expanded', 'false');\n chip.setAttribute('aria-controls', STEPS_ID);\n seal.append(chip, closeButton(p));\n return [seal, steps];\n}\n\nfunction renderCard(p: BannerProps): HTMLElement[] {\n const card = el(p.doc, 'div', 'gs-card');\n const app = el(p.doc, 'div', 'gs-app');\n app.append(el(p.doc, 'i'));\n const txt = el(p.doc, 'div', 'gs-txt');\n txt.append(el(p.doc, 'b', '', p.appName), el(p.doc, 'span', '', p.labels.installBody));\n const acts = el(p.doc, 'div', 'gs-acts');\n if (p.variant === InstallVariant.Prompt) {\n acts.append(button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n }\n acts.append(button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.notNow, onClick: p.onDismiss }));\n card.append(closeButton(p), app, txt);\n if (p.variant === InstallVariant.Ios) {\n card.append(renderSteps(p));\n }\n card.append(acts);\n return [card];\n}\n\nexport function renderBanner(p: BannerProps): HTMLElement {\n const wrap = el(p.doc, 'div', 'gs gs-install');\n wrap.dataset.layout = p.layout;\n wrap.dataset.variant = p.variant;\n wrap.setAttribute('role', 'region');\n wrap.setAttribute('aria-label', p.variant === InstallVariant.Prompt ? p.labels.install : p.labels.addToHome);\n wrap.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n p.onDismiss();\n }\n });\n wrap.append(...(p.layout === BannerLayout.Card ? renderCard(p) : renderChip(p)));\n return wrap;\n}\n","export const DESKTOP_MIN_WIDTH = 1024;\nconst IOS_DEVICE_RE = /iPad|iPhone|iPod/;\nconst IOS_OTHER_BROWSER_RE = /CriOS|FxiOS|EdgiOS|OPiOS/;\n\ninterface IosNavigator extends Navigator {\n standalone?: boolean;\n}\n\nexport function isStandalone(win: Window): boolean {\n const media = typeof win.matchMedia === 'function' && win.matchMedia('(display-mode: standalone)').matches;\n return media || (win.navigator as IosNavigator).standalone === true;\n}\n\nexport function isIosSafari(win: Window): boolean {\n const ua = win.navigator.userAgent;\n const iPadAsMac = ua.includes('Macintosh') && win.navigator.maxTouchPoints > 1;\n const iosDevice = IOS_DEVICE_RE.test(ua) || iPadAsMac;\n return iosDevice && !IOS_OTHER_BROWSER_RE.test(ua);\n}\n\nexport function isDesktop(win: Window): boolean {\n return win.innerWidth >= DESKTOP_MIN_WIDTH;\n}\n","const DAY_MS = 86_400_000;\n\nexport function snoozeKey(appName: string, override?: string): string {\n return override ?? `gs-install-snooze:${appName}`;\n}\n\nexport function isSnoozed(win: Window, key: string, days: number, now: number): boolean {\n try {\n const raw = win.localStorage.getItem(key);\n if (raw === null) {\n return false;\n }\n const at = Number(raw);\n return Number.isFinite(at) && now - at < days * DAY_MS;\n } catch {\n return false;\n }\n}\n\nexport function writeSnooze(win: Window, key: string, now: number): void {\n try {\n win.localStorage.setItem(key, String(now));\n } catch {\n // Storage blocked (private mode, quota): the banner simply shows again next load.\n }\n}\n","import type { Disposable, InstallLabels } from '../types';\nimport { renderBanner } from './banner';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\nimport { isDesktop, isIosSafari, isStandalone } from './platform';\nimport { isSnoozed, snoozeKey, writeSnooze } from './snooze';\n\nexport const DEFAULT_SNOOZE_DAYS = 14;\nconst ACCEPTED = 'accepted';\n\nexport interface BeforeInstallPromptEvent extends Event {\n prompt(): Promise<void>;\n userChoice: Promise<{ outcome: string }>;\n}\n\nexport interface InstallOptions {\n appName: string;\n labels: InstallLabels;\n snoozeDays?: number;\n storageKey?: string;\n win?: Window;\n now?: () => number;\n}\n\ninterface InstallState {\n deferred: BeforeInstallPromptEvent | null;\n variant: InstallVariant | null;\n node: HTMLElement | null;\n}\n\nfunction createController(opts: InstallOptions, win: Window, now: () => number): {\n state: InstallState;\n mount(): void;\n unmount(): void;\n} {\n const key = snoozeKey(opts.appName, opts.storageKey);\n const state: InstallState = { deferred: null, variant: null, node: null };\n const unmount = (): void => {\n state.node?.remove();\n state.node = null;\n };\n const dismiss = (): void => {\n writeSnooze(win, key, now());\n unmount();\n };\n const install = async (): Promise<void> => {\n const evt = state.deferred;\n state.deferred = null;\n if (!evt) {\n return;\n }\n try {\n await evt.prompt();\n const choice = await evt.userChoice;\n if (choice.outcome === ACCEPTED) {\n unmount();\n return;\n }\n dismiss();\n } catch {\n unmount();\n }\n };\n const mount = (): void => {\n if (state.variant === null) {\n return;\n }\n unmount();\n state.node = renderBanner({\n doc: win.document,\n layout: isDesktop(win) ? BannerLayout.Card : BannerLayout.Chip,\n variant: state.variant,\n appName: opts.appName,\n labels: opts.labels,\n onInstall: () => void install(),\n onDismiss: dismiss,\n });\n win.document.body.append(state.node);\n };\n return { state, mount, unmount };\n}\n\nexport function startInstall(opts: InstallOptions): Disposable {\n const win = opts.win ?? window;\n const now = opts.now ?? ((): number => Date.now());\n const key = snoozeKey(opts.appName, opts.storageKey);\n if (isStandalone(win) || isSnoozed(win, key, opts.snoozeDays ?? DEFAULT_SNOOZE_DAYS, now())) {\n return { dispose: (): void => undefined };\n }\n const ctl = createController(opts, win, now);\n const onPrompt = (e: Event): void => {\n e.preventDefault();\n ctl.state.deferred = e as BeforeInstallPromptEvent;\n ctl.state.variant = InstallVariant.Prompt;\n ctl.mount();\n };\n const onInstalled = (): void => {\n ctl.state.variant = null;\n ctl.unmount();\n };\n const onResize = (): void => {\n const node = ctl.state.node;\n if (node && (node.dataset.layout === BannerLayout.Card) !== isDesktop(win)) {\n ctl.mount();\n }\n };\n win.addEventListener('beforeinstallprompt', onPrompt);\n win.addEventListener('appinstalled', onInstalled);\n win.addEventListener('resize', onResize);\n if (isIosSafari(win)) {\n ctl.state.variant = InstallVariant.Ios;\n ctl.mount();\n }\n return {\n dispose: (): void => {\n win.removeEventListener('beforeinstallprompt', onPrompt);\n win.removeEventListener('appinstalled', onInstalled);\n win.removeEventListener('resize', onResize);\n ctl.unmount();\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport interface LifecycleOptions {\n onHidden?(): void;\n onVisible?(): void;\n}\n\nexport interface ResumableAudio {\n resume(): Promise<void> | void;\n}\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\nconst UNLOCK_EVENTS = ['pointerdown', 'keydown'] as const;\n\nexport function startLifecycle(opts: LifecycleOptions, doc: Document = document): Disposable {\n const onChange = (): void => {\n if (doc.visibilityState === 'hidden') {\n opts.onHidden?.();\n return;\n }\n opts.onVisible?.();\n };\n doc.addEventListener('visibilitychange', onChange);\n return { dispose: (): void => doc.removeEventListener('visibilitychange', onChange) };\n}\n\nexport function unlockAudio(ctx: ResumableAudio, win: Window = window): Disposable {\n const detach = (): void => {\n UNLOCK_EVENTS.forEach((type) => win.removeEventListener(type, onFirst, true));\n };\n function onFirst(): void {\n detach();\n try {\n Promise.resolve(ctx.resume()).catch(() => undefined);\n } catch {\n // A browser that refuses resume() leaves the game silent, never crashed.\n }\n }\n UNLOCK_EVENTS.forEach((type) => win.addEventListener(type, onFirst, true));\n return { dispose: detach };\n}\n\nexport function prefersReducedMotion(win: Window = window): boolean {\n if (new URLSearchParams(win.location.search).get('reducedMotion') === '1') {\n return true;\n }\n return typeof win.matchMedia === 'function' && win.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n","const STYLE_ID = 'gs-styles';\n\nconst THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;\n\nconst ROOT = `.gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}`;\n\nconst BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}\n.gs *{box-sizing:border-box}\n.gs button{min-width:44px;min-height:44px;margin:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}\n.gs button:focus-visible{outline:2px solid var(--gs-focus);outline-offset:2px}\n.gs svg{width:20px;height:20px;flex:none}\n.gs-ico{display:inline-flex}\n.gs-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 18px;border-radius:var(--gs-radius);font:700 16px/1 var(--gs-font-text);white-space:nowrap}\n.gs-primary{background:var(--gs-accent);color:var(--gs-on-accent)}\n.gs .gs-ghost{color:var(--gs-ink);border:1px solid var(--gs-edge)}\n.gs-x{width:44px;height:44px;display:grid;place-items:center;color:var(--gs-ink-dim);flex:none}\n.gs-txt{min-width:0}\n.gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}\n.gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`;\n\nconst INSTALL = `.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}\n.gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(24px + var(--gs-safe-bottom))}\n.gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}\n.gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}\n.gs-chip svg{color:var(--gs-accent)}\n.gs-seal .gs-x{border-left:1px solid var(--gs-edge)}\n.gs-steps{margin:8px 0 0;width:262px;padding:10px 14px;list-style:none;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);display:grid;gap:2px;counter-reset:s}\n.gs-steps[hidden]{display:none}\n.gs-steps li{display:flex;align-items:center;gap:10px;min-height:36px;font-size:15px;color:var(--gs-ink);counter-increment:s}\n.gs-steps li::before{content:counter(s);font:400 15px var(--gs-font-display);color:var(--gs-ink-dim);width:12px}\n.gs-steps svg{width:17px;height:17px;color:var(--gs-accent)}\n.gs-card{position:relative;width:344px;max-width:calc(100vw - 48px);padding:18px;border-radius:var(--gs-radius);background:var(--gs-surface);border:1px solid var(--gs-edge);display:grid;gap:12px}\n.gs-card .gs-x{position:absolute;top:4px;right:4px}\n.gs-card .gs-txt{padding-right:36px}\n.gs-card .gs-acts{display:flex;gap:8px}\n.gs-card .gs-steps{width:auto;margin:0;border:0;padding:0;background:none}\n.gs-app{width:40px;height:40px;border-radius:var(--gs-radius);background:var(--gs-surface-solid);border:1px solid var(--gs-edge);display:grid;place-items:center}\n.gs-app i{width:13px;height:13px;border-radius:50%;background:var(--gs-accent);box-shadow:0 0 10px var(--gs-accent)}`;\n\nconst CRASH = `.gs-crash{position:fixed;inset:0;z-index:2147483001;background:var(--gs-scrim);display:grid;place-items:center;padding:20px}\n.gs-panel{max-width:340px;background:var(--gs-surface-solid);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);padding:24px}\n.gs-h{margin:0;font:400 28px/1.15 var(--gs-font-display);color:var(--gs-ink)}\n.gs-panel p{font-size:16px;line-height:1.5;color:var(--gs-ink-dim);margin:10px 0 0}\n.gs-panel .gs-acts{display:flex;flex-direction:column;gap:8px;margin-top:20px}\n.gs-panel .gs-ref{font:13px ui-monospace,monospace}\n@media (min-width:1024px){.gs-panel{max-width:460px;padding:32px}.gs-panel .gs-acts{flex-direction:row}}`;\n\nexport const GAME_SHELL_CSS = [THEME, ROOT, BASE, INSTALL, CRASH].join('\\n');\n\nexport function injectStyles(doc: Document = document): void {\n if (doc.getElementById(STYLE_ID)) {\n return;\n }\n const style = doc.createElement('style');\n style.id = STYLE_ID;\n style.textContent = GAME_SHELL_CSS;\n doc.head.append(style);\n}\n","import type { Disposable } from '../types';\n\nexport interface VersionPollOptions {\n url: string;\n intervalMs: number;\n onNewVersion(): void;\n fetchFn?: typeof fetch;\n win?: Window;\n}\n\nexport function startVersionPoll(opts: VersionPollOptions): Disposable {\n const win = opts.win ?? window;\n const fetchFn = opts.fetchFn ?? ((input: RequestInfo | URL, init?: RequestInit): Promise<Response> => win.fetch(input, init));\n let baseline: string | null = null;\n let fired = false;\n let busy = false;\n\n const check = async (): Promise<void> => {\n if (fired || busy) {\n return;\n }\n busy = true;\n try {\n const res = await fetchFn(opts.url, { cache: 'no-store' });\n if (!res.ok) {\n return;\n }\n const value = (await res.text()).trim();\n if (baseline === null) {\n baseline = value;\n } else if (value !== baseline) {\n fired = true;\n opts.onNewVersion();\n }\n } catch {\n // Offline or a deploy mid-flight: the next tick tries again.\n } finally {\n busy = false;\n }\n };\n const onVisibility = (): void => {\n if (win.document.visibilityState === 'visible') {\n void check();\n }\n };\n\n void check();\n const timer = win.setInterval(() => void check(), opts.intervalMs);\n win.document.addEventListener('visibilitychange', onVisibility);\n return {\n dispose: (): void => {\n win.clearInterval(timer);\n win.document.removeEventListener('visibilitychange', onVisibility);\n },\n };\n}\n","import { startCrash } from './crash/crash';\nimport type { CrashInfo } from './crash/crashKind';\nimport { startFit } from './fit/fit';\nimport { startInstall } from './install/install';\nimport { startLifecycle, type LifecycleOptions } from './lifecycle/lifecycle';\nimport { injectStyles } from './styles';\nimport type { Disposable, GameShellLabels } from './types';\nimport { startVersionPoll } from './version/versionPoll';\n\nexport interface GameShellOptions {\n root: HTMLElement;\n appName: string;\n labels: GameShellLabels;\n appVersion?: string;\n install?: { snoozeDays?: number; storageKey?: string } | false;\n version?: { url: string; intervalMs: number; onNewVersion(): void };\n crash?: { report?(info: CrashInfo): string | void } | false;\n lifecycle?: LifecycleOptions;\n}\n\nexport function initGameShell(opts: GameShellOptions): Disposable {\n const doc = opts.root.ownerDocument;\n injectStyles(doc);\n opts.root.classList.add('gs-root');\n const parts: Disposable[] = [startFit()];\n if (opts.install !== false) {\n parts.push(startInstall({ appName: opts.appName, labels: opts.labels, ...opts.install }));\n }\n if (opts.crash !== false) {\n parts.push(startCrash({ labels: opts.labels, report: opts.crash?.report, appVersion: opts.appVersion }));\n }\n if (opts.lifecycle) {\n parts.push(startLifecycle(opts.lifecycle, doc));\n }\n if (opts.version) {\n parts.push(startVersionPoll(opts.version));\n }\n return {\n dispose: (): void => {\n parts.forEach((part) => part.dispose());\n opts.root.classList.remove('gs-root');\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/crash/crashKind.ts","../src/dom.ts","../src/crash/crashOverlay.ts","../src/crash/crash.ts","../src/fit/fit.ts","../src/icons.ts","../src/install/banner.ts","../src/install/platform.ts","../src/install/snooze.ts","../src/install/install.ts","../src/lifecycle/lifecycle.ts","../src/styles.ts","../src/version/versionPoll.ts","../src/initGameShell.ts"],"names":["svg"],"mappings":"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","file":"index.mjs","sourcesContent":["export const CRASH_KIND = {\n Error: 'error',\n Rejection: 'rejection',\n} as const;\n\nexport type CrashKind = (typeof CRASH_KIND)[keyof typeof CRASH_KIND];\n\nexport interface CrashInfo {\n kind: CrashKind;\n message: string;\n source?: string;\n}\n","export function el<K extends keyof HTMLElementTagNameMap>(\n doc: Document,\n tag: K,\n className = '',\n text = '',\n): HTMLElementTagNameMap[K] {\n const node = doc.createElement(tag);\n if (className !== '') {\n node.className = className;\n }\n if (text !== '') {\n node.textContent = text;\n }\n return node;\n}\n\nexport function iconSpan(doc: Document, svg: string): HTMLSpanElement {\n const span = el(doc, 'span', 'gs-ico');\n span.innerHTML = svg;\n return span;\n}\n\nexport interface ButtonSpec {\n className: string;\n text?: string;\n ariaLabel?: string;\n icon?: string;\n onClick(): void;\n}\n\nexport function button(doc: Document, spec: ButtonSpec): HTMLButtonElement {\n const btn = el(doc, 'button', spec.className);\n btn.type = 'button';\n if (spec.icon !== undefined) {\n btn.append(iconSpan(doc, spec.icon));\n }\n if (spec.text !== undefined) {\n btn.append(doc.createTextNode(spec.text));\n }\n if (spec.ariaLabel !== undefined) {\n btn.setAttribute('aria-label', spec.ariaLabel);\n }\n btn.addEventListener('click', () => spec.onClick());\n return btn;\n}\n","import { button, el } from '../dom';\nimport type { CrashLabels } from '../types';\n\nexport const CRASH_TITLE_ID = 'gs-crash-title';\nconst CRASH_BODY_ID = 'gs-crash-body';\n\nexport interface CrashOverlayProps {\n doc: Document;\n labels: CrashLabels;\n reference?: string;\n onReload(): void;\n onCopy(): void;\n}\n\nexport interface CrashOverlayView {\n root: HTMLElement;\n reload: HTMLButtonElement;\n}\n\nexport function renderCrashOverlay(p: CrashOverlayProps): CrashOverlayView {\n const root = el(p.doc, 'div', 'gs gs-crash');\n root.setAttribute('role', 'alertdialog');\n root.setAttribute('aria-modal', 'true');\n root.setAttribute('aria-labelledby', CRASH_TITLE_ID);\n root.setAttribute('aria-describedby', CRASH_BODY_ID);\n const panel = el(p.doc, 'div', 'gs-panel');\n const title = el(p.doc, 'h2', 'gs-h', p.labels.crashTitle);\n title.id = CRASH_TITLE_ID;\n const body = el(p.doc, 'p', '', p.labels.crashBody);\n body.id = CRASH_BODY_ID;\n const acts = el(p.doc, 'div', 'gs-acts');\n const reload = button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.reload, onClick: p.onReload });\n acts.append(reload, button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.copyDetails, onClick: p.onCopy }));\n panel.append(title, body, acts);\n if (p.reference !== undefined && p.reference !== '') {\n panel.append(el(p.doc, 'p', 'gs-ref', `${p.labels.errorReported} ${p.reference}`));\n }\n root.append(panel);\n return { root, reload };\n}\n","import type { CrashLabels, Disposable } from '../types';\nimport { CRASH_KIND, type CrashInfo } from './crashKind';\nimport { renderCrashOverlay } from './crashOverlay';\n\nexport interface CrashOptions {\n labels: CrashLabels;\n report?: (info: CrashInfo) => string | void;\n appVersion?: string;\n win?: Window;\n reload?: () => void;\n}\n\nfunction fromErrorEvent(e: ErrorEvent): CrashInfo {\n const err: unknown = e.error;\n const stack = err instanceof Error ? err.stack : undefined;\n const location = e.filename !== '' ? `${e.filename}:${e.lineno}:${e.colno}` : undefined;\n const message = e.message !== '' ? e.message : String(err);\n return { kind: CRASH_KIND.Error, message, source: stack ?? location };\n}\n\nfunction fromRejection(e: Event): CrashInfo {\n const reason: unknown = (e as PromiseRejectionEvent).reason;\n if (reason instanceof Error) {\n return { kind: CRASH_KIND.Rejection, message: reason.message, source: reason.stack };\n }\n return { kind: CRASH_KIND.Rejection, message: String(reason) };\n}\n\nfunction safeReport(opts: CrashOptions, info: CrashInfo): string | undefined {\n try {\n return opts.report?.(info) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction copyDetails(win: Window, info: CrashInfo, appVersion?: string): void {\n const text = [info.message, info.source, appVersion]\n .filter((part): part is string => part !== undefined && part !== '')\n .join('\\n');\n try {\n win.navigator.clipboard.writeText(text).catch(() => undefined);\n } catch {\n // No clipboard API (insecure context): nothing to copy into.\n }\n}\n\nexport function startCrash(opts: CrashOptions): Disposable {\n const win = opts.win ?? window;\n const reload = opts.reload ?? ((): void => win.location.reload());\n let overlay: HTMLElement | null = null;\n\n const handle = (info: CrashInfo): void => {\n const reference = safeReport(opts, info);\n if (overlay) {\n return;\n }\n const view = renderCrashOverlay({\n doc: win.document,\n labels: opts.labels,\n reference,\n onReload: reload,\n onCopy: () => copyDetails(win, info, opts.appVersion),\n });\n overlay = view.root;\n win.document.body.append(overlay);\n view.reload.focus();\n };\n const onError = (e: Event): void => {\n if (e instanceof ErrorEvent) {\n handle(fromErrorEvent(e));\n }\n };\n const onRejection = (e: Event): void => handle(fromRejection(e));\n\n win.addEventListener('error', onError);\n win.addEventListener('unhandledrejection', onRejection);\n return {\n dispose: (): void => {\n win.removeEventListener('error', onError);\n win.removeEventListener('unhandledrejection', onRejection);\n overlay?.remove();\n overlay = null;\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport const GS_RESIZE_EVENT = 'gs:resize';\nexport const GS_VH_VAR = '--gs-vh';\n\nexport interface GsResizeDetail {\n width: number;\n height: number;\n}\n\nfunction measure(win: Window): GsResizeDetail {\n const vv = win.visualViewport;\n if (vv) {\n return { width: vv.width, height: vv.height };\n }\n return { width: win.innerWidth, height: win.innerHeight };\n}\n\nfunction scheduler(win: Window): (cb: () => void) => void {\n if (typeof win.requestAnimationFrame === 'function') {\n return (cb) => {\n win.requestAnimationFrame(() => cb());\n };\n }\n return (cb) => {\n win.setTimeout(cb, 0);\n };\n}\n\nexport function startFit(win: Window = window): Disposable {\n const root = win.document.documentElement;\n const schedule = scheduler(win);\n let last = measure(win);\n let pending = false;\n let disposed = false;\n root.style.setProperty(GS_VH_VAR, `${last.height}px`);\n\n const apply = (): void => {\n pending = false;\n const next = measure(win);\n const unchanged = next.width === last.width && next.height === last.height;\n if (disposed || unchanged) {\n return;\n }\n last = next;\n root.style.setProperty(GS_VH_VAR, `${next.height}px`);\n win.dispatchEvent(new CustomEvent<GsResizeDetail>(GS_RESIZE_EVENT, { detail: next }));\n };\n const onChange = (): void => {\n if (pending) {\n return;\n }\n pending = true;\n schedule(apply);\n };\n\n const vv = win.visualViewport;\n vv?.addEventListener('resize', onChange);\n win.addEventListener('resize', onChange);\n win.addEventListener('orientationchange', onChange);\n return {\n dispose: (): void => {\n disposed = true;\n vv?.removeEventListener('resize', onChange);\n win.removeEventListener('resize', onChange);\n win.removeEventListener('orientationchange', onChange);\n },\n };\n}\n","const svg = (paths: string): string =>\n `<svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n\nexport const ICONS = {\n download: svg('<path d=\"M12 4v11M7 10l5 5 5-5M5 20h14\"/>'),\n add: svg('<path d=\"M12 5v14M5 12h14\"/>'),\n close: svg('<path d=\"M6 6l12 12M18 6L6 18\"/>'),\n share: svg('<path d=\"M12 15V4M8 8l4-4 4 4M6 12v8h12v-8\"/>'),\n} as const;\n","import { button, el, iconSpan } from '../dom';\nimport { ICONS } from '../icons';\nimport type { InstallLabels } from '../types';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\n\nexport const STEPS_ID = 'gs-install-steps';\n\nexport interface BannerProps {\n doc: Document;\n layout: BannerLayout;\n variant: InstallVariant;\n appName: string;\n labels: InstallLabels;\n onInstall(): void;\n onDismiss(): void;\n}\n\nfunction renderSteps(p: BannerProps): HTMLOListElement {\n const list = el(p.doc, 'ol', 'gs-steps');\n list.id = STEPS_ID;\n const share = el(p.doc, 'li');\n share.append(iconSpan(p.doc, ICONS.share), p.doc.createTextNode(p.labels.tapShare));\n const add = el(p.doc, 'li');\n add.append(iconSpan(p.doc, ICONS.add), p.doc.createTextNode(p.labels.tapAdd));\n list.append(share, add);\n return list;\n}\n\nfunction closeButton(p: BannerProps): HTMLButtonElement {\n return button(p.doc, { className: 'gs-x', ariaLabel: p.labels.notNow, icon: ICONS.close, onClick: p.onDismiss });\n}\n\nfunction renderChip(p: BannerProps): HTMLElement[] {\n const seal = el(p.doc, 'div', 'gs-seal');\n if (p.variant === InstallVariant.Prompt) {\n seal.append(button(p.doc, { className: 'gs-chip', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n seal.append(closeButton(p));\n return [seal];\n }\n const steps = renderSteps(p);\n steps.hidden = true;\n const chip = button(p.doc, {\n className: 'gs-chip',\n text: p.labels.addToHome,\n icon: ICONS.add,\n onClick: () => {\n steps.hidden = !steps.hidden;\n chip.setAttribute('aria-expanded', String(!steps.hidden));\n },\n });\n chip.setAttribute('aria-expanded', 'false');\n chip.setAttribute('aria-controls', STEPS_ID);\n seal.append(chip, closeButton(p));\n return [seal, steps];\n}\n\nfunction renderCard(p: BannerProps): HTMLElement[] {\n const card = el(p.doc, 'div', 'gs-card');\n const app = el(p.doc, 'div', 'gs-app');\n app.append(el(p.doc, 'i'));\n const txt = el(p.doc, 'div', 'gs-txt');\n txt.append(el(p.doc, 'b', '', p.appName), el(p.doc, 'span', '', p.labels.installBody));\n const acts = el(p.doc, 'div', 'gs-acts');\n if (p.variant === InstallVariant.Prompt) {\n acts.append(button(p.doc, { className: 'gs-btn gs-primary', text: p.labels.install, icon: ICONS.download, onClick: p.onInstall }));\n }\n acts.append(button(p.doc, { className: 'gs-btn gs-ghost', text: p.labels.notNow, onClick: p.onDismiss }));\n card.append(closeButton(p), app, txt);\n if (p.variant === InstallVariant.Ios) {\n card.append(renderSteps(p));\n }\n card.append(acts);\n return [card];\n}\n\nexport function renderBanner(p: BannerProps): HTMLElement {\n const wrap = el(p.doc, 'div', 'gs gs-install');\n wrap.dataset.layout = p.layout;\n wrap.dataset.variant = p.variant;\n wrap.setAttribute('role', 'region');\n wrap.setAttribute('aria-label', p.variant === InstallVariant.Prompt ? p.labels.install : p.labels.addToHome);\n wrap.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n p.onDismiss();\n }\n });\n wrap.append(...(p.layout === BannerLayout.Card ? renderCard(p) : renderChip(p)));\n return wrap;\n}\n","export const DESKTOP_MIN_WIDTH = 1024;\nconst IOS_DEVICE_RE = /iPad|iPhone|iPod/;\nconst IOS_OTHER_BROWSER_RE = /CriOS|FxiOS|EdgiOS|OPiOS/;\n\ninterface IosNavigator extends Navigator {\n standalone?: boolean;\n}\n\nexport function isStandalone(win: Window): boolean {\n const media = typeof win.matchMedia === 'function' && win.matchMedia('(display-mode: standalone)').matches;\n return media || (win.navigator as IosNavigator).standalone === true;\n}\n\nexport function isIosSafari(win: Window): boolean {\n const ua = win.navigator.userAgent;\n const iPadAsMac = ua.includes('Macintosh') && win.navigator.maxTouchPoints > 1;\n const iosDevice = IOS_DEVICE_RE.test(ua) || iPadAsMac;\n return iosDevice && !IOS_OTHER_BROWSER_RE.test(ua);\n}\n\nexport function isDesktop(win: Window): boolean {\n return win.innerWidth >= DESKTOP_MIN_WIDTH;\n}\n","const DAY_MS = 86_400_000;\n\nexport function snoozeKey(appName: string, override?: string): string {\n return override ?? `gs-install-snooze:${appName}`;\n}\n\nexport function isSnoozed(win: Window, key: string, days: number, now: number): boolean {\n try {\n const raw = win.localStorage.getItem(key);\n if (raw === null) {\n return false;\n }\n const at = Number(raw);\n return Number.isFinite(at) && now - at < days * DAY_MS;\n } catch {\n return false;\n }\n}\n\nexport function writeSnooze(win: Window, key: string, now: number): void {\n try {\n win.localStorage.setItem(key, String(now));\n } catch {\n // Storage blocked (private mode, quota): the banner simply shows again next load.\n }\n}\n","import type { Disposable, InstallLabels } from '../types';\nimport { renderBanner } from './banner';\nimport { BannerLayout } from './BannerLayout';\nimport { InstallVariant } from './InstallVariant';\nimport { isDesktop, isIosSafari, isStandalone } from './platform';\nimport { isSnoozed, snoozeKey, writeSnooze } from './snooze';\n\nexport const DEFAULT_SNOOZE_DAYS = 14;\nconst ACCEPTED = 'accepted';\n\nexport interface BeforeInstallPromptEvent extends Event {\n prompt(): Promise<void>;\n userChoice: Promise<{ outcome: string }>;\n}\n\nexport interface InstallOptions {\n appName: string;\n labels: InstallLabels;\n snoozeDays?: number;\n storageKey?: string;\n win?: Window;\n now?: () => number;\n}\n\ninterface InstallState {\n deferred: BeforeInstallPromptEvent | null;\n variant: InstallVariant | null;\n node: HTMLElement | null;\n}\n\nfunction createController(opts: InstallOptions, win: Window, now: () => number): {\n state: InstallState;\n mount(): void;\n unmount(): void;\n} {\n const key = snoozeKey(opts.appName, opts.storageKey);\n const state: InstallState = { deferred: null, variant: null, node: null };\n const unmount = (): void => {\n state.node?.remove();\n state.node = null;\n };\n const dismiss = (): void => {\n writeSnooze(win, key, now());\n unmount();\n };\n const install = async (): Promise<void> => {\n const evt = state.deferred;\n state.deferred = null;\n if (!evt) {\n return;\n }\n try {\n await evt.prompt();\n const choice = await evt.userChoice;\n if (choice.outcome === ACCEPTED) {\n unmount();\n return;\n }\n dismiss();\n } catch {\n unmount();\n }\n };\n const mount = (): void => {\n if (state.variant === null) {\n return;\n }\n unmount();\n state.node = renderBanner({\n doc: win.document,\n layout: isDesktop(win) ? BannerLayout.Card : BannerLayout.Chip,\n variant: state.variant,\n appName: opts.appName,\n labels: opts.labels,\n onInstall: () => void install(),\n onDismiss: dismiss,\n });\n win.document.body.append(state.node);\n };\n return { state, mount, unmount };\n}\n\nexport function startInstall(opts: InstallOptions): Disposable {\n const win = opts.win ?? window;\n const now = opts.now ?? ((): number => Date.now());\n const key = snoozeKey(opts.appName, opts.storageKey);\n if (isStandalone(win) || isSnoozed(win, key, opts.snoozeDays ?? DEFAULT_SNOOZE_DAYS, now())) {\n return { dispose: (): void => undefined };\n }\n const ctl = createController(opts, win, now);\n const onPrompt = (e: Event): void => {\n e.preventDefault();\n ctl.state.deferred = e as BeforeInstallPromptEvent;\n ctl.state.variant = InstallVariant.Prompt;\n ctl.mount();\n };\n const onInstalled = (): void => {\n ctl.state.variant = null;\n ctl.unmount();\n };\n const onResize = (): void => {\n const node = ctl.state.node;\n if (node && (node.dataset.layout === BannerLayout.Card) !== isDesktop(win)) {\n ctl.mount();\n }\n };\n win.addEventListener('beforeinstallprompt', onPrompt);\n win.addEventListener('appinstalled', onInstalled);\n win.addEventListener('resize', onResize);\n if (isIosSafari(win)) {\n ctl.state.variant = InstallVariant.Ios;\n ctl.mount();\n }\n return {\n dispose: (): void => {\n win.removeEventListener('beforeinstallprompt', onPrompt);\n win.removeEventListener('appinstalled', onInstalled);\n win.removeEventListener('resize', onResize);\n ctl.unmount();\n },\n };\n}\n","import type { Disposable } from '../types';\n\nexport interface LifecycleOptions {\n onHidden?(): void;\n onVisible?(): void;\n}\n\nexport interface ResumableAudio {\n resume(): Promise<void> | void;\n}\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\nconst UNLOCK_EVENTS = ['pointerdown', 'keydown'] as const;\n\nexport function startLifecycle(opts: LifecycleOptions, doc: Document = document): Disposable {\n const onChange = (): void => {\n if (doc.visibilityState === 'hidden') {\n opts.onHidden?.();\n return;\n }\n opts.onVisible?.();\n };\n doc.addEventListener('visibilitychange', onChange);\n return { dispose: (): void => doc.removeEventListener('visibilitychange', onChange) };\n}\n\nexport function unlockAudio(ctx: ResumableAudio, win: Window = window): Disposable {\n const detach = (): void => {\n UNLOCK_EVENTS.forEach((type) => win.removeEventListener(type, onFirst, true));\n };\n function onFirst(): void {\n detach();\n try {\n Promise.resolve(ctx.resume()).catch(() => undefined);\n } catch {\n // A browser that refuses resume() leaves the game silent, never crashed.\n }\n }\n UNLOCK_EVENTS.forEach((type) => win.addEventListener(type, onFirst, true));\n return { dispose: detach };\n}\n\nexport function prefersReducedMotion(win: Window = window): boolean {\n if (new URLSearchParams(win.location.search).get('reducedMotion') === '1') {\n return true;\n }\n return typeof win.matchMedia === 'function' && win.matchMedia(REDUCED_MOTION_QUERY).matches;\n}\n","const STYLE_ID = 'gs-styles';\n\nconst THEME = `:where(:root){--gs-font-display:system-ui,'Segoe UI',sans-serif;--gs-font-text:system-ui,'Segoe UI',sans-serif;--gs-surface:rgba(24,26,29,.95);--gs-surface-solid:#181a1d;--gs-edge:#41464d;--gs-ink:#f3f3f1;--gs-ink-dim:#b9bdc2;--gs-accent:#f3f3f1;--gs-on-accent:#181a1d;--gs-scrim:rgba(0,0,0,.72);--gs-radius:12px;--gs-radius-pill:12px;--gs-focus:#9cc2ff;--gs-card-bottom:60px;--gs-safe-top:env(safe-area-inset-top,0px);--gs-safe-right:env(safe-area-inset-right,0px);--gs-safe-bottom:env(safe-area-inset-bottom,0px);--gs-safe-left:env(safe-area-inset-left,0px)}`;\n\nconst ROOT = `.gs-root{width:100%;height:100vh;height:100dvh;height:var(--gs-vh,100dvh)}`;\n\nconst BASE = `.gs{font-family:var(--gs-font-text);color:var(--gs-ink);box-sizing:border-box}\n.gs *{box-sizing:border-box}\n.gs button{min-width:44px;min-height:44px;margin:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer;-webkit-tap-highlight-color:transparent}\n.gs button:focus-visible{outline:2px solid var(--gs-focus);outline-offset:2px}\n.gs svg{width:20px;height:20px;flex:none}\n.gs-ico{display:inline-flex}\n.gs-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;padding:0 18px;border-radius:var(--gs-radius);font:700 16px/1 var(--gs-font-text);white-space:nowrap}\n.gs-primary{background:var(--gs-accent);color:var(--gs-on-accent)}\n.gs .gs-ghost{color:var(--gs-ink);border:1px solid var(--gs-edge)}\n.gs-x{width:44px;height:44px;display:grid;place-items:center;color:var(--gs-ink-dim);flex:none}\n.gs-txt{min-width:0}\n.gs-txt b{display:block;font:400 18px/1.2 var(--gs-font-display);color:var(--gs-ink)}\n.gs-txt span{display:block;font-size:14px;line-height:1.4;color:var(--gs-ink-dim);margin-top:3px}`;\n\nconst INSTALL = `.gs-install{position:fixed;z-index:2147483000;top:calc(12px + var(--gs-safe-top));left:calc(12px + var(--gs-safe-left))}\n.gs-install[data-layout=card]{top:auto;left:auto;right:calc(24px + var(--gs-safe-right));bottom:calc(var(--gs-card-bottom,60px) + var(--gs-safe-bottom))}\n.gs-seal{display:flex;align-items:center;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius-pill)}\n.gs-chip{display:flex;align-items:center;gap:8px;padding:0 6px 0 14px;font:700 15px var(--gs-font-text);color:var(--gs-ink)}\n.gs-chip svg{color:var(--gs-accent)}\n.gs-seal .gs-x{border-left:1px solid var(--gs-edge)}\n.gs-steps{margin:8px 0 0;width:262px;padding:10px 14px;list-style:none;background:var(--gs-surface);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);display:grid;gap:2px;counter-reset:s}\n.gs-steps[hidden]{display:none}\n.gs-steps li{display:flex;align-items:center;gap:10px;min-height:36px;font-size:15px;color:var(--gs-ink);counter-increment:s}\n.gs-steps li::before{content:counter(s);font:400 15px var(--gs-font-display);color:var(--gs-ink-dim);width:12px}\n.gs-steps svg{width:17px;height:17px;color:var(--gs-accent)}\n.gs-card{position:relative;width:344px;max-width:calc(100vw - 48px);padding:18px;border-radius:var(--gs-radius);background:var(--gs-surface);border:1px solid var(--gs-edge);display:grid;gap:12px}\n.gs-card .gs-x{position:absolute;top:4px;right:4px}\n.gs-card .gs-txt{padding-right:36px}\n.gs-card .gs-acts{display:flex;gap:8px}\n.gs-card .gs-steps{width:auto;margin:0;border:0;padding:0;background:none}\n.gs-app{width:40px;height:40px;border-radius:var(--gs-radius);background:var(--gs-surface-solid);border:1px solid var(--gs-edge);display:grid;place-items:center}\n.gs-app i{width:13px;height:13px;border-radius:50%;background:var(--gs-accent);box-shadow:0 0 10px var(--gs-accent)}`;\n\nconst CRASH = `.gs-crash{position:fixed;inset:0;z-index:2147483001;background:var(--gs-scrim);display:grid;place-items:center;padding:20px}\n.gs-panel{max-width:340px;background:var(--gs-surface-solid);border:1px solid var(--gs-edge);border-radius:var(--gs-radius);padding:24px}\n.gs-h{margin:0;font:400 28px/1.15 var(--gs-font-display);color:var(--gs-ink)}\n.gs-panel p{font-size:16px;line-height:1.5;color:var(--gs-ink-dim);margin:10px 0 0}\n.gs-panel .gs-acts{display:flex;flex-direction:column;gap:8px;margin-top:20px}\n.gs-panel .gs-ref{font:13px ui-monospace,monospace}\n@media (min-width:1024px){.gs-panel{max-width:460px;padding:32px}.gs-panel .gs-acts{flex-direction:row}}`;\n\nexport const GAME_SHELL_CSS = [THEME, ROOT, BASE, INSTALL, CRASH].join('\\n');\n\nexport function injectStyles(doc: Document = document): void {\n if (doc.getElementById(STYLE_ID)) {\n return;\n }\n const style = doc.createElement('style');\n style.id = STYLE_ID;\n style.textContent = GAME_SHELL_CSS;\n doc.head.append(style);\n}\n","import type { Disposable } from '../types';\n\nexport interface VersionPollOptions {\n url: string;\n intervalMs: number;\n onNewVersion(): void;\n fetchFn?: typeof fetch;\n win?: Window;\n}\n\nexport function startVersionPoll(opts: VersionPollOptions): Disposable {\n const win = opts.win ?? window;\n const fetchFn = opts.fetchFn ?? ((input: RequestInfo | URL, init?: RequestInit): Promise<Response> => win.fetch(input, init));\n let baseline: string | null = null;\n let fired = false;\n let busy = false;\n\n const check = async (): Promise<void> => {\n if (fired || busy) {\n return;\n }\n busy = true;\n try {\n const res = await fetchFn(opts.url, { cache: 'no-store' });\n if (!res.ok) {\n return;\n }\n const value = (await res.text()).trim();\n if (baseline === null) {\n baseline = value;\n } else if (value !== baseline) {\n fired = true;\n opts.onNewVersion();\n }\n } catch {\n // Offline or a deploy mid-flight: the next tick tries again.\n } finally {\n busy = false;\n }\n };\n const onVisibility = (): void => {\n if (win.document.visibilityState === 'visible') {\n void check();\n }\n };\n\n void check();\n const timer = win.setInterval(() => void check(), opts.intervalMs);\n win.document.addEventListener('visibilitychange', onVisibility);\n return {\n dispose: (): void => {\n win.clearInterval(timer);\n win.document.removeEventListener('visibilitychange', onVisibility);\n },\n };\n}\n","import { startCrash } from './crash/crash';\nimport type { CrashInfo } from './crash/crashKind';\nimport { startFit } from './fit/fit';\nimport { startInstall } from './install/install';\nimport { startLifecycle, type LifecycleOptions } from './lifecycle/lifecycle';\nimport { injectStyles } from './styles';\nimport type { Disposable, GameShellLabels } from './types';\nimport { startVersionPoll } from './version/versionPoll';\n\nexport interface GameShellOptions {\n root: HTMLElement;\n appName: string;\n labels: GameShellLabels;\n appVersion?: string;\n install?: { snoozeDays?: number; storageKey?: string } | false;\n version?: { url: string; intervalMs: number; onNewVersion(): void };\n crash?: { report?(info: CrashInfo): string | void } | false;\n lifecycle?: LifecycleOptions;\n}\n\nexport function initGameShell(opts: GameShellOptions): Disposable {\n const doc = opts.root.ownerDocument;\n injectStyles(doc);\n opts.root.classList.add('gs-root');\n const parts: Disposable[] = [startFit()];\n if (opts.install !== false) {\n parts.push(startInstall({ appName: opts.appName, labels: opts.labels, ...opts.install }));\n }\n if (opts.crash !== false) {\n parts.push(startCrash({ labels: opts.labels, report: opts.crash?.report, appVersion: opts.appVersion }));\n }\n if (opts.lifecycle) {\n parts.push(startLifecycle(opts.lifecycle, doc));\n }\n if (opts.version) {\n parts.push(startVersionPoll(opts.version));\n }\n return {\n dispose: (): void => {\n parts.forEach((part) => part.dispose());\n opts.root.classList.remove('gs-root');\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dloizides/game-shell",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Framework-free web game shell: fits the visible viewport (--gs-vh), offers install (chip / card / iOS steps), shows a crash overlay, pauses on hide, unlocks audio, polls for new versions. ESM + CJS + IIFE (global GameShell) + game-shell.css. Zero runtime deps.",
5
5
  "keywords": [
6
6
  "game",