@mblinkov/whats-missing 20.0.5 → 20.0.6

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,36 +1,29 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),n=require("react"),oe=window.origin+"/cloud/speakid/games/whatsmissing/",M=(r,c)=>r.map(([l,o])=>({src:`${oe}${c}/${o.replace(/\s/g,"%20")}.png`,name:o})),ne=[["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"]],re=[["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"]],ie=[["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"]],B={food:M(ne,"food"),animals:M(re,"animals"),toys:M(ie,"toys")},le=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),n=require("react"),oe=window.origin+"/cloud/speakid/games/whatsmissing/",M=(r,c)=>r.map(([a,o])=>({src:`${oe}${c}/${o.replace(/\s/g,"%20")}.png`,name:o})),ne=[["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"]],re=[["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"]],ie=[["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"]],B={food:M(ne,"food"),animals:M(re,"animals"),toys:M(ie,"toys")},ae=`
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=le,document.head.appendChild(r)}const ae={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"},gmLogoImg:{height:"clamp(28px, 5vw, 40px)",width:"auto",background:"transparent"},gmHourglass:{fontSize:"42px",...ae}},de=window.origin+"/cloud/speakid/games/whatsmissing/logo.png",ce=()=>{const r=document.createElement("style");r.textContent=`
7
- html, body, #root {
8
- margin: 0;
9
- padding: 0;
10
- height: 100%;
11
- }
12
- *, *::before, *::after {
6
+ `;if(typeof document<"u"&&!document.getElementById("spin-keyframes")){const r=document.createElement("style");r.id="spin-keyframes",r.innerHTML=ae,document.head.appendChild(r)}const le={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:"crisp-edges",transform:"translateZ(0)",backfaceVisibility:"hidden",WebkitFontSmoothing:"antialiased"},gmHourglass:{fontSize:"42px",...le}},de=window.origin+"/cloud/speakid/games/whatsmissing/logo.png",ce=()=>{const r=document.createElement("style");r.textContent=`
7
+ #whats-missing-root, #whats-missing-root * {
13
8
  box-sizing: border-box;
14
- }
15
- body {
16
9
  font-family: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
10
+ }
11
+
12
+ #whats-missing-root {
17
13
  background-color: #fff;
18
14
  color: #1f2937;
15
+ text-align: center;
19
16
  }
20
- button, input {
21
- font-family: inherit;
22
- outline: none;
23
- border: none;
24
- background: none;
25
- }
26
- img {
17
+
18
+ #whats-missing-root img {
27
19
  max-width: 100%;
28
20
  height: auto;
29
21
  display: block;
30
22
  user-select: none;
31
23
  }
24
+
32
25
  @keyframes spin {
33
26
  from { transform: rotate(0deg); }
34
27
  to { transform: rotate(360deg); }
35
28
  }
