star-canvas 0.1.5 → 0.1.7

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/PROMPT.md CHANGED
@@ -60,24 +60,22 @@ game(({ ctx, width, height, on, loop, ui, canvas }) => {
60
60
  });
61
61
 
62
62
  // 2. Render HTML to the safe UI overlay
63
- // UI is interactive by default (scroll, buttons work)
64
- // Adding canvas.addEventListener makes UI click-through automatically
65
63
  ui.render(`
66
64
  <div class="absolute top-4 left-4 text-white">
67
- <button id="start-btn" class="px-4 py-2 bg-blue-500 rounded pointer-events-auto">
65
+ <button id="start-btn" class="px-4 py-2 bg-blue-500 rounded">
68
66
  Click Me
69
67
  </button>
70
68
  </div>
71
69
  `);
72
70
 
73
- // 3. Listen for button clicks
71
+ // 3. Listen for button clicks — on() auto-enables pointer-events for the target
74
72
  on('click', '#start-btn', () => {
75
73
  console.log('Button clicked!');
76
74
  });
77
75
 
78
76
  // 4. For canvas games: listen for taps on canvas
79
- // This automatically makes UI click-through (taps pass through to canvas)
80
- // Buttons with pointer-events-auto still work
77
+ // Taps pass through the UI overlay to the canvas layer
78
+ // Elements targeted by on() are automatically interactive
81
79
  canvas.addEventListener('pointerdown', (e) => {
82
80
  console.log('Canvas/screen tapped!', e);
83
81
  });
@@ -142,7 +140,7 @@ A safe manager for your HTML overlay, stacked on top of the canvas.
142
140
  - `ui.el(selector)`: Scoped `querySelector` for the UI root.
143
141
  - `ui.all(selector)`: Scoped `querySelectorAll` for the UI root.
144
142
 
145
- **Auto-detection:** When you add `canvas.addEventListener('pointerdown', ...)`, the SDK automatically makes UI click-through so taps reach the canvas. Buttons with `pointer-events-auto` still work.
143
+ **Auto-detection:** When you add `canvas.addEventListener('pointerdown', ...)`, the SDK automatically makes UI click-through so taps reach the canvas. Elements targeted by `on()` are automatically interactive — no extra CSS classes needed. Native `<button>` and `<a>` elements are also always interactive.
146
144
 
147
145
  ### Cursor Management
148
146
 
