@mblinkov/whats-missing 20.0.16 → 20.0.18

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.
@@ -1,9 +1,9 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("react"),re=window.origin+"/cloud/speakid/games/whatsmissing/",B=(r,a)=>r.map(([l,n])=>({src:`${re}${a}/${n.replace(/\s/g,"%20")}.png`,name:n})),ae=[["apple","apple"],["banana","banana"],["bread","bread"],["burger","burger"],["cake","cake"],["carrot","carrot"],["cheese","cheese"],["chicken","chicken"],["chocolate","chocolate"],["corn","corn"],["donut","donut"],["fish","fish"],["fries","fries"],["grapes","grapes"],["ice_cream","ice cream"],["milk","milk"],["orange","orange"],["pear","pear"],["pizza","pizza"],["rice","rice"],["sandwich","sandwich"],["soup","soup"],["strawberry","strawberry"],["tomato","tomato"],["watermelon","watermelon"]],le=[["bear","bear"],["cat","cat"],["crocodile","crocodile"],["dolphin","dolphin"],["elephant","elephant"],["fox","fox"],["giraffe","giraffe"],["horse","horse"],["kangaroo","kangaroo"],["lion","lion"],["monkey","monkey"],["owl","owl"],["panda","panda"],["penguin","penguin"],["squirrel","squirrel"],["tiger","tiger"],["tortoise","tortoise"],["wolf","wolf"],["zebra","zebra"]],de=[["ball","ball"],["balloon","balloon"],["blocks","blocks"],["car","car"],["doll","doll"],["drum","drum"],["guitar","guitar"],["jump_rope","jump rope"],["kite","kite"],["paints","paints"],["plane","plane"],["puzzle","puzzle"],["rocket","rocket"],["scooter","scooter"],["skateboard","skateboard"],["slide","slide"],["teddy_bear","teddy bear"],["yo-yo","yo-yo"],["crayons","crayons"]],L={food:B(ae,"food"),animals:B(le,"animals"),toys:B(de,"toys")},ce=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("react"),ae=window.origin+"/cloud/speakid/games/whatsmissing/",L=(r,a)=>r.map(([l,n])=>({src:`${ae}${a}/${n.replace(/\s/g,"%20")}.png`,name:n})),le=[["apple","apple"],["banana","banana"],["bread","bread"],["burger","burger"],["cake","cake"],["carrot","carrot"],["cheese","cheese"],["chicken","chicken"],["chocolate","chocolate"],["corn","corn"],["donut","donut"],["fish","fish"],["fries","fries"],["grapes","grapes"],["ice_cream","ice cream"],["milk","milk"],["orange","orange"],["pear","pear"],["pizza","pizza"],["rice","rice"],["sandwich","sandwich"],["soup","soup"],["strawberry","strawberry"],["tomato","tomato"],["watermelon","watermelon"]],de=[["bear","bear"],["cat","cat"],["crocodile","crocodile"],["dolphin","dolphin"],["elephant","elephant"],["fox","fox"],["giraffe","giraffe"],["horse","horse"],["kangaroo","kangaroo"],["lion","lion"],["monkey","monkey"],["owl","owl"],["panda","panda"],["penguin","penguin"],["squirrel","squirrel"],["tiger","tiger"],["tortoise","tortoise"],["wolf","wolf"],["zebra","zebra"]],ce=[["ball","ball"],["balloon","balloon"],["blocks","blocks"],["car","car"],["doll","doll"],["drum","drum"],["guitar","guitar"],["jump_rope","jump rope"],["kite","kite"],["paints","paints"],["plane","plane"],["puzzle","puzzle"],["rocket","rocket"],["scooter","scooter"],["skateboard","skateboard"],["slide","slide"],["teddy_bear","teddy bear"],["yo-yo","yo-yo"],["crayons","crayons"]],W={food:L(le,"food"),animals:L(de,"animals"),toys:L(ce,"toys")},me=`
2
2
  @keyframes spin {
3
3
  from { transform: rotate(0deg); }
4
4
  to { transform: rotate(360deg); }
5
5
  }
6
- `;if(typeof document<"u"&&!document.getElementById("spin-keyframes")){const r=document.createElement("style");r.id="spin-keyframes",r.innerHTML=ce,document.head.appendChild(r)}const me={animation:"spin 1.4s linear infinite"},s={gmCenterScreen:{position:"relative",zIndex:1,minHeight:"100vh",width:"100%",display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",textAlign:"center",color:"#1f2937",padding:"24px 16px",boxSizing:"border-box",transform:"translateY(20px)"},gmHeadline1:{fontWeight:700,fontSize:"clamp(28px, 4vw, 40px)",lineHeight:"110%"},gmHeadline3:{fontWeight:600,fontSize:"18px",lineHeight:"130%"},gmBodyM:{fontWeight:400,fontSize:"16px",lineHeight:"140%"},gmBodyS:{fontWeight:400,fontSize:"14px",lineHeight:"140%",color:"#6b7280"},gmButton:{fontFamily:'"Geist", system-ui, -apple-system, "Segoe UI", Roboto, Arial, "Noto Sans"',fontWeight:600,fontSize:"16px",padding:"10px 16px",borderRadius:"12px",border:"1px solid #e5e7eb",background:"#ec4c44",color:"#ffffff",cursor:"pointer",boxShadow:"0 6px 18px rgba(236, 76, 68, .18)",transition:"transform .06s ease, box-shadow .2s ease, background .2s ease, opacity .2s ease"},gmButtonActive:{background:"#333",color:"#fff"},gmGameLayout:{position:"relative",width:"100%",maxWidth:"600px",minHeight:"100vh",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",color:"#1f2937",padding:"16px 8px",margin:"0 auto"},gmGrid:{width:"100%",maxWidth:"calc(210px * 3 + 20px * 2)",margin:"0 auto",display:"grid",gridTemplateColumns:"repeat(3, 210px)",gridAutoRows:"210px",gap:"20px",justifyContent:"center"},gmCard:{border:"1px solid #e5e7eb",borderRadius:"16px",background:"#f9f9f9",aspectRatio:"1 / 1",display:"flex",alignItems:"center",justifyContent:"center",overflow:"hidden",transition:"transform .2s ease, box-shadow .2s ease, border-color .2s ease"},gmCorrect:{border:"2px solid #10b981",boxShadow:"0 0 18px rgba(16,185,129,.45)",background:"#ecfdf5"},gmWrong:{border:"2px solid #ec4c44",boxShadow:"0 0 18px rgba(236,76,68,.35)",background:"#fef2f2"},gmInput:{padding:"6px 10px",borderRadius:"6px",border:"1px solid #ccc",fontSize:"16px",fontFamily:'"Geist", system-ui',width:"160px"},gmTable:{marginTop:"20px",marginBottom:"32px",borderCollapse:"collapse",width:"100%",maxWidth:"520px",tableLayout:"fixed",textAlign:"center"},gmTableCell:{padding:"8px 12px",borderBottom:"1px solid #e5e7eb",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},gmLogoFixed:{position:"absolute",top:"16px",left:"24px",width:"120px",zIndex:10,pointerEvents:"none",background:"transparent",transform:"none",willChange:"auto"},gmLogoImg:{height:"clamp(28px, 5vw, 40px)",width:"auto",background:"transparent",objectFit:"contain",imageRendering:"auto",transform:"translateZ(0)",backfaceVisibility:"hidden",WebkitFontSmoothing:"antialiased"},gmHourglass:{fontSize:"42px",...me}},ge=()=>{const r=document.createElement("style");r.textContent=`
6
+ `;if(typeof document<"u"&&!document.getElementById("spin-keyframes")){const r=document.createElement("style");r.id="spin-keyframes",r.innerHTML=me,document.head.appendChild(r)}const ge={animation:"spin 1.4s linear infinite"},s={gmCenterScreen:{position:"relative",zIndex:1,minHeight:"100vh",width:"100%",display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",textAlign:"center",color:"#1f2937",padding:"24px 16px",boxSizing:"border-box",transform:"translateY(20px)"},gmHeadline1:{fontWeight:700,fontSize:"clamp(28px, 4vw, 40px)",lineHeight:"110%"},gmHeadline3:{fontWeight:600,fontSize:"18px",lineHeight:"130%"},gmBodyM:{fontWeight:400,fontSize:"16px",lineHeight:"140%"},gmBodyS:{fontWeight:400,fontSize:"14px",lineHeight:"140%",color:"#6b7280"},gmButton:{fontFamily:'"Geist", system-ui, -apple-system, "Segoe UI", Roboto, Arial, "Noto Sans"',fontWeight:600,fontSize:"16px",padding:"10px 16px",borderRadius:"12px",border:"1px solid #e5e7eb",background:"#ec4c44",color:"#ffffff",cursor:"pointer",boxShadow:"0 6px 18px rgba(236, 76, 68, .18)",transition:"transform .06s ease, box-shadow .2s ease, background .2s ease, opacity .2s ease"},gmButtonActive:{background:"#333",color:"#fff"},gmGameLayout:{position:"relative",width:"100%",maxWidth:"600px",minHeight:"100vh",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",color:"#1f2937",padding:"16px 8px",margin:"0 auto"},gmGrid:{width:"100%",maxWidth:"calc(210px * 3 + 20px * 2)",margin:"0 auto",display:"grid",gridTemplateColumns:"repeat(3, 210px)",gridAutoRows:"210px",gap:"20px",justifyContent:"center"},gmCard:{border:"1px solid #e5e7eb",borderRadius:"16px",background:"#f9f9f9",aspectRatio:"1 / 1",display:"flex",alignItems:"center",justifyContent:"center",overflow:"hidden",transition:"transform .2s ease, box-shadow .2s ease, border-color .2s ease"},gmCorrect:{border:"2px solid #10b981",boxShadow:"0 0 18px rgba(16,185,129,.45)",background:"#ecfdf5"},gmWrong:{border:"2px solid #ec4c44",boxShadow:"0 0 18px rgba(236,76,68,.35)",background:"#fef2f2"},gmInput:{padding:"6px 10px",borderRadius:"6px",border:"1px solid #ccc",fontSize:"16px",fontFamily:'"Geist", system-ui',width:"160px"},gmTable:{marginTop:"20px",marginBottom:"32px",borderCollapse:"collapse",width:"100%",maxWidth:"520px",tableLayout:"fixed",textAlign:"center"},gmTableCell:{padding:"8px 12px",borderBottom:"1px solid #e5e7eb",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},gmLogoFixed:{position:"absolute",top:"16px",left:"24px",width:"120px",zIndex:10,pointerEvents:"none",background:"transparent",transform:"none",willChange:"auto"},gmLogoImg:{height:"clamp(28px, 5vw, 40px)",width:"auto",background:"transparent",objectFit:"contain",imageRendering:"auto",transform:"translateZ(0)",backfaceVisibility:"hidden",WebkitFontSmoothing:"antialiased"},gmHourglass:{fontSize:"42px",...ge}},ue=()=>{const r=document.createElement("style");r.textContent=`
7
7
  #whats-missing-root, #whats-missing-root * {
8
8
  box-sizing: border-box;
9
9
  font-family: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
@@ -14,5 +14,9 @@
14
14
  display: block;
15
15
  user-select: none;
16
16
  }
17
- html, body { margin: 0; padding: 0; }
18
- `,document.head.appendChild(r)},ue=(r,a)=>{const l=Array.from({length:r.length+1},()=>Array(a.length+1).fill(0));for(let n=0;n<=r.length;n++)l[n][0]=n;for(let n=0;n<=a.length;n++)l[0][n]=n;for(let n=1;n<=r.length;n++)for(let c=1;c<=a.length;c++)l[n][c]=r[n-1]===a[c-1]?l[n-1][c-1]:Math.min(l[n-1][c-1],l[n][c-1],l[n-1][c])+1;return l[r.length][a.length]};function he(){const r=o.useRef(null);o.useEffect(()=>(ge(),()=>{document.body.style.overflow=""}),[]);const[a,l]=o.useState(null),[n,c]=o.useState([]),[b,K]=o.useState(4),[x,W]=o.useState(!1),[w,E]=o.useState(1),[h,Z]=o.useState(null),[g,j]=o.useState("ready"),[G,F]=o.useState(3),[v,C]=o.useState(10),[T,Y]=o.useState(20),[J,z]=o.useState(0),[S,R]=o.useState(!1),[k,D]=o.useState(""),[p,I]=o.useState(!1),[H,q]=o.useState(!1),[O,y]=o.useState(null),[Q,M]=o.useState([]),[X,P]=o.useState([]),[u,ee]=o.useState(!1),[te,U]=o.useState(1);o.useEffect(()=>{const t=()=>{const i=window.innerWidth<768;if(ee(i),i)U(1);else{const f=Math.min(window.innerWidth/1440,window.innerHeight/768);U(f)}};return t(),window.addEventListener("resize",t),()=>window.removeEventListener("resize",t)},[]);const $=t=>[...t].sort(()=>Math.random()-.5).slice(0,6),N=()=>{if(!a)return;const t=$(L[a]);c(t),W(!0),R(!1),E(1),z(0),M([]),P([]),V(t,[],!0)},V=(t=n,i=X,m=!1)=>{const d=$(t.length?t:L[a]);let f=Math.floor(Math.random()*d.length),A=d[f].name,_=0;for(;i.includes(A)&&_<20;)f=Math.floor(Math.random()*d.length),A=d[f].name,_++;c(d),Z(f),P([...i,A]),I(!1),D(""),Y(20),y(null),m?(j("ready"),F(3),C(10)):(j("memorize"),C(10))};o.useEffect(()=>{if(!(!x||S||p)){if(g==="ready")if(G<=0)j("memorize");else{const t=setTimeout(()=>F(i=>i-1),1e3);return()=>clearTimeout(t)}if(g==="memorize")if(v<=0)j("guess");else{const t=setTimeout(()=>C(i=>i-1),1e3);return()=>clearTimeout(t)}if(g==="guess"){if(T<=0){I(!0),y("wrong");const i=n[h].name;M(m=>[...m,{round:w,answer:k,correct:i,result:"wrong"}]);return}const t=setTimeout(()=>Y(i=>i-1),1e3);return()=>clearTimeout(t)}}},[g,G,v,T,x,S,p,n,h,w,k]);const se=()=>{if(h===null||H)return;const t=n[h].name,i=k.toLowerCase().trim();let m="wrong";i===t?(z(d=>d+1),y("correct"),m="correct"):ue(i,t)===1?(z(d=>d+.5),y("almost"),m="almost"):(y("wrong"),m="wrong"),M(d=>[...d,{round:w,answer:i,correct:t,result:m}]),q(!0),setTimeout(()=>{q(!1),I(!0)},600)},ne=()=>w<b?(E(t=>t+1),V()):R(!0),oe=()=>{W(!1),R(!1),l(null)},ie=o.useMemo(()=>e.jsx("div",{style:s.gmLogoFixed,children:e.jsxs("picture",{children:[e.jsx("source",{srcSet:window.origin+"/cloud/speakid/games/whatsmissing/logo.svg",type:"image/svg+xml"}),e.jsx("img",{src:window.origin+"/cloud/speakid/games/whatsmissing/logo.png",alt:"SPEAKID Logo",style:s.gmLogoImg,loading:"lazy"})]})}),[]);return e.jsx("div",{ref:r,style:{width:"100%",height:"100vh",display:"flex",justifyContent:"center",alignItems:"center",background:"linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",transition:"background 0.3s ease"},children:e.jsx("div",{style:{width:u?"100%":1440,height:u?"100%":768,display:"flex",justifyContent:"center",alignItems:"center",overflow:"hidden",borderRadius:u?0:"20px",background:"linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",boxShadow:u?"none":"0 0 40px rgba(0,0,0,0.1)",margin:u?"0 auto":"unset"},children:e.jsx("div",{style:{transform:u?"none":`scale(${te})`,transformOrigin:"center center",width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center"},children:e.jsxs("div",{id:"whats-missing-root",children:[!u&&ie,!a&&!x&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsx("h1",{style:s.gmHeadline1,children:"WHAT'S MISSING?"}),e.jsx("p",{style:s.gmBodyM,children:"Select a theme:"}),e.jsx("div",{style:{display:"flex",gap:16},children:["animals","food","toys"].map(t=>e.jsx("button",{style:s.gmButton,onClick:()=>l(t),children:t==="animals"?"🐶 Animals":t==="food"?"🍎 Food":"🧸 Toys"},t))}),e.jsxs("div",{style:{marginTop:24},children:[e.jsx("p",{style:s.gmBodyS,children:"Choose number of rounds:"}),e.jsx("div",{style:{display:"flex",gap:12,marginTop:8},children:[3,4,5].map(t=>e.jsx("button",{style:{...s.gmButton,...b===t?s.gmButtonActive:{}},onClick:()=>K(t),children:t},t))})]})]}),a&&!x&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsxs("h1",{style:s.gmHeadline1,children:["Theme selected: ",a]}),e.jsxs("p",{style:s.gmBodyM,children:["Rounds: ",b]}),e.jsx("button",{style:s.gmButton,onClick:N,children:"▶ Start game"})]}),S&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsx("h1",{style:s.gmHeadline1,children:"Results"}),e.jsxs("h2",{style:s.gmHeadline3,children:["Your score: ",J," / ",b]}),e.jsx("p",{style:{...s.gmBodyM,color:"#10b981",marginTop:12},children:"Yahoo! You did it! 🍬✨"}),e.jsxs("table",{style:s.gmTable,children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Round"}),e.jsx("th",{children:"Your Answer"}),e.jsx("th",{children:"Correct"}),e.jsx("th",{children:"Result"})]})}),e.jsx("tbody",{children:Q.map((t,i)=>e.jsxs("tr",{children:[e.jsx("td",{style:s.gmTableCell,children:t.round}),e.jsx("td",{style:s.gmTableCell,children:t.answer||"—"}),e.jsx("td",{style:s.gmTableCell,children:t.correct}),e.jsx("td",{style:s.gmTableCell,children:t.result==="correct"?"✔ Correct":t.result==="almost"?"◐ Almost (0.5)":"✘ Wrong"})]},i))})]}),e.jsxs("div",{style:{display:"flex",gap:12,marginTop:24},children:[e.jsx("button",{style:s.gmButton,onClick:N,children:"🔁 Play again"}),e.jsx("button",{style:s.gmButton,onClick:oe,children:"⬅️ Choose theme"})]})]}),x&&!S&&e.jsxs("div",{style:s.gmGameLayout,children:[e.jsxs("div",{style:{minHeight:160,display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center"},children:[g==="ready"&&e.jsxs(e.Fragment,{children:[e.jsx("h1",{style:{...s.gmHeadline1,color:"#ec4c44"},children:"GET READY"}),e.jsx("div",{style:s.gmHourglass,children:"⏳"})]}),g==="memorize"&&e.jsxs("p",{style:{...s.gmBodyM,color:"#10b981"},children:["MEMORIZE (",v,")"]}),g==="guess"&&!p&&e.jsxs("p",{style:s.gmBodyM,children:["⏳ Time left: ",T,"s"]})]}),g!=="ready"&&e.jsx("div",{style:{...s.gmGrid,gridTemplateColumns:u?"repeat(2, 1fr)":"repeat(3, 210px)",gridAutoRows:u?"150px":"210px",gap:u?"12px":"20px",justifyItems:"center"},children:n.map((t,i)=>{const m=h===i&&g==="guess"&&!p;return e.jsx("div",{style:{...s.gmCard,...O==="correct"&&h===i?s.gmCorrect:{},...O==="wrong"&&h===i?s.gmWrong:{}},children:!m&&e.jsx("img",{src:t.src,alt:t.name,style:{width:"100%",height:"100%",objectFit:"cover"}})},i)})}),e.jsxs("div",{style:{marginTop:16,height:80},children:[g==="guess"&&!p&&e.jsxs("div",{children:[e.jsx("input",{type:"text",placeholder:"Type the missing word",value:k,onChange:t=>D(t.target.value),style:s.gmInput}),e.jsx("button",{style:{...s.gmButton,marginLeft:8},onClick:se,disabled:H,children:H?"...":"Check"})]}),p&&e.jsx("button",{style:s.gmButton,onClick:ne,children:"Next round"})]})]})]})})})})}exports.Game=he;exports.themes=L;
17
+ html, body {
18
+ margin: 0;
19
+ padding: 0;
20
+ zoom: 1 !important; /* ✅ защита от подзума */
21
+ }
22
+ `,document.head.appendChild(r)},he=(r,a)=>{const l=Array.from({length:r.length+1},()=>Array(a.length+1).fill(0));for(let n=0;n<=r.length;n++)l[n][0]=n;for(let n=0;n<=a.length;n++)l[0][n]=n;for(let n=1;n<=r.length;n++)for(let c=1;c<=a.length;c++)l[n][c]=r[n-1]===a[c-1]?l[n-1][c-1]:Math.min(l[n-1][c-1],l[n][c-1],l[n-1][c])+1;return l[r.length][a.length]};function pe(){const r=o.useRef(null);o.useEffect(()=>(ue(),()=>{document.body.style.overflow=""}),[]);const[a,l]=o.useState(null),[n,c]=o.useState([]),[w,X]=o.useState(4),[x,E]=o.useState(!1),[j,F]=o.useState(1),[h,J]=o.useState(null),[g,S]=o.useState("ready"),[G,q]=o.useState(3),[T,z]=o.useState(10),[R,Y]=o.useState(20),[Q,I]=o.useState(0),[k,M]=o.useState(!1),[v,D]=o.useState(""),[p,H]=o.useState(!1),[A,P]=o.useState(!1),[U,y]=o.useState(null),[ee,B]=o.useState([]),[te,N]=o.useState([]),[u,se]=o.useState(!1),[fe,O]=o.useState(1),[V,_]=o.useState(null);o.useEffect(()=>{const t=()=>{const i=window.innerWidth<768;if(se(i),i)_(null),O(1);else{const f=Math.min(window.innerWidth,window.innerHeight),b=Math.max(360,Math.round(f*.97)),C=Math.min(b,1e3);_(C),O(1)}};return t(),window.addEventListener("resize",t),()=>window.removeEventListener("resize",t)},[]);const $=t=>[...t].sort(()=>Math.random()-.5).slice(0,6),K=()=>{if(!a)return;const t=$(W[a]);c(t),E(!0),M(!1),F(1),I(0),B([]),N([]),Z(t,[],!0)},Z=(t=n,i=te,m=!1)=>{const d=$(t.length?t:W[a]);let f=Math.floor(Math.random()*d.length),b=d[f].name,C=0;for(;i.includes(b)&&C<20;)f=Math.floor(Math.random()*d.length),b=d[f].name,C++;c(d),J(f),N([...i,b]),H(!1),D(""),Y(20),y(null),m?(S("ready"),q(3),z(10)):(S("memorize"),z(10))};o.useEffect(()=>{if(!(!x||k||p)){if(g==="ready")if(G<=0)S("memorize");else{const t=setTimeout(()=>q(i=>i-1),1e3);return()=>clearTimeout(t)}if(g==="memorize")if(T<=0)S("guess");else{const t=setTimeout(()=>z(i=>i-1),1e3);return()=>clearTimeout(t)}if(g==="guess"){if(R<=0){H(!0),y("wrong");const i=n[h].name;B(m=>[...m,{round:j,answer:v,correct:i,result:"wrong"}]);return}const t=setTimeout(()=>Y(i=>i-1),1e3);return()=>clearTimeout(t)}}},[g,G,T,R,x,k,p,n,h,j,v]);const ne=()=>{if(h===null||A)return;const t=n[h].name,i=v.toLowerCase().trim();let m="wrong";i===t?(I(d=>d+1),y("correct"),m="correct"):he(i,t)===1?(I(d=>d+.5),y("almost"),m="almost"):(y("wrong"),m="wrong"),B(d=>[...d,{round:j,answer:i,correct:t,result:m}]),P(!0),setTimeout(()=>{P(!1),H(!0)},600)},oe=()=>j<w?(F(t=>t+1),Z()):M(!0),ie=()=>{E(!1),M(!1),l(null)},re=o.useMemo(()=>e.jsx("div",{style:{...s.gmLogoFixed,position:"absolute",top:16,left:16,zIndex:30},children:e.jsxs("picture",{children:[e.jsx("source",{srcSet:window.origin+"/cloud/speakid/games/whatsmissing/logo.svg",type:"image/svg+xml"}),e.jsx("img",{src:window.origin+"/cloud/speakid/games/whatsmissing/logo.png",alt:"SPEAKID Logo",style:s.gmLogoImg,loading:"lazy"})]})}),[]);return e.jsx("div",{ref:r,style:{width:"100%",height:"100vh",display:"flex",justifyContent:"center",alignItems:"center",background:"linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",transition:"background 0.3s ease",overflowX:"clip"},children:e.jsx("div",{style:{width:u?"100%":V||1e3,height:u?"100%":V||1e3,display:"flex",justifyContent:"center",alignItems:"center",overflow:"hidden",borderRadius:u?0:"20px",background:"linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",boxShadow:u?"none":"0 0 40px rgba(0,0,0,0.1)",margin:u?"0 auto":"unset",position:"relative"},children:e.jsx("div",{style:{transform:"none",width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center"},children:e.jsxs("div",{id:"whats-missing-root",children:[!u&&re,!a&&!x&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsx("h1",{style:s.gmHeadline1,children:"WHAT'S MISSING?"}),e.jsx("p",{style:s.gmBodyM,children:"Select a theme:"}),e.jsx("div",{style:{display:"flex",gap:16},children:["animals","food","toys"].map(t=>e.jsx("button",{style:s.gmButton,onClick:()=>l(t),children:t==="animals"?"🐶 Animals":t==="food"?"🍎 Food":"🧸 Toys"},t))}),e.jsxs("div",{style:{marginTop:24},children:[e.jsx("p",{style:s.gmBodyS,children:"Choose number of rounds:"}),e.jsx("div",{style:{display:"flex",gap:12,marginTop:8},children:[3,4,5].map(t=>e.jsx("button",{style:{...s.gmButton,...w===t?s.gmButtonActive:{}},onClick:()=>X(t),children:t},t))})]})]}),a&&!x&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsxs("h1",{style:s.gmHeadline1,children:["Theme selected: ",a]}),e.jsxs("p",{style:s.gmBodyM,children:["Rounds: ",w]}),e.jsx("button",{style:s.gmButton,onClick:K,children:"▶ Start game"})]}),k&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsx("h1",{style:s.gmHeadline1,children:"Results"}),e.jsxs("h2",{style:s.gmHeadline3,children:["Your score: ",Q," / ",w]}),e.jsx("p",{style:{...s.gmBodyM,color:"#10b981",marginTop:12},children:"Yahoo! You did it! 🍬✨"}),e.jsxs("table",{style:s.gmTable,children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Round"}),e.jsx("th",{children:"Your Answer"}),e.jsx("th",{children:"Correct"}),e.jsx("th",{children:"Result"})]})}),e.jsx("tbody",{children:ee.map((t,i)=>e.jsxs("tr",{children:[e.jsx("td",{style:s.gmTableCell,children:t.round}),e.jsx("td",{style:s.gmTableCell,children:t.answer||"—"}),e.jsx("td",{style:s.gmTableCell,children:t.correct}),e.jsx("td",{style:s.gmTableCell,children:t.result==="correct"?"✔ Correct":t.result==="almost"?"◐ Almost (0.5)":"✘ Wrong"})]},i))})]}),e.jsxs("div",{style:{display:"flex",gap:12,marginTop:24},children:[e.jsx("button",{style:s.gmButton,onClick:K,children:"🔁 Play again"}),e.jsx("button",{style:s.gmButton,onClick:ie,children:"⬅️ Choose theme"})]})]}),x&&!k&&e.jsxs("div",{style:s.gmGameLayout,children:[e.jsxs("div",{style:{minHeight:160,display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center"},children:[g==="ready"&&e.jsxs(e.Fragment,{children:[e.jsx("h1",{style:{...s.gmHeadline1,color:"#ec4c44"},children:"GET READY"}),e.jsx("div",{style:s.gmHourglass,children:"⏳"})]}),g==="memorize"&&e.jsxs("p",{style:{...s.gmBodyM,color:"#10b981"},children:["MEMORIZE (",T,")"]}),g==="guess"&&!p&&e.jsxs("p",{style:s.gmBodyM,children:["⏳ Time left: ",R,"s"]})]}),g!=="ready"&&e.jsx("div",{style:{...s.gmGrid,gridTemplateColumns:u?"repeat(2, 1fr)":"repeat(3, 210px)",gridAutoRows:u?"150px":"210px",gap:u?"12px":"20px",justifyItems:"center"},children:n.map((t,i)=>{const m=h===i&&g==="guess"&&!p;return e.jsx("div",{style:{...s.gmCard,...U==="correct"&&h===i?s.gmCorrect:{},...U==="wrong"&&h===i?s.gmWrong:{}},children:!m&&e.jsx("img",{src:t.src,alt:t.name,style:{width:"100%",height:"100%",objectFit:"cover"}})},i)})}),e.jsxs("div",{style:{marginTop:16,height:80},children:[g==="guess"&&!p&&e.jsxs("div",{children:[e.jsx("input",{type:"text",placeholder:"Type the missing word",value:v,onChange:t=>D(t.target.value),style:s.gmInput}),e.jsx("button",{style:{...s.gmButton,marginLeft:8},onClick:ne,disabled:A,children:A?"...":"Check"})]}),p&&e.jsx("button",{style:s.gmButton,onClick:oe,children:"Next round"})]})]})]})})})})}exports.Game=pe;exports.themes=W;
@@ -1,9 +1,9 @@
1
- import { jsx as t, jsxs as r, Fragment as ae } from "react/jsx-runtime";
2
- import { useRef as de, useEffect as j, useState as s, useMemo as ce } from "react";
3
- const me = window.origin + "/cloud/speakid/games/whatsmissing/", W = (l, a) => l.map(([d, o]) => ({
4
- src: `${me}${a}/${o.replace(/\s/g, "%20")}.png`,
1
+ import { jsx as t, jsxs as s, Fragment as de } from "react/jsx-runtime";
2
+ import { useRef as ce, useEffect as W, useState as r, useMemo as me } from "react";
3
+ const ge = window.origin + "/cloud/speakid/games/whatsmissing/", F = (l, a) => l.map(([d, o]) => ({
4
+ src: `${ge}${a}/${o.replace(/\s/g, "%20")}.png`,
5
5
  name: o
6
- })), ge = [
6
+ })), he = [
7
7
  ["apple", "apple"],
8
8
  ["banana", "banana"],
9
9
  ["bread", "bread"],
@@ -29,7 +29,7 @@ const me = window.origin + "/cloud/speakid/games/whatsmissing/", W = (l, a) => l
29
29
  ["strawberry", "strawberry"],
30
30
  ["tomato", "tomato"],
31
31
  ["watermelon", "watermelon"]
32
- ], he = [
32
+ ], ue = [
33
33
  ["bear", "bear"],
34
34
  ["cat", "cat"],
35
35
  ["crocodile", "crocodile"],
@@ -69,11 +69,11 @@ const me = window.origin + "/cloud/speakid/games/whatsmissing/", W = (l, a) => l
69
69
  ["teddy_bear", "teddy bear"],
70
70
  ["yo-yo", "yo-yo"],
71
71
  ["crayons", "crayons"]
72
- ], Z = {
73
- food: W(ge, "food"),
74
- animals: W(he, "animals"),
75
- toys: W(pe, "toys")
76
- }, ue = `
72
+ ], J = {
73
+ food: F(he, "food"),
74
+ animals: F(ue, "animals"),
75
+ toys: F(pe, "toys")
76
+ }, fe = `
77
77
  @keyframes spin {
78
78
  from { transform: rotate(0deg); }
79
79
  to { transform: rotate(360deg); }
@@ -81,9 +81,9 @@ const me = window.origin + "/cloud/speakid/games/whatsmissing/", W = (l, a) => l
81
81
  `;
82
82
  if (typeof document < "u" && !document.getElementById("spin-keyframes")) {
83
83
  const l = document.createElement("style");
84
- l.id = "spin-keyframes", l.innerHTML = ue, document.head.appendChild(l);
84
+ l.id = "spin-keyframes", l.innerHTML = fe, document.head.appendChild(l);
85
85
  }
86
- const fe = {
86
+ const ye = {
87
87
  animation: "spin 1.4s linear infinite"
88
88
  }, n = {
89
89
  gmCenterScreen: {
@@ -233,9 +233,9 @@ const fe = {
233
233
  },
234
234
  gmHourglass: {
235
235
  fontSize: "42px",
236
- ...fe
236
+ ...ye
237
237
  }
238
- }, ye = () => {
238
+ }, xe = () => {
239
239
  const l = document.createElement("style");
240
240
  l.textContent = `
241
241
  #whats-missing-root, #whats-missing-root * {
@@ -248,7 +248,11 @@ const fe = {
248
248
  display: block;
249
249
  user-select: none;
250
250
  }
251
- html, body { margin: 0; padding: 0; }
251
+ html, body {
252
+ margin: 0;
253
+ padding: 0;
254
+ zoom: 1 !important; /* ✅ защита от подзума */
255
+ }
252
256
  `, document.head.appendChild(l);
253
257
  }, be = (l, a) => {
254
258
  const d = Array.from({ length: l.length + 1 }, () => Array(a.length + 1).fill(0));
@@ -259,78 +263,81 @@ const fe = {
259
263
  d[o][m] = l[o - 1] === a[m - 1] ? d[o - 1][m - 1] : Math.min(d[o - 1][m - 1], d[o][m - 1], d[o - 1][m]) + 1;
260
264
  return d[l.length][a.length];
261
265
  };
262
- function ke() {
263
- const l = de(null);
264
- j(() => (ye(), () => {
266
+ function Ce() {
267
+ const l = ce(null);
268
+ W(() => (xe(), () => {
265
269
  document.body.style.overflow = "";
266
270
  }), []);
267
- const [a, d] = s(null), [o, m] = s([]), [w, J] = s(4), [b, E] = s(!1), [k, G] = s(1), [u, Q] = s(null), [h, v] = s("ready"), [F, Y] = s(3), [S, z] = s(10), [R, D] = s(20), [X, I] = s(0), [C, H] = s(!1), [T, U] = s(""), [f, M] = s(!1), [A, $] = s(!1), [N, x] = s(null), [ee, B] = s([]), [te, O] = s([]), [p, ne] = s(!1), [oe, P] = s(1);
268
- j(() => {
271
+ const [a, d] = r(null), [o, m] = r([]), [k, Q] = r(4), [x, E] = r(!1), [v, G] = r(1), [p, ee] = r(null), [h, C] = r("ready"), [Y, D] = r(3), [R, I] = r(10), [M, q] = r(20), [te, H] = r(0), [S, A] = r(!1), [z, P] = r(""), [f, B] = r(!1), [L, U] = r(!1), [N, b] = r(null), [ne, j] = r([]), [oe, V] = r([]), [u, ie] = r(!1), [we, _] = r(1), [$, K] = r(null);
272
+ W(() => {
269
273
  const e = () => {
270
274
  const i = window.innerWidth < 768;
271
- if (ne(i), i)
272
- P(1);
275
+ if (ie(i), i)
276
+ K(null), _(1);
273
277
  else {
274
- const y = Math.min(window.innerWidth / 1440, window.innerHeight / 768);
275
- P(y);
278
+ const y = Math.min(window.innerWidth, window.innerHeight), w = Math.max(360, Math.round(y * 0.97)), T = Math.min(w, 1e3);
279
+ K(T), _(1);
276
280
  }
277
281
  };
278
282
  return e(), window.addEventListener("resize", e), () => window.removeEventListener("resize", e);
279
283
  }, []);
280
- const V = (e) => [...e].sort(() => Math.random() - 0.5).slice(0, 6), _ = () => {
284
+ const O = (e) => [...e].sort(() => Math.random() - 0.5).slice(0, 6), Z = () => {
281
285
  if (!a) return;
282
- const e = V(Z[a]);
283
- m(e), E(!0), H(!1), G(1), I(0), B([]), O([]), q(e, [], !0);
284
- }, q = (e = o, i = te, g = !1) => {
285
- const c = V(e.length ? e : Z[a]);
286
- let y = Math.floor(Math.random() * c.length), L = c[y].name, K = 0;
287
- for (; i.includes(L) && K < 20; )
288
- y = Math.floor(Math.random() * c.length), L = c[y].name, K++;
289
- m(c), Q(y), O([...i, L]), M(!1), U(""), D(20), x(null), g ? (v("ready"), Y(3), z(10)) : (v("memorize"), z(10));
286
+ const e = O(J[a]);
287
+ m(e), E(!0), A(!1), G(1), H(0), j([]), V([]), X(e, [], !0);
288
+ }, X = (e = o, i = oe, g = !1) => {
289
+ const c = O(e.length ? e : J[a]);
290
+ let y = Math.floor(Math.random() * c.length), w = c[y].name, T = 0;
291
+ for (; i.includes(w) && T < 20; )
292
+ y = Math.floor(Math.random() * c.length), w = c[y].name, T++;
293
+ m(c), ee(y), V([...i, w]), B(!1), P(""), q(20), b(null), g ? (C("ready"), D(3), I(10)) : (C("memorize"), I(10));
290
294
  };
291
- j(() => {
292
- if (!(!b || C || f)) {
295
+ W(() => {
296
+ if (!(!x || S || f)) {
293
297
  if (h === "ready")
294
- if (F <= 0) v("memorize");
298
+ if (Y <= 0) C("memorize");
295
299
  else {
296
- const e = setTimeout(() => Y((i) => i - 1), 1e3);
300
+ const e = setTimeout(() => D((i) => i - 1), 1e3);
297
301
  return () => clearTimeout(e);
298
302
  }
299
303
  if (h === "memorize")
300
- if (S <= 0) v("guess");
304
+ if (R <= 0) C("guess");
301
305
  else {
302
- const e = setTimeout(() => z((i) => i - 1), 1e3);
306
+ const e = setTimeout(() => I((i) => i - 1), 1e3);
303
307
  return () => clearTimeout(e);
304
308
  }
305
309
  if (h === "guess") {
306
- if (R <= 0) {
307
- M(!0), x("wrong");
308
- const i = o[u].name;
309
- B((g) => [
310
+ if (M <= 0) {
311
+ B(!0), b("wrong");
312
+ const i = o[p].name;
313
+ j((g) => [
310
314
  ...g,
311
- { round: k, answer: T, correct: i, result: "wrong" }
315
+ { round: v, answer: z, correct: i, result: "wrong" }
312
316
  ]);
313
317
  return;
314
318
  }
315
- const e = setTimeout(() => D((i) => i - 1), 1e3);
319
+ const e = setTimeout(() => q((i) => i - 1), 1e3);
316
320
  return () => clearTimeout(e);
317
321
  }
318
322
  }
319
- }, [h, F, S, R, b, C, f, o, u, k, T]);
320
- const ie = () => {
321
- if (u === null || A) return;
322
- const e = o[u].name, i = T.toLowerCase().trim();
323
+ }, [h, Y, R, M, x, S, f, o, p, v, z]);
324
+ const re = () => {
325
+ if (p === null || L) return;
326
+ const e = o[p].name, i = z.toLowerCase().trim();
323
327
  let g = "wrong";
324
- i === e ? (I((c) => c + 1), x("correct"), g = "correct") : be(i, e) === 1 ? (I((c) => c + 0.5), x("almost"), g = "almost") : (x("wrong"), g = "wrong"), B((c) => [...c, { round: k, answer: i, correct: e, result: g }]), $(!0), setTimeout(() => {
325
- $(!1), M(!0);
328
+ i === e ? (H((c) => c + 1), b("correct"), g = "correct") : be(i, e) === 1 ? (H((c) => c + 0.5), b("almost"), g = "almost") : (b("wrong"), g = "wrong"), j((c) => [...c, { round: v, answer: i, correct: e, result: g }]), U(!0), setTimeout(() => {
329
+ U(!1), B(!0);
326
330
  }, 600);
327
- }, re = () => k < w ? (G((e) => e + 1), q()) : H(!0), se = () => {
328
- E(!1), H(!1), d(null);
329
- }, le = ce(
330
- () => /* @__PURE__ */ t("div", { style: n.gmLogoFixed, children: /* @__PURE__ */ r("picture", { children: [
331
- /* @__PURE__ */ t("source", { srcSet: window.origin + "/cloud/speakid/games/whatsmissing/logo.svg", type: "image/svg+xml" }),
332
- /* @__PURE__ */ t("img", { src: window.origin + "/cloud/speakid/games/whatsmissing/logo.png", alt: "SPEAKID Logo", style: n.gmLogoImg, loading: "lazy" })
333
- ] }) }),
331
+ }, se = () => v < k ? (G((e) => e + 1), X()) : A(!0), le = () => {
332
+ E(!1), A(!1), d(null);
333
+ }, ae = me(
334
+ () => (
335
+ // ensure logo is positioned inside the square container
336
+ /* @__PURE__ */ t("div", { style: { ...n.gmLogoFixed, position: "absolute", top: 16, left: 16, zIndex: 30 }, children: /* @__PURE__ */ s("picture", { children: [
337
+ /* @__PURE__ */ t("source", { srcSet: window.origin + "/cloud/speakid/games/whatsmissing/logo.svg", type: "image/svg+xml" }),
338
+ /* @__PURE__ */ t("img", { src: window.origin + "/cloud/speakid/games/whatsmissing/logo.png", alt: "SPEAKID Logo", style: n.gmLogoImg, loading: "lazy" })
339
+ ] }) })
340
+ ),
334
341
  []
335
342
  );
336
343
  return /* @__PURE__ */ t(
@@ -344,98 +351,100 @@ function ke() {
344
351
  justifyContent: "center",
345
352
  alignItems: "center",
346
353
  background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
347
- transition: "background 0.3s ease"
354
+ transition: "background 0.3s ease",
355
+ overflowX: "clip"
348
356
  },
349
357
  children: /* @__PURE__ */ t(
350
358
  "div",
351
359
  {
352
360
  style: {
353
- width: p ? "100%" : 1440,
354
- height: p ? "100%" : 768,
361
+ width: u ? "100%" : $ || 1e3,
362
+ height: u ? "100%" : $ || 1e3,
355
363
  display: "flex",
356
364
  justifyContent: "center",
357
365
  alignItems: "center",
358
366
  overflow: "hidden",
359
- borderRadius: p ? 0 : "20px",
367
+ borderRadius: u ? 0 : "20px",
360
368
  background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
361
- boxShadow: p ? "none" : "0 0 40px rgba(0,0,0,0.1)",
362
- margin: p ? "0 auto" : "unset"
369
+ boxShadow: u ? "none" : "0 0 40px rgba(0,0,0,0.1)",
370
+ margin: u ? "0 auto" : "unset",
371
+ position: "relative"
372
+ // needed so absolute logo is inside the square
363
373
  },
364
374
  children: /* @__PURE__ */ t(
365
375
  "div",
366
376
  {
367
377
  style: {
368
- transform: p ? "none" : `scale(${oe})`,
369
- transformOrigin: "center center",
378
+ transform: "none",
370
379
  width: "100%",
371
380
  height: "100%",
372
381
  display: "flex",
373
382
  justifyContent: "center",
374
383
  alignItems: "center"
375
384
  },
376
- children: /* @__PURE__ */ r("div", { id: "whats-missing-root", children: [
377
- !p && le,
378
- !a && !b && /* @__PURE__ */ r("div", { style: n.gmCenterScreen, children: [
385
+ children: /* @__PURE__ */ s("div", { id: "whats-missing-root", children: [
386
+ !u && ae,
387
+ !a && !x && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
379
388
  /* @__PURE__ */ t("h1", { style: n.gmHeadline1, children: "WHAT'S MISSING?" }),
380
389
  /* @__PURE__ */ t("p", { style: n.gmBodyM, children: "Select a theme:" }),
381
390
  /* @__PURE__ */ t("div", { style: { display: "flex", gap: 16 }, children: ["animals", "food", "toys"].map((e) => /* @__PURE__ */ t("button", { style: n.gmButton, onClick: () => d(e), children: e === "animals" ? "🐶 Animals" : e === "food" ? "🍎 Food" : "🧸 Toys" }, e)) }),
382
- /* @__PURE__ */ r("div", { style: { marginTop: 24 }, children: [
391
+ /* @__PURE__ */ s("div", { style: { marginTop: 24 }, children: [
383
392
  /* @__PURE__ */ t("p", { style: n.gmBodyS, children: "Choose number of rounds:" }),
384
393
  /* @__PURE__ */ t("div", { style: { display: "flex", gap: 12, marginTop: 8 }, children: [3, 4, 5].map((e) => /* @__PURE__ */ t(
385
394
  "button",
386
395
  {
387
396
  style: {
388
397
  ...n.gmButton,
389
- ...w === e ? n.gmButtonActive : {}
398
+ ...k === e ? n.gmButtonActive : {}
390
399
  },
391
- onClick: () => J(e),
400
+ onClick: () => Q(e),
392
401
  children: e
393
402
  },
394
403
  e
395
404
  )) })
396
405
  ] })
397
406
  ] }),
398
- a && !b && /* @__PURE__ */ r("div", { style: n.gmCenterScreen, children: [
399
- /* @__PURE__ */ r("h1", { style: n.gmHeadline1, children: [
407
+ a && !x && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
408
+ /* @__PURE__ */ s("h1", { style: n.gmHeadline1, children: [
400
409
  "Theme selected: ",
401
410
  a
402
411
  ] }),
403
- /* @__PURE__ */ r("p", { style: n.gmBodyM, children: [
412
+ /* @__PURE__ */ s("p", { style: n.gmBodyM, children: [
404
413
  "Rounds: ",
405
- w
414
+ k
406
415
  ] }),
407
- /* @__PURE__ */ t("button", { style: n.gmButton, onClick: _, children: "▶ Start game" })
416
+ /* @__PURE__ */ t("button", { style: n.gmButton, onClick: Z, children: "▶ Start game" })
408
417
  ] }),
409
- C && /* @__PURE__ */ r("div", { style: n.gmCenterScreen, children: [
418
+ S && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
410
419
  /* @__PURE__ */ t("h1", { style: n.gmHeadline1, children: "Results" }),
411
- /* @__PURE__ */ r("h2", { style: n.gmHeadline3, children: [
420
+ /* @__PURE__ */ s("h2", { style: n.gmHeadline3, children: [
412
421
  "Your score: ",
413
- X,
422
+ te,
414
423
  " / ",
415
- w
424
+ k
416
425
  ] }),
417
426
  /* @__PURE__ */ t("p", { style: { ...n.gmBodyM, color: "#10b981", marginTop: 12 }, children: "Yahoo! You did it! 🍬✨" }),
418
- /* @__PURE__ */ r("table", { style: n.gmTable, children: [
419
- /* @__PURE__ */ t("thead", { children: /* @__PURE__ */ r("tr", { children: [
427
+ /* @__PURE__ */ s("table", { style: n.gmTable, children: [
428
+ /* @__PURE__ */ t("thead", { children: /* @__PURE__ */ s("tr", { children: [
420
429
  /* @__PURE__ */ t("th", { children: "Round" }),
421
430
  /* @__PURE__ */ t("th", { children: "Your Answer" }),
422
431
  /* @__PURE__ */ t("th", { children: "Correct" }),
423
432
  /* @__PURE__ */ t("th", { children: "Result" })
424
433
  ] }) }),
425
- /* @__PURE__ */ t("tbody", { children: ee.map((e, i) => /* @__PURE__ */ r("tr", { children: [
434
+ /* @__PURE__ */ t("tbody", { children: ne.map((e, i) => /* @__PURE__ */ s("tr", { children: [
426
435
  /* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.round }),
427
436
  /* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.answer || "—" }),
428
437
  /* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.correct }),
429
438
  /* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.result === "correct" ? "✔ Correct" : e.result === "almost" ? "◐ Almost (0.5)" : "✘ Wrong" })
430
439
  ] }, i)) })
431
440
  ] }),
432
- /* @__PURE__ */ r("div", { style: { display: "flex", gap: 12, marginTop: 24 }, children: [
433
- /* @__PURE__ */ t("button", { style: n.gmButton, onClick: _, children: "🔁 Play again" }),
434
- /* @__PURE__ */ t("button", { style: n.gmButton, onClick: se, children: "⬅️ Choose theme" })
441
+ /* @__PURE__ */ s("div", { style: { display: "flex", gap: 12, marginTop: 24 }, children: [
442
+ /* @__PURE__ */ t("button", { style: n.gmButton, onClick: Z, children: "🔁 Play again" }),
443
+ /* @__PURE__ */ t("button", { style: n.gmButton, onClick: le, children: "⬅️ Choose theme" })
435
444
  ] })
436
445
  ] }),
437
- b && !C && /* @__PURE__ */ r("div", { style: n.gmGameLayout, children: [
438
- /* @__PURE__ */ r(
446
+ x && !S && /* @__PURE__ */ s("div", { style: n.gmGameLayout, children: [
447
+ /* @__PURE__ */ s(
439
448
  "div",
440
449
  {
441
450
  style: {
@@ -446,18 +455,18 @@ function ke() {
446
455
  alignItems: "center"
447
456
  },
448
457
  children: [
449
- h === "ready" && /* @__PURE__ */ r(ae, { children: [
458
+ h === "ready" && /* @__PURE__ */ s(de, { children: [
450
459
  /* @__PURE__ */ t("h1", { style: { ...n.gmHeadline1, color: "#ec4c44" }, children: "GET READY" }),
451
460
  /* @__PURE__ */ t("div", { style: n.gmHourglass, children: "⏳" })
452
461
  ] }),
453
- h === "memorize" && /* @__PURE__ */ r("p", { style: { ...n.gmBodyM, color: "#10b981" }, children: [
462
+ h === "memorize" && /* @__PURE__ */ s("p", { style: { ...n.gmBodyM, color: "#10b981" }, children: [
454
463
  "MEMORIZE (",
455
- S,
464
+ R,
456
465
  ")"
457
466
  ] }),
458
- h === "guess" && !f && /* @__PURE__ */ r("p", { style: n.gmBodyM, children: [
467
+ h === "guess" && !f && /* @__PURE__ */ s("p", { style: n.gmBodyM, children: [
459
468
  "⏳ Time left: ",
460
- R,
469
+ M,
461
470
  "s"
462
471
  ] })
463
472
  ]
@@ -468,20 +477,20 @@ function ke() {
468
477
  {
469
478
  style: {
470
479
  ...n.gmGrid,
471
- gridTemplateColumns: p ? "repeat(2, 1fr)" : "repeat(3, 210px)",
472
- gridAutoRows: p ? "150px" : "210px",
473
- gap: p ? "12px" : "20px",
480
+ gridTemplateColumns: u ? "repeat(2, 1fr)" : "repeat(3, 210px)",
481
+ gridAutoRows: u ? "150px" : "210px",
482
+ gap: u ? "12px" : "20px",
474
483
  justifyItems: "center"
475
484
  },
476
485
  children: o.map((e, i) => {
477
- const g = u === i && h === "guess" && !f;
486
+ const g = p === i && h === "guess" && !f;
478
487
  return /* @__PURE__ */ t(
479
488
  "div",
480
489
  {
481
490
  style: {
482
491
  ...n.gmCard,
483
- ...N === "correct" && u === i ? n.gmCorrect : {},
484
- ...N === "wrong" && u === i ? n.gmWrong : {}
492
+ ...N === "correct" && p === i ? n.gmCorrect : {},
493
+ ...N === "wrong" && p === i ? n.gmWrong : {}
485
494
  },
486
495
  children: !g && /* @__PURE__ */ t(
487
496
  "img",
@@ -501,21 +510,29 @@ function ke() {
501
510
  })
502
511
  }
503
512
  ),
504
- /* @__PURE__ */ r("div", { style: { marginTop: 16, height: 80 }, children: [
505
- h === "guess" && !f && /* @__PURE__ */ r("div", { children: [
513
+ /* @__PURE__ */ s("div", { style: { marginTop: 16, height: 80 }, children: [
514
+ h === "guess" && !f && /* @__PURE__ */ s("div", { children: [
506
515
  /* @__PURE__ */ t(
507
516
  "input",
508
517
  {
509
518
  type: "text",
510
519
  placeholder: "Type the missing word",
511
- value: T,
512
- onChange: (e) => U(e.target.value),
520
+ value: z,
521
+ onChange: (e) => P(e.target.value),
513
522
  style: n.gmInput
514
523
  }
515
524
  ),
516
- /* @__PURE__ */ t("button", { style: { ...n.gmButton, marginLeft: 8 }, onClick: ie, disabled: A, children: A ? "..." : "Check" })
525
+ /* @__PURE__ */ t(
526
+ "button",
527
+ {
528
+ style: { ...n.gmButton, marginLeft: 8 },
529
+ onClick: re,
530
+ disabled: L,
531
+ children: L ? "..." : "Check"
532
+ }
533
+ )
517
534
  ] }),
518
- f && /* @__PURE__ */ t("button", { style: n.gmButton, onClick: re, children: "Next round" })
535
+ f && /* @__PURE__ */ t("button", { style: n.gmButton, onClick: se, children: "Next round" })
519
536
  ] })
520
537
  ] })
521
538
  ] })
@@ -527,6 +544,6 @@ function ke() {
527
544
  );
528
545
  }
529
546
  export {
530
- ke as Game,
531
- Z as themes
547
+ Ce as Game,
548
+ J as themes
532
549
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mblinkov/whats-missing",
3
- "version": "20.0.16",
3
+ "version": "20.0.18",
4
4
  "main": "dist/whats-missing.umd.js",
5
5
  "module": "dist/whats-missing.es.js",
6
6
  "types": "dist/index.d.ts",
package/src/Game.tsx CHANGED
@@ -1,3 +1,4 @@
1
+ // ...existing code...
1
2
  import { useState, useEffect, useMemo, useRef } from "react";
2
3
  import { themes } from "./themes";
3
4
  import { styles } from "./Game.styles";
@@ -25,7 +26,11 @@ const globalReset = () => {
25
26
  display: block;
26
27
  user-select: none;
27
28
  }
28
- html, body { margin: 0; padding: 0; }
29
+ html, body {
30
+ margin: 0;
31
+ padding: 0;
32
+ zoom: 1 !important; /* ✅ защита от подзума */
33
+ }
29
34
  `;
30
35
  document.head.appendChild(style);
31
36
  };
@@ -76,20 +81,29 @@ export default function Game() {
76
81
  const [usedHidden, setUsedHidden] = useState<string[]>([]);
77
82
  const [isMobile, setIsMobile] = useState(false);
78
83
  const [scale, setScale] = useState(1);
84
+ const [containerSize, setContainerSize] = useState<number | null>(null);
79
85
 
80
- // ✅ адаптив под мобилки и десктоп
86
+ // ✅ адаптив под мобилки, планшеты и десктоп
81
87
  useEffect(() => {
82
88
  const resize = () => {
83
89
  const mobile = window.innerWidth < 768;
90
+ const tablet = window.innerWidth >= 768 && window.innerWidth < 1200;
91
+
92
+ // treat only phones as "mobile" so tablets use the desktop (square/centered) layout
84
93
  setIsMobile(mobile);
85
94
 
86
- if (!mobile) {
87
- // виртуальный размер игры (1440x768)
88
- const baseW = 1440;
89
- const baseH = 768;
90
- const ratio = Math.min(window.innerWidth / baseW, window.innerHeight / baseH);
91
- setScale(ratio);
95
+ if (mobile) {
96
+ // mobile: fluid full-width layout
97
+ setContainerSize(null);
98
+ setScale(1);
92
99
  } else {
100
+ // tablets and desktops: fit into a centered square (max 1000)
101
+ const safeFactor = 0.97;
102
+ const maxSquare = 1000;
103
+ const available = Math.min(window.innerWidth, window.innerHeight);
104
+ const sizePx = Math.max(360, Math.round(available * safeFactor)); // don't go too small
105
+ const finalSize = Math.min(sizePx, maxSquare);
106
+ setContainerSize(finalSize);
93
107
  setScale(1);
94
108
  }
95
109
  };
@@ -209,7 +223,8 @@ export default function Game() {
209
223
 
210
224
  const MemoizedLogo = useMemo(
211
225
  () => (
212
- <div style={styles.gmLogoFixed}>
226
+ // ensure logo is positioned inside the square container
227
+ <div style={{ ...styles.gmLogoFixed, position: "absolute", top: 16, left: 16, zIndex: 30 }}>
213
228
  <picture>
214
229
  <source srcSet={window.origin + "/cloud/speakid/games/whatsmissing/logo.svg"} type="image/svg+xml" />
215
230
  <img src={window.origin + "/cloud/speakid/games/whatsmissing/logo.png"} alt="SPEAKID Logo" style={styles.gmLogoImg} loading="lazy" />
@@ -219,9 +234,6 @@ export default function Game() {
219
234
  []
220
235
  );
221
236
 
222
- // =============================
223
- // RENDER
224
- // =============================
225
237
  return (
226
238
  <div
227
239
  ref={containerRef}
@@ -233,12 +245,13 @@ export default function Game() {
233
245
  alignItems: "center",
234
246
  background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
235
247
  transition: "background 0.3s ease",
248
+ overflowX: "clip"
236
249
  }}
237
250
  >
238
251
  <div
239
252
  style={{
240
- width: isMobile ? "100%" : 1440,
241
- height: isMobile ? "100%" : 768,
253
+ width: isMobile ? "100%" : containerSize || 1000,
254
+ height: isMobile ? "100%" : containerSize || 1000,
242
255
  display: "flex",
243
256
  justifyContent: "center",
244
257
  alignItems: "center",
@@ -246,14 +259,13 @@ export default function Game() {
246
259
  borderRadius: isMobile ? 0 : "20px",
247
260
  background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
248
261
  boxShadow: isMobile ? "none" : "0 0 40px rgba(0,0,0,0.1)",
249
- margin: isMobile ? "0 auto" : "unset",
262
+ margin: isMobile ? "0 auto" : "unset",
263
+ position: "relative", // needed so absolute logo is inside the square
250
264
  }}
251
265
  >
252
- {/* ✅ добавленный блок для правильного масштабирования и центрирования */}
253
266
  <div
254
267
  style={{
255
- transform: isMobile ? "none" : `scale(${scale})`,
256
- transformOrigin: "center center",
268
+ transform: "none",
257
269
  width: "100%",
258
270
  height: "100%",
259
271
  display: "flex",
@@ -263,7 +275,6 @@ export default function Game() {
263
275
  >
264
276
  <div id="whats-missing-root">
265
277
  {!isMobile && MemoizedLogo}
266
-
267
278
  {/* ====== ИГРОВАЯ ЛОГИКА ====== */}
268
279
  {!theme && !started && (
269
280
  <div style={styles.gmCenterScreen}>
@@ -295,7 +306,6 @@ export default function Game() {
295
306
  </div>
296
307
  </div>
297
308
  )}
298
-
299
309
  {theme && !started && (
300
310
  <div style={styles.gmCenterScreen}>
301
311
  <h1 style={styles.gmHeadline1}>Theme selected: {theme}</h1>
@@ -305,7 +315,6 @@ export default function Game() {
305
315
  </button>
306
316
  </div>
307
317
  )}
308
-
309
318
  {finished && (
310
319
  <div style={styles.gmCenterScreen}>
311
320
  <h1 style={styles.gmHeadline1}>Results</h1>
@@ -349,7 +358,6 @@ export default function Game() {
349
358
  </div>
350
359
  </div>
351
360
  )}
352
-
353
361
  {started && !finished && (
354
362
  <div style={styles.gmGameLayout}>
355
363
  <div
@@ -367,29 +375,41 @@ export default function Game() {
367
375
  <div style={styles.gmHourglass}>⏳</div>
368
376
  </>
369
377
  )}
370
- {phase === "memorize" && <p style={{ ...styles.gmBodyM, color: "#10b981" }}>MEMORIZE ({memorizeTime})</p>}
371
- {phase === "guess" && !answered && <p style={styles.gmBodyM}>⏳ Time left: {timeLeft}s</p>}
378
+ {phase === "memorize" && (
379
+ <p style={{ ...styles.gmBodyM, color: "#10b981" }}>
380
+ MEMORIZE ({memorizeTime})
381
+ </p>
382
+ )}
383
+ {phase === "guess" && !answered && (
384
+ <p style={styles.gmBodyM}>⏳ Time left: {timeLeft}s</p>
385
+ )}
372
386
  </div>
373
-
374
387
  {phase !== "ready" && (
375
388
  <div
376
389
  style={{
377
390
  ...styles.gmGrid,
378
- gridTemplateColumns: isMobile ? "repeat(2, 1fr)" : "repeat(3, 210px)",
391
+ gridTemplateColumns: isMobile
392
+ ? "repeat(2, 1fr)"
393
+ : "repeat(3, 210px)",
379
394
  gridAutoRows: isMobile ? "150px" : "210px",
380
395
  gap: isMobile ? "12px" : "20px",
381
396
  justifyItems: "center",
382
397
  }}
383
398
  >
384
399
  {files.map((file, i) => {
385
- const isHidden = hiddenIndex === i && phase === "guess" && !answered;
400
+ const isHidden =
401
+ hiddenIndex === i && phase === "guess" && !answered;
386
402
  return (
387
403
  <div
388
404
  key={i}
389
405
  style={{
390
406
  ...styles.gmCard,
391
- ...(result === "correct" && hiddenIndex === i ? styles.gmCorrect : {}),
392
- ...(result === "wrong" && hiddenIndex === i ? styles.gmWrong : {}),
407
+ ...(result === "correct" && hiddenIndex === i
408
+ ? styles.gmCorrect
409
+ : {}),
410
+ ...(result === "wrong" && hiddenIndex === i
411
+ ? styles.gmWrong
412
+ : {}),
393
413
  }}
394
414
  >
395
415
  {!isHidden && (
@@ -408,7 +428,6 @@ export default function Game() {
408
428
  })}
409
429
  </div>
410
430
  )}
411
-
412
431
  <div style={{ marginTop: 16, height: 80 }}>
413
432
  {phase === "guess" && !answered && (
414
433
  <div>
@@ -419,12 +438,20 @@ export default function Game() {
419
438
  onChange={(e) => setInputValue(e.target.value)}
420
439
  style={styles.gmInput}
421
440
  />
422
- <button style={{ ...styles.gmButton, marginLeft: 8 }} onClick={checkAnswer} disabled={animating}>
441
+ <button
442
+ style={{ ...styles.gmButton, marginLeft: 8 }}
443
+ onClick={checkAnswer}
444
+ disabled={animating}
445
+ >
423
446
  {animating ? "..." : "Check"}
424
447
  </button>
425
448
  </div>
426
449
  )}
427
- {answered && <button style={styles.gmButton} onClick={nextRound}>Next round</button>}
450
+ {answered && (
451
+ <button style={styles.gmButton} onClick={nextRound}>
452
+ Next round
453
+ </button>
454
+ )}
428
455
  </div>
429
456
  </div>
430
457
  )}
@@ -433,4 +460,4 @@ export default function Game() {
433
460
  </div>
434
461
  </div>
435
462
  );
436
- }
463
+ }