star-canvas 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/dist/index.cjs +20 -7
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.mjs +20 -7
- package/dist/legacy.cjs +20 -7
- package/dist/legacy.mjs +20 -7
- package/package.json +9 -3
package/dist/index.cjs
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var A=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var J=(a,o)=>{for(var l in o)A(a,l,{get:o[l],enumerable:!0})},K=(a,o,l,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of j(o))!V.call(a,s)&&s!==l&&A(a,s,{get:()=>o[s],enumerable:!(t=U(o,s))||t.enumerable});return a};var Q=a=>K(A({},"__esModule",{value:!0}),a);var ne={};J(ne,{createDragState:()=>W,game:()=>te,version:()=>Z});module.exports=Q(ne);var Z="0.8.0",X={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function W(a){let o=null,l=0,t=0;return{point(s){return a(s)},grab(s,d){let{x:y,y:T}=a(s);o=d,l=y-d.x,t=T-d.y},move(s){if(o){let{x:d,y}=a(s);o.x=d-l,o.y=y-t}},release(){let s=o;return o=null,s},get dragging(){return o}}}function Y(){return typeof window<"u"&&typeof document<"u"}function ee(){if(!Y()||document.getElementById("star-dom-base"))return;let a=document.createElement("style");a.id="star-dom-base",a.textContent=`
|
|
2
2
|
html, body { height: 100%; }
|
|
3
3
|
body {
|
|
4
4
|
margin: 0; min-height: 100dvh; overflow: hidden; background: #000;
|
|
5
5
|
-webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
|
|
6
6
|
}
|
|
7
|
-
/* Canvas is
|
|
8
|
-
.star-canvas {
|
|
9
|
-
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
10
|
-
overflow: hidden; touch-action: none;
|
|
7
|
+
/* Canvas is rendering only - no pointer events */
|
|
8
|
+
.star-canvas {
|
|
9
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
10
|
+
overflow: hidden; touch-action: none;
|
|
11
11
|
z-index: 0;
|
|
12
12
|
display: block;
|
|
13
|
+
pointer-events: none;
|
|
14
|
+
}
|
|
15
|
+
/* Input layer captures all game input (including letterbox areas) */
|
|
16
|
+
.star-input {
|
|
17
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
18
|
+
z-index: 5;
|
|
19
|
+
touch-action: none;
|
|
13
20
|
}
|
|
14
|
-
/* UI overlay -
|
|
21
|
+
/* UI overlay - container is non-interactive, children opt-in */
|
|
15
22
|
.star-ui {
|
|
16
23
|
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
17
24
|
overflow-y: auto; z-index: 10;
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
}
|
|
27
|
+
/* Interactive UI elements opt-in to receive pointer events */
|
|
28
|
+
.star-ui button, .star-ui a, .star-ui input, .star-ui select,
|
|
29
|
+
.star-ui textarea, .star-ui [data-interactive] {
|
|
30
|
+
pointer-events: auto;
|
|
18
31
|
}
|
|
19
|
-
`,document.head.appendChild(
|
|
32
|
+
`,document.head.appendChild(a)}function te(a,o={}){Y()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>q(a,o),{once:!0}):queueMicrotask(()=>q(a,o)))}function q(a,o){if(ee(),window.__STAR_DOM__?.destroy)try{window.__STAR_DOM__.destroy()}catch{}document.querySelectorAll(".star-ui, .star-canvas, .star-input").forEach(e=>e.remove());let l=document.createElement("div");l.className="star-ui",document.body.appendChild(l);let t=document.createElement("canvas");t.className="star-canvas",document.body.appendChild(t);let s=t.getContext("2d",o.contextAttributes??{alpha:!0});if(!s)throw new Error("[star-dom] Failed to get 2D context");if(o.preventContextMenu!==!1){let e=n=>n.preventDefault();t.addEventListener("contextmenu",e)}let d=document.createElement("div");d.className="star-input",document.body.appendChild(d);let y=[],T=[],O=[],R=null,w=null;Object.defineProperty(t,"onclick",{get:()=>R,set:e=>{w&&(d.removeEventListener("click",w),w=null),R=e,e&&(w=n=>e.call(t,n),d.addEventListener("click",w))}});let F=t.addEventListener.bind(t),$=t.removeEventListener.bind(t),H=new WeakMap;t.addEventListener=function(e,n,r){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let i=(p=>n.call(t,p));H.set(n,i),d.addEventListener(e,i,r)}else F(e,n,r)},t.removeEventListener=function(e,n,r){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let i=H.get(n);i&&(d.removeEventListener(e,i,r),H.delete(n))}else $(e,n,r)};let B=o.preset??"landscape",D=X[B]??X.landscape,L=o.width??D.width,M=o.height??D.height,I=o.maxPixelRatio??2,k=o.pixelRatio??"device",S=o.fit??"contain",b=1,c=L??1,u=M??1,G=new Set,C=null,x=[];function N(){return Math.min(typeof k=="number"?Math.max(1,k):Math.max(1,window.devicePixelRatio||1),I)}function h(){b=N();let e=document.body.getBoundingClientRect(),n=Math.max(1,Math.floor(e.width||window.innerWidth||800)),r=Math.max(1,Math.floor(e.height||window.innerHeight||600));if(L&&M){c=L,u=M;let m=c/u,v=n/r,f=1;if(S==="contain"?f=v>m?r/u:n/c:S==="cover"&&(f=v>m?n/c:r/u),S==="stretch")t.style.width="100%",t.style.height="100%";else{let g=Math.floor(c*f),z=Math.floor(u*f);t.style.width=`${g}px`,t.style.height=`${z}px`,t.style.position="absolute",t.style.left=`${Math.floor((n-g)/2)}px`,t.style.top=`${Math.floor((r-z)/2)}px`}}else if(M){u=M;let m=n/r;c=Math.floor(u*m),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else if(L){c=L;let m=n/r;u=Math.floor(c/m),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else c=n,u=r,t.style.width=`${c}px`,t.style.height=`${u}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let i=Math.max(1,Math.floor(c*b)),p=Math.max(1,Math.floor(u*b));t.width!==i&&(t.width=i),t.height!==p&&(t.height=p),s.setTransform(b,0,0,b,0,0),G.forEach(m=>m())}let P=new ResizeObserver(h);P.observe(document.body),x.push(()=>P.disconnect()),window.addEventListener("resize",h),x.push(()=>window.removeEventListener("resize",h));let _=window.visualViewport;_&&(_.addEventListener("resize",h),x.push(()=>_.removeEventListener("resize",h)));let E={stage:document.body,canvas:t,ctx:s,get width(){return c},get height(){return u},get dpr(){return b},resize:h,toStagePoint:e=>{let n=t.getBoundingClientRect(),r=(e.clientX-n.left)*(c/n.width),i=(e.clientY-n.top)*(u/n.height);return r=Math.max(0,Math.min(c,r)),i=Math.max(0,Math.min(u,i)),{x:r,y:i}},createDrag:()=>W(E.toStagePoint),onTap:e=>{y.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{O.push(e)},on:(e,n,r,i)=>{let p=v=>{let g=v.target?.closest?.(n);g&&r.call(g,v)};document.addEventListener(e,p,i);let m=()=>document.removeEventListener(e,p,i);return x.push(m),m},loop:e=>{let r=0,i=!1,p=0,m=v=>{if(!i)return;let f=p?Math.min((v-p)/1e3,.1):0;p=v;try{e(f,v)}catch(g){console.error("[star-dom] Game loop error:",g)}r=requestAnimationFrame(m)};return C={get running(){return i},start(){i||(i=!0,p=performance.now(),r=requestAnimationFrame(m))},stop(){i&&(i=!1,cancelAnimationFrame(r))}},C.start(),C},ui:{root:l,render:e=>{l.innerHTML!==e&&(l.innerHTML=e)},el:e=>l.querySelector(e),all:e=>l.querySelectorAll(e)},destroy:()=>{C?.stop(),x.forEach(e=>e()),x=[],G.clear(),t.parentElement&&t.parentElement.removeChild(t),l.parentElement&&l.parentElement.removeChild(l),d.parentElement&&d.parentElement.removeChild(d)},scoped:e=>{s.save();try{e()}finally{s.restore()}}};d.addEventListener("pointerdown",e=>{let n={...E.toStagePoint(e),event:e};y.forEach(r=>r(n))}),d.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(r=>r(n))}),d.addEventListener("pointerup",e=>{let n={...E.toStagePoint(e),event:e};O.forEach(r=>r(n))}),window.__STAR_DOM__={destroy:E.destroy},requestAnimationFrame(()=>requestAnimationFrame(()=>{h();try{a(E)}catch(e){console.error("[star-dom] Game initialization failed:",e)}}))}0&&(module.exports={createDragState,game,version});
|
package/dist/index.d.cts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*
|
|
14
14
|
* ~1.5KB min+gz, zero deps, SSR-safe, iframe-first.
|
|
15
15
|
*/
|
|
16
|
-
declare const version = "0.
|
|
16
|
+
declare const version = "0.8.0";
|
|
17
17
|
declare global {
|
|
18
18
|
interface Window {
|
|
19
19
|
__STAR_DOM__?: {
|
|
@@ -37,6 +37,14 @@ interface GameUI {
|
|
|
37
37
|
/** Scoped querySelectorAll for the UI root. */
|
|
38
38
|
all: <T extends Element = HTMLElement>(selector: string) => NodeListOf<T>;
|
|
39
39
|
}
|
|
40
|
+
/** Point with coordinates and the original event */
|
|
41
|
+
interface InputPoint {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
event: PointerEvent;
|
|
45
|
+
}
|
|
46
|
+
/** Input handler type */
|
|
47
|
+
type InputHandler = (point: InputPoint) => void;
|
|
40
48
|
interface GameContext {
|
|
41
49
|
/** The root <div> element for the canvas. */
|
|
42
50
|
readonly stage: HTMLElement;
|
|
@@ -56,7 +64,7 @@ interface GameContext {
|
|
|
56
64
|
loop: (tick: GameTick) => GameLoop;
|
|
57
65
|
/** The dedicated UI overlay manager. */
|
|
58
66
|
readonly ui: GameUI;
|
|
59
|
-
/** Converts DOM event coords to logical stage coords (CSS px). */
|
|
67
|
+
/** Converts DOM event coords to logical stage coords (CSS px). Clamps to canvas bounds. */
|
|
60
68
|
toStagePoint: (e: {
|
|
61
69
|
clientX: number;
|
|
62
70
|
clientY: number;
|
|
@@ -69,6 +77,12 @@ interface GameContext {
|
|
|
69
77
|
x: number;
|
|
70
78
|
y: number;
|
|
71
79
|
}>() => DragState<T>;
|
|
80
|
+
/** Register handler for tap/click (fires on pointerdown). Works anywhere on screen including letterbox. */
|
|
81
|
+
onTap: (handler: InputHandler) => void;
|
|
82
|
+
/** Register handler for pointer move. Works anywhere on screen including letterbox. */
|
|
83
|
+
onMove: (handler: InputHandler) => void;
|
|
84
|
+
/** Register handler for pointer release (fires on pointerup). Works anywhere on screen including letterbox. */
|
|
85
|
+
onRelease: (handler: InputHandler) => void;
|
|
72
86
|
/** Re-calculates stage size (rarely needed). */
|
|
73
87
|
resize: () => void;
|
|
74
88
|
/** Cleans up all listeners and observers. */
|
|
@@ -163,4 +177,4 @@ declare function createDragState<T extends {
|
|
|
163
177
|
*/
|
|
164
178
|
declare function game(setup: (g: GameContext) => void, options?: GameOptions): void;
|
|
165
179
|
|
|
166
|
-
export { type DragState, type GameContext, type GameLoop, type GameOptions, type GameTick, type GameUI, createDragState, game, version };
|
|
180
|
+
export { type DragState, type GameContext, type GameLoop, type GameOptions, type GameTick, type GameUI, type InputHandler, type InputPoint, createDragState, game, version };
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*
|
|
14
14
|
* ~1.5KB min+gz, zero deps, SSR-safe, iframe-first.
|
|
15
15
|
*/
|
|
16
|
-
declare const version = "0.
|
|
16
|
+
declare const version = "0.8.0";
|
|
17
17
|
declare global {
|
|
18
18
|
interface Window {
|
|
19
19
|
__STAR_DOM__?: {
|
|
@@ -37,6 +37,14 @@ interface GameUI {
|
|
|
37
37
|
/** Scoped querySelectorAll for the UI root. */
|
|
38
38
|
all: <T extends Element = HTMLElement>(selector: string) => NodeListOf<T>;
|
|
39
39
|
}
|
|
40
|
+
/** Point with coordinates and the original event */
|
|
41
|
+
interface InputPoint {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
event: PointerEvent;
|
|
45
|
+
}
|
|
46
|
+
/** Input handler type */
|
|
47
|
+
type InputHandler = (point: InputPoint) => void;
|
|
40
48
|
interface GameContext {
|
|
41
49
|
/** The root <div> element for the canvas. */
|
|
42
50
|
readonly stage: HTMLElement;
|
|
@@ -56,7 +64,7 @@ interface GameContext {
|
|
|
56
64
|
loop: (tick: GameTick) => GameLoop;
|
|
57
65
|
/** The dedicated UI overlay manager. */
|
|
58
66
|
readonly ui: GameUI;
|
|
59
|
-
/** Converts DOM event coords to logical stage coords (CSS px). */
|
|
67
|
+
/** Converts DOM event coords to logical stage coords (CSS px). Clamps to canvas bounds. */
|
|
60
68
|
toStagePoint: (e: {
|
|
61
69
|
clientX: number;
|
|
62
70
|
clientY: number;
|
|
@@ -69,6 +77,12 @@ interface GameContext {
|
|
|
69
77
|
x: number;
|
|
70
78
|
y: number;
|
|
71
79
|
}>() => DragState<T>;
|
|
80
|
+
/** Register handler for tap/click (fires on pointerdown). Works anywhere on screen including letterbox. */
|
|
81
|
+
onTap: (handler: InputHandler) => void;
|
|
82
|
+
/** Register handler for pointer move. Works anywhere on screen including letterbox. */
|
|
83
|
+
onMove: (handler: InputHandler) => void;
|
|
84
|
+
/** Register handler for pointer release (fires on pointerup). Works anywhere on screen including letterbox. */
|
|
85
|
+
onRelease: (handler: InputHandler) => void;
|
|
72
86
|
/** Re-calculates stage size (rarely needed). */
|
|
73
87
|
resize: () => void;
|
|
74
88
|
/** Cleans up all listeners and observers. */
|
|
@@ -163,4 +177,4 @@ declare function createDragState<T extends {
|
|
|
163
177
|
*/
|
|
164
178
|
declare function game(setup: (g: GameContext) => void, options?: GameOptions): void;
|
|
165
179
|
|
|
166
|
-
export { type DragState, type GameContext, type GameLoop, type GameOptions, type GameTick, type GameUI, createDragState, game, version };
|
|
180
|
+
export { type DragState, type GameContext, type GameLoop, type GameOptions, type GameTick, type GameUI, type InputHandler, type InputPoint, createDragState, game, version };
|
package/dist/index.mjs
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
|
-
var
|
|
1
|
+
var U="0.8.0",z={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function B(m){let i=null,c=0,t=0;return{point(u){return m(u)},grab(u,a){let{x:y,y:T}=m(u);i=a,c=y-a.x,t=T-a.y},move(u){if(i){let{x:a,y}=m(u);i.x=a-c,i.y=y-t}},release(){let u=i;return i=null,u},get dragging(){return i}}}function q(){return typeof window<"u"&&typeof document<"u"}function N(){if(!q()||document.getElementById("star-dom-base"))return;let m=document.createElement("style");m.id="star-dom-base",m.textContent=`
|
|
2
2
|
html, body { height: 100%; }
|
|
3
3
|
body {
|
|
4
4
|
margin: 0; min-height: 100dvh; overflow: hidden; background: #000;
|
|
5
5
|
-webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
|
|
6
6
|
}
|
|
7
|
-
/* Canvas is
|
|
8
|
-
.star-canvas {
|
|
9
|
-
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
10
|
-
overflow: hidden; touch-action: none;
|
|
7
|
+
/* Canvas is rendering only - no pointer events */
|
|
8
|
+
.star-canvas {
|
|
9
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
10
|
+
overflow: hidden; touch-action: none;
|
|
11
11
|
z-index: 0;
|
|
12
12
|
display: block;
|
|
13
|
+
pointer-events: none;
|
|
14
|
+
}
|
|
15
|
+
/* Input layer captures all game input (including letterbox areas) */
|
|
16
|
+
.star-input {
|
|
17
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
18
|
+
z-index: 5;
|
|
19
|
+
touch-action: none;
|
|
13
20
|
}
|
|
14
|
-
/* UI overlay -
|
|
21
|
+
/* UI overlay - container is non-interactive, children opt-in */
|
|
15
22
|
.star-ui {
|
|
16
23
|
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
17
24
|
overflow-y: auto; z-index: 10;
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
}
|
|
27
|
+
/* Interactive UI elements opt-in to receive pointer events */
|
|
28
|
+
.star-ui button, .star-ui a, .star-ui input, .star-ui select,
|
|
29
|
+
.star-ui textarea, .star-ui [data-interactive] {
|
|
30
|
+
pointer-events: auto;
|
|
18
31
|
}
|
|
19
|
-
`,document.head.appendChild(
|
|
32
|
+
`,document.head.appendChild(m)}function j(m,i={}){q()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>X(m,i),{once:!0}):queueMicrotask(()=>X(m,i)))}function X(m,i){if(N(),window.__STAR_DOM__?.destroy)try{window.__STAR_DOM__.destroy()}catch{}document.querySelectorAll(".star-ui, .star-canvas, .star-input").forEach(e=>e.remove());let c=document.createElement("div");c.className="star-ui",document.body.appendChild(c);let t=document.createElement("canvas");t.className="star-canvas",document.body.appendChild(t);let u=t.getContext("2d",i.contextAttributes??{alpha:!0});if(!u)throw new Error("[star-dom] Failed to get 2D context");if(i.preventContextMenu!==!1){let e=n=>n.preventDefault();t.addEventListener("contextmenu",e)}let a=document.createElement("div");a.className="star-input",document.body.appendChild(a);let y=[],T=[],A=[],O=null,w=null;Object.defineProperty(t,"onclick",{get:()=>O,set:e=>{w&&(a.removeEventListener("click",w),w=null),O=e,e&&(w=n=>e.call(t,n),a.addEventListener("click",w))}});let W=t.addEventListener.bind(t),Y=t.removeEventListener.bind(t),H=new WeakMap;t.addEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let r=(p=>n.call(t,p));H.set(n,r),a.addEventListener(e,r,o)}else W(e,n,o)},t.removeEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let r=H.get(n);r&&(a.removeEventListener(e,r,o),H.delete(n))}else Y(e,n,o)};let F=i.preset??"landscape",R=z[F]??z.landscape,L=i.width??R.width,M=i.height??R.height,D=i.maxPixelRatio??2,I=i.pixelRatio??"device",S=i.fit??"contain",b=1,s=L??1,l=M??1,k=new Set,C=null,x=[];function $(){return Math.min(typeof I=="number"?Math.max(1,I):Math.max(1,window.devicePixelRatio||1),D)}function h(){b=$();let e=document.body.getBoundingClientRect(),n=Math.max(1,Math.floor(e.width||window.innerWidth||800)),o=Math.max(1,Math.floor(e.height||window.innerHeight||600));if(L&&M){s=L,l=M;let d=s/l,v=n/o,f=1;if(S==="contain"?f=v>d?o/l:n/s:S==="cover"&&(f=v>d?n/s:o/l),S==="stretch")t.style.width="100%",t.style.height="100%";else{let g=Math.floor(s*f),P=Math.floor(l*f);t.style.width=`${g}px`,t.style.height=`${P}px`,t.style.position="absolute",t.style.left=`${Math.floor((n-g)/2)}px`,t.style.top=`${Math.floor((o-P)/2)}px`}}else if(M){l=M;let d=n/o;s=Math.floor(l*d),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else if(L){s=L;let d=n/o;l=Math.floor(s/d),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else s=n,l=o,t.style.width=`${s}px`,t.style.height=`${l}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let r=Math.max(1,Math.floor(s*b)),p=Math.max(1,Math.floor(l*b));t.width!==r&&(t.width=r),t.height!==p&&(t.height=p),u.setTransform(b,0,0,b,0,0),k.forEach(d=>d())}let G=new ResizeObserver(h);G.observe(document.body),x.push(()=>G.disconnect()),window.addEventListener("resize",h),x.push(()=>window.removeEventListener("resize",h));let _=window.visualViewport;_&&(_.addEventListener("resize",h),x.push(()=>_.removeEventListener("resize",h)));let E={stage:document.body,canvas:t,ctx:u,get width(){return s},get height(){return l},get dpr(){return b},resize:h,toStagePoint:e=>{let n=t.getBoundingClientRect(),o=(e.clientX-n.left)*(s/n.width),r=(e.clientY-n.top)*(l/n.height);return o=Math.max(0,Math.min(s,o)),r=Math.max(0,Math.min(l,r)),{x:o,y:r}},createDrag:()=>B(E.toStagePoint),onTap:e=>{y.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{A.push(e)},on:(e,n,o,r)=>{let p=v=>{let g=v.target?.closest?.(n);g&&o.call(g,v)};document.addEventListener(e,p,r);let d=()=>document.removeEventListener(e,p,r);return x.push(d),d},loop:e=>{let o=0,r=!1,p=0,d=v=>{if(!r)return;let f=p?Math.min((v-p)/1e3,.1):0;p=v;try{e(f,v)}catch(g){console.error("[star-dom] Game loop error:",g)}o=requestAnimationFrame(d)};return C={get running(){return r},start(){r||(r=!0,p=performance.now(),o=requestAnimationFrame(d))},stop(){r&&(r=!1,cancelAnimationFrame(o))}},C.start(),C},ui:{root:c,render:e=>{c.innerHTML!==e&&(c.innerHTML=e)},el:e=>c.querySelector(e),all:e=>c.querySelectorAll(e)},destroy:()=>{C?.stop(),x.forEach(e=>e()),x=[],k.clear(),t.parentElement&&t.parentElement.removeChild(t),c.parentElement&&c.parentElement.removeChild(c),a.parentElement&&a.parentElement.removeChild(a)},scoped:e=>{u.save();try{e()}finally{u.restore()}}};a.addEventListener("pointerdown",e=>{let n={...E.toStagePoint(e),event:e};y.forEach(o=>o(n))}),a.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(o=>o(n))}),a.addEventListener("pointerup",e=>{let n={...E.toStagePoint(e),event:e};A.forEach(o=>o(n))}),window.__STAR_DOM__={destroy:E.destroy},requestAnimationFrame(()=>requestAnimationFrame(()=>{h();try{m(E)}catch(e){console.error("[star-dom] Game initialization failed:",e)}}))}export{B as createDragState,j as game,U as version};
|
package/dist/legacy.cjs
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var H=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var Q=(i,o)=>{for(var s in o)H(i,s,{get:o[s],enumerable:!0})},Z=(i,o,s,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let l of J(o))!K.call(i,l)&&l!==s&&H(i,l,{get:()=>o[l],enumerable:!(t=V(o,l))||t.enumerable});return i};var ee=i=>Z(H({},"__esModule",{value:!0}),i);var oe={};Q(oe,{createDragState:()=>_,game:()=>ne,version:()=>Y});module.exports=ee(oe);var Y="0.8.0",q={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function _(i){let o=null,s=0,t=0;return{point(l){return i(l)},grab(l,d){let{x:y,y:T}=i(l);o=d,s=y-d.x,t=T-d.y},move(l){if(o){let{x:d,y}=i(l);o.x=d-s,o.y=y-t}},release(){let l=o;return o=null,l},get dragging(){return o}}}function F(){return typeof window<"u"&&typeof document<"u"}function te(){if(!F()||document.getElementById("star-dom-base"))return;let i=document.createElement("style");i.id="star-dom-base",i.textContent=`
|
|
2
2
|
html, body { height: 100%; }
|
|
3
3
|
body {
|
|
4
4
|
margin: 0; min-height: 100dvh; overflow: hidden; background: #000;
|
|
5
5
|
-webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
|
|
6
6
|
}
|
|
7
|
-
/* Canvas is
|
|
8
|
-
.star-canvas {
|
|
9
|
-
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
10
|
-
overflow: hidden; touch-action: none;
|
|
7
|
+
/* Canvas is rendering only - no pointer events */
|
|
8
|
+
.star-canvas {
|
|
9
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
10
|
+
overflow: hidden; touch-action: none;
|
|
11
11
|
z-index: 0;
|
|
12
12
|
display: block;
|
|
13
|
+
pointer-events: none;
|
|
14
|
+
}
|
|
15
|
+
/* Input layer captures all game input (including letterbox areas) */
|
|
16
|
+
.star-input {
|
|
17
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
18
|
+
z-index: 5;
|
|
19
|
+
touch-action: none;
|
|
13
20
|
}
|
|
14
|
-
/* UI overlay -
|
|
21
|
+
/* UI overlay - container is non-interactive, children opt-in */
|
|
15
22
|
.star-ui {
|
|
16
23
|
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
17
24
|
overflow-y: auto; z-index: 10;
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
}
|
|
27
|
+
/* Interactive UI elements opt-in to receive pointer events */
|
|
28
|
+
.star-ui button, .star-ui a, .star-ui input, .star-ui select,
|
|
29
|
+
.star-ui textarea, .star-ui [data-interactive] {
|
|
30
|
+
pointer-events: auto;
|
|
18
31
|
}
|
|
19
|
-
`,document.head.appendChild(
|
|
32
|
+
`,document.head.appendChild(i)}function $(i,o={}){F()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>W(i,o),{once:!0}):queueMicrotask(()=>W(i,o)))}function W(i,o){if(te(),window.__STAR_DOM__?.destroy)try{window.__STAR_DOM__.destroy()}catch{}document.querySelectorAll(".star-ui, .star-canvas, .star-input").forEach(e=>e.remove());let s=document.createElement("div");s.className="star-ui",document.body.appendChild(s);let t=document.createElement("canvas");t.className="star-canvas",document.body.appendChild(t);let l=t.getContext("2d",o.contextAttributes??{alpha:!0});if(!l)throw new Error("[star-dom] Failed to get 2D context");if(o.preventContextMenu!==!1){let e=n=>n.preventDefault();t.addEventListener("contextmenu",e)}let d=document.createElement("div");d.className="star-input",document.body.appendChild(d);let y=[],T=[],A=[],D=null,w=null;Object.defineProperty(t,"onclick",{get:()=>D,set:e=>{w&&(d.removeEventListener("click",w),w=null),D=e,e&&(w=n=>e.call(t,n),d.addEventListener("click",w))}});let B=t.addEventListener.bind(t),U=t.removeEventListener.bind(t),G=new WeakMap;t.addEventListener=function(e,n,r){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let a=(p=>n.call(t,p));G.set(n,a),d.addEventListener(e,a,r)}else B(e,n,r)},t.removeEventListener=function(e,n,r){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let a=G.get(n);a&&(d.removeEventListener(e,a,r),G.delete(n))}else U(e,n,r)};let N=o.preset??"landscape",I=q[N]??q.landscape,L=o.width??I.width,M=o.height??I.height,R=o.maxPixelRatio??2,k=o.pixelRatio??"device",O=o.fit??"contain",b=1,c=L??1,u=M??1,P=new Set,C=null,x=[];function j(){return Math.min(typeof k=="number"?Math.max(1,k):Math.max(1,window.devicePixelRatio||1),R)}function h(){b=j();let e=document.body.getBoundingClientRect(),n=Math.max(1,Math.floor(e.width||window.innerWidth||800)),r=Math.max(1,Math.floor(e.height||window.innerHeight||600));if(L&&M){c=L,u=M;let m=c/u,v=n/r,f=1;if(O==="contain"?f=v>m?r/u:n/c:O==="cover"&&(f=v>m?n/c:r/u),O==="stretch")t.style.width="100%",t.style.height="100%";else{let g=Math.floor(c*f),X=Math.floor(u*f);t.style.width=`${g}px`,t.style.height=`${X}px`,t.style.position="absolute",t.style.left=`${Math.floor((n-g)/2)}px`,t.style.top=`${Math.floor((r-X)/2)}px`}}else if(M){u=M;let m=n/r;c=Math.floor(u*m),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else if(L){c=L;let m=n/r;u=Math.floor(c/m),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else c=n,u=r,t.style.width=`${c}px`,t.style.height=`${u}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let a=Math.max(1,Math.floor(c*b)),p=Math.max(1,Math.floor(u*b));t.width!==a&&(t.width=a),t.height!==p&&(t.height=p),l.setTransform(b,0,0,b,0,0),P.forEach(m=>m())}let z=new ResizeObserver(h);z.observe(document.body),x.push(()=>z.disconnect()),window.addEventListener("resize",h),x.push(()=>window.removeEventListener("resize",h));let S=window.visualViewport;S&&(S.addEventListener("resize",h),x.push(()=>S.removeEventListener("resize",h)));let E={stage:document.body,canvas:t,ctx:l,get width(){return c},get height(){return u},get dpr(){return b},resize:h,toStagePoint:e=>{let n=t.getBoundingClientRect(),r=(e.clientX-n.left)*(c/n.width),a=(e.clientY-n.top)*(u/n.height);return r=Math.max(0,Math.min(c,r)),a=Math.max(0,Math.min(u,a)),{x:r,y:a}},createDrag:()=>_(E.toStagePoint),onTap:e=>{y.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{A.push(e)},on:(e,n,r,a)=>{let p=v=>{let g=v.target?.closest?.(n);g&&r.call(g,v)};document.addEventListener(e,p,a);let m=()=>document.removeEventListener(e,p,a);return x.push(m),m},loop:e=>{let r=0,a=!1,p=0,m=v=>{if(!a)return;let f=p?Math.min((v-p)/1e3,.1):0;p=v;try{e(f,v)}catch(g){console.error("[star-dom] Game loop error:",g)}r=requestAnimationFrame(m)};return C={get running(){return a},start(){a||(a=!0,p=performance.now(),r=requestAnimationFrame(m))},stop(){a&&(a=!1,cancelAnimationFrame(r))}},C.start(),C},ui:{root:s,render:e=>{s.innerHTML!==e&&(s.innerHTML=e)},el:e=>s.querySelector(e),all:e=>s.querySelectorAll(e)},destroy:()=>{C?.stop(),x.forEach(e=>e()),x=[],P.clear(),t.parentElement&&t.parentElement.removeChild(t),s.parentElement&&s.parentElement.removeChild(s),d.parentElement&&d.parentElement.removeChild(d)},scoped:e=>{l.save();try{e()}finally{l.restore()}}};d.addEventListener("pointerdown",e=>{let n={...E.toStagePoint(e),event:e};y.forEach(r=>r(n))}),d.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(r=>r(n))}),d.addEventListener("pointerup",e=>{let n={...E.toStagePoint(e),event:e};A.forEach(r=>r(n))}),window.__STAR_DOM__={destroy:E.destroy},requestAnimationFrame(()=>requestAnimationFrame(()=>{h();try{i(E)}catch(e){console.error("[star-dom] Game initialization failed:",e)}}))}function ne(i,o={}){let s={preset:"responsive",...o};return $(i,s)}0&&(module.exports={createDragState,game,version});
|
package/dist/legacy.mjs
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
|
-
var
|
|
1
|
+
var N="0.8.0",z={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function q(l){let i=null,s=0,t=0;return{point(m){return l(m)},grab(m,a){let{x:y,y:T}=l(m);i=a,s=y-a.x,t=T-a.y},move(m){if(i){let{x:a,y}=l(m);i.x=a-s,i.y=y-t}},release(){let m=i;return i=null,m},get dragging(){return i}}}function W(){return typeof window<"u"&&typeof document<"u"}function j(){if(!W()||document.getElementById("star-dom-base"))return;let l=document.createElement("style");l.id="star-dom-base",l.textContent=`
|
|
2
2
|
html, body { height: 100%; }
|
|
3
3
|
body {
|
|
4
4
|
margin: 0; min-height: 100dvh; overflow: hidden; background: #000;
|
|
5
5
|
-webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
|
|
6
6
|
}
|
|
7
|
-
/* Canvas is
|
|
8
|
-
.star-canvas {
|
|
9
|
-
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
10
|
-
overflow: hidden; touch-action: none;
|
|
7
|
+
/* Canvas is rendering only - no pointer events */
|
|
8
|
+
.star-canvas {
|
|
9
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
10
|
+
overflow: hidden; touch-action: none;
|
|
11
11
|
z-index: 0;
|
|
12
12
|
display: block;
|
|
13
|
+
pointer-events: none;
|
|
14
|
+
}
|
|
15
|
+
/* Input layer captures all game input (including letterbox areas) */
|
|
16
|
+
.star-input {
|
|
17
|
+
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
18
|
+
z-index: 5;
|
|
19
|
+
touch-action: none;
|
|
13
20
|
}
|
|
14
|
-
/* UI overlay -
|
|
21
|
+
/* UI overlay - container is non-interactive, children opt-in */
|
|
15
22
|
.star-ui {
|
|
16
23
|
position: absolute; inset: 0; width: 100%; height: 100%;
|
|
17
24
|
overflow-y: auto; z-index: 10;
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
}
|
|
27
|
+
/* Interactive UI elements opt-in to receive pointer events */
|
|
28
|
+
.star-ui button, .star-ui a, .star-ui input, .star-ui select,
|
|
29
|
+
.star-ui textarea, .star-ui [data-interactive] {
|
|
30
|
+
pointer-events: auto;
|
|
18
31
|
}
|
|
19
|
-
`,document.head.appendChild(
|
|
32
|
+
`,document.head.appendChild(l)}function Y(l,i={}){W()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>X(l,i),{once:!0}):queueMicrotask(()=>X(l,i)))}function X(l,i){if(j(),window.__STAR_DOM__?.destroy)try{window.__STAR_DOM__.destroy()}catch{}document.querySelectorAll(".star-ui, .star-canvas, .star-input").forEach(e=>e.remove());let s=document.createElement("div");s.className="star-ui",document.body.appendChild(s);let t=document.createElement("canvas");t.className="star-canvas",document.body.appendChild(t);let m=t.getContext("2d",i.contextAttributes??{alpha:!0});if(!m)throw new Error("[star-dom] Failed to get 2D context");if(i.preventContextMenu!==!1){let e=n=>n.preventDefault();t.addEventListener("contextmenu",e)}let a=document.createElement("div");a.className="star-input",document.body.appendChild(a);let y=[],T=[],H=[],_=null,w=null;Object.defineProperty(t,"onclick",{get:()=>_,set:e=>{w&&(a.removeEventListener("click",w),w=null),_=e,e&&(w=n=>e.call(t,n),a.addEventListener("click",w))}});let F=t.addEventListener.bind(t),$=t.removeEventListener.bind(t),G=new WeakMap;t.addEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let r=(p=>n.call(t,p));G.set(n,r),a.addEventListener(e,r,o)}else F(e,n,o)},t.removeEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let r=G.get(n);r&&(a.removeEventListener(e,r,o),G.delete(n))}else $(e,n,o)};let B=i.preset??"landscape",A=z[B]??z.landscape,L=i.width??A.width,M=i.height??A.height,D=i.maxPixelRatio??2,I=i.pixelRatio??"device",O=i.fit??"contain",b=1,d=L??1,c=M??1,R=new Set,C=null,x=[];function U(){return Math.min(typeof I=="number"?Math.max(1,I):Math.max(1,window.devicePixelRatio||1),D)}function h(){b=U();let e=document.body.getBoundingClientRect(),n=Math.max(1,Math.floor(e.width||window.innerWidth||800)),o=Math.max(1,Math.floor(e.height||window.innerHeight||600));if(L&&M){d=L,c=M;let u=d/c,v=n/o,f=1;if(O==="contain"?f=v>u?o/c:n/d:O==="cover"&&(f=v>u?n/d:o/c),O==="stretch")t.style.width="100%",t.style.height="100%";else{let g=Math.floor(d*f),P=Math.floor(c*f);t.style.width=`${g}px`,t.style.height=`${P}px`,t.style.position="absolute",t.style.left=`${Math.floor((n-g)/2)}px`,t.style.top=`${Math.floor((o-P)/2)}px`}}else if(M){c=M;let u=n/o;d=Math.floor(c*u),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else if(L){d=L;let u=n/o;c=Math.floor(d/u),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else d=n,c=o,t.style.width=`${d}px`,t.style.height=`${c}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let r=Math.max(1,Math.floor(d*b)),p=Math.max(1,Math.floor(c*b));t.width!==r&&(t.width=r),t.height!==p&&(t.height=p),m.setTransform(b,0,0,b,0,0),R.forEach(u=>u())}let k=new ResizeObserver(h);k.observe(document.body),x.push(()=>k.disconnect()),window.addEventListener("resize",h),x.push(()=>window.removeEventListener("resize",h));let S=window.visualViewport;S&&(S.addEventListener("resize",h),x.push(()=>S.removeEventListener("resize",h)));let E={stage:document.body,canvas:t,ctx:m,get width(){return d},get height(){return c},get dpr(){return b},resize:h,toStagePoint:e=>{let n=t.getBoundingClientRect(),o=(e.clientX-n.left)*(d/n.width),r=(e.clientY-n.top)*(c/n.height);return o=Math.max(0,Math.min(d,o)),r=Math.max(0,Math.min(c,r)),{x:o,y:r}},createDrag:()=>q(E.toStagePoint),onTap:e=>{y.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{H.push(e)},on:(e,n,o,r)=>{let p=v=>{let g=v.target?.closest?.(n);g&&o.call(g,v)};document.addEventListener(e,p,r);let u=()=>document.removeEventListener(e,p,r);return x.push(u),u},loop:e=>{let o=0,r=!1,p=0,u=v=>{if(!r)return;let f=p?Math.min((v-p)/1e3,.1):0;p=v;try{e(f,v)}catch(g){console.error("[star-dom] Game loop error:",g)}o=requestAnimationFrame(u)};return C={get running(){return r},start(){r||(r=!0,p=performance.now(),o=requestAnimationFrame(u))},stop(){r&&(r=!1,cancelAnimationFrame(o))}},C.start(),C},ui:{root:s,render:e=>{s.innerHTML!==e&&(s.innerHTML=e)},el:e=>s.querySelector(e),all:e=>s.querySelectorAll(e)},destroy:()=>{C?.stop(),x.forEach(e=>e()),x=[],R.clear(),t.parentElement&&t.parentElement.removeChild(t),s.parentElement&&s.parentElement.removeChild(s),a.parentElement&&a.parentElement.removeChild(a)},scoped:e=>{m.save();try{e()}finally{m.restore()}}};a.addEventListener("pointerdown",e=>{let n={...E.toStagePoint(e),event:e};y.forEach(o=>o(n))}),a.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(o=>o(n))}),a.addEventListener("pointerup",e=>{let n={...E.toStagePoint(e),event:e};H.forEach(o=>o(n))}),window.__STAR_DOM__={destroy:E.destroy},requestAnimationFrame(()=>requestAnimationFrame(()=>{h();try{l(E)}catch(e){console.error("[star-dom] Game initialization failed:",e)}}))}function K(l,i={}){let s={preset:"responsive",...i};return Y(l,s)}export{q as createDragState,K as game,N as version};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "star-canvas",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Canvas game utilities for reliable game initialization - part of Star SDK.",
|
|
6
6
|
"type": "module",
|
|
@@ -10,8 +10,14 @@
|
|
|
10
10
|
"publicImport": "import { game } from 'star-canvas';",
|
|
11
11
|
"publicPath": "dist/index.mjs",
|
|
12
12
|
"outputs": [
|
|
13
|
-
{
|
|
14
|
-
|
|
13
|
+
{
|
|
14
|
+
"src": "dist/legacy.mjs",
|
|
15
|
+
"dest": "dom.js"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"src": "dist/index.mjs",
|
|
19
|
+
"dest": "v1/dom.js"
|
|
20
|
+
}
|
|
15
21
|
],
|
|
16
22
|
"skill": {
|
|
17
23
|
"name": "star-dom-sdk",
|