@@ -353,7 +351,7 @@ game(({ ctx, width, height, loop, toStagePoint, canvas }) => {
353
351
  import { game } from 'star-canvas';
354
352
  import { createLeaderboard } from 'star-leaderboard';
355
353
 
356
- const leaderboard = createLeaderboard({ gameId: 'YOUR_GAME_ID' });
354
+ const leaderboard = createLeaderboard({ gameId: '<gameId from .starrc>' });
357
355
 
358
356
  game(({ ctx, width, height, loop, ui, on, canvas, toStagePoint }) => {
359
357
  let score = 0;
@@ -370,13 +368,13 @@ game(({ ctx, width, height, loop, ui, on, canvas, toStagePoint }) => {
370
368
  // 1. Listen for screen taps - this makes UI click-through automatically
371
369
  canvas.addEventListener('pointerdown', handleTap);
372
370
 
373
- // 2. Listen for button clicks - buttons need pointer-events-auto
371
+ // 2. Listen for button clicks on() auto-enables pointer-events for the selector
374
372
  on('click', '#leaderboard-btn', (e) => {
375
373
  e.stopPropagation();
376
374
  leaderboard.show();
377
375
  });
378
376
 
379
- // 3. Render UI - buttons need pointer-events-auto to intercept clicks
377
+ // 3. Render UI elements targeted by on() are automatically interactive
380
378
  let lastState = null;
381
379
  let lastScore = -1;
382
380
 
@@ -403,7 +401,7 @@ game(({ ctx, width, height, loop, ui, on, canvas, toStagePoint }) => {
403
401
  <div class="h-full flex flex-col items-center justify-center text-white">
404
402
  <div class="text-3xl mb-4">GAME OVER</div>
405
403
  <div class="text-6xl mb-4">\${score}</div>
406
- <button id="leaderboard-btn" class="px-6 py-3 mb-4 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-bold shadow-lg shadow-blue-500/20 pointer-events-auto">
404
+ <button id="leaderboard-btn" class="px-6 py-3 mb-4 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl font-bold shadow-lg shadow-blue-500/20">
407
405
  VIEW LEADERBOARD
408
406
  </button>
409
407
  <div class="text-xl animate-pulse">TAP TO RESTART</div>
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var A=Object.defineProperty;var U=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var J=(a,r)=>{for(var l in r)A(a,l,{get:r[l],enumerable:!0})},K=(a,r,l,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of j(r))!V.call(a,s)&&s!==l&&A(a,s,{get:()=>r[s],enumerable:!(t=U(r,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 r=null,l=0,t=0;return{point(s){return a(s)},grab(s,c){let{x:y,y:T}=a(s);r=c,l=y-c.x,t=T-c.y},move(s){if(r){let{x:c,y}=a(s);r.x=c-l,r.y=y-t}},release(){let s=r;return r=null,s},get dragging(){return r}}}function Y(){return typeof window<"u"&&typeof document<"u"}function ee(){if(!Y()||document.getElementById("star-canvas-base"))return;let a=document.createElement("style");a.id="star-canvas-base",a.textContent=`
1
+ "use strict";var A=Object.defineProperty;var V=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var Q=(a,r)=>{for(var s in r)A(a,s,{get:r[s],enumerable:!0})},Z=(a,r,s,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let l of J(r))!K.call(a,l)&&l!==s&&A(a,l,{get:()=>r[l],enumerable:!(t=V(r,l))||t.enumerable});return a};var ee=a=>Z(A({},"__esModule",{value:!0}),a);var re={};Q(re,{createDragState:()=>q,game:()=>oe,version:()=>te});module.exports=ee(re);var te="0.8.0",Y={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function q(a){let r=null,s=0,t=0;return{point(l){return a(l)},grab(l,c){let{x:b,y:T}=a(l);r=c,s=b-c.x,t=T-c.y},move(l){if(r){let{x:c,y:b}=a(l);r.x=c-s,r.y=b-t}},release(){let l=r;return r=null,l},get dragging(){return r}}}function F(){return typeof window<"u"&&typeof document<"u"}function ne(){if(!F()||document.getElementById("star-canvas-base"))return;let a=document.createElement("style");a.id="star-canvas-base",a.textContent=`
2
2
  html, body { height: 100%; }
3
3
  body {
4
4
  margin: 0; min-height: 100dvh; overflow: hidden; background: #000;
@@ -29,4 +29,4 @@
29
29
  .star-ui textarea, .star-ui [data-interactive] {
30
30
  pointer-events: auto;
31
31
  }
32
- `,document.head.appendChild(a)}function te(a,r={}){Y()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>q(a,r),{once:!0}):queueMicrotask(()=>q(a,r)))}function q(a,r){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",r.contextAttributes??{alpha:!0});if(!s)throw new Error("[star-canvas] Failed to get 2D context");if(r.preventContextMenu!==!1){let e=n=>n.preventDefault();t.addEventListener("contextmenu",e)}let c=document.createElement("div");c.className="star-input",document.body.appendChild(c);let y=[],T=[],O=[],R=null,w=null;Object.defineProperty(t,"onclick",{get:()=>R,set:e=>{w&&(c.removeEventListener("click",w),w=null),R=e,e&&(w=n=>e.call(t,n),c.addEventListener("click",w))}});let F=t.addEventListener.bind(t),$=t.removeEventListener.bind(t),H=new WeakMap;t.addEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let i=(p=>n.call(t,p));H.set(n,i),c.addEventListener(e,i,o)}else F(e,n,o)},t.removeEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let i=H.get(n);i&&(c.removeEventListener(e,i,o),H.delete(n))}else $(e,n,o)};let B=r.preset??"landscape",D=X[B]??X.landscape,L=r.width??D.width,M=r.height??D.height,I=r.maxPixelRatio??2,k=r.pixelRatio??"device",S=r.fit??"contain",b=1,d=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)),o=Math.max(1,Math.floor(e.height||window.innerHeight||600));if(L&&M){d=L,u=M;let m=d/u,v=n/o,f=1;if(S==="contain"?f=v>m?o/u:n/d:S==="cover"&&(f=v>m?n/d:o/u),S==="stretch")t.style.width="100%",t.style.height="100%";else{let g=Math.floor(d*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((o-z)/2)}px`}}else if(M){u=M;let m=n/o;d=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){d=L;let m=n/o;u=Math.floor(d/m),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else d=n,u=o,t.style.width=`${d}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(d*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 d},get height(){return u},get dpr(){return b},resize:h,toStagePoint:e=>{let n=t.getBoundingClientRect(),o=(e.clientX-n.left)*(d/n.width),i=(e.clientY-n.top)*(u/n.height);return o=Math.max(0,Math.min(d,o)),i=Math.max(0,Math.min(u,i)),{x:o,y:i}},createDrag:()=>W(E.toStagePoint),onTap:e=>{y.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{O.push(e)},on:(e,n,o,i)=>{let p=v=>{let g=v.target?.closest?.(n);g&&o.call(g,v)};document.addEventListener(e,p,i);let m=()=>document.removeEventListener(e,p,i);return x.push(m),m},loop:e=>{let o=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-canvas] Game loop error:",g)}o=requestAnimationFrame(m)};return C={get running(){return i},start(){i||(i=!0,p=performance.now(),o=requestAnimationFrame(m))},stop(){i&&(i=!1,cancelAnimationFrame(o))}},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),c.parentElement&&c.parentElement.removeChild(c)},scoped:e=>{s.save();try{e()}finally{s.restore()}}};c.addEventListener("pointerdown",e=>{let n={...E.toStagePoint(e),event:e};y.forEach(o=>o(n))}),c.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(o=>o(n))}),c.addEventListener("pointerup",e=>{let n={...E.toStagePoint(e),event:e};O.forEach(o=>o(n))}),window.__STAR_DOM__={destroy:E.destroy},requestAnimationFrame(()=>requestAnimationFrame(()=>{h();try{a(E)}catch(e){console.error("[star-canvas] Game initialization failed:",e)}}))}0&&(module.exports={createDragState,game,version});
32
+ `,document.head.appendChild(a)}function oe(a,r={}){F()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>$(a,r),{once:!0}):queueMicrotask(()=>$(a,r)))}function $(a,r){if(ne(),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",r.contextAttributes??{alpha:!0});if(!l)throw new Error("[star-canvas] Failed to get 2D context");if(r.preventContextMenu!==!1){let e=n=>n.preventDefault();t.addEventListener("contextmenu",e)}let c=document.createElement("div");c.className="star-input",document.body.appendChild(c);let b=[],T=[],O=[],R=null,w=null;Object.defineProperty(t,"onclick",{get:()=>R,set:e=>{w&&(c.removeEventListener("click",w),w=null),R=e,e&&(w=n=>{S(n)||e.call(t,n)},c.addEventListener("click",w))}});let N=t.addEventListener.bind(t),W=t.removeEventListener.bind(t),I=new WeakMap;function S(e){let n=e;if(n.clientX==null||n.clientY==null)return!1;let o=document.elementFromPoint(n.clientX,n.clientY);return o!==null&&o!==s&&s.contains(o)}let B=/^(click|pointerdown|mousedown|touchstart)$/;t.addEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let i=B.test(e),p=(d=>{i&&S(d)||n.call(t,d)});I.set(n,p),c.addEventListener(e,p,o)}else N(e,n,o)},t.removeEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let i=I.get(n);i&&(c.removeEventListener(e,i,o),I.delete(n))}else W(e,n,o)};let U=r.preset??"landscape",D=Y[U]??Y.landscape,L=r.width??D.width,M=r.height??D.height,k=r.maxPixelRatio??2,P=r.pixelRatio??"device",H=r.fit??"contain",x=1,u=L??1,m=M??1,G=new Set,C=null,g=[];function j(){return Math.min(typeof P=="number"?Math.max(1,P):Math.max(1,window.devicePixelRatio||1),k)}function y(){x=j();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){u=L,m=M;let d=u/m,v=n/o,h=1;if(H==="contain"?h=v>d?o/m:n/u:H==="cover"&&(h=v>d?n/u:o/m),H==="stretch")t.style.width="100%",t.style.height="100%";else{let f=Math.floor(u*h),X=Math.floor(m*h);t.style.width=`${f}px`,t.style.height=`${X}px`,t.style.position="absolute",t.style.left=`${Math.floor((n-f)/2)}px`,t.style.top=`${Math.floor((o-X)/2)}px`}}else if(M){m=M;let d=n/o;u=Math.floor(m*d),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else if(L){u=L;let d=n/o;m=Math.floor(u/d),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else u=n,m=o,t.style.width=`${u}px`,t.style.height=`${m}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let i=Math.max(1,Math.floor(u*x)),p=Math.max(1,Math.floor(m*x));t.width!==i&&(t.width=i),t.height!==p&&(t.height=p),l.setTransform(x,0,0,x,0,0),G.forEach(d=>d())}let z=new ResizeObserver(y);z.observe(document.body),g.push(()=>z.disconnect()),window.addEventListener("resize",y),g.push(()=>window.removeEventListener("resize",y));let _=window.visualViewport;_&&(_.addEventListener("resize",y),g.push(()=>_.removeEventListener("resize",y)));let E={stage:document.body,canvas:t,ctx:l,get width(){return u},get height(){return m},get dpr(){return x},resize:y,toStagePoint:e=>{let n=t.getBoundingClientRect(),o=(e.clientX-n.left)*(u/n.width),i=(e.clientY-n.top)*(m/n.height);return o=Math.max(0,Math.min(u,o)),i=Math.max(0,Math.min(m,i)),{x:o,y:i}},createDrag:()=>q(E.toStagePoint),onTap:e=>{b.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{O.push(e)},on:(e,n,o,i)=>{if(/^(click|pointer|mouse|touch)/.test(e))try{let v=n.split(",").map(f=>`.star-ui ${f.trim()}`).join(", "),h=document.createElement("style");h.textContent=`${v} { pointer-events: auto; }`,document.head.appendChild(h),g.push(()=>h.remove())}catch{}let p=v=>{let f=v.target?.closest?.(n);f&&o.call(f,v)};document.addEventListener(e,p,i);let d=()=>document.removeEventListener(e,p,i);return g.push(d),d},loop:e=>{let o=0,i=!1,p=0,d=v=>{if(!i)return;let h=p?Math.min((v-p)/1e3,.1):0;p=v;try{e(h,v)}catch(f){console.error("[star-canvas] Game loop error:",f)}o=requestAnimationFrame(d)};return C={get running(){return i},start(){i||(i=!0,p=performance.now(),o=requestAnimationFrame(d))},stop(){i&&(i=!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(),g.forEach(e=>e()),g=[],G.clear(),t.parentElement&&t.parentElement.removeChild(t),s.parentElement&&s.parentElement.removeChild(s),c.parentElement&&c.parentElement.removeChild(c)},scoped:e=>{l.save();try{e()}finally{l.restore()}}};c.addEventListener("pointerdown",e=>{if(S(e))return;let n={...E.toStagePoint(e),event:e};b.forEach(o=>o(n))}),c.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(o=>o(n))}),c.addEventListener("pointerup",e=>{let n={...E.toStagePoint(e),event:e};O.forEach(o=>o(n))}),window.__STAR_DOM__={destroy:E.destroy},requestAnimationFrame(()=>requestAnimationFrame(()=>{y();try{a(E)}catch(e){console.error("[star-canvas] Game initialization failed:",e)}}))}0&&(module.exports={createDragState,game,version});
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- var U="0.8.0",z={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function B(m){let i=null,d=0,t=0;return{point(u){return m(u)},grab(u,a){let{x:y,y:T}=m(u);i=a,d=y-a.x,t=T-a.y},move(u){if(i){let{x:a,y}=m(u);i.x=a-d,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-canvas-base"))return;let m=document.createElement("style");m.id="star-canvas-base",m.textContent=`
1
+ var V="0.8.0",X={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function U(p){let i=null,l=0,t=0;return{point(u){return p(u)},grab(u,a){let{x:b,y:T}=p(u);i=a,l=b-a.x,t=T-a.y},move(u){if(i){let{x:a,y:b}=p(u);i.x=a-l,i.y=b-t}},release(){let u=i;return i=null,u},get dragging(){return i}}}function $(){return typeof window<"u"&&typeof document<"u"}function j(){if(!$()||document.getElementById("star-canvas-base"))return;let p=document.createElement("style");p.id="star-canvas-base",p.textContent=`
2
2
  html, body { height: 100%; }
3
3
  body {
4
4
  margin: 0; min-height: 100dvh; overflow: hidden; background: #000;
@@ -29,4 +29,4 @@ var U="0.8.0",z={landscape:{width:640,height:360},portrait:{width:360,height:640
29
29
  .star-ui textarea, .star-ui [data-interactive] {
30
30
  pointer-events: auto;
31
31
  }
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 d=document.createElement("div");d.className="star-ui",document.body.appendChild(d);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-canvas] 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,r){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let o=(p=>n.call(t,p));H.set(n,o),a.addEventListener(e,o,r)}else W(e,n,r)},t.removeEventListener=function(e,n,r){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let o=H.get(n);o&&(a.removeEventListener(e,o,r),H.delete(n))}else Y(e,n,r)};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)),r=Math.max(1,Math.floor(e.height||window.innerHeight||600));if(L&&M){s=L,l=M;let c=s/l,v=n/r,f=1;if(S==="contain"?f=v>c?r/l:n/s:S==="cover"&&(f=v>c?n/s:r/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((r-P)/2)}px`}}else if(M){l=M;let c=n/r;s=Math.floor(l*c),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 c=n/r;l=Math.floor(s/c),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else s=n,l=r,t.style.width=`${s}px`,t.style.height=`${l}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let o=Math.max(1,Math.floor(s*b)),p=Math.max(1,Math.floor(l*b));t.width!==o&&(t.width=o),t.height!==p&&(t.height=p),u.setTransform(b,0,0,b,0,0),k.forEach(c=>c())}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(),r=(e.clientX-n.left)*(s/n.width),o=(e.clientY-n.top)*(l/n.height);return r=Math.max(0,Math.min(s,r)),o=Math.max(0,Math.min(l,o)),{x:r,y:o}},createDrag:()=>B(E.toStagePoint),onTap:e=>{y.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{A.push(e)},on:(e,n,r,o)=>{let p=v=>{let g=v.target?.closest?.(n);g&&r.call(g,v)};document.addEventListener(e,p,o);let c=()=>document.removeEventListener(e,p,o);return x.push(c),c},loop:e=>{let r=0,o=!1,p=0,c=v=>{if(!o)return;let f=p?Math.min((v-p)/1e3,.1):0;p=v;try{e(f,v)}catch(g){console.error("[star-canvas] Game loop error:",g)}r=requestAnimationFrame(c)};return C={get running(){return o},start(){o||(o=!0,p=performance.now(),r=requestAnimationFrame(c))},stop(){o&&(o=!1,cancelAnimationFrame(r))}},C.start(),C},ui:{root:d,render:e=>{d.innerHTML!==e&&(d.innerHTML=e)},el:e=>d.querySelector(e),all:e=>d.querySelectorAll(e)},destroy:()=>{C?.stop(),x.forEach(e=>e()),x=[],k.clear(),t.parentElement&&t.parentElement.removeChild(t),d.parentElement&&d.parentElement.removeChild(d),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(r=>r(n))}),a.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(r=>r(n))}),a.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{m(E)}catch(e){console.error("[star-canvas] Game initialization failed:",e)}}))}export{B as createDragState,j as game,U as version};
32
+ `,document.head.appendChild(p)}function J(p,i={}){$()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>Y(p,i),{once:!0}):queueMicrotask(()=>Y(p,i)))}function Y(p,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 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 u=t.getContext("2d",i.contextAttributes??{alpha:!0});if(!u)throw new Error("[star-canvas] 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 b=[],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=>{S(n)||e.call(t,n)},a.addEventListener("click",w))}});let q=t.addEventListener.bind(t),F=t.removeEventListener.bind(t),I=new WeakMap;function S(e){let n=e;if(n.clientX==null||n.clientY==null)return!1;let o=document.elementFromPoint(n.clientX,n.clientY);return o!==null&&o!==l&&l.contains(o)}let N=/^(click|pointerdown|mousedown|touchstart)$/;t.addEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let r=N.test(e),m=(s=>{r&&S(s)||n.call(t,s)});I.set(n,m),a.addEventListener(e,m,o)}else q(e,n,o)},t.removeEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let r=I.get(n);r&&(a.removeEventListener(e,r,o),I.delete(n))}else F(e,n,o)};let W=i.preset??"landscape",R=X[W]??X.landscape,L=i.width??R.width,M=i.height??R.height,D=i.maxPixelRatio??2,k=i.pixelRatio??"device",H=i.fit??"contain",x=1,c=L??1,d=M??1,P=new Set,C=null,g=[];function B(){return Math.min(typeof k=="number"?Math.max(1,k):Math.max(1,window.devicePixelRatio||1),D)}function y(){x=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){c=L,d=M;let s=c/d,v=n/o,h=1;if(H==="contain"?h=v>s?o/d:n/c:H==="cover"&&(h=v>s?n/c:o/d),H==="stretch")t.style.width="100%",t.style.height="100%";else{let f=Math.floor(c*h),z=Math.floor(d*h);t.style.width=`${f}px`,t.style.height=`${z}px`,t.style.position="absolute",t.style.left=`${Math.floor((n-f)/2)}px`,t.style.top=`${Math.floor((o-z)/2)}px`}}else if(M){d=M;let s=n/o;c=Math.floor(d*s),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 s=n/o;d=Math.floor(c/s),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else c=n,d=o,t.style.width=`${c}px`,t.style.height=`${d}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let r=Math.max(1,Math.floor(c*x)),m=Math.max(1,Math.floor(d*x));t.width!==r&&(t.width=r),t.height!==m&&(t.height=m),u.setTransform(x,0,0,x,0,0),P.forEach(s=>s())}let G=new ResizeObserver(y);G.observe(document.body),g.push(()=>G.disconnect()),window.addEventListener("resize",y),g.push(()=>window.removeEventListener("resize",y));let _=window.visualViewport;_&&(_.addEventListener("resize",y),g.push(()=>_.removeEventListener("resize",y)));let E={stage:document.body,canvas:t,ctx:u,get width(){return c},get height(){return d},get dpr(){return x},resize:y,toStagePoint:e=>{let n=t.getBoundingClientRect(),o=(e.clientX-n.left)*(c/n.width),r=(e.clientY-n.top)*(d/n.height);return o=Math.max(0,Math.min(c,o)),r=Math.max(0,Math.min(d,r)),{x:o,y:r}},createDrag:()=>U(E.toStagePoint),onTap:e=>{b.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{A.push(e)},on:(e,n,o,r)=>{if(/^(click|pointer|mouse|touch)/.test(e))try{let v=n.split(",").map(f=>`.star-ui ${f.trim()}`).join(", "),h=document.createElement("style");h.textContent=`${v} { pointer-events: auto; }`,document.head.appendChild(h),g.push(()=>h.remove())}catch{}let m=v=>{let f=v.target?.closest?.(n);f&&o.call(f,v)};document.addEventListener(e,m,r);let s=()=>document.removeEventListener(e,m,r);return g.push(s),s},loop:e=>{let o=0,r=!1,m=0,s=v=>{if(!r)return;let h=m?Math.min((v-m)/1e3,.1):0;m=v;try{e(h,v)}catch(f){console.error("[star-canvas] Game loop error:",f)}o=requestAnimationFrame(s)};return C={get running(){return r},start(){r||(r=!0,m=performance.now(),o=requestAnimationFrame(s))},stop(){r&&(r=!1,cancelAnimationFrame(o))}},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(),g.forEach(e=>e()),g=[],P.clear(),t.parentElement&&t.parentElement.removeChild(t),l.parentElement&&l.parentElement.removeChild(l),a.parentElement&&a.parentElement.removeChild(a)},scoped:e=>{u.save();try{e()}finally{u.restore()}}};a.addEventListener("pointerdown",e=>{if(S(e))return;let n={...E.toStagePoint(e),event:e};b.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(()=>{y();try{p(E)}catch(e){console.error("[star-canvas] Game initialization failed:",e)}}))}export{U as createDragState,J as game,V as version};
package/dist/legacy.cjs CHANGED
@@ -1,4 +1,4 @@
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,c){let{x:y,y:T}=i(l);o=c,s=y-c.x,t=T-c.y},move(l){if(o){let{x:c,y}=i(l);o.x=c-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-canvas-base"))return;let i=document.createElement("style");i.id="star-canvas-base",i.textContent=`
1
+ "use strict";var H=Object.defineProperty;var K=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var ee=(i,r)=>{for(var a in r)H(i,a,{get:r[a],enumerable:!0})},te=(i,r,a,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let l of Q(r))!Z.call(i,l)&&l!==a&&H(i,l,{get:()=>r[l],enumerable:!(t=K(r,l))||t.enumerable});return i};var ne=i=>te(H({},"__esModule",{value:!0}),i);var ie={};ee(ie,{createDragState:()=>_,game:()=>re,version:()=>F});module.exports=ne(ie);var F="0.8.0",$={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function _(i){let r=null,a=0,t=0;return{point(l){return i(l)},grab(l,c){let{x:b,y:T}=i(l);r=c,a=b-c.x,t=T-c.y},move(l){if(r){let{x:c,y:b}=i(l);r.x=c-a,r.y=b-t}},release(){let l=r;return r=null,l},get dragging(){return r}}}function N(){return typeof window<"u"&&typeof document<"u"}function oe(){if(!N()||document.getElementById("star-canvas-base"))return;let i=document.createElement("style");i.id="star-canvas-base",i.textContent=`
2
2
  html, body { height: 100%; }
3
3
  body {
4
4
  margin: 0; min-height: 100dvh; overflow: hidden; background: #000;
@@ -29,4 +29,4 @@
29
29
  .star-ui textarea, .star-ui [data-interactive] {
30
30
  pointer-events: auto;
31
31
  }
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-canvas] Failed to get 2D context");if(o.preventContextMenu!==!1){let e=n=>n.preventDefault();t.addEventListener("contextmenu",e)}let c=document.createElement("div");c.className="star-input",document.body.appendChild(c);let y=[],T=[],A=[],D=null,w=null;Object.defineProperty(t,"onclick",{get:()=>D,set:e=>{w&&(c.removeEventListener("click",w),w=null),D=e,e&&(w=n=>e.call(t,n),c.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),c.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&&(c.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,d=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){d=L,u=M;let m=d/u,v=n/r,f=1;if(O==="contain"?f=v>m?r/u:n/d:O==="cover"&&(f=v>m?n/d:r/u),O==="stretch")t.style.width="100%",t.style.height="100%";else{let g=Math.floor(d*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;d=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){d=L;let m=n/r;u=Math.floor(d/m),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else d=n,u=r,t.style.width=`${d}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(d*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 d},get height(){return u},get dpr(){return b},resize:h,toStagePoint:e=>{let n=t.getBoundingClientRect(),r=(e.clientX-n.left)*(d/n.width),a=(e.clientY-n.top)*(u/n.height);return r=Math.max(0,Math.min(d,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-canvas] 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),c.parentElement&&c.parentElement.removeChild(c)},scoped:e=>{l.save();try{e()}finally{l.restore()}}};c.addEventListener("pointerdown",e=>{let n={...E.toStagePoint(e),event:e};y.forEach(r=>r(n))}),c.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(r=>r(n))}),c.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-canvas] Game initialization failed:",e)}}))}function ne(i,o={}){let s={preset:"responsive",...o};return $(i,s)}0&&(module.exports={createDragState,game,version});
32
+ `,document.head.appendChild(i)}function W(i,r={}){N()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>q(i,r),{once:!0}):queueMicrotask(()=>q(i,r)))}function q(i,r){if(oe(),window.__STAR_DOM__?.destroy)try{window.__STAR_DOM__.destroy()}catch{}document.querySelectorAll(".star-ui, .star-canvas, .star-input").forEach(e=>e.remove());let a=document.createElement("div");a.className="star-ui",document.body.appendChild(a);let t=document.createElement("canvas");t.className="star-canvas",document.body.appendChild(t);let l=t.getContext("2d",r.contextAttributes??{alpha:!0});if(!l)throw new Error("[star-canvas] Failed to get 2D context");if(r.preventContextMenu!==!1){let e=n=>n.preventDefault();t.addEventListener("contextmenu",e)}let c=document.createElement("div");c.className="star-input",document.body.appendChild(c);let b=[],T=[],A=[],D=null,w=null;Object.defineProperty(t,"onclick",{get:()=>D,set:e=>{w&&(c.removeEventListener("click",w),w=null),D=e,e&&(w=n=>{O(n)||e.call(t,n)},c.addEventListener("click",w))}});let U=t.addEventListener.bind(t),B=t.removeEventListener.bind(t),G=new WeakMap;function O(e){let n=e;if(n.clientX==null||n.clientY==null)return!1;let o=document.elementFromPoint(n.clientX,n.clientY);return o!==null&&o!==a&&a.contains(o)}let j=/^(click|pointerdown|mousedown|touchstart)$/;t.addEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let s=j.test(e),p=(d=>{s&&O(d)||n.call(t,d)});G.set(n,p),c.addEventListener(e,p,o)}else U(e,n,o)},t.removeEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let s=G.get(n);s&&(c.removeEventListener(e,s,o),G.delete(n))}else B(e,n,o)};let V=r.preset??"landscape",R=$[V]??$.landscape,L=r.width??R.width,M=r.height??R.height,k=r.maxPixelRatio??2,P=r.pixelRatio??"device",S=r.fit??"contain",x=1,u=L??1,m=M??1,z=new Set,C=null,g=[];function J(){return Math.min(typeof P=="number"?Math.max(1,P):Math.max(1,window.devicePixelRatio||1),k)}function y(){x=J();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){u=L,m=M;let d=u/m,v=n/o,h=1;if(S==="contain"?h=v>d?o/m:n/u:S==="cover"&&(h=v>d?n/u:o/m),S==="stretch")t.style.width="100%",t.style.height="100%";else{let f=Math.floor(u*h),Y=Math.floor(m*h);t.style.width=`${f}px`,t.style.height=`${Y}px`,t.style.position="absolute",t.style.left=`${Math.floor((n-f)/2)}px`,t.style.top=`${Math.floor((o-Y)/2)}px`}}else if(M){m=M;let d=n/o;u=Math.floor(m*d),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else if(L){u=L;let d=n/o;m=Math.floor(u/d),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else u=n,m=o,t.style.width=`${u}px`,t.style.height=`${m}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let s=Math.max(1,Math.floor(u*x)),p=Math.max(1,Math.floor(m*x));t.width!==s&&(t.width=s),t.height!==p&&(t.height=p),l.setTransform(x,0,0,x,0,0),z.forEach(d=>d())}let X=new ResizeObserver(y);X.observe(document.body),g.push(()=>X.disconnect()),window.addEventListener("resize",y),g.push(()=>window.removeEventListener("resize",y));let I=window.visualViewport;I&&(I.addEventListener("resize",y),g.push(()=>I.removeEventListener("resize",y)));let E={stage:document.body,canvas:t,ctx:l,get width(){return u},get height(){return m},get dpr(){return x},resize:y,toStagePoint:e=>{let n=t.getBoundingClientRect(),o=(e.clientX-n.left)*(u/n.width),s=(e.clientY-n.top)*(m/n.height);return o=Math.max(0,Math.min(u,o)),s=Math.max(0,Math.min(m,s)),{x:o,y:s}},createDrag:()=>_(E.toStagePoint),onTap:e=>{b.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{A.push(e)},on:(e,n,o,s)=>{if(/^(click|pointer|mouse|touch)/.test(e))try{let v=n.split(",").map(f=>`.star-ui ${f.trim()}`).join(", "),h=document.createElement("style");h.textContent=`${v} { pointer-events: auto; }`,document.head.appendChild(h),g.push(()=>h.remove())}catch{}let p=v=>{let f=v.target?.closest?.(n);f&&o.call(f,v)};document.addEventListener(e,p,s);let d=()=>document.removeEventListener(e,p,s);return g.push(d),d},loop:e=>{let o=0,s=!1,p=0,d=v=>{if(!s)return;let h=p?Math.min((v-p)/1e3,.1):0;p=v;try{e(h,v)}catch(f){console.error("[star-canvas] Game loop error:",f)}o=requestAnimationFrame(d)};return C={get running(){return s},start(){s||(s=!0,p=performance.now(),o=requestAnimationFrame(d))},stop(){s&&(s=!1,cancelAnimationFrame(o))}},C.start(),C},ui:{root:a,render:e=>{a.innerHTML!==e&&(a.innerHTML=e)},el:e=>a.querySelector(e),all:e=>a.querySelectorAll(e)},destroy:()=>{C?.stop(),g.forEach(e=>e()),g=[],z.clear(),t.parentElement&&t.parentElement.removeChild(t),a.parentElement&&a.parentElement.removeChild(a),c.parentElement&&c.parentElement.removeChild(c)},scoped:e=>{l.save();try{e()}finally{l.restore()}}};c.addEventListener("pointerdown",e=>{if(O(e))return;let n={...E.toStagePoint(e),event:e};b.forEach(o=>o(n))}),c.addEventListener("pointermove",e=>{let n={...E.toStagePoint(e),event:e};T.forEach(o=>o(n))}),c.addEventListener("pointerup",e=>{let n={...E.toStagePoint(e),event:e};A.forEach(o=>o(n))}),window.__STAR_DOM__={destroy:E.destroy},requestAnimationFrame(()=>requestAnimationFrame(()=>{y();try{i(E)}catch(e){console.error("[star-canvas] Game initialization failed:",e)}}))}function re(i,r={}){let a={preset:"responsive",...r};return W(i,a)}0&&(module.exports={createDragState,game,version});
package/dist/legacy.mjs CHANGED
@@ -1,4 +1,4 @@
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-canvas-base"))return;let l=document.createElement("style");l.id="star-canvas-base",l.textContent=`
1
+ var V="0.8.0",X={landscape:{width:640,height:360},portrait:{width:360,height:640},responsive:{}};function $(c){let r=null,s=0,t=0;return{point(m){return c(m)},grab(m,a){let{x:b,y:T}=c(m);r=a,s=b-a.x,t=T-a.y},move(m){if(r){let{x:a,y:b}=c(m);r.x=a-s,r.y=b-t}},release(){let m=r;return r=null,m},get dragging(){return r}}}function q(){return typeof window<"u"&&typeof document<"u"}function J(){if(!q()||document.getElementById("star-canvas-base"))return;let c=document.createElement("style");c.id="star-canvas-base",c.textContent=`
2
2
  html, body { height: 100%; }
3
3
  body {
4
4
  margin: 0; min-height: 100dvh; overflow: hidden; background: #000;
@@ -29,4 +29,4 @@ var N="0.8.0",z={landscape:{width:640,height:360},portrait:{width:360,height:640
29
29
  .star-ui textarea, .star-ui [data-interactive] {
30
30
  pointer-events: auto;
31
31
  }
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-canvas] 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,c=L??1,d=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){c=L,d=M;let u=c/d,v=n/o,f=1;if(O==="contain"?f=v>u?o/d:n/c:O==="cover"&&(f=v>u?n/c:o/d),O==="stretch")t.style.width="100%",t.style.height="100%";else{let g=Math.floor(c*f),P=Math.floor(d*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){d=M;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 if(L){c=L;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 c=n,d=o,t.style.width=`${c}px`,t.style.height=`${d}px`,t.style.position="absolute",t.style.left="0",t.style.top="0";let r=Math.max(1,Math.floor(c*b)),p=Math.max(1,Math.floor(d*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 c},get height(){return d},get dpr(){return b},resize:h,toStagePoint:e=>{let n=t.getBoundingClientRect(),o=(e.clientX-n.left)*(c/n.width),r=(e.clientY-n.top)*(d/n.height);return o=Math.max(0,Math.min(c,o)),r=Math.max(0,Math.min(d,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-canvas] 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-canvas] 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};
32
+ `,document.head.appendChild(c)}function F(c,r={}){q()&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>Y(c,r),{once:!0}):queueMicrotask(()=>Y(c,r)))}function Y(c,r){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",r.contextAttributes??{alpha:!0});if(!m)throw new Error("[star-canvas] Failed to get 2D context");if(r.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 b=[],T=[],H=[],_=null,w=null;Object.defineProperty(t,"onclick",{get:()=>_,set:e=>{w&&(a.removeEventListener("click",w),w=null),_=e,e&&(w=n=>{O(n)||e.call(t,n)},a.addEventListener("click",w))}});let N=t.addEventListener.bind(t),W=t.removeEventListener.bind(t),G=new WeakMap;function O(e){let n=e;if(n.clientX==null||n.clientY==null)return!1;let o=document.elementFromPoint(n.clientX,n.clientY);return o!==null&&o!==s&&s.contains(o)}let U=/^(click|pointerdown|mousedown|touchstart)$/;t.addEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let i=U.test(e),p=(l=>{i&&O(l)||n.call(t,l)});G.set(n,p),a.addEventListener(e,p,o)}else N(e,n,o)},t.removeEventListener=function(e,n,o){if(/^(click|pointer|mouse|touch)/.test(e)&&typeof n=="function"){let i=G.get(n);i&&(a.removeEventListener(e,i,o),G.delete(n))}else W(e,n,o)};let B=r.preset??"landscape",A=X[B]??X.landscape,L=r.width??A.width,M=r.height??A.height,D=r.maxPixelRatio??2,R=r.pixelRatio??"device",S=r.fit??"contain",x=1,d=L??1,u=M??1,k=new Set,C=null,g=[];function j(){return Math.min(typeof R=="number"?Math.max(1,R):Math.max(1,window.devicePixelRatio||1),D)}function y(){x=j();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,u=M;let l=d/u,v=n/o,h=1;if(S==="contain"?h=v>l?o/u:n/d:S==="cover"&&(h=v>l?n/d:o/u),S==="stretch")t.style.width="100%",t.style.height="100%";else{let f=Math.floor(d*h),z=Math.floor(u*h);t.style.width=`${f}px`,t.style.height=`${z}px`,t.style.position="absolute",t.style.left=`${Math.floor((n-f)/2)}px`,t.style.top=`${Math.floor((o-z)/2)}px`}}else if(M){u=M;let l=n/o;d=Math.floor(u*l),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 l=n/o;u=Math.floor(d/l),t.style.width="100%",t.style.height="100%",t.style.position="absolute",t.style.left="0",t.style.top="0"}else d=n,u=o,t.style.width=`${d}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(d*x)),p=Math.max(1,Math.floor(u*x));t.width!==i&&(t.width=i),t.height!==p&&(t.height=p),m.setTransform(x,0,0,x,0,0),k.forEach(l=>l())}let P=new ResizeObserver(y);P.observe(document.body),g.push(()=>P.disconnect()),window.addEventListener("resize",y),g.push(()=>window.removeEventListener("resize",y));let I=window.visualViewport;I&&(I.addEventListener("resize",y),g.push(()=>I.removeEventListener("resize",y)));let E={stage:document.body,canvas:t,ctx:m,get width(){return d},get height(){return u},get dpr(){return x},resize:y,toStagePoint:e=>{let n=t.getBoundingClientRect(),o=(e.clientX-n.left)*(d/n.width),i=(e.clientY-n.top)*(u/n.height);return o=Math.max(0,Math.min(d,o)),i=Math.max(0,Math.min(u,i)),{x:o,y:i}},createDrag:()=>$(E.toStagePoint),onTap:e=>{b.push(e)},onMove:e=>{T.push(e)},onRelease:e=>{H.push(e)},on:(e,n,o,i)=>{if(/^(click|pointer|mouse|touch)/.test(e))try{let v=n.split(",").map(f=>`.star-ui ${f.trim()}`).join(", "),h=document.createElement("style");h.textContent=`${v} { pointer-events: auto; }`,document.head.appendChild(h),g.push(()=>h.remove())}catch{}let p=v=>{let f=v.target?.closest?.(n);f&&o.call(f,v)};document.addEventListener(e,p,i);let l=()=>document.removeEventListener(e,p,i);return g.push(l),l},loop:e=>{let o=0,i=!1,p=0,l=v=>{if(!i)return;let h=p?Math.min((v-p)/1e3,.1):0;p=v;try{e(h,v)}catch(f){console.error("[star-canvas] Game loop error:",f)}o=requestAnimationFrame(l)};return C={get running(){return i},start(){i||(i=!0,p=performance.now(),o=requestAnimationFrame(l))},stop(){i&&(i=!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(),g.forEach(e=>e()),g=[],k.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=>{if(O(e))return;let n={...E.toStagePoint(e),event:e};b.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(()=>{y();try{c(E)}catch(e){console.error("[star-canvas] Game initialization failed:",e)}}))}function Z(c,r={}){let s={preset:"responsive",...r};return F(c,s)}export{$ as createDragState,Z as game,V as version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "star-canvas",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "private": false,
5
5
  "description": "Canvas game utilities for reliable game initialization - part of Star SDK.",
6
6
  "type": "module",
@@ -48,6 +48,16 @@
48
48
  "clean": "rm -rf dist",
49
49
  "prepublishOnly": "node ../../apps/web/scripts/process-sdks.js --package star-canvas --public-only && yarn build"
50
50
  },
51
+ "license": "MIT",
52
+ "homepage": "https://buildwithstar.com/docs/sdk",
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "https://github.com/buildwithstar/star-sdk",
56
+ "directory": "packages/star-canvas"
57
+ },
58
+ "bugs": {
59
+ "url": "https://github.com/buildwithstar/star-sdk/issues"
60
+ },
51
61
  "keywords": [
52
62
  "dom",
53
63
  "canvas",