hangman-react-game 1.0.2 → 1.0.4

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.
@@ -0,0 +1,15 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ declare const Game: () => react_jsx_runtime.JSX.Element;
4
+
5
+ declare const useGame: () => {
6
+ newWord: () => void;
7
+ hasEnded: boolean;
8
+ hasWon: boolean;
9
+ failedAttempts: number;
10
+ guessLetter: (letter: string) => Promise<void>;
11
+ guessedLetters: string[];
12
+ word: string;
13
+ };
14
+
15
+ export { Game, useGame };
package/dist/index.mjs ADDED
@@ -0,0 +1,223 @@
1
+ // src/hooks/useGame.tsx
2
+ import { useEffect, useState } from "react";
3
+ var MAX_FAILED_ATTEMPTS = 10;
4
+ var wordDictionary = [
5
+ "apple",
6
+ "banana",
7
+ "cherry",
8
+ "date",
9
+ "elderberry",
10
+ "fig",
11
+ "grape",
12
+ "honeydew",
13
+ "kiwi",
14
+ "lemon",
15
+ "mango",
16
+ "nectarine",
17
+ "orange",
18
+ "papaya",
19
+ "quince",
20
+ "raspberry",
21
+ "strawberry",
22
+ "tangerine",
23
+ "ugli",
24
+ "vanilla",
25
+ "watermelon",
26
+ "xigua",
27
+ "yellow",
28
+ "zucchini",
29
+ "abstract",
30
+ "breeze",
31
+ "cactus",
32
+ "dolphin",
33
+ "eagle",
34
+ "forest",
35
+ "giraffe",
36
+ "horizon",
37
+ "island",
38
+ "jungle",
39
+ "kaleidoscope",
40
+ "lighthouse",
41
+ "mountain",
42
+ "nebula",
43
+ "ocean",
44
+ "prairie",
45
+ "quasar",
46
+ "rainbow",
47
+ "sunrise",
48
+ "tornado",
49
+ "universe",
50
+ "volcano",
51
+ "whale",
52
+ "xerox",
53
+ "yacht",
54
+ "zephyr",
55
+ "albatross",
56
+ "butterfly",
57
+ "chameleon",
58
+ "dinosaur",
59
+ "elephant",
60
+ "flamingo",
61
+ "gazelle",
62
+ "hippopotamus",
63
+ "iguana",
64
+ "jellyfish",
65
+ "kangaroo",
66
+ "lion",
67
+ "monkey",
68
+ "narwhal",
69
+ "octopus",
70
+ "penguin",
71
+ "quail",
72
+ "rhinoceros",
73
+ "squirrel",
74
+ "turtle",
75
+ "umbrella",
76
+ "vulture",
77
+ "walrus",
78
+ "xylophone",
79
+ "yak",
80
+ "zebra",
81
+ "astronomy",
82
+ "biology",
83
+ "chemistry",
84
+ "democracy",
85
+ "ecosystem",
86
+ "fossil",
87
+ "genetics",
88
+ "hypothesis",
89
+ "innovation",
90
+ "jurisdiction",
91
+ "kinetic",
92
+ "laboratory",
93
+ "meteorology",
94
+ "neuroscience",
95
+ "observation",
96
+ "physics",
97
+ "quantum",
98
+ "robotics",
99
+ "synthesis",
100
+ "theorem",
101
+ "unicorn",
102
+ "velocity",
103
+ "wavelength",
104
+ "xenon",
105
+ "youth",
106
+ "zenith",
107
+ "bamboozlement",
108
+ "flabbergasted",
109
+ "hypothetical",
110
+ "juxtaposition",
111
+ "labyrinthine",
112
+ "nebulousness",
113
+ "quintessential",
114
+ "sesquipedalian",
115
+ "transcendental",
116
+ "unpredictable",
117
+ "verisimilitude",
118
+ "whippersnapper",
119
+ "xenotransplant",
120
+ "yesteryear",
121
+ "zigzaggedness"
122
+ ];
123
+ var useGame = () => {
124
+ const [word, setWord] = useState("");
125
+ const [guessedLetters, setGuessedLetters] = useState([]);
126
+ const [failedAttempts, setFailedAttempts] = useState(0);
127
+ const [hasEnded, setHasEnded] = useState(false);
128
+ const [hasWon, setHasWon] = useState(false);
129
+ const censorWord = (w) => w.split("").map((x) => (guessedLetters.includes(x) || x === " " ? x : "_") + " ").join("");
130
+ const newWord = () => setWord(wordDictionary[Math.floor(Math.random() * wordDictionary.length)]);
131
+ const guessLetter = async (letter) => {
132
+ if (!hasEnded && letter.length === 1) {
133
+ if (!word.includes(letter))
134
+ setFailedAttempts(failedAttempts + 1);
135
+ setGuessedLetters([...guessedLetters, letter]);
136
+ }
137
+ };
138
+ useEffect(() => newWord(), []);
139
+ useEffect(() => {
140
+ setGuessedLetters([]);
141
+ setFailedAttempts(0);
142
+ setHasEnded(false);
143
+ setHasWon(false);
144
+ }, [word]);
145
+ useEffect(() => {
146
+ if (failedAttempts >= MAX_FAILED_ATTEMPTS)
147
+ setHasEnded(true);
148
+ }, [failedAttempts]);
149
+ useEffect(() => {
150
+ if (word && !censorWord(word).includes("_")) {
151
+ setHasWon(true);
152
+ setHasEnded(true);
153
+ }
154
+ }, [guessedLetters]);
155
+ return {
156
+ newWord,
157
+ hasEnded,
158
+ hasWon,
159
+ failedAttempts,
160
+ guessLetter,
161
+ guessedLetters,
162
+ word: hasEnded ? word : censorWord(word)
163
+ };
164
+ };
165
+ var useGame_default = useGame;
166
+
167
+ // src/components/Hangman.tsx
168
+ import { useEffect as useEffect2 } from "react";
169
+ import { jsx } from "react/jsx-runtime";
170
+ var Hangman = ({ failedAttempts }) => {
171
+ useEffect2(() => {
172
+ }, [failedAttempts]);
173
+ const hangmanParts = [
174
+ // ROD
175
+ /* @__PURE__ */ jsx("line", { x1: "20", y1: "230", x2: "100", y2: "230", stroke: "black" }),
176
+ /* @__PURE__ */ jsx("line", { x1: "60", y1: "20", x2: "60", y2: "230", stroke: "black" }),
177
+ /* @__PURE__ */ jsx("line", { x1: "60", y1: "20", x2: "140", y2: "20", stroke: "black" }),
178
+ /* @__PURE__ */ jsx("line", { x1: "140", y1: "20", x2: "140", y2: "50", stroke: "black" }),
179
+ // HEAD
180
+ /* @__PURE__ */ jsx("circle", { cx: "140", cy: "70", r: "20", stroke: "black" }),
181
+ // BODY
182
+ /* @__PURE__ */ jsx("line", { x1: "140", y1: "90", x2: "140", y2: "150", stroke: "black" }),
183
+ // ARMS
184
+ /* @__PURE__ */ jsx("line", { x1: "140", y1: "120", x2: "120", y2: "100", stroke: "black" }),
185
+ /* @__PURE__ */ jsx("line", { x1: "140", y1: "120", x2: "160", y2: "100", stroke: "black" }),
186
+ // LEGS
187
+ /* @__PURE__ */ jsx("line", { x1: "140", y1: "150", x2: "120", y2: "180", stroke: "black" }),
188
+ /* @__PURE__ */ jsx("line", { x1: "140", y1: "150", x2: "160", y2: "180", stroke: "black" })
189
+ ];
190
+ return /* @__PURE__ */ jsx("svg", { height: "250", width: "200", children: hangmanParts.slice(0, failedAttempts) });
191
+ };
192
+ var Hangman_default = Hangman;
193
+
194
+ // src/components/Game.tsx
195
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
196
+ var Game = () => {
197
+ const {
198
+ newWord,
199
+ hasEnded,
200
+ hasWon,
201
+ failedAttempts,
202
+ guessLetter,
203
+ guessedLetters,
204
+ word
205
+ } = useGame_default();
206
+ return /* @__PURE__ */ jsxs("div", { children: [
207
+ /* @__PURE__ */ jsx2("h1", { children: "Hangman game" }),
208
+ /* @__PURE__ */ jsx2("div", { className: "word", children: /* @__PURE__ */ jsx2("p", { children: word }) }),
209
+ /* @__PURE__ */ jsx2("div", { className: "hangman-illustrtion", children: /* @__PURE__ */ jsx2(Hangman_default, { failedAttempts }) }),
210
+ /* @__PURE__ */ jsx2("div", { className: "guessButtons", children: "abcdefghijklmnopqrstuvwxyz".split("").map((x) => /* @__PURE__ */ jsx2("button", { onClick: () => guessLetter(x), disabled: hasEnded || guessedLetters.includes(x), children: x }, x)) }),
211
+ hasEnded && /* @__PURE__ */ jsxs("div", { className: "game-over", children: [
212
+ hasWon && /* @__PURE__ */ jsx2("h1", { children: "Yay, you won" }),
213
+ !hasWon && /* @__PURE__ */ jsx2("h1", { children: "Too bad, you lose" })
214
+ ] }),
215
+ /* @__PURE__ */ jsx2("button", { onClick: newWord, children: "New word" })
216
+ ] });
217
+ };
218
+ var Game_default = Game;
219
+ export {
220
+ Game_default as Game,
221
+ useGame_default as useGame
222
+ };
223
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/useGame.tsx","../src/components/Hangman.tsx","../src/components/Game.tsx"],"sourcesContent":["import {useEffect, useState} from \"react\";\r\n\r\nconst MAX_FAILED_ATTEMPTS = 10;\r\nconst wordDictionary = [\r\n \"apple\",\r\n \"banana\",\r\n \"cherry\",\r\n \"date\",\r\n \"elderberry\",\r\n \"fig\",\r\n \"grape\",\r\n \"honeydew\",\r\n \"kiwi\",\r\n \"lemon\",\r\n \"mango\",\r\n \"nectarine\",\r\n \"orange\",\r\n \"papaya\",\r\n \"quince\",\r\n \"raspberry\",\r\n \"strawberry\",\r\n \"tangerine\",\r\n \"ugli\",\r\n \"vanilla\",\r\n \"watermelon\",\r\n \"xigua\",\r\n \"yellow\",\r\n \"zucchini\",\r\n \"abstract\",\r\n \"breeze\",\r\n \"cactus\",\r\n \"dolphin\",\r\n \"eagle\",\r\n \"forest\",\r\n \"giraffe\",\r\n \"horizon\",\r\n \"island\",\r\n \"jungle\",\r\n \"kaleidoscope\",\r\n \"lighthouse\",\r\n \"mountain\",\r\n \"nebula\",\r\n \"ocean\",\r\n \"prairie\",\r\n \"quasar\",\r\n \"rainbow\",\r\n \"sunrise\",\r\n \"tornado\",\r\n \"universe\",\r\n \"volcano\",\r\n \"whale\",\r\n \"xerox\",\r\n \"yacht\",\r\n \"zephyr\",\r\n \"albatross\",\r\n \"butterfly\",\r\n \"chameleon\",\r\n \"dinosaur\",\r\n \"elephant\",\r\n \"flamingo\",\r\n \"gazelle\",\r\n \"hippopotamus\",\r\n \"iguana\",\r\n \"jellyfish\",\r\n \"kangaroo\",\r\n \"lion\",\r\n \"monkey\",\r\n \"narwhal\",\r\n \"octopus\",\r\n \"penguin\",\r\n \"quail\",\r\n \"rhinoceros\",\r\n \"squirrel\",\r\n \"turtle\",\r\n \"umbrella\",\r\n \"vulture\",\r\n \"walrus\",\r\n \"xylophone\",\r\n \"yak\",\r\n \"zebra\",\r\n \"astronomy\",\r\n \"biology\",\r\n \"chemistry\",\r\n \"democracy\",\r\n \"ecosystem\",\r\n \"fossil\",\r\n \"genetics\",\r\n \"hypothesis\",\r\n \"innovation\",\r\n \"jurisdiction\",\r\n \"kinetic\",\r\n \"laboratory\",\r\n \"meteorology\",\r\n \"neuroscience\",\r\n \"observation\",\r\n \"physics\",\r\n \"quantum\",\r\n \"robotics\",\r\n \"synthesis\",\r\n \"theorem\",\r\n \"unicorn\",\r\n \"velocity\",\r\n \"wavelength\",\r\n \"xenon\",\r\n \"youth\",\r\n \"zenith\",\r\n \"bamboozlement\",\r\n \"flabbergasted\",\r\n \"hypothetical\",\r\n \"juxtaposition\",\r\n \"labyrinthine\",\r\n \"nebulousness\",\r\n \"quintessential\",\r\n \"sesquipedalian\",\r\n \"transcendental\",\r\n \"unpredictable\",\r\n \"verisimilitude\",\r\n \"whippersnapper\",\r\n \"xenotransplant\",\r\n \"yesteryear\",\r\n \"zigzaggedness\"\r\n];\r\n\r\nconst useGame = () => {\r\n // Should fetch random word from a dictionary (maybe vary by language)\r\n const [word, setWord] = useState(\"\");\r\n const [guessedLetters, setGuessedLetters] = useState<string[]>([]);\r\n const [failedAttempts, setFailedAttempts] = useState<number>(0);\r\n const [hasEnded, setHasEnded] = useState(false);\r\n const [hasWon, setHasWon] = useState(false);\r\n\r\n const censorWord = (w: string) => w.split(\"\").map(x => (guessedLetters.includes(x) || x === \" \" ? x : \"_\") + \" \").join(\"\");\r\n const newWord = () => setWord( wordDictionary[Math.floor( Math.random() * wordDictionary.length )]);\r\n \r\n const guessLetter = async (letter : string) => {\r\n if(!hasEnded && letter.length === 1){\r\n if(!word.includes(letter)) \r\n setFailedAttempts(failedAttempts+1);\r\n setGuessedLetters([...guessedLetters, letter]);\r\n }\r\n }\r\n \r\n useEffect(()=> newWord(), [])\r\n useEffect(()=> {\r\n setGuessedLetters([]);\r\n setFailedAttempts(0);\r\n setHasEnded(false);\r\n setHasWon(false);\r\n }, [word]);\r\n \r\n useEffect(()=> {\r\n if(failedAttempts >= MAX_FAILED_ATTEMPTS)\r\n setHasEnded(true);\r\n }, [failedAttempts]);\r\n \r\n useEffect(()=> {\r\n if(word && !censorWord(word).includes(\"_\")) {\r\n setHasWon(true);\r\n setHasEnded(true);\r\n }\r\n }, [guessedLetters]);\r\n\r\n return {\r\n newWord,\r\n hasEnded,\r\n hasWon,\r\n failedAttempts,\r\n guessLetter,\r\n guessedLetters,\r\n word : hasEnded ? word : censorWord(word)\r\n };\r\n}\r\nexport default useGame;","import { ReactElement, useEffect } from \"react\";\r\n\r\ntype HangmanProps = {\r\n failedAttempts: number\r\n}\r\n\r\nconst Hangman = ({failedAttempts} : HangmanProps) => {\r\n useEffect(() => {}, [failedAttempts]);\r\n const hangmanParts : ReactElement[] = [\r\n // ROD\r\n <line x1=\"20\" y1=\"230\" x2=\"100\" y2=\"230\" stroke=\"black\" />,\r\n <line x1=\"60\" y1=\"20\" x2=\"60\" y2=\"230\" stroke=\"black\" />,\r\n <line x1=\"60\" y1=\"20\" x2=\"140\" y2=\"20\" stroke=\"black\" />,\r\n <line x1=\"140\" y1=\"20\" x2=\"140\" y2=\"50\" stroke=\"black\" />,\r\n // HEAD\r\n <circle cx=\"140\" cy=\"70\" r=\"20\" stroke=\"black\" />,\r\n // BODY\r\n <line x1=\"140\" y1=\"90\" x2=\"140\" y2=\"150\" stroke=\"black\" />,\r\n // ARMS\r\n <line x1=\"140\" y1=\"120\" x2=\"120\" y2=\"100\" stroke=\"black\" />,\r\n <line x1=\"140\" y1=\"120\" x2=\"160\" y2=\"100\" stroke=\"black\" />,\r\n // LEGS\r\n <line x1=\"140\" y1=\"150\" x2=\"120\" y2=\"180\" stroke=\"black\" />,\r\n <line x1=\"140\" y1=\"150\" x2=\"160\" y2=\"180\" stroke=\"black\" />\r\n ];\r\n return (\r\n <svg height=\"250\" width=\"200\">\r\n {hangmanParts.slice(0, failedAttempts)}\r\n </svg>\r\n )\r\n}\r\nexport default Hangman;","import useGame from \"../hooks/useGame\";\r\nimport Hangman from \"./Hangman\";\r\n\r\nconst Game = () => {\r\n const {\r\n newWord,\r\n hasEnded,\r\n hasWon,\r\n failedAttempts,\r\n guessLetter,\r\n guessedLetters,\r\n word \r\n } = useGame();\r\n return (\r\n <div>\r\n <h1>Hangman game</h1>\r\n <div className=\"word\">\r\n <p>{word}</p>\r\n </div>\r\n <div className=\"hangman-illustrtion\">\r\n <Hangman failedAttempts={failedAttempts} />\r\n </div>\r\n <div className=\"guessButtons\">\r\n {\"abcdefghijklmnopqrstuvwxyz\".split(\"\").map(x => (\r\n <button key={x} onClick={() => guessLetter(x)} disabled={hasEnded || guessedLetters.includes(x)}>{x}</button>\r\n ))}\r\n </div>\r\n {hasEnded && (\r\n <div className=\"game-over\">\r\n {hasWon && (<h1>Yay, you won</h1>)}\r\n {!hasWon && (<h1>Too bad, you lose</h1>)}\r\n </div>\r\n )}\r\n <button onClick={newWord}>New word</button>\r\n </div>\r\n )\r\n};\r\nexport default Game;"],"mappings":";AAAA,SAAQ,WAAW,gBAAe;AAElC,IAAM,sBAAsB;AAC5B,IAAM,iBAAiB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;A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","names":["useEffect","jsx"]}
package/package.json CHANGED
@@ -1,29 +1,31 @@
1
1
  {
2
2
  "name": "hangman-react-game",
3
- "version": "1.0.2",
4
- "main": "dist/index.cjs",
5
- "module": "dist/index.mjs",
3
+ "version": "1.0.4",
4
+ "main": "dist/index.js",
5
+ "module": "dist/index.js",
6
+ "types": "dist/types/index.d.ts",
6
7
  "exports": {
7
8
  ".": {
8
- "import": "./dist/index.mjs",
9
- "require": "./dist/index.cjs"
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/types/index.d.ts"
10
11
  }
11
12
  },
12
13
  "scripts": {
13
- "build": "rollup -c"
14
+ "build": "tsup"
14
15
  },
15
16
  "peerDependencies": {
16
17
  "react": "^19.0.0",
17
18
  "react-dom": "^19.0.0"
18
19
  },
19
20
  "devDependencies": {
20
- "@babel/core": "^7.20.0",
21
- "@babel/preset-env": "^7.20.0",
22
- "@babel/preset-react": "^7.18.6",
23
21
  "@rollup/plugin-babel": "^6.0.3",
24
- "@rollup/plugin-node-resolve": "^15.0.1",
25
22
  "@rollup/plugin-commonjs": "^24.0.1",
26
- "rollup": "^3.29.0"
23
+ "@rollup/plugin-node-resolve": "^15.0.1",
24
+ "@types/react": "^19.1.13",
25
+ "@types/react-dom": "^19.1.9",
26
+ "rollup": "^3.29.0",
27
+ "tsup": "^8.5.0",
28
+ "typescript": "^5.9.2"
27
29
  },
28
30
  "author": "Isak Hølleland",
29
31
  "license": "MIT"
@@ -1,5 +1,5 @@
1
- import useGame from "../hooks/useGame.jsx";
2
- import Hangman from "./Hangman.jsx";
1
+ import useGame from "../hooks/useGame";
2
+ import Hangman from "./Hangman";
3
3
 
4
4
  const Game = () => {
5
5
  const {
@@ -1,8 +1,12 @@
1
- import { useEffect } from "react";
1
+ import { ReactElement, useEffect } from "react";
2
2
 
3
- const Hangman = ({failedAttempts}) => {
3
+ type HangmanProps = {
4
+ failedAttempts: number
5
+ }
6
+
7
+ const Hangman = ({failedAttempts} : HangmanProps) => {
4
8
  useEffect(() => {}, [failedAttempts]);
5
- const hangmanParts = [
9
+ const hangmanParts : ReactElement[] = [
6
10
  // ROD
7
11
  <line x1="20" y1="230" x2="100" y2="230" stroke="black" />,
8
12
  <line x1="60" y1="20" x2="60" y2="230" stroke="black" />,
@@ -18,10 +22,10 @@ const Hangman = ({failedAttempts}) => {
18
22
  // LEGS
19
23
  <line x1="140" y1="150" x2="120" y2="180" stroke="black" />,
20
24
  <line x1="140" y1="150" x2="160" y2="180" stroke="black" />
21
- ].subarray(0, failedAttempts)
25
+ ];
22
26
  return (
23
27
  <svg height="250" width="200">
24
- {hangmanParts}
28
+ {hangmanParts.slice(0, failedAttempts)}
25
29
  </svg>
26
30
  )
27
31
  }
@@ -124,15 +124,15 @@ const wordDictionary = [
124
124
  const useGame = () => {
125
125
  // Should fetch random word from a dictionary (maybe vary by language)
126
126
  const [word, setWord] = useState("");
127
- const [guessedLetters, setGuessedLetters] = useState([]);
128
- const [failedAttempts, setFailedAttempts] = useState(0);
127
+ const [guessedLetters, setGuessedLetters] = useState<string[]>([]);
128
+ const [failedAttempts, setFailedAttempts] = useState<number>(0);
129
129
  const [hasEnded, setHasEnded] = useState(false);
130
130
  const [hasWon, setHasWon] = useState(false);
131
131
 
132
- const censorWord = (w) => w.split("").map(x => (guessedLetters.includes(x) || x === " " ? x : "_") + " ").join("");
132
+ const censorWord = (w: string) => w.split("").map(x => (guessedLetters.includes(x) || x === " " ? x : "_") + " ").join("");
133
133
  const newWord = () => setWord( wordDictionary[Math.floor( Math.random() * wordDictionary.length )]);
134
134
 
135
- const guessLetter = async (letter) => {
135
+ const guessLetter = async (letter : string) => {
136
136
  if(!hasEnded && letter.length === 1){
137
137
  if(!word.includes(letter))
138
138
  setFailedAttempts(failedAttempts+1);
package/src/index.tsx ADDED
@@ -0,0 +1,4 @@
1
+ import Game from "./components/Game";
2
+ import useGame from "./hooks/useGame";
3
+
4
+ export {Game, useGame};
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "jsx": "react-jsx",
6
+ "declaration": true,
7
+ "declarationDir": "dist/types",
8
+ "outDir": "dist",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "moduleResolution": "node"
13
+ },
14
+ "include": ["src"]
15
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.tsx'],
5
+ format: ['esm'],
6
+ dts: true,
7
+ sourcemap: true,
8
+ clean: true,
9
+ external: ['react', 'react-dom'],
10
+ });
package/.babelrc DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "presets": ["@babel/preset-env", "@babel/preset-react"]
3
- }