@mblinkov/whats-missing 20.0.19 → 20.0.21

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
- import { jsx as t, jsxs as s, Fragment as pe } from "react/jsx-runtime";
2
- import { useRef as he, useEffect as N, useState as r, useMemo as fe } from "react";
3
- const ye = window.origin + "/cloud/speakid/games/whatsmissing/", Y = (l, d) => l.map(([m, o]) => ({
4
- src: `${ye}${d}/${o.replace(/\s/g, "%20")}.png`,
1
+ import { jsx as t, jsxs as c, Fragment as ue } from "react/jsx-runtime";
2
+ import { useRef as te, useEffect as P, useState as d, useMemo as he, useLayoutEffect as fe } from "react";
3
+ const pe = window.origin + "/cloud/speakid/games/whatsmissing/", V = (l, g) => l.map(([m, o]) => ({
4
+ src: `${pe}${g}/${o.replace(/\s/g, "%20")}.png`,
5
5
  name: o
6
- })), xe = [
6
+ })), ye = [
7
7
  ["apple", "apple"],
8
8
  ["banana", "banana"],
9
9
  ["bread", "bread"],
@@ -69,11 +69,11 @@ const ye = window.origin + "/cloud/speakid/games/whatsmissing/", Y = (l, d) => l
69
69
  ["teddy_bear", "teddy bear"],
70
70
  ["yo-yo", "yo-yo"],
71
71
  ["crayons", "crayons"]
72
- ], ne = {
73
- food: Y(xe, "food"),
74
- animals: Y(be, "animals"),
75
- toys: Y(we, "toys")
76
- }, ve = `
72
+ ], ee = {
73
+ food: V(ye, "food"),
74
+ animals: V(be, "animals"),
75
+ toys: V(we, "toys")
76
+ }, xe = `
77
77
  @keyframes spin {
78
78
  from { transform: rotate(0deg); }
79
79
  to { transform: rotate(360deg); }
@@ -81,15 +81,17 @@ const ye = window.origin + "/cloud/speakid/games/whatsmissing/", Y = (l, d) => 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 = ve, document.head.appendChild(l);
84
+ l.id = "spin-keyframes", l.innerHTML = xe, document.head.appendChild(l);
85
85
  }
86
- const ke = {
86
+ const ve = {
87
87
  animation: "spin 1.4s linear infinite"
88
88
  }, n = {
89
89
  gmCenterScreen: {
90
90
  position: "relative",
91
91
  zIndex: 1,
92
- minHeight: "100vh",
92
+ // use percent so the component fits inside the centered square container
93
+ // (100vh caused overflow on tablets because it measured the viewport, not the container)
94
+ minHeight: "100%",
93
95
  width: "100%",
94
96
  display: "flex",
95
97
  flexDirection: "column",
@@ -144,7 +146,8 @@ const ke = {
144
146
  position: "relative",
145
147
  width: "100%",
146
148
  maxWidth: "600px",
147
- minHeight: "100vh",
149
+ // should fill the parent square, not the full viewport
150
+ minHeight: "100%",
148
151
  display: "flex",
149
152
  flexDirection: "column",
150
153
  alignItems: "center",
@@ -233,125 +236,159 @@ const ke = {
233
236
  },
234
237
  gmHourglass: {
235
238
  fontSize: "42px",
236
- ...ke
239
+ ...ve
237
240
  }
238
- }, Ce = () => {
241
+ }, ke = () => {
239
242
  const l = document.createElement("style");
240
243
  l.textContent = `
241
- #whats-missing-root, #whats-missing-root * {
242
- box-sizing: border-box;
243
- font-family: "Geist", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
244
- }
245
- #whats-missing-root img {
246
- max-width: 100%;
247
- height: auto;
248
- display: block;
249
- user-select: none;
250
- }
251
- html, body { margin: 0; padding: 0; }
244
+ /* scope only inside game root */
245
+ #whats-missing-root, #whats-missing-root * { box-sizing: border-box; }
246
+ #whats-missing-root img { max-width:100%; height:auto; display:block; user-select:none; }
252
247
  `, document.head.appendChild(l);
253
- }, Se = (l, d) => {
254
- const m = Array.from({ length: l.length + 1 }, () => Array(d.length + 1).fill(0));
248
+ }, ze = (l, g) => {
249
+ const m = Array.from({ length: l.length + 1 }, () => Array(g.length + 1).fill(0));
255
250
  for (let o = 0; o <= l.length; o++) m[o][0] = o;
256
- for (let o = 0; o <= d.length; o++) m[0][o] = o;
251
+ for (let o = 0; o <= g.length; o++) m[0][o] = o;
257
252
  for (let o = 1; o <= l.length; o++)
258
- for (let g = 1; g <= d.length; g++)
259
- m[o][g] = l[o - 1] === d[g - 1] ? m[o - 1][g - 1] : Math.min(m[o - 1][g - 1], m[o][g - 1], m[o - 1][g]) + 1;
260
- return m[l.length][d.length];
253
+ for (let u = 1; u <= g.length; u++)
254
+ m[o][u] = l[o - 1] === g[u - 1] ? m[o - 1][u - 1] : Math.min(m[o - 1][u - 1], m[o][u - 1], m[o - 1][u]) + 1;
255
+ return m[l.length][g.length];
261
256
  };
262
- function Me() {
263
- const l = he(null);
264
- N(() => (Ce(), () => {
265
- document.body.style.overflow = "";
266
- }), []);
267
- const [d, m] = r(null), [o, g] = r([]), [C, oe] = r(4), [v, D] = r(!1), [S, P] = r(1), [x, ie] = r(null), [u, z] = r("ready"), [O, U] = r(3), [H, B] = r(10), [A, V] = r(20), [re, L] = r(0), [T, j] = r(!1), [M, q] = r(""), [w, F] = r(!1), [W, _] = r(!1), [K, k] = r(null), [se, E] = r([]), [ae, Z] = r([]), [h, le] = r(!1), [R, X] = r(null), [b, G] = r(1);
268
- N(() => {
269
- const e = () => {
270
- const a = window.innerWidth < 768;
271
- if (le(a), a) {
272
- X(null);
273
- return;
274
- }
275
- const f = 0.97, p = 1e3, y = Math.min(window.innerWidth, window.innerHeight), I = Math.max(360, Math.round(y * f)), te = Math.min(I, p);
276
- X(te);
277
- }, i = () => {
257
+ function Ce(l, g = { minDesktopWidth: 1200, forceResize: !1 }) {
258
+ const m = te(null), o = g.minDesktopWidth ?? 1200, u = !!g.forceResize;
259
+ fe(() => {
260
+ if (typeof window > "u" || !l || !l.current) return;
261
+ const s = l.current, F = () => {
278
262
  try {
279
- const a = document.body, f = getComputedStyle(a), p = parseFloat(f.zoom || "");
280
- if (p && !isNaN(p) && p > 0) {
281
- G(p);
282
- return;
283
- }
284
- const y = f.transform;
285
- if (y && y !== "none") {
286
- const I = y.match(/matrix\(([^)]+)\)/);
287
- if (I) {
288
- const $ = I[1].split(",").map((ue) => parseFloat(ue))[0];
289
- if ($ && !isNaN($)) {
290
- G($);
291
- return;
292
- }
263
+ const i = document.body, a = getComputedStyle(i), y = parseFloat(i.style && i.style.zoom || "");
264
+ if (y && !isNaN(y) && y > 0) return y;
265
+ const k = parseFloat(a.zoom || "");
266
+ if (k && !isNaN(k) && k > 0) return k;
267
+ const S = a.transform || a.webkitTransform || a.mozTransform;
268
+ if (S && S !== "none") {
269
+ const T = S.match(/matrix\(([^)]+)\)/);
270
+ if (T) {
271
+ const z = T[1].split(",").map((E) => parseFloat(E))[0];
272
+ if (z && !isNaN(z)) return z;
293
273
  }
294
274
  }
295
275
  } catch {
296
276
  }
297
- G(1);
277
+ return 1;
278
+ }, x = () => {
279
+ if (o && window.innerWidth < o) {
280
+ C();
281
+ return;
282
+ }
283
+ const i = F();
284
+ if (!i || i === 1) {
285
+ C();
286
+ return;
287
+ }
288
+ m.current || (m.current = {
289
+ transform: s.style.transform || null,
290
+ transformOrigin: s.style.transformOrigin || null,
291
+ width: s.style.width || null,
292
+ height: s.style.height || null,
293
+ willChange: s.style.willChange || null
294
+ });
295
+ const a = 1 / i;
296
+ u && (s.style.width = `${i * 100}%`, s.style.height = `${i * 100}%`), s.style.transform = `scale(${a})`, s.style.transformOrigin = "top left", s.style.willChange = "transform", typeof process < "u" && process.env && process.env.NODE_ENV === "development" && console.debug("[useNeutralizeBodyZoom] applied scale:", { scale: i, inv: a, forceResize: u });
297
+ }, C = () => {
298
+ if (!m.current) return;
299
+ const i = m.current;
300
+ i.transform === null ? s.style.removeProperty("transform") : s.style.transform = i.transform, i.transformOrigin === null ? s.style.removeProperty("transform-origin") : s.style.transformOrigin = i.transformOrigin, i.width === null ? s.style.removeProperty("width") : s.style.width = i.width, i.height === null ? s.style.removeProperty("height") : s.style.height = i.height, i.willChange === null ? s.style.removeProperty("will-change") : s.style.willChange = i.willChange, m.current = null, process.env.NODE_ENV === "development" && console.debug("[useNeutralizeBodyZoom] restored original styles");
298
301
  };
299
- e(), i(), window.addEventListener("resize", e), window.addEventListener("resize", i);
300
- const c = new MutationObserver(i);
301
- return c.observe(document.body, { attributes: !0, attributeFilter: ["style", "class"] }), () => {
302
- window.removeEventListener("resize", e), window.removeEventListener("resize", i), c.disconnect();
302
+ let w = 0;
303
+ const v = () => {
304
+ cancelAnimationFrame(w), w = requestAnimationFrame(x);
305
+ }, p = new MutationObserver((i) => {
306
+ for (const a of i)
307
+ if (a.type === "attributes" && (a.attributeName === "style" || a.attributeName === "class")) {
308
+ v();
309
+ break;
310
+ }
311
+ });
312
+ return p.observe(document.body, { attributes: !0, attributeFilter: ["style", "class"] }), window.addEventListener("resize", v), v(), () => {
313
+ cancelAnimationFrame(w), p.disconnect(), window.removeEventListener("resize", v), C();
314
+ };
315
+ }, [l, o, u]);
316
+ }
317
+ function Me() {
318
+ const l = te(null);
319
+ Ce(l, { minDesktopWidth: 1200, forceResize: !1 }), P(() => (ke(), () => {
320
+ document.body.style.overflow = "";
321
+ }), []);
322
+ const [g, m] = d(null), [o, u] = d([]), [s, F] = d(4), [x, C] = d(!1), [w, v] = d(1), [p, i] = d(null), [a, y] = d("ready"), [k, S] = d(3), [T, B] = d(10), [z, E] = d(20), [ne, W] = d(0), [A, N] = d(!1), [H, Y] = d(""), [R, j] = d(!1), [D, $] = d(!1), [q, L] = d(null), [oe, G] = d([]), [re, Z] = d([]), [b, ie] = d(!1), [Se, _] = d(1), [U, K] = d(null);
323
+ P(() => {
324
+ const e = () => {
325
+ const h = window.visualViewport, f = h ? Math.round(h.width) : window.innerWidth, I = h ? Math.round(h.height) : window.innerHeight, M = f < 768;
326
+ if (ie(M), M)
327
+ K(null), _(1);
328
+ else {
329
+ const ce = Math.min(f, I), me = Math.max(360, Math.round(ce * 0.97)), ge = Math.min(me, 1e3);
330
+ K(ge), _(1);
331
+ }
332
+ };
333
+ e(), window.addEventListener("resize", e);
334
+ const r = window.visualViewport;
335
+ return r && typeof r.addEventListener == "function" && (r.addEventListener("resize", e), r.addEventListener("scroll", e)), () => {
336
+ window.removeEventListener("resize", e), r && typeof r.removeEventListener == "function" && (r.removeEventListener("resize", e), r.removeEventListener("scroll", e));
303
337
  };
304
338
  }, []);
305
- const J = (e) => [...e].sort(() => Math.random() - 0.5).slice(0, 6), Q = () => {
306
- if (!d) return;
307
- const e = J(ne[d]);
308
- g(e), D(!0), j(!1), P(1), L(0), E([]), Z([]), ee(e, [], !0);
309
- }, ee = (e = o, i = ae, c = !1) => {
310
- const a = J(e.length ? e : ne[d]);
311
- let f = Math.floor(Math.random() * a.length), p = a[f].name, y = 0;
312
- for (; i.includes(p) && y < 20; )
313
- f = Math.floor(Math.random() * a.length), p = a[f].name, y++;
314
- g(a), ie(f), Z([...i, p]), F(!1), q(""), V(20), k(null), c ? (z("ready"), U(3), B(10)) : (z("memorize"), B(10));
339
+ const X = (e) => [...e].sort(() => Math.random() - 0.5).slice(0, 6), J = () => {
340
+ if (!g) return;
341
+ const e = X(ee[g]);
342
+ u(e), C(!0), N(!1), v(1), W(0), G([]), Z([]), Q(e, [], !0);
343
+ }, Q = (e = o, r = re, h = !1) => {
344
+ const f = X(e.length ? e : ee[g]);
345
+ let I = Math.floor(Math.random() * f.length), M = f[I].name, O = 0;
346
+ for (; r.includes(M) && O < 20; )
347
+ I = Math.floor(Math.random() * f.length), M = f[I].name, O++;
348
+ u(f), i(I), Z([...r, M]), j(!1), Y(""), E(20), L(null), h ? (y("ready"), S(3), B(10)) : (y("memorize"), B(10));
315
349
  };
316
- N(() => {
317
- if (!(!v || T || w)) {
318
- if (u === "ready")
319
- if (O <= 0) z("memorize");
350
+ P(() => {
351
+ if (!(!x || A || R)) {
352
+ if (a === "ready")
353
+ if (k <= 0) y("memorize");
320
354
  else {
321
- const e = setTimeout(() => U((i) => i - 1), 1e3);
355
+ const e = setTimeout(() => S((r) => r - 1), 1e3);
322
356
  return () => clearTimeout(e);
323
357
  }
324
- if (u === "memorize")
325
- if (H <= 0) z("guess");
358
+ if (a === "memorize")
359
+ if (T <= 0) y("guess");
326
360
  else {
327
- const e = setTimeout(() => B((i) => i - 1), 1e3);
361
+ const e = setTimeout(() => B((r) => r - 1), 1e3);
328
362
  return () => clearTimeout(e);
329
363
  }
330
- if (u === "guess") {
331
- if (A <= 0) {
332
- F(!0), k("wrong");
333
- const i = o[x].name;
334
- E((c) => [...c, { round: S, answer: M, correct: i, result: "wrong" }]);
364
+ if (a === "guess") {
365
+ if (z <= 0) {
366
+ j(!0), L("wrong");
367
+ const r = o[p].name;
368
+ G((h) => [
369
+ ...h,
370
+ { round: w, answer: H, correct: r, result: "wrong" }
371
+ ]);
335
372
  return;
336
373
  }
337
- const e = setTimeout(() => V((i) => i - 1), 1e3);
374
+ const e = setTimeout(() => E((r) => r - 1), 1e3);
338
375
  return () => clearTimeout(e);
339
376
  }
340
377
  }
341
- }, [u, O, H, A, v, T, w, o, x, S, M]);
342
- const de = () => {
343
- if (x === null || W) return;
344
- const e = o[x].name, i = M.toLowerCase().trim();
345
- let c = "wrong";
346
- i === e ? (L((a) => a + 1), k("correct"), c = "correct") : Se(i, e) === 1 ? (L((a) => a + 0.5), k("almost"), c = "almost") : (k("wrong"), c = "wrong"), E((a) => [...a, { round: S, answer: i, correct: e, result: c }]), _(!0), setTimeout(() => {
347
- _(!1), F(!0);
378
+ }, [a, k, T, z, x, A, R, o, p, w, H]);
379
+ const se = () => {
380
+ if (p === null || D) return;
381
+ const e = o[p].name, r = H.toLowerCase().trim();
382
+ let h = "wrong";
383
+ r === e ? (W((f) => f + 1), L("correct"), h = "correct") : ze(r, e) === 1 ? (W((f) => f + 0.5), L("almost"), h = "almost") : (L("wrong"), h = "wrong"), G((f) => [...f, { round: w, answer: r, correct: e, result: h }]), $(!0), setTimeout(() => {
384
+ $(!1), j(!0);
348
385
  }, 600);
349
- }, ce = () => S < C ? (P((e) => e + 1), ee()) : j(!0), me = () => {
350
- D(!1), j(!1), m(null);
351
- }, ge = fe(
386
+ }, le = () => w < s ? (v((e) => e + 1), Q()) : N(!0), ae = () => {
387
+ C(!1), N(!1), m(null);
388
+ }, de = he(
352
389
  () => (
353
390
  // ensure logo is positioned inside the square container
354
- /* @__PURE__ */ t("div", { style: { ...n.gmLogoFixed, position: "absolute", top: 16, left: 16, zIndex: 30 }, children: /* @__PURE__ */ s("picture", { children: [
391
+ /* @__PURE__ */ t("div", { style: { ...n.gmLogoFixed, position: "absolute", top: 16, left: 16, zIndex: 30 }, children: /* @__PURE__ */ c("picture", { children: [
355
392
  /* @__PURE__ */ t("source", { srcSet: window.origin + "/cloud/speakid/games/whatsmissing/logo.svg", type: "image/svg+xml" }),
356
393
  /* @__PURE__ */ t("img", { src: window.origin + "/cloud/speakid/games/whatsmissing/logo.png", alt: "SPEAKID Logo", style: n.gmLogoImg, loading: "lazy" })
357
394
  ] }) })
@@ -376,115 +413,181 @@ function Me() {
376
413
  "div",
377
414
  {
378
415
  style: {
379
- width: h ? "100%" : R ? `${Math.round(R * b)}px` : `${Math.round(1e3 * b)}px`,
380
- height: h ? "100%" : R ? `${Math.round(R * b)}px` : `${Math.round(1e3 * b)}px`,
416
+ width: b ? "100%" : U || 1e3,
417
+ height: b ? "100%" : U || 1e3,
381
418
  display: "flex",
382
419
  justifyContent: "center",
383
420
  alignItems: "center",
384
421
  overflow: "hidden",
385
- borderRadius: h ? 0 : "20px",
422
+ borderRadius: b ? 0 : "20px",
386
423
  background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
387
- boxShadow: h ? "none" : "0 0 40px rgba(0,0,0,0.1)",
388
- margin: h ? "0 auto" : "unset",
424
+ boxShadow: b ? "none" : "0 0 40px rgba(0,0,0,0.1)",
425
+ margin: b ? "0 auto" : "unset",
389
426
  position: "relative"
427
+ // needed so absolute logo is inside the square
390
428
  },
391
429
  children: /* @__PURE__ */ t(
392
430
  "div",
393
431
  {
394
432
  style: {
395
- transform: b && b !== 1 ? `scale(${1 / b})` : "none",
396
- transformOrigin: "top left",
433
+ transform: "none",
397
434
  width: "100%",
398
435
  height: "100%",
399
436
  display: "flex",
400
437
  justifyContent: "center",
401
438
  alignItems: "center"
402
439
  },
403
- children: /* @__PURE__ */ s("div", { id: "whats-missing-root", children: [
404
- !h && ge,
405
- !d && !v && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
440
+ children: /* @__PURE__ */ c("div", { id: "whats-missing-root", children: [
441
+ !b && de,
442
+ !g && !x && /* @__PURE__ */ c("div", { style: n.gmCenterScreen, children: [
406
443
  /* @__PURE__ */ t("h1", { style: n.gmHeadline1, children: "WHAT'S MISSING?" }),
407
444
  /* @__PURE__ */ t("p", { style: n.gmBodyM, children: "Select a theme:" }),
408
445
  /* @__PURE__ */ t("div", { style: { display: "flex", gap: 16 }, children: ["animals", "food", "toys"].map((e) => /* @__PURE__ */ t("button", { style: n.gmButton, onClick: () => m(e), children: e === "animals" ? "🐶 Animals" : e === "food" ? "🍎 Food" : "🧸 Toys" }, e)) }),
409
- /* @__PURE__ */ s("div", { style: { marginTop: 24 }, children: [
446
+ /* @__PURE__ */ c("div", { style: { marginTop: 24 }, children: [
410
447
  /* @__PURE__ */ t("p", { style: n.gmBodyS, children: "Choose number of rounds:" }),
411
448
  /* @__PURE__ */ t("div", { style: { display: "flex", gap: 12, marginTop: 8 }, children: [3, 4, 5].map((e) => /* @__PURE__ */ t(
412
449
  "button",
413
450
  {
414
- style: { ...n.gmButton, ...C === e ? n.gmButtonActive : {} },
415
- onClick: () => oe(e),
451
+ style: {
452
+ ...n.gmButton,
453
+ ...s === e ? n.gmButtonActive : {}
454
+ },
455
+ onClick: () => F(e),
416
456
  children: e
417
457
  },
418
458
  e
419
459
  )) })
420
460
  ] })
421
461
  ] }),
422
- d && !v && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
423
- /* @__PURE__ */ s("h1", { style: n.gmHeadline1, children: [
462
+ g && !x && /* @__PURE__ */ c("div", { style: n.gmCenterScreen, children: [
463
+ /* @__PURE__ */ c("h1", { style: n.gmHeadline1, children: [
424
464
  "Theme selected: ",
425
- d
465
+ g
426
466
  ] }),
427
- /* @__PURE__ */ s("p", { style: n.gmBodyM, children: [
467
+ /* @__PURE__ */ c("p", { style: n.gmBodyM, children: [
428
468
  "Rounds: ",
429
- C
469
+ s
430
470
  ] }),
431
- /* @__PURE__ */ t("button", { style: n.gmButton, onClick: Q, children: "▶ Start game" })
471
+ /* @__PURE__ */ t("button", { style: n.gmButton, onClick: J, children: "▶ Start game" })
432
472
  ] }),
433
- T && /* @__PURE__ */ s("div", { style: n.gmCenterScreen, children: [
473
+ A && /* @__PURE__ */ c("div", { style: n.gmCenterScreen, children: [
434
474
  /* @__PURE__ */ t("h1", { style: n.gmHeadline1, children: "Results" }),
435
- /* @__PURE__ */ s("h2", { style: n.gmHeadline3, children: [
475
+ /* @__PURE__ */ c("h2", { style: n.gmHeadline3, children: [
436
476
  "Your score: ",
437
- re,
477
+ ne,
438
478
  " / ",
439
- C
479
+ s
440
480
  ] }),
441
481
  /* @__PURE__ */ t("p", { style: { ...n.gmBodyM, color: "#10b981", marginTop: 12 }, children: "Yahoo! You did it! 🍬✨" }),
442
- /* @__PURE__ */ s("table", { style: n.gmTable, children: [
443
- /* @__PURE__ */ t("thead", { children: /* @__PURE__ */ s("tr", { children: [
482
+ /* @__PURE__ */ c("table", { style: n.gmTable, children: [
483
+ /* @__PURE__ */ t("thead", { children: /* @__PURE__ */ c("tr", { children: [
444
484
  /* @__PURE__ */ t("th", { children: "Round" }),
445
485
  /* @__PURE__ */ t("th", { children: "Your Answer" }),
446
486
  /* @__PURE__ */ t("th", { children: "Correct" }),
447
487
  /* @__PURE__ */ t("th", { children: "Result" })
448
488
  ] }) }),
449
- /* @__PURE__ */ t("tbody", { children: se.map((e, i) => /* @__PURE__ */ s("tr", { children: [
489
+ /* @__PURE__ */ t("tbody", { children: oe.map((e, r) => /* @__PURE__ */ c("tr", { children: [
450
490
  /* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.round }),
451
491
  /* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.answer || "—" }),
452
492
  /* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.correct }),
453
493
  /* @__PURE__ */ t("td", { style: n.gmTableCell, children: e.result === "correct" ? "✔ Correct" : e.result === "almost" ? "◐ Almost (0.5)" : "✘ Wrong" })
454
- ] }, i)) })
494
+ ] }, r)) })
455
495
  ] }),
456
- /* @__PURE__ */ s("div", { style: { display: "flex", gap: 12, marginTop: 24 }, children: [
457
- /* @__PURE__ */ t("button", { style: n.gmButton, onClick: Q, children: "🔁 Play again" }),
458
- /* @__PURE__ */ t("button", { style: n.gmButton, onClick: me, children: "⬅️ Choose theme" })
496
+ /* @__PURE__ */ c("div", { style: { display: "flex", gap: 12, marginTop: 24 }, children: [
497
+ /* @__PURE__ */ t("button", { style: n.gmButton, onClick: J, children: "🔁 Play again" }),
498
+ /* @__PURE__ */ t("button", { style: n.gmButton, onClick: ae, children: "⬅️ Choose theme" })
459
499
  ] })
460
500
  ] }),
461
- v && !T && /* @__PURE__ */ s("div", { style: n.gmGameLayout, children: [
462
- /* @__PURE__ */ s("div", { style: { minHeight: 160, display: "flex", flexDirection: "column", justifyContent: "center", alignItems: "center" }, children: [
463
- u === "ready" && /* @__PURE__ */ s(pe, { children: [
464
- /* @__PURE__ */ t("h1", { style: { ...n.gmHeadline1, color: "#ec4c44" }, children: "GET READY" }),
465
- /* @__PURE__ */ t("div", { style: n.gmHourglass, children: "⏳" })
466
- ] }),
467
- u === "memorize" && /* @__PURE__ */ s("p", { style: { ...n.gmBodyM, color: "#10b981" }, children: [
468
- "MEMORIZE (",
469
- H,
470
- ")"
471
- ] }),
472
- u === "guess" && !w && /* @__PURE__ */ s("p", { style: n.gmBodyM, children: [
473
- " Time left: ",
474
- A,
475
- "s"
476
- ] })
477
- ] }),
478
- u !== "ready" && /* @__PURE__ */ t("div", { style: { ...n.gmGrid, gridTemplateColumns: h ? "repeat(2, 1fr)" : "repeat(3, 210px)", gridAutoRows: h ? "150px" : "210px", gap: h ? "12px" : "20px", justifyItems: "center" }, children: o.map((e, i) => {
479
- const c = x === i && u === "guess" && !w;
480
- return /* @__PURE__ */ t("div", { style: { ...n.gmCard, ...K === "correct" && x === i ? n.gmCorrect : {}, ...K === "wrong" && x === i ? n.gmWrong : {} }, children: !c && /* @__PURE__ */ t("img", { src: e.src, alt: e.name, style: { width: "100%", height: "100%", objectFit: "cover" } }) }, i);
481
- }) }),
482
- /* @__PURE__ */ s("div", { style: { marginTop: 16, height: 80 }, children: [
483
- u === "guess" && !w && /* @__PURE__ */ s("div", { children: [
484
- /* @__PURE__ */ t("input", { type: "text", placeholder: "Type the missing word", value: M, onChange: (e) => q(e.target.value), style: n.gmInput }),
485
- /* @__PURE__ */ t("button", { style: { ...n.gmButton, marginLeft: 8 }, onClick: de, disabled: W, children: W ? "..." : "Check" })
501
+ x && !A && /* @__PURE__ */ c("div", { style: n.gmGameLayout, children: [
502
+ /* @__PURE__ */ c(
503
+ "div",
504
+ {
505
+ style: {
506
+ minHeight: 160,
507
+ display: "flex",
508
+ flexDirection: "column",
509
+ justifyContent: "center",
510
+ alignItems: "center"
511
+ },
512
+ children: [
513
+ a === "ready" && /* @__PURE__ */ c(ue, { children: [
514
+ /* @__PURE__ */ t("h1", { style: { ...n.gmHeadline1, color: "#ec4c44" }, children: "GET READY" }),
515
+ /* @__PURE__ */ t("div", { style: n.gmHourglass, children: "⏳" })
516
+ ] }),
517
+ a === "memorize" && /* @__PURE__ */ c("p", { style: { ...n.gmBodyM, color: "#10b981" }, children: [
518
+ "MEMORIZE (",
519
+ T,
520
+ ")"
521
+ ] }),
522
+ a === "guess" && !R && /* @__PURE__ */ c("p", { style: n.gmBodyM, children: [
523
+ " Time left: ",
524
+ z,
525
+ "s"
526
+ ] })
527
+ ]
528
+ }
529
+ ),
530
+ a !== "ready" && /* @__PURE__ */ t(
531
+ "div",
532
+ {
533
+ style: {
534
+ ...n.gmGrid,
535
+ gridTemplateColumns: b ? "repeat(2, 1fr)" : "repeat(3, 210px)",
536
+ gridAutoRows: b ? "150px" : "210px",
537
+ gap: b ? "12px" : "20px",
538
+ justifyItems: "center"
539
+ },
540
+ children: o.map((e, r) => {
541
+ const h = p === r && a === "guess" && !R;
542
+ return /* @__PURE__ */ t(
543
+ "div",
544
+ {
545
+ style: {
546
+ ...n.gmCard,
547
+ ...q === "correct" && p === r ? n.gmCorrect : {},
548
+ ...q === "wrong" && p === r ? n.gmWrong : {}
549
+ },
550
+ children: !h && /* @__PURE__ */ t(
551
+ "img",
552
+ {
553
+ src: e.src,
554
+ alt: e.name,
555
+ style: {
556
+ width: "100%",
557
+ height: "100%",
558
+ objectFit: "cover"
559
+ }
560
+ }
561
+ )
562
+ },
563
+ r
564
+ );
565
+ })
566
+ }
567
+ ),
568
+ /* @__PURE__ */ c("div", { style: { marginTop: 16, height: 80 }, children: [
569
+ a === "guess" && !R && /* @__PURE__ */ c("div", { children: [
570
+ /* @__PURE__ */ t(
571
+ "input",
572
+ {
573
+ type: "text",
574
+ placeholder: "Type the missing word",
575
+ value: H,
576
+ onChange: (e) => Y(e.target.value),
577
+ style: n.gmInput
578
+ }
579
+ ),
580
+ /* @__PURE__ */ t(
581
+ "button",
582
+ {
583
+ style: { ...n.gmButton, marginLeft: 8 },
584
+ onClick: se,
585
+ disabled: D,
586
+ children: D ? "..." : "Check"
587
+ }
588
+ )
486
589
  ] }),
487
- w && /* @__PURE__ */ t("button", { style: n.gmButton, onClick: ce, children: "Next round" })
590
+ R && /* @__PURE__ */ t("button", { type: "button", style: n.gmButton, onClick: le, children: "Next round" })
488
591
  ] })
489
592
  ] })
490
593
  ] })
@@ -497,5 +600,5 @@ function Me() {
497
600
  }
498
601
  export {
499
602
  Me as Game,
500
- ne as themes
603
+ ee as themes
501
604
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mblinkov/whats-missing",
3
- "version": "20.0.19",
3
+ "version": "20.0.21",
4
4
  "main": "dist/whats-missing.umd.js",
5
5
  "module": "dist/whats-missing.es.js",
6
6
  "types": "dist/index.d.ts",
@@ -14,6 +14,7 @@
14
14
  "preview": "vite preview"
15
15
  },
16
16
  "devDependencies": {
17
+ "@types/node": "^24.7.2",
17
18
  "@types/react": "^19.2.2",
18
19
  "@types/react-dom": "^19.2.1",
19
20
  "@vitejs/plugin-react": "^5.0.4",
@@ -25,7 +25,9 @@ export const styles: Record<string, CSSProperties> = {
25
25
  gmCenterScreen: {
26
26
  position: "relative",
27
27
  zIndex: 1,
28
- minHeight: "100vh",
28
+ // use percent so the component fits inside the centered square container
29
+ // (100vh caused overflow on tablets because it measured the viewport, not the container)
30
+ minHeight: "100%",
29
31
  width: "100%",
30
32
  display: "flex",
31
33
  flexDirection: "column",
@@ -100,7 +102,8 @@ export const styles: Record<string, CSSProperties> = {
100
102
  position: "relative",
101
103
  width: "100%",
102
104
  maxWidth: "600px",
103
- minHeight: "100vh",
105
+ // should fill the parent square, not the full viewport
106
+ minHeight: "100%",
104
107
  display: "flex",
105
108
  flexDirection: "column",
106
109
  alignItems: "center",
@@ -203,7 +206,8 @@ export const styles: Record<string, CSSProperties> = {
203
206
  flexDirection: "column",
204
207
  alignItems: "center",
205
208
  justifyContent: "center",
206
- height: "60vh",
209
+ // use percent so the wrapper scales with the container square
210
+ height: "60%",
207
211
  gap: "16px",
208
212
  },
209
213