@mblinkov/whats-missing 20.0.17 → 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.
- package/dist/whats-missing.cjs.js +3 -3
- package/dist/whats-missing.es.js +123 -119
- package/package.json +1 -1
- package/src/Game.tsx +22 -13
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),o=require("react"),
|
|
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=
|
|
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;
|
|
@@ -19,4 +19,4 @@
|
|
|
19
19
|
padding: 0;
|
|
20
20
|
zoom: 1 !important; /* ✅ защита от подзума */
|
|
21
21
|
}
|
|
22
|
-
`,document.head.appendChild(r)},
|
|
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;
|
package/dist/whats-missing.es.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { jsx as t, jsxs as
|
|
2
|
-
import { useRef as
|
|
3
|
-
const
|
|
4
|
-
src: `${
|
|
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
|
-
})),
|
|
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/", j = (l, a) => l
|
|
|
29
29
|
["strawberry", "strawberry"],
|
|
30
30
|
["tomato", "tomato"],
|
|
31
31
|
["watermelon", "watermelon"]
|
|
32
|
-
],
|
|
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/", j = (l, a) => l
|
|
|
69
69
|
["teddy_bear", "teddy bear"],
|
|
70
70
|
["yo-yo", "yo-yo"],
|
|
71
71
|
["crayons", "crayons"]
|
|
72
|
-
],
|
|
73
|
-
food:
|
|
74
|
-
animals:
|
|
75
|
-
toys:
|
|
76
|
-
},
|
|
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/", j = (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 =
|
|
84
|
+
l.id = "spin-keyframes", l.innerHTML = fe, document.head.appendChild(l);
|
|
85
85
|
}
|
|
86
|
-
const
|
|
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
|
-
...
|
|
236
|
+
...ye
|
|
237
237
|
}
|
|
238
|
-
},
|
|
238
|
+
}, xe = () => {
|
|
239
239
|
const l = document.createElement("style");
|
|
240
240
|
l.textContent = `
|
|
241
241
|
#whats-missing-root, #whats-missing-root * {
|
|
@@ -255,85 +255,89 @@ const fe = {
|
|
|
255
255
|
}
|
|
256
256
|
`, document.head.appendChild(l);
|
|
257
257
|
}, be = (l, a) => {
|
|
258
|
-
const
|
|
259
|
-
for (let o = 0; o <= l.length; o++)
|
|
260
|
-
for (let o = 0; o <= a.length; o++)
|
|
258
|
+
const d = Array.from({ length: l.length + 1 }, () => Array(a.length + 1).fill(0));
|
|
259
|
+
for (let o = 0; o <= l.length; o++) d[o][0] = o;
|
|
260
|
+
for (let o = 0; o <= a.length; o++) d[0][o] = o;
|
|
261
261
|
for (let o = 1; o <= l.length; o++)
|
|
262
|
-
for (let
|
|
263
|
-
|
|
264
|
-
return
|
|
262
|
+
for (let m = 1; m <= a.length; m++)
|
|
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;
|
|
264
|
+
return d[l.length][a.length];
|
|
265
265
|
};
|
|
266
|
-
function
|
|
267
|
-
const l =
|
|
268
|
-
|
|
266
|
+
function Ce() {
|
|
267
|
+
const l = ce(null);
|
|
268
|
+
W(() => (xe(), () => {
|
|
269
269
|
document.body.style.overflow = "";
|
|
270
270
|
}), []);
|
|
271
|
-
const [a,
|
|
272
|
-
|
|
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(() => {
|
|
273
273
|
const e = () => {
|
|
274
|
-
const i = window.innerWidth < 768
|
|
275
|
-
if (
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
274
|
+
const i = window.innerWidth < 768;
|
|
275
|
+
if (ie(i), i)
|
|
276
|
+
K(null), _(1);
|
|
277
|
+
else {
|
|
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);
|
|
280
|
+
}
|
|
280
281
|
};
|
|
281
282
|
return e(), window.addEventListener("resize", e), () => window.removeEventListener("resize", e);
|
|
282
283
|
}, []);
|
|
283
|
-
const
|
|
284
|
+
const O = (e) => [...e].sort(() => Math.random() - 0.5).slice(0, 6), Z = () => {
|
|
284
285
|
if (!a) return;
|
|
285
|
-
const e =
|
|
286
|
-
|
|
287
|
-
},
|
|
288
|
-
const
|
|
289
|
-
let
|
|
290
|
-
for (; i.includes(w) &&
|
|
291
|
-
|
|
292
|
-
|
|
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));
|
|
293
294
|
};
|
|
294
|
-
|
|
295
|
-
if (!(!
|
|
295
|
+
W(() => {
|
|
296
|
+
if (!(!x || S || f)) {
|
|
296
297
|
if (h === "ready")
|
|
297
|
-
if (
|
|
298
|
+
if (Y <= 0) C("memorize");
|
|
298
299
|
else {
|
|
299
|
-
const e = setTimeout(() =>
|
|
300
|
+
const e = setTimeout(() => D((i) => i - 1), 1e3);
|
|
300
301
|
return () => clearTimeout(e);
|
|
301
302
|
}
|
|
302
303
|
if (h === "memorize")
|
|
303
|
-
if (
|
|
304
|
+
if (R <= 0) C("guess");
|
|
304
305
|
else {
|
|
305
|
-
const e = setTimeout(() =>
|
|
306
|
+
const e = setTimeout(() => I((i) => i - 1), 1e3);
|
|
306
307
|
return () => clearTimeout(e);
|
|
307
308
|
}
|
|
308
309
|
if (h === "guess") {
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
const i = o[
|
|
312
|
-
|
|
313
|
-
...
|
|
314
|
-
{ round: v, answer:
|
|
310
|
+
if (M <= 0) {
|
|
311
|
+
B(!0), b("wrong");
|
|
312
|
+
const i = o[p].name;
|
|
313
|
+
j((g) => [
|
|
314
|
+
...g,
|
|
315
|
+
{ round: v, answer: z, correct: i, result: "wrong" }
|
|
315
316
|
]);
|
|
316
317
|
return;
|
|
317
318
|
}
|
|
318
|
-
const e = setTimeout(() =>
|
|
319
|
+
const e = setTimeout(() => q((i) => i - 1), 1e3);
|
|
319
320
|
return () => clearTimeout(e);
|
|
320
321
|
}
|
|
321
322
|
}
|
|
322
|
-
}, [h,
|
|
323
|
-
const
|
|
324
|
-
if (
|
|
325
|
-
const e = o[
|
|
326
|
-
let
|
|
327
|
-
i === e ? (H((
|
|
328
|
-
|
|
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();
|
|
327
|
+
let g = "wrong";
|
|
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);
|
|
329
330
|
}, 600);
|
|
330
|
-
},
|
|
331
|
-
E(!1),
|
|
332
|
-
},
|
|
333
|
-
() =>
|
|
334
|
-
|
|
335
|
-
/* @__PURE__ */ t("
|
|
336
|
-
|
|
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
|
+
),
|
|
337
341
|
[]
|
|
338
342
|
);
|
|
339
343
|
return /* @__PURE__ */ t(
|
|
@@ -354,37 +358,37 @@ function ke() {
|
|
|
354
358
|
"div",
|
|
355
359
|
{
|
|
356
360
|
style: {
|
|
357
|
-
width:
|
|
358
|
-
height:
|
|
361
|
+
width: u ? "100%" : $ || 1e3,
|
|
362
|
+
height: u ? "100%" : $ || 1e3,
|
|
359
363
|
display: "flex",
|
|
360
364
|
justifyContent: "center",
|
|
361
365
|
alignItems: "center",
|
|
362
366
|
overflow: "hidden",
|
|
363
|
-
borderRadius:
|
|
367
|
+
borderRadius: u ? 0 : "20px",
|
|
364
368
|
background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
|
|
365
|
-
boxShadow:
|
|
366
|
-
margin:
|
|
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
|
|
367
373
|
},
|
|
368
374
|
children: /* @__PURE__ */ t(
|
|
369
375
|
"div",
|
|
370
376
|
{
|
|
371
377
|
style: {
|
|
372
|
-
transform:
|
|
373
|
-
transformOrigin: "top center",
|
|
374
|
-
// ✅ фикс вертикального смещения
|
|
378
|
+
transform: "none",
|
|
375
379
|
width: "100%",
|
|
376
380
|
height: "100%",
|
|
377
381
|
display: "flex",
|
|
378
382
|
justifyContent: "center",
|
|
379
383
|
alignItems: "center"
|
|
380
384
|
},
|
|
381
|
-
children: /* @__PURE__ */
|
|
382
|
-
!
|
|
383
|
-
!a && !
|
|
385
|
+
children: /* @__PURE__ */ s("div", { id: "whats-missing-root", children: [
|
|
386
|
+
!u && ae,
|
|
387
|
+
!a && !x && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
|
|
384
388
|
/* @__PURE__ */ t("h1", { style: n.gmHeadline1, children: "WHAT'S MISSING?" }),
|
|
385
389
|
/* @__PURE__ */ t("p", { style: n.gmBodyM, children: "Select a theme:" }),
|
|
386
|
-
/* @__PURE__ */ t("div", { style: { display: "flex", gap: 16 }, children: ["animals", "food", "toys"].map((e) => /* @__PURE__ */ t("button", { style: n.gmButton, onClick: () =>
|
|
387
|
-
/* @__PURE__ */
|
|
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)) }),
|
|
391
|
+
/* @__PURE__ */ s("div", { style: { marginTop: 24 }, children: [
|
|
388
392
|
/* @__PURE__ */ t("p", { style: n.gmBodyS, children: "Choose number of rounds:" }),
|
|
389
393
|
/* @__PURE__ */ t("div", { style: { display: "flex", gap: 12, marginTop: 8 }, children: [3, 4, 5].map((e) => /* @__PURE__ */ t(
|
|
390
394
|
"button",
|
|
@@ -393,54 +397,54 @@ function ke() {
|
|
|
393
397
|
...n.gmButton,
|
|
394
398
|
...k === e ? n.gmButtonActive : {}
|
|
395
399
|
},
|
|
396
|
-
onClick: () =>
|
|
400
|
+
onClick: () => Q(e),
|
|
397
401
|
children: e
|
|
398
402
|
},
|
|
399
403
|
e
|
|
400
404
|
)) })
|
|
401
405
|
] })
|
|
402
406
|
] }),
|
|
403
|
-
a && !
|
|
404
|
-
/* @__PURE__ */
|
|
407
|
+
a && !x && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
|
|
408
|
+
/* @__PURE__ */ s("h1", { style: n.gmHeadline1, children: [
|
|
405
409
|
"Theme selected: ",
|
|
406
410
|
a
|
|
407
411
|
] }),
|
|
408
|
-
/* @__PURE__ */
|
|
412
|
+
/* @__PURE__ */ s("p", { style: n.gmBodyM, children: [
|
|
409
413
|
"Rounds: ",
|
|
410
414
|
k
|
|
411
415
|
] }),
|
|
412
|
-
/* @__PURE__ */ t("button", { style: n.gmButton, onClick:
|
|
416
|
+
/* @__PURE__ */ t("button", { style: n.gmButton, onClick: Z, children: "▶ Start game" })
|
|
413
417
|
] }),
|
|
414
|
-
|
|
418
|
+
S && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
|
|
415
419
|
/* @__PURE__ */ t("h1", { style: n.gmHeadline1, children: "Results" }),
|
|
416
|
-
/* @__PURE__ */
|
|
420
|
+
/* @__PURE__ */ s("h2", { style: n.gmHeadline3, children: [
|
|
417
421
|
"Your score: ",
|
|
418
|
-
|
|
422
|
+
te,
|
|
419
423
|
" / ",
|
|
420
424
|
k
|
|
421
425
|
] }),
|
|
422
426
|
/* @__PURE__ */ t("p", { style: { ...n.gmBodyM, color: "#10b981", marginTop: 12 }, children: "Yahoo! You did it! 🍬✨" }),
|
|
423
|
-
/* @__PURE__ */
|
|
424
|
-
/* @__PURE__ */ t("thead", { children: /* @__PURE__ */
|
|
427
|
+
/* @__PURE__ */ s("table", { style: n.gmTable, children: [
|
|
428
|
+
/* @__PURE__ */ t("thead", { children: /* @__PURE__ */ s("tr", { children: [
|
|
425
429
|
/* @__PURE__ */ t("th", { children: "Round" }),
|
|
426
430
|
/* @__PURE__ */ t("th", { children: "Your Answer" }),
|
|
427
431
|
/* @__PURE__ */ t("th", { children: "Correct" }),
|
|
428
432
|
/* @__PURE__ */ t("th", { children: "Result" })
|
|
429
433
|
] }) }),
|
|
430
|
-
/* @__PURE__ */ t("tbody", { children:
|
|
434
|
+
/* @__PURE__ */ t("tbody", { children: ne.map((e, i) => /* @__PURE__ */ s("tr", { children: [
|
|
431
435
|
/* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.round }),
|
|
432
436
|
/* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.answer || "—" }),
|
|
433
437
|
/* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.correct }),
|
|
434
438
|
/* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.result === "correct" ? "✔ Correct" : e.result === "almost" ? "◐ Almost (0.5)" : "✘ Wrong" })
|
|
435
439
|
] }, i)) })
|
|
436
440
|
] }),
|
|
437
|
-
/* @__PURE__ */
|
|
438
|
-
/* @__PURE__ */ t("button", { style: n.gmButton, onClick:
|
|
439
|
-
/* @__PURE__ */ t("button", { style: n.gmButton, onClick:
|
|
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" })
|
|
440
444
|
] })
|
|
441
445
|
] }),
|
|
442
|
-
|
|
443
|
-
/* @__PURE__ */
|
|
446
|
+
x && !S && /* @__PURE__ */ s("div", { style: n.gmGameLayout, children: [
|
|
447
|
+
/* @__PURE__ */ s(
|
|
444
448
|
"div",
|
|
445
449
|
{
|
|
446
450
|
style: {
|
|
@@ -451,18 +455,18 @@ function ke() {
|
|
|
451
455
|
alignItems: "center"
|
|
452
456
|
},
|
|
453
457
|
children: [
|
|
454
|
-
h === "ready" && /* @__PURE__ */
|
|
458
|
+
h === "ready" && /* @__PURE__ */ s(de, { children: [
|
|
455
459
|
/* @__PURE__ */ t("h1", { style: { ...n.gmHeadline1, color: "#ec4c44" }, children: "GET READY" }),
|
|
456
460
|
/* @__PURE__ */ t("div", { style: n.gmHourglass, children: "⏳" })
|
|
457
461
|
] }),
|
|
458
|
-
h === "memorize" && /* @__PURE__ */
|
|
462
|
+
h === "memorize" && /* @__PURE__ */ s("p", { style: { ...n.gmBodyM, color: "#10b981" }, children: [
|
|
459
463
|
"MEMORIZE (",
|
|
460
|
-
|
|
464
|
+
R,
|
|
461
465
|
")"
|
|
462
466
|
] }),
|
|
463
|
-
h === "guess" && !f && /* @__PURE__ */
|
|
467
|
+
h === "guess" && !f && /* @__PURE__ */ s("p", { style: n.gmBodyM, children: [
|
|
464
468
|
"⏳ Time left: ",
|
|
465
|
-
|
|
469
|
+
M,
|
|
466
470
|
"s"
|
|
467
471
|
] })
|
|
468
472
|
]
|
|
@@ -473,22 +477,22 @@ function ke() {
|
|
|
473
477
|
{
|
|
474
478
|
style: {
|
|
475
479
|
...n.gmGrid,
|
|
476
|
-
gridTemplateColumns:
|
|
477
|
-
gridAutoRows:
|
|
478
|
-
gap:
|
|
480
|
+
gridTemplateColumns: u ? "repeat(2, 1fr)" : "repeat(3, 210px)",
|
|
481
|
+
gridAutoRows: u ? "150px" : "210px",
|
|
482
|
+
gap: u ? "12px" : "20px",
|
|
479
483
|
justifyItems: "center"
|
|
480
484
|
},
|
|
481
485
|
children: o.map((e, i) => {
|
|
482
|
-
const
|
|
486
|
+
const g = p === i && h === "guess" && !f;
|
|
483
487
|
return /* @__PURE__ */ t(
|
|
484
488
|
"div",
|
|
485
489
|
{
|
|
486
490
|
style: {
|
|
487
491
|
...n.gmCard,
|
|
488
|
-
...N === "correct" &&
|
|
489
|
-
...N === "wrong" &&
|
|
492
|
+
...N === "correct" && p === i ? n.gmCorrect : {},
|
|
493
|
+
...N === "wrong" && p === i ? n.gmWrong : {}
|
|
490
494
|
},
|
|
491
|
-
children: !
|
|
495
|
+
children: !g && /* @__PURE__ */ t(
|
|
492
496
|
"img",
|
|
493
497
|
{
|
|
494
498
|
src: e.src,
|
|
@@ -506,15 +510,15 @@ function ke() {
|
|
|
506
510
|
})
|
|
507
511
|
}
|
|
508
512
|
),
|
|
509
|
-
/* @__PURE__ */
|
|
510
|
-
h === "guess" && !f && /* @__PURE__ */
|
|
513
|
+
/* @__PURE__ */ s("div", { style: { marginTop: 16, height: 80 }, children: [
|
|
514
|
+
h === "guess" && !f && /* @__PURE__ */ s("div", { children: [
|
|
511
515
|
/* @__PURE__ */ t(
|
|
512
516
|
"input",
|
|
513
517
|
{
|
|
514
518
|
type: "text",
|
|
515
519
|
placeholder: "Type the missing word",
|
|
516
|
-
value:
|
|
517
|
-
onChange: (e) =>
|
|
520
|
+
value: z,
|
|
521
|
+
onChange: (e) => P(e.target.value),
|
|
518
522
|
style: n.gmInput
|
|
519
523
|
}
|
|
520
524
|
),
|
|
@@ -522,13 +526,13 @@ function ke() {
|
|
|
522
526
|
"button",
|
|
523
527
|
{
|
|
524
528
|
style: { ...n.gmButton, marginLeft: 8 },
|
|
525
|
-
onClick:
|
|
526
|
-
disabled:
|
|
527
|
-
children:
|
|
529
|
+
onClick: re,
|
|
530
|
+
disabled: L,
|
|
531
|
+
children: L ? "..." : "Check"
|
|
528
532
|
}
|
|
529
533
|
)
|
|
530
534
|
] }),
|
|
531
|
-
f && /* @__PURE__ */ t("button", { style: n.gmButton, onClick:
|
|
535
|
+
f && /* @__PURE__ */ t("button", { style: n.gmButton, onClick: se, children: "Next round" })
|
|
532
536
|
] })
|
|
533
537
|
] })
|
|
534
538
|
] })
|
|
@@ -540,6 +544,6 @@ function ke() {
|
|
|
540
544
|
);
|
|
541
545
|
}
|
|
542
546
|
export {
|
|
543
|
-
|
|
544
|
-
|
|
547
|
+
Ce as Game,
|
|
548
|
+
J as themes
|
|
545
549
|
};
|
package/package.json
CHANGED
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";
|
|
@@ -80,6 +81,7 @@ export default function Game() {
|
|
|
80
81
|
const [usedHidden, setUsedHidden] = useState<string[]>([]);
|
|
81
82
|
const [isMobile, setIsMobile] = useState(false);
|
|
82
83
|
const [scale, setScale] = useState(1);
|
|
84
|
+
const [containerSize, setContainerSize] = useState<number | null>(null);
|
|
83
85
|
|
|
84
86
|
// ✅ адаптив под мобилки, планшеты и десктоп
|
|
85
87
|
useEffect(() => {
|
|
@@ -87,15 +89,21 @@ export default function Game() {
|
|
|
87
89
|
const mobile = window.innerWidth < 768;
|
|
88
90
|
const tablet = window.innerWidth >= 768 && window.innerWidth < 1200;
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
// treat only phones as "mobile" so tablets use the desktop (square/centered) layout
|
|
93
|
+
setIsMobile(mobile);
|
|
91
94
|
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const ratio = Math.min(window.innerWidth / baseW, window.innerHeight / baseH) * 0.97;
|
|
97
|
-
setScale(ratio);
|
|
95
|
+
if (mobile) {
|
|
96
|
+
// mobile: fluid full-width layout
|
|
97
|
+
setContainerSize(null);
|
|
98
|
+
setScale(1);
|
|
98
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);
|
|
99
107
|
setScale(1);
|
|
100
108
|
}
|
|
101
109
|
};
|
|
@@ -215,7 +223,8 @@ export default function Game() {
|
|
|
215
223
|
|
|
216
224
|
const MemoizedLogo = useMemo(
|
|
217
225
|
() => (
|
|
218
|
-
|
|
226
|
+
// ensure logo is positioned inside the square container
|
|
227
|
+
<div style={{ ...styles.gmLogoFixed, position: "absolute", top: 16, left: 16, zIndex: 30 }}>
|
|
219
228
|
<picture>
|
|
220
229
|
<source srcSet={window.origin + "/cloud/speakid/games/whatsmissing/logo.svg"} type="image/svg+xml" />
|
|
221
230
|
<img src={window.origin + "/cloud/speakid/games/whatsmissing/logo.png"} alt="SPEAKID Logo" style={styles.gmLogoImg} loading="lazy" />
|
|
@@ -241,8 +250,8 @@ export default function Game() {
|
|
|
241
250
|
>
|
|
242
251
|
<div
|
|
243
252
|
style={{
|
|
244
|
-
width: isMobile ? "100%" :
|
|
245
|
-
height: isMobile ? "100%" :
|
|
253
|
+
width: isMobile ? "100%" : containerSize || 1000,
|
|
254
|
+
height: isMobile ? "100%" : containerSize || 1000,
|
|
246
255
|
display: "flex",
|
|
247
256
|
justifyContent: "center",
|
|
248
257
|
alignItems: "center",
|
|
@@ -251,12 +260,12 @@ export default function Game() {
|
|
|
251
260
|
background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
|
|
252
261
|
boxShadow: isMobile ? "none" : "0 0 40px rgba(0,0,0,0.1)",
|
|
253
262
|
margin: isMobile ? "0 auto" : "unset",
|
|
263
|
+
position: "relative", // needed so absolute logo is inside the square
|
|
254
264
|
}}
|
|
255
265
|
>
|
|
256
266
|
<div
|
|
257
267
|
style={{
|
|
258
|
-
transform:
|
|
259
|
-
transformOrigin: "top center", // ✅ фикс вертикального смещения
|
|
268
|
+
transform: "none",
|
|
260
269
|
width: "100%",
|
|
261
270
|
height: "100%",
|
|
262
271
|
display: "flex",
|
|
@@ -451,4 +460,4 @@ export default function Game() {
|
|
|
451
460
|
</div>
|
|
452
461
|
</div>
|
|
453
462
|
);
|
|
454
|
-
}
|
|
463
|
+
}
|