@mblinkov/whats-missing 20.0.26 → 20.0.28
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 +219 -192
- package/package.json +1 -1
- package/src/Game.tsx +247 -211
package/package.json
CHANGED
package/src/Game.tsx
CHANGED
|
@@ -37,7 +37,7 @@ const levenshtein = (a: string, b: string) => {
|
|
|
37
37
|
return dp[a.length][b.length];
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
// ✅ фикс визуального подзума
|
|
40
|
+
// ✅ фикс визуального подзума
|
|
41
41
|
export function useNeutralizeBodyZoom(
|
|
42
42
|
ref: React.RefObject<HTMLDivElement | null>,
|
|
43
43
|
opts: { minDesktopWidth?: number; forceResize?: boolean } = { minDesktopWidth: 1200, forceResize: false }
|
|
@@ -58,7 +58,6 @@ export function useNeutralizeBodyZoom(
|
|
|
58
58
|
if (zoomInline && !isNaN(zoomInline) && zoomInline > 0) return zoomInline;
|
|
59
59
|
const zoomComputed = parseFloat((cs.zoom as string) || "");
|
|
60
60
|
if (zoomComputed && !isNaN(zoomComputed) && zoomComputed > 0) return zoomComputed;
|
|
61
|
-
|
|
62
61
|
const probe = document.createElement("div");
|
|
63
62
|
probe.style.position = "absolute";
|
|
64
63
|
probe.style.left = "0";
|
|
@@ -66,7 +65,6 @@ export function useNeutralizeBodyZoom(
|
|
|
66
65
|
probe.style.width = "100px";
|
|
67
66
|
probe.style.height = "1px";
|
|
68
67
|
probe.style.visibility = "hidden";
|
|
69
|
-
probe.style.pointerEvents = "none";
|
|
70
68
|
document.documentElement.appendChild(probe);
|
|
71
69
|
const rect = probe.getBoundingClientRect();
|
|
72
70
|
document.documentElement.removeChild(probe);
|
|
@@ -270,7 +268,10 @@ export default function Game({
|
|
|
270
268
|
setAnswered(true);
|
|
271
269
|
setResult("wrong");
|
|
272
270
|
const correct = files[hiddenIndex!].name;
|
|
273
|
-
setResultsTable((prev) => [
|
|
271
|
+
setResultsTable((prev) => [
|
|
272
|
+
...prev,
|
|
273
|
+
{ round: currentRound, answer: inputValue, correct, result: "wrong" },
|
|
274
|
+
]);
|
|
274
275
|
return;
|
|
275
276
|
}
|
|
276
277
|
const t = setTimeout(() => setTimeLeft((s) => s - 1), 1000);
|
|
@@ -303,7 +304,8 @@ export default function Game({
|
|
|
303
304
|
}, 600);
|
|
304
305
|
};
|
|
305
306
|
|
|
306
|
-
const nextRound = () =>
|
|
307
|
+
const nextRound = () =>
|
|
308
|
+
currentRound < rounds ? (setCurrentRound((r) => r + 1), startRound()) : setFinished(true);
|
|
307
309
|
|
|
308
310
|
const exitGame = () => {
|
|
309
311
|
setStarted(false);
|
|
@@ -315,14 +317,33 @@ export default function Game({
|
|
|
315
317
|
() => (
|
|
316
318
|
<div style={{ ...styles.gmLogoFixed, position: "absolute", top: 16, left: 16, zIndex: 30 }}>
|
|
317
319
|
<picture>
|
|
318
|
-
<source
|
|
319
|
-
|
|
320
|
+
<source
|
|
321
|
+
srcSet={window.origin + "/cloud/speakid/games/whatsmissing/logo.svg"}
|
|
322
|
+
type="image/svg+xml"
|
|
323
|
+
/>
|
|
324
|
+
<img
|
|
325
|
+
src={window.origin + "/cloud/speakid/games/whatsmissing/logo.png"}
|
|
326
|
+
alt="SPEAKID Logo"
|
|
327
|
+
style={styles.gmLogoImg}
|
|
328
|
+
loading="lazy"
|
|
329
|
+
/>
|
|
320
330
|
</picture>
|
|
321
331
|
</div>
|
|
322
332
|
),
|
|
323
333
|
[]
|
|
324
334
|
);
|
|
325
335
|
|
|
336
|
+
// ✅ масштаб интерфейса под реальное разрешение
|
|
337
|
+
const baseWidth = 1440;
|
|
338
|
+
const baseHeight = 900;
|
|
339
|
+
const scale =
|
|
340
|
+
typeof window !== "undefined"
|
|
341
|
+
? Math.min(
|
|
342
|
+
(screenWidth ?? window.innerWidth) / baseWidth,
|
|
343
|
+
(screenHeight ?? window.innerHeight) / baseHeight
|
|
344
|
+
)
|
|
345
|
+
: 1;
|
|
346
|
+
|
|
326
347
|
return (
|
|
327
348
|
<div
|
|
328
349
|
ref={containerRef}
|
|
@@ -333,241 +354,256 @@ export default function Game({
|
|
|
333
354
|
justifyContent: "center",
|
|
334
355
|
alignItems: "center",
|
|
335
356
|
background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
|
|
336
|
-
transition: "background 0.3s ease",
|
|
337
357
|
overflow: "hidden",
|
|
338
358
|
zIndex: 1,
|
|
339
|
-
pointerEvents: "auto",
|
|
340
359
|
}}
|
|
341
360
|
>
|
|
342
361
|
<div
|
|
343
362
|
ref={squareRef}
|
|
344
363
|
style={{
|
|
345
|
-
width:
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
alignItems: "center",
|
|
352
|
-
overflow: "hidden",
|
|
364
|
+
width: isMobile
|
|
365
|
+
? "100%"
|
|
366
|
+
: `${Math.min(gameCubeSize ?? 1000, screenWidth ?? 1000, screenHeight ?? 1000)}px`,
|
|
367
|
+
height: isMobile
|
|
368
|
+
? "100%"
|
|
369
|
+
: `${Math.min(gameCubeSize ?? 1000, screenWidth ?? 1000, screenHeight ?? 1000)}px`,
|
|
353
370
|
borderRadius: isMobile ? 0 : "20px",
|
|
354
371
|
background: "linear-gradient(to bottom, #fff8f8 0%, #f9fafb 100%)",
|
|
355
|
-
boxShadow: isMobile ? "none" : "0 0 40px rgba(0,0,0,0.08)",
|
|
356
372
|
position: "relative",
|
|
373
|
+
overflow: "hidden",
|
|
374
|
+
boxShadow: isMobile ? "none" : "0 0 40px rgba(0,0,0,0.08)",
|
|
375
|
+
display: "flex",
|
|
376
|
+
justifyContent: "center",
|
|
377
|
+
alignItems: "center",
|
|
357
378
|
}}
|
|
358
379
|
>
|
|
359
380
|
<div
|
|
381
|
+
id="whats-missing-root"
|
|
360
382
|
style={{
|
|
361
|
-
transform:
|
|
362
|
-
transformOrigin: "
|
|
363
|
-
width:
|
|
364
|
-
height:
|
|
383
|
+
transform: `scale(${scale})`,
|
|
384
|
+
transformOrigin: "center center",
|
|
385
|
+
width: `${100 / scale}%`,
|
|
386
|
+
height: `${100 / scale}%`,
|
|
365
387
|
display: "flex",
|
|
388
|
+
flexDirection: "column",
|
|
366
389
|
justifyContent: "center",
|
|
367
390
|
alignItems: "center",
|
|
368
391
|
}}
|
|
369
392
|
>
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
{
|
|
375
|
-
<
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
{
|
|
380
|
-
|
|
381
|
-
|
|
393
|
+
{!isMobile && MemoizedLogo}
|
|
394
|
+
|
|
395
|
+
{/* ====== ЛОББИ ====== */}
|
|
396
|
+
{!theme && !started && (
|
|
397
|
+
<div style={styles.gmCenterScreen}>
|
|
398
|
+
<h1 style={styles.gmHeadline1}>WHAT'S MISSING?</h1>
|
|
399
|
+
<p style={styles.gmBodyM}>Select a theme:</p>
|
|
400
|
+
<div style={{ display: "flex", gap: 16 }}>
|
|
401
|
+
{["animals", "food", "toys"].map((t) => (
|
|
402
|
+
<button key={t} style={styles.gmButton} onClick={() => setTheme(t as Theme)}>
|
|
403
|
+
{t === "animals" ? "🐶 Animals" : t === "food" ? "🍎 Food" : "🧸 Toys"}
|
|
404
|
+
</button>
|
|
405
|
+
))}
|
|
406
|
+
</div>
|
|
407
|
+
<div style={{ marginTop: 24 }}>
|
|
408
|
+
<p style={styles.gmBodyS}>Choose number of rounds:</p>
|
|
409
|
+
<div style={{ display: "flex", gap: 12, marginTop: 8 }}>
|
|
410
|
+
{[3, 4, 5].map((n) => (
|
|
411
|
+
<button
|
|
412
|
+
key={n}
|
|
413
|
+
style={{
|
|
414
|
+
...styles.gmButton,
|
|
415
|
+
...(rounds === n ? styles.gmButtonActive : {}),
|
|
416
|
+
}}
|
|
417
|
+
onClick={() => setRounds(n)}
|
|
418
|
+
>
|
|
419
|
+
{n}
|
|
382
420
|
</button>
|
|
383
421
|
))}
|
|
384
422
|
</div>
|
|
385
|
-
<div style={{ marginTop: 24 }}>
|
|
386
|
-
<p style={styles.gmBodyS}>Choose number of rounds:</p>
|
|
387
|
-
<div style={{ display: "flex", gap: 12, marginTop: 8 }}>
|
|
388
|
-
{[3, 4, 5].map((n) => (
|
|
389
|
-
<button
|
|
390
|
-
key={n}
|
|
391
|
-
style={{
|
|
392
|
-
...styles.gmButton,
|
|
393
|
-
...(rounds === n ? styles.gmButtonActive : {}),
|
|
394
|
-
}}
|
|
395
|
-
onClick={() => setRounds(n)}
|
|
396
|
-
>
|
|
397
|
-
{n}
|
|
398
|
-
</button>
|
|
399
|
-
))}
|
|
400
|
-
</div>
|
|
401
|
-
</div>
|
|
402
423
|
</div>
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
424
|
+
</div>
|
|
425
|
+
)}
|
|
426
|
+
|
|
427
|
+
{/* ====== ПОДТВЕРЖДЕНИЕ ====== */}
|
|
428
|
+
{theme && !started && (
|
|
429
|
+
<div style={styles.gmCenterScreen}>
|
|
430
|
+
<h1 style={styles.gmHeadline1}>Theme selected: {theme}</h1>
|
|
431
|
+
<p style={styles.gmBodyM}>Rounds: {rounds}</p>
|
|
432
|
+
<button style={styles.gmButton} onClick={startGame}>
|
|
433
|
+
▶ Start game
|
|
434
|
+
</button>
|
|
435
|
+
</div>
|
|
436
|
+
)}
|
|
437
|
+
|
|
438
|
+
{/* ====== РЕЗУЛЬТАТЫ ====== */}
|
|
439
|
+
{finished && (
|
|
440
|
+
<div style={styles.gmCenterScreen}>
|
|
441
|
+
<h1 style={styles.gmHeadline1}>Results</h1>
|
|
442
|
+
<h2 style={styles.gmHeadline3}>
|
|
443
|
+
Your score: {score} / {rounds}
|
|
444
|
+
</h2>
|
|
445
|
+
<p style={{ ...styles.gmBodyM, color: "#10b981", marginTop: 12 }}>
|
|
446
|
+
Yahoo! You did it! 🍬✨
|
|
447
|
+
</p>
|
|
448
|
+
<table style={styles.gmTable}>
|
|
449
|
+
<thead>
|
|
450
|
+
<tr>
|
|
451
|
+
<th>Round</th>
|
|
452
|
+
<th>Your Answer</th>
|
|
453
|
+
<th>Correct</th>
|
|
454
|
+
<th>Result</th>
|
|
455
|
+
</tr>
|
|
456
|
+
</thead>
|
|
457
|
+
<tbody>
|
|
458
|
+
{resultsTable.map((r, i) => (
|
|
459
|
+
<tr key={i}>
|
|
460
|
+
<td style={styles.gmTableCell}>{r.round}</td>
|
|
461
|
+
<td style={styles.gmTableCell}>{r.answer || "—"}</td>
|
|
462
|
+
<td style={styles.gmTableCell}>{r.correct}</td>
|
|
463
|
+
<td style={styles.gmTableCell}>
|
|
464
|
+
{r.result === "correct"
|
|
465
|
+
? "✔ Correct"
|
|
466
|
+
: r.result === "almost"
|
|
467
|
+
? "◐ Almost (0.5)"
|
|
468
|
+
: "✘ Wrong"}
|
|
469
|
+
</td>
|
|
470
|
+
</tr>
|
|
471
|
+
))}
|
|
472
|
+
</tbody>
|
|
473
|
+
</table>
|
|
474
|
+
<div style={{ display: "flex", gap: 12, marginTop: 24 }}>
|
|
410
475
|
<button style={styles.gmButton} onClick={startGame}>
|
|
411
|
-
|
|
476
|
+
🔁 Play again
|
|
477
|
+
</button>
|
|
478
|
+
<button style={styles.gmButton} onClick={exitGame}>
|
|
479
|
+
⬅️ Choose theme
|
|
412
480
|
</button>
|
|
413
481
|
</div>
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
</
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
? "◐ Almost (0.5)"
|
|
444
|
-
: "✘ Wrong"}
|
|
445
|
-
</td>
|
|
446
|
-
</tr>
|
|
447
|
-
))}
|
|
448
|
-
</tbody>
|
|
449
|
-
</table>
|
|
450
|
-
<div style={{ display: "flex", gap: 12, marginTop: 24 }}>
|
|
451
|
-
<button style={styles.gmButton} onClick={startGame}>
|
|
452
|
-
🔁 Play again
|
|
453
|
-
</button>
|
|
454
|
-
<button style={styles.gmButton} onClick={exitGame}>
|
|
455
|
-
⬅️ Choose theme
|
|
456
|
-
</button>
|
|
457
|
-
</div>
|
|
482
|
+
</div>
|
|
483
|
+
)}
|
|
484
|
+
|
|
485
|
+
{/* ====== ИГРОВОЙ ЭКРАН ====== */}
|
|
486
|
+
{started && !finished && (
|
|
487
|
+
<div style={styles.gmGameLayout}>
|
|
488
|
+
<div
|
|
489
|
+
style={{
|
|
490
|
+
minHeight: 160,
|
|
491
|
+
display: "flex",
|
|
492
|
+
flexDirection: "column",
|
|
493
|
+
justifyContent: "center",
|
|
494
|
+
alignItems: "center",
|
|
495
|
+
}}
|
|
496
|
+
>
|
|
497
|
+
{phase === "ready" && (
|
|
498
|
+
<>
|
|
499
|
+
<h1 style={{ ...styles.gmHeadline1, color: "#ec4c44" }}>GET READY</h1>
|
|
500
|
+
<div style={styles.gmHourglass}>⏳</div>
|
|
501
|
+
</>
|
|
502
|
+
)}
|
|
503
|
+
{phase === "memorize" && (
|
|
504
|
+
<p style={{ ...styles.gmBodyM, color: "#10b981" }}>
|
|
505
|
+
MEMORIZE ({memorizeTime})
|
|
506
|
+
</p>
|
|
507
|
+
)}
|
|
508
|
+
{phase === "guess" && !answered && (
|
|
509
|
+
<p style={styles.gmBodyM}>⏳ Time left: {timeLeft}s</p>
|
|
510
|
+
)}
|
|
458
511
|
</div>
|
|
459
|
-
)}
|
|
460
|
-
|
|
461
|
-
{/* ====== ИГРОВОЙ ЭКРАН ====== */}
|
|
462
|
-
{started && !finished && (
|
|
463
|
-
<div style={styles.gmGameLayout}>
|
|
464
|
-
<div
|
|
465
|
-
style={{
|
|
466
|
-
minHeight: 160,
|
|
467
|
-
display: "flex",
|
|
468
|
-
flexDirection: "column",
|
|
469
|
-
justifyContent: "center",
|
|
470
|
-
alignItems: "center",
|
|
471
|
-
}}
|
|
472
|
-
>
|
|
473
|
-
{phase === "ready" && (
|
|
474
|
-
<>
|
|
475
|
-
<h1 style={{ ...styles.gmHeadline1, color: "#ec4c44" }}>GET READY</h1>
|
|
476
|
-
<div style={styles.gmHourglass}>⏳</div>
|
|
477
|
-
</>
|
|
478
|
-
)}
|
|
479
|
-
{phase === "memorize" && (
|
|
480
|
-
<p style={{ ...styles.gmBodyM, color: "#10b981" }}>
|
|
481
|
-
MEMORIZE ({memorizeTime})
|
|
482
|
-
</p>
|
|
483
|
-
)}
|
|
484
|
-
{phase === "guess" && !answered && (
|
|
485
|
-
<p style={styles.gmBodyM}>⏳ Time left: {timeLeft}s</p>
|
|
486
|
-
)}
|
|
487
|
-
</div>
|
|
488
512
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
513
|
+
{/* Сетка карточек */}
|
|
514
|
+
{phase !== "ready" && (() => {
|
|
515
|
+
const gap = isMobile ? 12 : 20;
|
|
516
|
+
const innerGutters = 32;
|
|
517
|
+
const effective = Math.min(
|
|
518
|
+
squareRef.current?.clientWidth ?? gameCubeSize ?? 1000,
|
|
519
|
+
squareRef.current?.clientHeight ?? screenHeight ?? 1000,
|
|
520
|
+
screenWidth ?? 1000
|
|
521
|
+
);
|
|
522
|
+
const columns = isMobile ? 2 : 3;
|
|
523
|
+
const cardSize = Math.max(
|
|
524
|
+
90,
|
|
525
|
+
Math.floor((effective - innerGutters - gap * (columns - 1)) / columns)
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
return (
|
|
529
|
+
<div
|
|
530
|
+
style={{
|
|
531
|
+
...styles.gmGrid,
|
|
532
|
+
gridTemplateColumns: `repeat(${columns}, ${cardSize}px)`,
|
|
533
|
+
gridAutoRows: `${cardSize}px`,
|
|
534
|
+
gap: `${gap}px`,
|
|
535
|
+
justifyContent: "center",
|
|
536
|
+
justifyItems: "center",
|
|
537
|
+
padding: 8,
|
|
538
|
+
boxSizing: "border-box",
|
|
539
|
+
}}
|
|
540
|
+
>
|
|
541
|
+
{files.map((file, i) => {
|
|
542
|
+
const isHidden = hiddenIndex === i && phase === "guess" && !answered;
|
|
543
|
+
return (
|
|
544
|
+
<div
|
|
545
|
+
key={i}
|
|
546
|
+
style={{
|
|
547
|
+
...styles.gmCard,
|
|
548
|
+
width: `${cardSize}px`,
|
|
549
|
+
height: `${cardSize}px`,
|
|
550
|
+
padding: isMobile ? 8 : 10,
|
|
551
|
+
boxSizing: "border-box",
|
|
552
|
+
...(result === "correct" && hiddenIndex === i
|
|
553
|
+
? styles.gmCorrect
|
|
554
|
+
: {}),
|
|
555
|
+
...(result === "wrong" && hiddenIndex === i
|
|
556
|
+
? styles.gmWrong
|
|
557
|
+
: {}),
|
|
558
|
+
}}
|
|
559
|
+
>
|
|
560
|
+
{!isHidden && (
|
|
561
|
+
<img
|
|
562
|
+
src={file.src}
|
|
563
|
+
alt={file.name}
|
|
564
|
+
style={{
|
|
565
|
+
width: "100%",
|
|
566
|
+
height: "100%",
|
|
567
|
+
objectFit: "cover",
|
|
568
|
+
display: "block",
|
|
569
|
+
}}
|
|
570
|
+
/>
|
|
571
|
+
)}
|
|
572
|
+
</div>
|
|
573
|
+
);
|
|
574
|
+
})}
|
|
575
|
+
</div>
|
|
576
|
+
);
|
|
577
|
+
})()}
|
|
578
|
+
|
|
579
|
+
{/* Инпут и кнопки */}
|
|
580
|
+
<div style={{ marginTop: 16, height: 80 }}>
|
|
581
|
+
{phase === "guess" && !answered && (
|
|
582
|
+
<div>
|
|
583
|
+
<input
|
|
584
|
+
type="text"
|
|
585
|
+
placeholder="Type the missing word"
|
|
586
|
+
value={inputValue}
|
|
587
|
+
onChange={(e) => setInputValue(e.target.value)}
|
|
588
|
+
style={styles.gmInput}
|
|
589
|
+
/>
|
|
590
|
+
<button
|
|
591
|
+
style={{ ...styles.gmButton, marginLeft: 8 }}
|
|
592
|
+
onClick={checkAnswer}
|
|
593
|
+
disabled={animating}
|
|
512
594
|
>
|
|
513
|
-
{
|
|
514
|
-
const isHidden = hiddenIndex === i && phase === "guess" && !answered;
|
|
515
|
-
return (
|
|
516
|
-
<div
|
|
517
|
-
key={i}
|
|
518
|
-
style={{
|
|
519
|
-
...styles.gmCard,
|
|
520
|
-
width: `${cardSize}px`,
|
|
521
|
-
height: `${cardSize}px`,
|
|
522
|
-
padding: isMobile ? 8 : 10,
|
|
523
|
-
boxSizing: "border-box",
|
|
524
|
-
...(result === "correct" && hiddenIndex === i ? styles.gmCorrect : {}),
|
|
525
|
-
...(result === "wrong" && hiddenIndex === i ? styles.gmWrong : {}),
|
|
526
|
-
}}
|
|
527
|
-
>
|
|
528
|
-
{!isHidden && (
|
|
529
|
-
<img
|
|
530
|
-
src={file.src}
|
|
531
|
-
alt={file.name}
|
|
532
|
-
style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }}
|
|
533
|
-
/>
|
|
534
|
-
)}
|
|
535
|
-
</div>
|
|
536
|
-
);
|
|
537
|
-
})}
|
|
538
|
-
</div>
|
|
539
|
-
);
|
|
540
|
-
})()}
|
|
541
|
-
|
|
542
|
-
{/* Инпут и кнопки */}
|
|
543
|
-
<div style={{ marginTop: 16, height: 80 }}>
|
|
544
|
-
{phase === "guess" && !answered && (
|
|
545
|
-
<div>
|
|
546
|
-
<input
|
|
547
|
-
type="text"
|
|
548
|
-
placeholder="Type the missing word"
|
|
549
|
-
value={inputValue}
|
|
550
|
-
onChange={(e) => setInputValue(e.target.value)}
|
|
551
|
-
style={styles.gmInput}
|
|
552
|
-
/>
|
|
553
|
-
<button
|
|
554
|
-
style={{ ...styles.gmButton, marginLeft: 8 }}
|
|
555
|
-
onClick={checkAnswer}
|
|
556
|
-
disabled={animating}
|
|
557
|
-
>
|
|
558
|
-
{animating ? "..." : "Check"}
|
|
559
|
-
</button>
|
|
560
|
-
</div>
|
|
561
|
-
)}
|
|
562
|
-
{answered && (
|
|
563
|
-
<button type="button" style={styles.gmButton} onClick={nextRound}>
|
|
564
|
-
Next round
|
|
595
|
+
{animating ? "..." : "Check"}
|
|
565
596
|
</button>
|
|
566
|
-
|
|
567
|
-
|
|
597
|
+
</div>
|
|
598
|
+
)}
|
|
599
|
+
{answered && (
|
|
600
|
+
<button type="button" style={styles.gmButton} onClick={nextRound}>
|
|
601
|
+
Next round
|
|
602
|
+
</button>
|
|
603
|
+
)}
|
|
568
604
|
</div>
|
|
569
|
-
|
|
570
|
-
|
|
605
|
+
</div>
|
|
606
|
+
)}
|
|
571
607
|
</div>
|
|
572
608
|
</div>
|
|
573
609
|
</div>
|