36
- `,document.head.appendChild(r)},me=(r,c)=>{const l=Array.from({length:r.length+1},()=>Array(c.length+1).fill(0));for(let o=0;o<=r.length;o++)l[o][0]=o;for(let o=0;o<=c.length;o++)l[0][o]=o;for(let o=1;o<=r.length;o++)for(let a=1;a<=c.length;a++)l[o][a]=r[o-1]===c[a-1]?l[o-1][a-1]:Math.min(l[o-1][a-1],l[o][a-1],l[o-1][a])+1;return l[r.length][c.length]};function ge(){n.useEffect(()=>{ce()},[]);const[r,c]=n.useState(null),[l,o]=n.useState([]),[a,$]=n.useState(4),[h,L]=n.useState(!1),[f,W]=n.useState(1),[u,K]=n.useState(null),[m,y]=n.useState("ready"),[E,G]=n.useState(3),[k,C]=n.useState(7),[T,F]=n.useState(20),[V,v]=n.useState(0),[b,z]=n.useState(!1),[w,D]=n.useState(""),[p,R]=n.useState(!1),[I,q]=n.useState(!1),[P,x]=n.useState(null),[Z,A]=n.useState([]),[J,U]=n.useState([]),[j,Q]=n.useState(!1);n.useEffect(()=>{const t=()=>Q(window.innerWidth<768);return t(),window.addEventListener("resize",t),()=>window.removeEventListener("resize",t)},[]);const Y=t=>[...t].sort(()=>Math.random()-.5).slice(0,6),N=()=>{if(!r)return;const t=Y(B[r]);o(t),L(!0),z(!1),W(1),v(0),A([]),U([]),O(t,[],!0)},O=(t=l,i=J,g=!1)=>{const d=Y(t.length?t:B[r]);let S=Math.floor(Math.random()*d.length),H=d[S].name,_=0;for(;i.includes(H)&&_<20;)S=Math.floor(Math.random()*d.length),H=d[S].name,_++;o(d),K(S),U([...i,H]),R(!1),D(""),F(20),x(null),g?(y("ready"),G(3),C(7)):(y("memorize"),C(7))};n.useEffect(()=>{if(!(!h||b||p)){if(m==="ready")if(E<=0)y("memorize");else{const t=setTimeout(()=>G(i=>i-1),1e3);return()=>clearTimeout(t)}if(m==="memorize")if(k<=0)y("guess");else{const t=setTimeout(()=>C(i=>i-1),1e3);return()=>clearTimeout(t)}if(m==="guess"){if(T<=0){R(!0),x("wrong");const i=l[u].name;A(g=>[...g,{round:f,answer:w,correct:i,result:"wrong"}]);return}const t=setTimeout(()=>F(i=>i-1),1e3);return()=>clearTimeout(t)}}},[m,E,k,T,h,b,p,l,u,f,w]);const X=()=>{if(u===null||I)return;const t=l[u].name,i=w.toLowerCase().trim();let g="wrong";i===t?(v(d=>d+1),x("correct"),g="correct"):me(i,t)===1?(v(d=>d+.5),x("almost"),g="almost"):(x("wrong"),g="wrong"),A(d=>[...d,{round:f,answer:i,correct:t,result:g}]),q(!0),setTimeout(()=>{q(!1),R(!0)},600)},ee=()=>f<a?(W(t=>t+1),O()):z(!0),te=()=>{L(!1),z(!1),c(null)},se=n.useMemo(()=>e.jsx("div",{style:s.gmLogoFixed,children:e.jsx("img",{src:de,alt:"SPEAKID Logo",style:s.gmLogoImg})}),[]);return e.jsx("div",{id:"whats-missing-root",style:{all:"initial",display:"block"},children:e.jsxs("div",{style:{all:"unset"},children:[!j&&se,!r&&!h&&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:()=>c(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,...a===t?s.gmButtonActive:{}},onClick:()=>$(t),children:t},t))})]})]}),r&&!h&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsxs("h1",{style:s.gmHeadline1,children:["Theme selected: ",r]}),e.jsxs("p",{style:s.gmBodyM,children:["Rounds: ",a]}),e.jsx("button",{style:s.gmButton,onClick:N,children:"▶ Start game"})]}),b&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsx("h1",{style:s.gmHeadline1,children:"Results"}),e.jsxs("h2",{style:s.gmHeadline3,children:["Your score: ",V," / ",a]}),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:Z.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:te,children:"⬅️ Choose theme"})]})]}),h&&!b&&e.jsxs("div",{style:s.gmGameLayout,children:[e.jsxs("div",{style:{minHeight:160,display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center"},children:[m==="ready"&&e.jsxs(e.Fragment,{children:[e.jsx("h1",{style:{...s.gmHeadline1,color:"#ec4c44"},children:"GET READY"}),e.jsx("div",{style:s.gmHourglass,children:"⏳"})]}),m==="memorize"&&e.jsxs("p",{style:{...s.gmBodyM,color:"#10b981"},children:["MEMORIZE (",k,")"]}),m==="guess"&&!p&&e.jsxs("p",{style:s.gmBodyM,children:["⏳ Time left: ",T,"s"]})]}),m!=="ready"&&e.jsx("div",{style:{...s.gmGrid,gridTemplateColumns:j?"repeat(2, 1fr)":"repeat(3, 210px)",gridAutoRows:j?"150px":"210px",gap:j?"12px":"20px",justifyItems:"center",...window.innerWidth>2e3?{gridTemplateColumns:"repeat(3, 260px)",gridAutoRows:"260px",gap:"28px"}:{},...window.innerWidth>2560?{gridTemplateColumns:"repeat(3, 300px)",gridAutoRows:"300px",gap:"32px"}:{}},children:l.map((t,i)=>{const g=u===i&&m==="guess"&&!p;return e.jsx("div",{style:{...s.gmCard,...P==="correct"&&u===i?s.gmCorrect:{},...P==="wrong"&&u===i?s.gmWrong:{}},children:!g&&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:[m==="guess"&&!p&&e.jsxs("div",{children:[e.jsx("input",{type:"text",placeholder:"Type the missing word",value:w,onChange:t=>D(t.target.value),style:s.gmInput}),e.jsx("button",{style:{...s.gmButton,marginLeft:8},onClick:X,disabled:I,children:I?"...":"Check"})]}),p&&e.jsx("button",{style:s.gmButton,onClick:ee,children:"Next round"})]})]})]})})}exports.Game=ge;exports.themes=B;
29
+ `,document.head.appendChild(r)},me=(r,c)=>{const a=Array.from({length:r.length+1},()=>Array(c.length+1).fill(0));for(let o=0;o<=r.length;o++)a[o][0]=o;for(let o=0;o<=c.length;o++)a[0][o]=o;for(let o=1;o<=r.length;o++)for(let l=1;l<=c.length;l++)a[o][l]=r[o-1]===c[l-1]?a[o-1][l-1]:Math.min(a[o-1][l-1],a[o][l-1],a[o-1][l])+1;return a[r.length][c.length]};function ge(){n.useEffect(()=>{ce()},[]);const[r,c]=n.useState(null),[a,o]=n.useState([]),[l,_]=n.useState(4),[h,L]=n.useState(!1),[f,W]=n.useState(1),[u,$]=n.useState(null),[m,y]=n.useState("ready"),[E,G]=n.useState(3),[k,C]=n.useState(7),[T,F]=n.useState(20),[K,v]=n.useState(0),[b,z]=n.useState(!1),[w,D]=n.useState(""),[p,R]=n.useState(!1),[I,q]=n.useState(!1),[P,x]=n.useState(null),[Z,A]=n.useState([]),[J,U]=n.useState([]),[j,Q]=n.useState(!1);n.useEffect(()=>{const t=()=>Q(window.innerWidth<768);return t(),window.addEventListener("resize",t),()=>window.removeEventListener("resize",t)},[]);const Y=t=>[...t].sort(()=>Math.random()-.5).slice(0,6),N=()=>{if(!r)return;const t=Y(B[r]);o(t),L(!0),z(!1),W(1),v(0),A([]),U([]),O(t,[],!0)},O=(t=a,i=J,g=!1)=>{const d=Y(t.length?t:B[r]);let S=Math.floor(Math.random()*d.length),H=d[S].name,V=0;for(;i.includes(H)&&V<20;)S=Math.floor(Math.random()*d.length),H=d[S].name,V++;o(d),$(S),U([...i,H]),R(!1),D(""),F(20),x(null),g?(y("ready"),G(3),C(7)):(y("memorize"),C(7))};n.useEffect(()=>{if(!(!h||b||p)){if(m==="ready")if(E<=0)y("memorize");else{const t=setTimeout(()=>G(i=>i-1),1e3);return()=>clearTimeout(t)}if(m==="memorize")if(k<=0)y("guess");else{const t=setTimeout(()=>C(i=>i-1),1e3);return()=>clearTimeout(t)}if(m==="guess"){if(T<=0){R(!0),x("wrong");const i=a[u].name;A(g=>[...g,{round:f,answer:w,correct:i,result:"wrong"}]);return}const t=setTimeout(()=>F(i=>i-1),1e3);return()=>clearTimeout(t)}}},[m,E,k,T,h,b,p,a,u,f,w]);const X=()=>{if(u===null||I)return;const t=a[u].name,i=w.toLowerCase().trim();let g="wrong";i===t?(v(d=>d+1),x("correct"),g="correct"):me(i,t)===1?(v(d=>d+.5),x("almost"),g="almost"):(x("wrong"),g="wrong"),A(d=>[...d,{round:f,answer:i,correct:t,result:g}]),q(!0),setTimeout(()=>{q(!1),R(!0)},600)},ee=()=>f<l?(W(t=>t+1),O()):z(!0),te=()=>{L(!1),z(!1),c(null)},se=n.useMemo(()=>e.jsx("div",{style:s.gmLogoFixed,children:e.jsx("img",{src:de,alt:"SPEAKID Logo",style:s.gmLogoImg})}),[]);return e.jsxs("div",{id:"whats-missing-root",children:[!j&&se,!r&&!h&&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:()=>c(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,...l===t?s.gmButtonActive:{}},onClick:()=>_(t),children:t},t))})]})]}),r&&!h&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsxs("h1",{style:s.gmHeadline1,children:["Theme selected: ",r]}),e.jsxs("p",{style:s.gmBodyM,children:["Rounds: ",l]}),e.jsx("button",{style:s.gmButton,onClick:N,children:"▶ Start game"})]}),b&&e.jsxs("div",{style:s.gmCenterScreen,children:[e.jsx("h1",{style:s.gmHeadline1,children:"Results"}),e.jsxs("h2",{style:s.gmHeadline3,children:["Your score: ",K," / ",l]}),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:Z.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:te,children:"⬅️ Choose theme"})]})]}),h&&!b&&e.jsxs("div",{style:s.gmGameLayout,children:[e.jsxs("div",{style:{minHeight:160,display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center"},children:[m==="ready"&&e.jsxs(e.Fragment,{children:[e.jsx("h1",{style:{...s.gmHeadline1,color:"#ec4c44"},children:"GET READY"}),e.jsx("div",{style:s.gmHourglass,children:"⏳"})]}),m==="memorize"&&e.jsxs("p",{style:{...s.gmBodyM,color:"#10b981"},children:["MEMORIZE (",k,")"]}),m==="guess"&&!p&&e.jsxs("p",{style:s.gmBodyM,children:["⏳ Time left: ",T,"s"]})]}),m!=="ready"&&e.jsx("div",{style:{...s.gmGrid,gridTemplateColumns:j?"repeat(2, 1fr)":"repeat(3, 210px)",gridAutoRows:j?"150px":"210px",gap:j?"12px":"20px",justifyItems:"center",...window.innerWidth>2e3?{gridTemplateColumns:"repeat(3, 260px)",gridAutoRows:"260px",gap:"28px"}:{},...window.innerWidth>2560?{gridTemplateColumns:"repeat(3, 300px)",gridAutoRows:"300px",gap:"32px"}:{}},children:a.map((t,i)=>{const g=u===i&&m==="guess"&&!p;return e.jsx("div",{style:{...s.gmCard,...P==="correct"&&u===i?s.gmCorrect:{},...P==="wrong"&&u===i?s.gmWrong:{}},children:!g&&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:[m==="guess"&&!p&&e.jsxs("div",{children:[e.jsx("input",{type:"text",placeholder:"Type the missing word",value:w,onChange:t=>D(t.target.value),style:s.gmInput}),e.jsx("button",{style:{...s.gmButton,marginLeft:8},onClick:X,disabled:I,children:I?"...":"Check"})]}),p&&e.jsx("button",{style:s.gmButton,onClick:ee,children:"Next round"})]})]})]})}exports.Game=ge;exports.themes=B;
@@ -69,7 +69,7 @@ const le = window.origin + "/cloud/speakid/games/whatsmissing/", W = (r, m) => r
69
69
  ["teddy_bear", "teddy bear"],
70
70
  ["yo-yo", "yo-yo"],
71
71
  ["crayons", "crayons"]
72
- ], O = {
72
+ ], K = {
73
73
  food: W(ae, "food"),
74
74
  animals: W(de, "animals"),
75
75
  toys: W(ce, "toys")
@@ -209,7 +209,7 @@ const ge = {
209
209
  overflow: "hidden",
210
210
  textOverflow: "ellipsis"
211
211
  },
212
- // ✅ Исправленный логотип: без белого фона, не ломает верстку
212
+ // ✅ Обновлено только для качества логотипа
213
213
  gmLogoFixed: {
214
214
  position: "absolute",
215
215
  top: "16px",
@@ -217,51 +217,51 @@ const ge = {
217
217
  width: "120px",
218
218
  zIndex: 10,
219
219
  pointerEvents: "none",
220
- background: "transparent"
220
+ background: "transparent",
221
+ transform: "none",
222
+ willChange: "auto"
221
223
  },
222
224
  gmLogoImg: {
223
225
  height: "clamp(28px, 5vw, 40px)",
224
226
  width: "auto",
225
- background: "transparent"
227
+ background: "transparent",
228
+ objectFit: "contain",
229
+ imageRendering: "crisp-edges",
230
+ transform: "translateZ(0)",
231
+ backfaceVisibility: "hidden",
232
+ WebkitFontSmoothing: "antialiased"
226
233
  },
227
234
  gmHourglass: {
228
235
  fontSize: "42px",
229
236
  ...ge
230
237
  }
231
- }, pe = window.origin + "/cloud/speakid/games/whatsmissing/logo.png", ue = () => {
238
+ }, pe = window.origin + "/cloud/speakid/games/whatsmissing/logo.png", he = () => {
232
239
  const r = document.createElement("style");
233
240
  r.textContent = `
234
- html, body, #root {
235
- margin: 0;
236
- padding: 0;
237
- height: 100%;
238
- }
239
- *, *::before, *::after {
241
+ #whats-missing-root, #whats-missing-root * {
240
242
  box-sizing: border-box;
241
- }
242
- body {
243
243
  font-family: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
244
+ }
245
+
246
+ #whats-missing-root {
244
247
  background-color: #fff;
245
248
  color: #1f2937;
249
+ text-align: center;
246
250
  }
247
- button, input {
248
- font-family: inherit;
249
- outline: none;
250
- border: none;
251
- background: none;
252
- }
253
- img {
251
+
252
+ #whats-missing-root img {
254
253
  max-width: 100%;
255
254
  height: auto;
256
255
  display: block;
257
256
  user-select: none;
258
257
  }
258
+
259
259
  @keyframes spin {
260
260
  from { transform: rotate(0deg); }
261
261
  to { transform: rotate(360deg); }
262
262
  }
263
263
  `, document.head.appendChild(r);
264
- }, he = (r, m) => {
264
+ }, ue = (r, m) => {
265
265
  const a = Array.from({ length: r.length + 1 }, () => Array(m.length + 1).fill(0));
266
266
  for (let n = 0; n <= r.length; n++) a[n][0] = n;
267
267
  for (let n = 0; n <= m.length; n++) a[0][n] = n;
@@ -272,26 +272,26 @@ const ge = {
272
272
  };
273
273
  function xe() {
274
274
  L(() => {
275
- ue();
275
+ he();
276
276
  }, []);
277
- const [r, m] = l(null), [a, n] = l([]), [d, V] = l(4), [f, j] = l(!1), [x, E] = l(1), [u, Z] = l(null), [g, b] = l("ready"), [G, F] = l(3), [v, S] = l(7), [z, D] = l(20), [J, R] = l(0), [w, I] = l(!1), [k, U] = l(""), [h, A] = l(!1), [H, Y] = l(!1), [N, y] = l(null), [Q, M] = l([]), [X, P] = l([]), [C, ee] = l(!1);
277
+ const [r, m] = l(null), [a, n] = l([]), [d, O] = l(4), [f, j] = l(!1), [x, E] = l(1), [h, Z] = l(null), [g, b] = l("ready"), [G, F] = l(3), [v, S] = l(7), [z, D] = l(20), [J, R] = l(0), [w, I] = l(!1), [k, U] = l(""), [u, A] = l(!1), [H, Y] = l(!1), [N, y] = l(null), [Q, M] = l([]), [X, P] = l([]), [C, ee] = l(!1);
278
278
  L(() => {
279
279
  const e = () => ee(window.innerWidth < 768);
280
280
  return e(), window.addEventListener("resize", e), () => window.removeEventListener("resize", e);
281
281
  }, []);
282
- const _ = (e) => [...e].sort(() => Math.random() - 0.5).slice(0, 6), $ = () => {
282
+ const V = (e) => [...e].sort(() => Math.random() - 0.5).slice(0, 6), _ = () => {
283
283
  if (!r) return;
284
- const e = _(O[r]);
285
- n(e), j(!0), I(!1), E(1), R(0), M([]), P([]), q(e, [], !0);
286
- }, q = (e = a, i = X, p = !1) => {
287
- const c = _(e.length ? e : O[r]);
288
- let T = Math.floor(Math.random() * c.length), B = c[T].name, K = 0;
289
- for (; i.includes(B) && K < 20; )
290
- T = Math.floor(Math.random() * c.length), B = c[T].name, K++;
284
+ const e = V(K[r]);
285
+ n(e), j(!0), I(!1), E(1), R(0), M([]), P([]), $(e, [], !0);
286
+ }, $ = (e = a, i = X, p = !1) => {
287
+ const c = V(e.length ? e : K[r]);
288
+ let T = Math.floor(Math.random() * c.length), B = c[T].name, q = 0;
289
+ for (; i.includes(B) && q < 20; )
290
+ T = Math.floor(Math.random() * c.length), B = c[T].name, q++;
291
291
  n(c), Z(T), P([...i, B]), A(!1), U(""), D(20), y(null), p ? (b("ready"), F(3), S(7)) : (b("memorize"), S(7));
292
292
  };
293
293
  L(() => {
294
- if (!(!f || w || h)) {
294
+ if (!(!f || w || u)) {
295
295
  if (g === "ready")
296
296
  if (G <= 0)
297
297
  b("memorize");
@@ -309,7 +309,7 @@ function xe() {
309
309
  if (g === "guess") {
310
310
  if (z <= 0) {
311
311
  A(!0), y("wrong");
312
- const i = a[u].name;
312
+ const i = a[h].name;
313
313
  M((p) => [
314
314
  ...p,
315
315
  { round: x, answer: k, correct: i, result: "wrong" }
@@ -327,42 +327,34 @@ function xe() {
327
327
  z,
328
328
  f,
329
329
  w,
330
- h,
331
- a,
332
330
  u,
331
+ a,
332
+ h,
333
333
  x,
334
334
  k
335
335
  ]);
336
336
  const te = () => {
337
- if (u === null || H) return;
338
- const e = a[u].name, i = k.toLowerCase().trim();
337
+ if (h === null || H) return;
338
+ const e = a[h].name, i = k.toLowerCase().trim();
339
339
  let p = "wrong";
340
- i === e ? (R((c) => c + 1), y("correct"), p = "correct") : he(i, e) === 1 ? (R((c) => c + 0.5), y("almost"), p = "almost") : (y("wrong"), p = "wrong"), M((c) => [
340
+ i === e ? (R((c) => c + 1), y("correct"), p = "correct") : ue(i, e) === 1 ? (R((c) => c + 0.5), y("almost"), p = "almost") : (y("wrong"), p = "wrong"), M((c) => [
341
341
  ...c,
342
342
  { round: x, answer: i, correct: e, result: p }
343
343
  ]), Y(!0), setTimeout(() => {
344
344
  Y(!1), A(!0);
345
345
  }, 600);
346
- }, oe = () => x < d ? (E((e) => e + 1), q()) : I(!0), ne = () => {
346
+ }, oe = () => x < d ? (E((e) => e + 1), $()) : I(!0), ne = () => {
347
347
  j(!1), I(!1), m(null);
348
348
  }, re = se(
349
349
  () => /* @__PURE__ */ o("div", { style: t.gmLogoFixed, children: /* @__PURE__ */ o("img", { src: pe, alt: "SPEAKID Logo", style: t.gmLogoImg }) }),
350
350
  []
351
351
  );
352
- return /* @__PURE__ */ o("div", { id: "whats-missing-root", style: { all: "initial", display: "block" }, children: /* @__PURE__ */ s("div", { style: { all: "unset" }, children: [
352
+ return /* @__PURE__ */ s("div", { id: "whats-missing-root", children: [
353
353
  !C && re,
354
354
  !r && !f && /* @__PURE__ */ s("div", { style: t.gmCenterScreen, children: [
355
355
  /* @__PURE__ */ o("h1", { style: t.gmHeadline1, children: "WHAT'S MISSING?" }),
356
356
  /* @__PURE__ */ o("p", { style: t.gmBodyM, children: "Select a theme:" }),
357
- /* @__PURE__ */ o("div", { style: { display: "flex", gap: 16 }, children: ["animals", "food", "toys"].map((e) => /* @__PURE__ */ o(
358
- "button",
359
- {
360
- style: t.gmButton,
361
- onClick: () => m(e),
362
- children: e === "animals" ? "🐶 Animals" : e === "food" ? "🍎 Food" : "🧸 Toys"
363
- },
364
- e
365
- )) }),
357
+ /* @__PURE__ */ o("div", { style: { display: "flex", gap: 16 }, children: ["animals", "food", "toys"].map((e) => /* @__PURE__ */ o("button", { style: t.gmButton, onClick: () => m(e), children: e === "animals" ? "🐶 Animals" : e === "food" ? "🍎 Food" : "🧸 Toys" }, e)) }),
366
358
  /* @__PURE__ */ s("div", { style: { marginTop: 24 }, children: [
367
359
  /* @__PURE__ */ o("p", { style: t.gmBodyS, children: "Choose number of rounds:" }),
368
360
  /* @__PURE__ */ o("div", { style: { display: "flex", gap: 12, marginTop: 8 }, children: [3, 4, 5].map((e) => /* @__PURE__ */ o(
@@ -372,7 +364,7 @@ function xe() {
372
364
  ...t.gmButton,
373
365
  ...d === e ? t.gmButtonActive : {}
374
366
  },
375
- onClick: () => V(e),
367
+ onClick: () => O(e),
376
368
  children: e
377
369
  },
378
370
  e
@@ -388,7 +380,7 @@ function xe() {
388
380
  "Rounds: ",
389
381
  d
390
382
  ] }),
391
- /* @__PURE__ */ o("button", { style: t.gmButton, onClick: $, children: "▶ Start game" })
383
+ /* @__PURE__ */ o("button", { style: t.gmButton, onClick: _, children: "▶ Start game" })
392
384
  ] }),
393
385
  w && /* @__PURE__ */ s("div", { style: t.gmCenterScreen, children: [
394
386
  /* @__PURE__ */ o("h1", { style: t.gmHeadline1, children: "Results" }),
@@ -413,7 +405,7 @@ function xe() {
413
405
  ] }, i)) })
414
406
  ] }),
415
407
  /* @__PURE__ */ s("div", { style: { display: "flex", gap: 12, marginTop: 24 }, children: [
416
- /* @__PURE__ */ o("button", { style: t.gmButton, onClick: $, children: "🔁 Play again" }),
408
+ /* @__PURE__ */ o("button", { style: t.gmButton, onClick: _, children: "🔁 Play again" }),
417
409
  /* @__PURE__ */ o("button", { style: t.gmButton, onClick: ne, children: "⬅️ Choose theme" })
418
410
  ] })
419
411
  ] }),
@@ -438,7 +430,7 @@ function xe() {
438
430
  v,
439
431
  ")"
440
432
  ] }),
441
- g === "guess" && !h && /* @__PURE__ */ s("p", { style: t.gmBodyM, children: [
433
+ g === "guess" && !u && /* @__PURE__ */ s("p", { style: t.gmBodyM, children: [
442
434
  "⏳ Time left: ",
443
435
  z,
444
436
  "s"
@@ -467,14 +459,14 @@ function xe() {
467
459
  } : {}
468
460
  },
469
461
  children: a.map((e, i) => {
470
- const p = u === i && g === "guess" && !h;
462
+ const p = h === i && g === "guess" && !u;
471
463
  return /* @__PURE__ */ o(
472
464
  "div",
473
465
  {
474
466
  style: {
475
467
  ...t.gmCard,
476
- ...N === "correct" && u === i ? t.gmCorrect : {},
477
- ...N === "wrong" && u === i ? t.gmWrong : {}
468
+ ...N === "correct" && h === i ? t.gmCorrect : {},
469
+ ...N === "wrong" && h === i ? t.gmWrong : {}
478
470
  },
479
471
  children: !p && /* @__PURE__ */ o(
480
472
  "img",
@@ -495,7 +487,7 @@ function xe() {
495
487
  }
496
488
  ),
497
489
  /* @__PURE__ */ s("div", { style: { marginTop: 16, height: 80 }, children: [
498
- g === "guess" && !h && /* @__PURE__ */ s("div", { children: [
490
+ g === "guess" && !u && /* @__PURE__ */ s("div", { children: [
499
491
  /* @__PURE__ */ o(
500
492
  "input",
501
493
  {
@@ -516,12 +508,12 @@ function xe() {
516
508
  }
517
509
  )
518
510
  ] }),
519
- h && /* @__PURE__ */ o("button", { style: t.gmButton, onClick: oe, children: "Next round" })
511
+ u && /* @__PURE__ */ o("button", { style: t.gmButton, onClick: oe, children: "Next round" })
520
512
  ] })
521
513
  ] })
522
- ] }) });
514
+ ] });
523
515
  }
524
516
  export {
525
517
  xe as Game,
526
- O as themes
518
+ K as themes
527
519
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mblinkov/whats-missing",
3
- "version": "20.0.5",
3
+ "version": "20.0.6",
4
4
  "main": "dist/whats-missing.umd.js",
5
5
  "module": "dist/whats-missing.es.js",
6
6
  "types": "dist/index.d.ts",
@@ -174,7 +174,7 @@ export const styles: Record<string, CSSProperties> = {
174
174
  textOverflow: "ellipsis",
175
175
  },
176
176
 
177
- // ✅ Исправленный логотип: без белого фона, не ломает верстку
177
+ // ✅ Обновлено только для качества логотипа
178
178
  gmLogoFixed: {
179
179
  position: "absolute",
180
180
  top: "16px",
@@ -183,12 +183,19 @@ export const styles: Record<string, CSSProperties> = {
183
183
  zIndex: 10,
184
184
  pointerEvents: "none",
185
185
  background: "transparent",
186
+ transform: "none",
187
+ willChange: "auto",
186
188
  },
187
189
 
188
190
  gmLogoImg: {
189
191
  height: "clamp(28px, 5vw, 40px)",
190
192
  width: "auto",
191
193
  background: "transparent",
194
+ objectFit: "contain",
195
+ imageRendering: "crisp-edges",
196
+ transform: "translateZ(0)",
197
+ backfaceVisibility: "hidden",
198
+ WebkitFontSmoothing: "antialiased",
192
199
  },
193
200
 
194
201
  gmReadyWrapper: {
package/src/Game.tsx CHANGED
@@ -13,34 +13,28 @@ type RoundResult = {
13
13
  result: "correct" | "almost" | "wrong";
14
14
  };
15
15
 
16
+ // ✅ только изоляция, всё остальное без изменений
16
17
  const globalReset = () => {
17
18
  const style = document.createElement("style");
18
19
  style.textContent = `
19
- html, body, #root {
20
- margin: 0;
21
- padding: 0;
22
- height: 100%;
23
- }
24
- *, *::before, *::after {
20
+ #whats-missing-root, #whats-missing-root * {
25
21
  box-sizing: border-box;
26
- }
27
- body {
28
22
  font-family: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
23
+ }
24
+
25
+ #whats-missing-root {
29
26
  background-color: #fff;
30
27
  color: #1f2937;
28
+ text-align: center;
31
29
  }
32
- button, input {
33
- font-family: inherit;
34
- outline: none;
35
- border: none;
36
- background: none;
37
- }
38
- img {
30
+
31
+ #whats-missing-root img {
39
32
  max-width: 100%;
40
33
  height: auto;
41
34
  display: block;
42
35
  user-select: none;
43
36
  }
37
+
44
38
  @keyframes spin {
45
39
  from { transform: rotate(0deg); }
46
40
  to { transform: rotate(360deg); }
@@ -234,210 +228,204 @@ export default function Game() {
234
228
  );
235
229
 
236
230
  return (
237
- <div id="whats-missing-root" style={{ all: "initial", display: "block" }}>
238
- <div style={{ all: "unset" }}>
239
- {!isMobile && MemoizedLogo}
231
+ <div id="whats-missing-root">
232
+ {!isMobile && MemoizedLogo}
240
233
 
241
- {!theme && !started && (
242
- <div style={styles.gmCenterScreen}>
243
- <h1 style={styles.gmHeadline1}>WHAT'S MISSING?</h1>
244
- <p style={styles.gmBodyM}>Select a theme:</p>
245
- <div style={{ display: "flex", gap: 16 }}>
246
- {["animals", "food", "toys"].map((t) => (
234
+ {!theme && !started && (
235
+ <div style={styles.gmCenterScreen}>
236
+ <h1 style={styles.gmHeadline1}>WHAT'S MISSING?</h1>
237
+ <p style={styles.gmBodyM}>Select a theme:</p>
238
+ <div style={{ display: "flex", gap: 16 }}>
239
+ {["animals", "food", "toys"].map((t) => (
240
+ <button key={t} style={styles.gmButton} onClick={() => setTheme(t as Theme)}>
241
+ {t === "animals" ? "🐶 Animals" : t === "food" ? "🍎 Food" : "🧸 Toys"}
242
+ </button>
243
+ ))}
244
+ </div>
245
+ <div style={{ marginTop: 24 }}>
246
+ <p style={styles.gmBodyS}>Choose number of rounds:</p>
247
+ <div style={{ display: "flex", gap: 12, marginTop: 8 }}>
248
+ {[3, 4, 5].map((n) => (
247
249
  <button
248
- key={t}
249
- style={styles.gmButton}
250
- onClick={() => setTheme(t as Theme)}
250
+ key={n}
251
+ style={{
252
+ ...styles.gmButton,
253
+ ...(rounds === n ? styles.gmButtonActive : {}),
254
+ }}
255
+ onClick={() => setRounds(n)}
251
256
  >
252
- {t === "animals" ? "🐶 Animals" : t === "food" ? "🍎 Food" : "🧸 Toys"}
257
+ {n}
253
258
  </button>
254
259
  ))}
255
260
  </div>
256
- <div style={{ marginTop: 24 }}>
257
- <p style={styles.gmBodyS}>Choose number of rounds:</p>
258
- <div style={{ display: "flex", gap: 12, marginTop: 8 }}>
259
- {[3, 4, 5].map((n) => (
260
- <button
261
- key={n}
262
- style={{
263
- ...styles.gmButton,
264
- ...(rounds === n ? styles.gmButtonActive : {}),
265
- }}
266
- onClick={() => setRounds(n)}
267
- >
268
- {n}
269
- </button>
270
- ))}
271
- </div>
272
- </div>
273
261
  </div>
274
- )}
262
+ </div>
263
+ )}
264
+
265
+ {theme && !started && (
266
+ <div style={styles.gmCenterScreen}>
267
+ <h1 style={styles.gmHeadline1}>Theme selected: {theme}</h1>
268
+ <p style={styles.gmBodyM}>Rounds: {rounds}</p>
269
+ <button style={styles.gmButton} onClick={startGame}>
270
+ ▶ Start game
271
+ </button>
272
+ </div>
273
+ )}
275
274
 
276
- {theme && !started && (
277
- <div style={styles.gmCenterScreen}>
278
- <h1 style={styles.gmHeadline1}>Theme selected: {theme}</h1>
279
- <p style={styles.gmBodyM}>Rounds: {rounds}</p>
275
+ {finished && (
276
+ <div style={styles.gmCenterScreen}>
277
+ <h1 style={styles.gmHeadline1}>Results</h1>
278
+ <h2 style={styles.gmHeadline3}>
279
+ Your score: {score} / {rounds}
280
+ </h2>
281
+ <table style={styles.gmTable}>
282
+ <thead>
283
+ <tr>
284
+ <th>Round</th>
285
+ <th>Your Answer</th>
286
+ <th>Correct</th>
287
+ <th>Result</th>
288
+ </tr>
289
+ </thead>
290
+ <tbody>
291
+ {resultsTable.map((r, i) => (
292
+ <tr key={i}>
293
+ <td style={styles.gmTableCell}>{r.round}</td>
294
+ <td style={styles.gmTableCell}>{r.answer || "—"}</td>
295
+ <td style={styles.gmTableCell}>{r.correct}</td>
296
+ <td style={styles.gmTableCell}>
297
+ {r.result === "correct"
298
+ ? "✔ Correct"
299
+ : r.result === "almost"
300
+ ? "◐ Almost (0.5)"
301
+ : "✘ Wrong"}
302
+ </td>
303
+ </tr>
304
+ ))}
305
+ </tbody>
306
+ </table>
307
+ <div style={{ display: "flex", gap: 12, marginTop: 24 }}>
280
308
  <button style={styles.gmButton} onClick={startGame}>
281
- Start game
309
+ 🔁 Play again
310
+ </button>
311
+ <button style={styles.gmButton} onClick={exitGame}>
312
+ ⬅️ Choose theme
282
313
  </button>
283
314
  </div>
284
- )}
315
+ </div>
316
+ )}
285
317
 
286
- {finished && (
287
- <div style={styles.gmCenterScreen}>
288
- <h1 style={styles.gmHeadline1}>Results</h1>
289
- <h2 style={styles.gmHeadline3}>
290
- Your score: {score} / {rounds}
291
- </h2>
292
- <table style={styles.gmTable}>
293
- <thead>
294
- <tr>
295
- <th>Round</th>
296
- <th>Your Answer</th>
297
- <th>Correct</th>
298
- <th>Result</th>
299
- </tr>
300
- </thead>
301
- <tbody>
302
- {resultsTable.map((r, i) => (
303
- <tr key={i}>
304
- <td style={styles.gmTableCell}>{r.round}</td>
305
- <td style={styles.gmTableCell}>{r.answer || "—"}</td>
306
- <td style={styles.gmTableCell}>{r.correct}</td>
307
- <td style={styles.gmTableCell}>
308
- {r.result === "correct"
309
- ? "✔ Correct"
310
- : r.result === "almost"
311
- ? "◐ Almost (0.5)"
312
- : "✘ Wrong"}
313
- </td>
314
- </tr>
315
- ))}
316
- </tbody>
317
- </table>
318
- <div style={{ display: "flex", gap: 12, marginTop: 24 }}>
319
- <button style={styles.gmButton} onClick={startGame}>
320
- 🔁 Play again
321
- </button>
322
- <button style={styles.gmButton} onClick={exitGame}>
323
- ⬅️ Choose theme
324
- </button>
325
- </div>
318
+ {started && !finished && (
319
+ <div style={styles.gmGameLayout}>
320
+ <div
321
+ style={{
322
+ minHeight: 160,
323
+ display: "flex",
324
+ flexDirection: "column",
325
+ justifyContent: "center",
326
+ alignItems: "center",
327
+ }}
328
+ >
329
+ {phase === "ready" && (
330
+ <>
331
+ <h1 style={{ ...styles.gmHeadline1, color: "#ec4c44" }}>GET READY</h1>
332
+ <div style={styles.gmHourglass}>⏳</div>
333
+ </>
334
+ )}
335
+ {phase === "memorize" && (
336
+ <p style={{ ...styles.gmBodyM, color: "#10b981" }}>
337
+ MEMORIZE ({memorizeTime})
338
+ </p>
339
+ )}
340
+ {phase === "guess" && !answered && (
341
+ <p style={styles.gmBodyM}>⏳ Time left: {timeLeft}s</p>
342
+ )}
326
343
  </div>
327
- )}
328
344
 
329
- {started && !finished && (
330
- <div style={styles.gmGameLayout}>
345
+ {phase !== "ready" && (
331
346
  <div
332
347
  style={{
333
- minHeight: 160,
334
- display: "flex",
335
- flexDirection: "column",
336
- justifyContent: "center",
337
- alignItems: "center",
348
+ ...styles.gmGrid,
349
+ gridTemplateColumns: isMobile ? "repeat(2, 1fr)" : "repeat(3, 210px)",
350
+ gridAutoRows: isMobile ? "150px" : "210px",
351
+ gap: isMobile ? "12px" : "20px",
352
+ justifyItems: "center",
353
+ ...(window.innerWidth > 2000
354
+ ? {
355
+ gridTemplateColumns: "repeat(3, 260px)",
356
+ gridAutoRows: "260px",
357
+ gap: "28px",
358
+ }
359
+ : {}),
360
+ ...(window.innerWidth > 2560
361
+ ? {
362
+ gridTemplateColumns: "repeat(3, 300px)",
363
+ gridAutoRows: "300px",
364
+ gap: "32px",
365
+ }
366
+ : {}),
338
367
  }}
339
368
  >
340
- {phase === "ready" && (
341
- <>
342
- <h1 style={{ ...styles.gmHeadline1, color: "#ec4c44" }}>GET READY</h1>
343
- <div style={styles.gmHourglass}>⏳</div>
344
- </>
345
- )}
346
- {phase === "memorize" && (
347
- <p style={{ ...styles.gmBodyM, color: "#10b981" }}>
348
- MEMORIZE ({memorizeTime})
349
- </p>
350
- )}
351
- {phase === "guess" && !answered && (
352
- <p style={styles.gmBodyM}>⏳ Time left: {timeLeft}s</p>
353
- )}
369
+ {files.map((file, i) => {
370
+ const isHidden =
371
+ hiddenIndex === i && phase === "guess" && !answered;
372
+ return (
373
+ <div
374
+ key={i}
375
+ style={{
376
+ ...styles.gmCard,
377
+ ...(result === "correct" && hiddenIndex === i
378
+ ? styles.gmCorrect
379
+ : {}),
380
+ ...(result === "wrong" && hiddenIndex === i
381
+ ? styles.gmWrong
382
+ : {}),
383
+ }}
384
+ >
385
+ {!isHidden && (
386
+ <img
387
+ src={file.src}
388
+ alt={file.name}
389
+ style={{
390
+ width: "100%",
391
+ height: "100%",
392
+ objectFit: "cover",
393
+ }}
394
+ />
395
+ )}
396
+ </div>
397
+ );
398
+ })}
354
399
  </div>
400
+ )}
355
401
 
356
- {phase !== "ready" && (
357
- <div
358
- style={{
359
- ...styles.gmGrid,
360
- gridTemplateColumns: isMobile ? "repeat(2, 1fr)" : "repeat(3, 210px)",
361
- gridAutoRows: isMobile ? "150px" : "210px",
362
- gap: isMobile ? "12px" : "20px",
363
- justifyItems: "center",
364
- ...(window.innerWidth > 2000
365
- ? {
366
- gridTemplateColumns: "repeat(3, 260px)",
367
- gridAutoRows: "260px",
368
- gap: "28px",
369
- }
370
- : {}),
371
- ...(window.innerWidth > 2560
372
- ? {
373
- gridTemplateColumns: "repeat(3, 300px)",
374
- gridAutoRows: "300px",
375
- gap: "32px",
376
- }
377
- : {}),
378
- }}
379
- >
380
- {files.map((file, i) => {
381
- const isHidden =
382
- hiddenIndex === i && phase === "guess" && !answered;
383
- return (
384
- <div
385
- key={i}
386
- style={{
387
- ...styles.gmCard,
388
- ...(result === "correct" && hiddenIndex === i
389
- ? styles.gmCorrect
390
- : {}),
391
- ...(result === "wrong" && hiddenIndex === i
392
- ? styles.gmWrong
393
- : {}),
394
- }}
395
- >
396
- {!isHidden && (
397
- <img
398
- src={file.src}
399
- alt={file.name}
400
- style={{
401
- width: "100%",
402
- height: "100%",
403
- objectFit: "cover",
404
- }}
405
- />
406
- )}
407
- </div>
408
- );
409
- })}
402
+ <div style={{ marginTop: 16, height: 80 }}>
403
+ {phase === "guess" && !answered && (
404
+ <div>
405
+ <input
406
+ type="text"
407
+ placeholder="Type the missing word"
408
+ value={inputValue}
409
+ onChange={(e) => setInputValue(e.target.value)}
410
+ style={styles.gmInput}
411
+ />
412
+ <button
413
+ style={{ ...styles.gmButton, marginLeft: 8 }}
414
+ onClick={checkAnswer}
415
+ disabled={animating}
416
+ >
417
+ {animating ? "..." : "Check"}
418
+ </button>
410
419
  </div>
411
420
  )}
412
-
413
- <div style={{ marginTop: 16, height: 80 }}>
414
- {phase === "guess" && !answered && (
415
- <div>
416
- <input
417
- type="text"
418
- placeholder="Type the missing word"
419
- value={inputValue}
420
- onChange={(e) => setInputValue(e.target.value)}
421
- style={styles.gmInput}
422
- />
423
- <button
424
- style={{ ...styles.gmButton, marginLeft: 8 }}
425
- onClick={checkAnswer}
426
- disabled={animating}
427
- >
428
- {animating ? "..." : "Check"}
429
- </button>
430
- </div>
431
- )}
432
- {answered && (
433
- <button style={styles.gmButton} onClick={nextRound}>
434
- Next round
435
- </button>
436
- )}
437
- </div>
421
+ {answered && (
422
+ <button style={styles.gmButton} onClick={nextRound}>
423
+ Next round
424
+ </button>
425
+ )}
438
426
  </div>
439
- )}
440
- </div>
427
+ </div>
428
+ )}
441
429
  </div>
442
430
  );
443
431
  }