@jeremyckahn/farmhand 1.23.2 → 1.23.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.
Files changed (169) hide show
  1. package/README.md +5 -0
  2. package/dist/assets/index-4ynbl-GC.js +392 -0
  3. package/dist/assets/index-4ynbl-GC.js.map +1 -0
  4. package/dist/assets/index-CaYdR-lC.css +1 -0
  5. package/dist/assets/jersey-10-latin-400-normal-DrL73VYW.woff2 +0 -0
  6. package/dist/assets/jersey-10-latin-ext-400-normal-uIKqQSaG.woff2 +0 -0
  7. package/dist/assets/jersey-20-latin-400-normal-bNi78tgO.woff2 +0 -0
  8. package/dist/assets/jersey-20-latin-ext-400-normal-BO3lmWef.woff2 +0 -0
  9. package/dist/assets/jersey-25-latin-400-normal-BuYJnnt7.woff2 +0 -0
  10. package/dist/assets/jersey-25-latin-ext-400-normal-CP5Jl3WN.woff2 +0 -0
  11. package/dist/index.html +2 -2
  12. package/dist/service-worker.js +1 -1
  13. package/dist/service-worker.js.map +1 -1
  14. package/package.json +7 -12
  15. package/src/common/services/randomNumber.test.ts +61 -1
  16. package/src/common/services/randomNumber.ts +36 -1
  17. package/src/common/utils.ts +22 -13
  18. package/src/components/AccountingView/AccountingView.tsx +7 -13
  19. package/src/components/Achievement/Achievement.tsx +2 -15
  20. package/src/components/AchievementsView/AchievementsView.tsx +2 -7
  21. package/src/components/AnimatedNumber/AnimatedNumber.tsx +0 -6
  22. package/src/components/AppBar/AppBar.tsx +21 -17
  23. package/src/components/Cellar/Cellar.tsx +0 -2
  24. package/src/components/Cellar/CellarInventoryTabPanel.tsx +0 -6
  25. package/src/components/Cellar/FermentationTabPanel.tsx +0 -6
  26. package/src/components/Cellar/Keg.tsx +0 -5
  27. package/src/components/Cellar/TabPanel/index.tsx +0 -7
  28. package/src/components/Cellar/WinemakingTabPanel.tsx +0 -6
  29. package/src/components/ContextPane/ContextPane.tsx +0 -6
  30. package/src/components/CowCard/Bloodline/Bloodline.tsx +0 -6
  31. package/src/components/CowCard/CowCard.tsx +7 -39
  32. package/src/components/CowCard/Subheader/Subheader.tsx +21 -44
  33. package/src/components/CowPen/Cow.tsx +5 -11
  34. package/src/components/CowPen/CowPen.test.tsx +4 -4
  35. package/src/components/CowPen/CowPen.tsx +5 -16
  36. package/src/components/CowPenContextMenu/CowPenContextMenu.tsx +2 -18
  37. package/src/components/CowPenContextMenu/TabPanel/index.tsx +0 -7
  38. package/src/components/Farmhand/Farmhand.context.tsx +4 -3
  39. package/src/components/Farmhand/Farmhand.tsx +11 -15
  40. package/src/components/Farmhand/FarmhandReducers.tsx +1 -2
  41. package/src/components/Farmhand/FarmhandService.test.ts +6 -9
  42. package/src/components/Farmhand/hooks/useFarmhandDayAdvancement.ts +2 -6
  43. package/src/components/Farmhand/hooks/useFarmhandNetwork.test.ts +2 -2
  44. package/src/components/Farmhand/hooks/useFarmhandNetwork.ts +15 -31
  45. package/src/components/Farmhand/useFarmhand.test.ts +7 -5
  46. package/src/components/Farmhand/useFarmhand.ts +24 -15
  47. package/src/components/FermentationRecipeList/FermentationRecipe.tsx +0 -5
  48. package/src/components/FermentationRecipeList/FermentationRecipeList.test.tsx +10 -11
  49. package/src/components/FermentationRecipeList/FermentationRecipeList.tsx +2 -3
  50. package/src/components/Field/Field.tsx +15 -50
  51. package/src/components/Forest/Forest.tsx +10 -7
  52. package/src/components/ForestPlot/ForestPlot.tsx +5 -5
  53. package/src/components/ForestQuickSelect/ForestQuickSelect.tsx +0 -12
  54. package/src/components/Home/Home.tsx +2 -7
  55. package/src/components/Home/SnowBackground.tsx +1 -1
  56. package/src/components/IngredientsList/IngredientsList.tsx +0 -7
  57. package/src/components/Inventory/Inventory.test.tsx +4 -4
  58. package/src/components/Inventory/Inventory.tsx +5 -12
  59. package/src/components/Item/Item.tsx +11 -29
  60. package/src/components/ItemList/ItemList.tsx +4 -11
  61. package/src/components/KeybindingsView/KeybindingsView.tsx +0 -2
  62. package/src/components/LogView/LogView.tsx +6 -28
  63. package/src/components/Navigation/DayAndProgressContainer.tsx +0 -8
  64. package/src/components/Navigation/Navigation.tsx +12 -33
  65. package/src/components/NotificationSystem/NotificationSystem.test.tsx +45 -3
  66. package/src/components/NotificationSystem/NotificationSystem.tsx +45 -32
  67. package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.test.tsx +2 -2
  68. package/src/components/OnlinePeersView/OnlinePeer/OnlinePeer.tsx +0 -11
  69. package/src/components/OnlinePeersView/OnlinePeersView.tsx +0 -10
  70. package/src/components/PixelIcon/createPixelIcon.test.tsx +59 -0
  71. package/src/components/PixelIcon/createPixelIcon.tsx +97 -0
  72. package/src/components/PixelIcon/icons.ts +445 -0
  73. package/src/components/PixelIcon/index.ts +3 -0
  74. package/src/components/Plot/Plot.tsx +3 -3
  75. package/src/components/PriceEventView/PriceEventView.tsx +0 -6
  76. package/src/components/ProgressBar/ProgressBar.tsx +9 -8
  77. package/src/components/QuantityInput/QuantityInput.tsx +6 -11
  78. package/src/components/QuickSelect/QuickSelect.tsx +0 -10
  79. package/src/components/Recipe/Recipe.tsx +0 -9
  80. package/src/components/RecipeList/RecipeList.tsx +0 -6
  81. package/src/components/SearchBar/SearchBar.tsx +4 -10
  82. package/src/components/SettingsView/RandomSeedInput.test.tsx +2 -4
  83. package/src/components/SettingsView/RandomSeedInput.tsx +5 -8
  84. package/src/components/SettingsView/SettingsView.test.tsx +21 -0
  85. package/src/components/SettingsView/SettingsView.tsx +24 -18
  86. package/src/components/Shop/Shop.tsx +0 -20
  87. package/src/components/Shop/TabPanel/index.tsx +0 -7
  88. package/src/components/Stage/Stage.tsx +11 -20
  89. package/src/components/StatsView/StatsView.tsx +0 -18
  90. package/src/components/TierPurchase/TierPurchase.tsx +0 -12
  91. package/src/components/Toolbelt/Toolbelt.tsx +5 -10
  92. package/src/components/UpdateNotifier/UpdateNotifier.tsx +33 -5
  93. package/src/components/UpgradePurchase/UpgradePurchase.tsx +0 -10
  94. package/src/components/WineRecipeList/WineRecipe.test.tsx +2 -2
  95. package/src/components/WineRecipeList/WineRecipe.tsx +0 -5
  96. package/src/components/WineRecipeList/WineRecipeList.tsx +2 -3
  97. package/src/components/Workshop/ForgeTabPanel.tsx +0 -8
  98. package/src/components/Workshop/KitchenTabPanel.tsx +0 -7
  99. package/src/components/Workshop/RecyclingTabPanel.tsx +0 -7
  100. package/src/components/Workshop/TabPanel/index.tsx +0 -7
  101. package/src/components/Workshop/WoodChipperTabPanel.tsx +0 -7
  102. package/src/components/Workshop/Workshop.tsx +0 -9
  103. package/src/components/Workshop/getUpgradesAvailable.ts +1 -1
  104. package/src/constants.ts +18 -13
  105. package/src/data/crops/grape.ts +13 -15
  106. package/src/data/maps.test.ts +3 -4
  107. package/src/data/maps.ts +27 -29
  108. package/src/enums.ts +47 -19
  109. package/src/factories/OreFactory.ts +2 -1
  110. package/src/farmhand.d.ts +6 -3
  111. package/src/game-logic/reducers/applyPrecipitation.ts +4 -4
  112. package/src/game-logic/reducers/generatePriceEvents.ts +6 -3
  113. package/src/game-logic/reducers/harvestForestPlot.ts +1 -2
  114. package/src/game-logic/reducers/makeFermentationRecipe.ts +2 -3
  115. package/src/game-logic/reducers/minePlot.test.ts +2 -2
  116. package/src/game-logic/reducers/minePlot.ts +1 -1
  117. package/src/game-logic/reducers/processCowFertilizerProduction.test.ts +16 -14
  118. package/src/game-logic/reducers/processFeedingCows.test.ts +2 -5
  119. package/src/game-logic/reducers/purchaseCow.ts +2 -7
  120. package/src/game-logic/reducers/showNotification.test.ts +20 -0
  121. package/src/game-logic/reducers/showNotification.ts +4 -2
  122. package/src/game-logic/reducers/updateAchievements.ts +1 -1
  123. package/src/game-logic/reducers/updateFinancialRecords.test.ts +21 -25
  124. package/src/game-logic/reducers/updateFinancialRecords.ts +2 -5
  125. package/src/game-logic/reducers/updateInventoryRecordsForNextDay.test.ts +12 -14
  126. package/src/handlers/ui-events.test.ts +44 -42
  127. package/src/handlers/ui-events.tsx +18 -3
  128. package/src/hooks/usePrefersReducedMotion.ts +10 -6
  129. package/src/index.tsx +0 -2
  130. package/src/mui-theme.ts +258 -37
  131. package/src/scripts/generate-crop-table.ts +3 -2
  132. package/src/setupTests.ts +18 -12
  133. package/src/strings.ts +1 -1
  134. package/src/styles/fonts.ts +73 -0
  135. package/src/styles/pixel.ts +151 -0
  136. package/src/styles/sx.ts +46 -33
  137. package/src/styles/tokens.ts +11 -0
  138. package/src/test-utils/index.ts +1 -0
  139. package/src/utils/chooseRandom.ts +4 -1
  140. package/src/utils/chooseRandomIndex.ts +6 -2
  141. package/src/utils/getCowImage.ts +22 -27
  142. package/src/utils/getMaxYieldOfFermentationRecipe.ts +2 -2
  143. package/src/utils/getPeerMetadata.ts +1 -1
  144. package/src/utils/getPlotImage.test.ts +14 -14
  145. package/src/utils/getPlotImage.ts +10 -10
  146. package/src/utils/getRandomUnlockedCrop.ts +5 -3
  147. package/src/utils/getRandomizedLifespan.test.ts +2 -8
  148. package/src/utils/getValueAdjustmentStream.test.ts +9 -0
  149. package/src/utils/getValueAdjustmentStream.ts +5 -0
  150. package/src/utils/isItemAFarmProduct.ts +2 -2
  151. package/src/utils/shouldPrecipitateToday.ts +3 -1
  152. package/src/utils/shouldStormToday.ts +2 -1
  153. package/src/utils/transformStateDataForImport.ts +3 -5
  154. package/dist/assets/francois-one-latin-400-normal-DD1rFI7H.woff2 +0 -0
  155. package/dist/assets/francois-one-latin-400-normal-DNXs7uOx.woff +0 -0
  156. package/dist/assets/francois-one-latin-ext-400-normal-CwRdWRZD.woff2 +0 -0
  157. package/dist/assets/francois-one-latin-ext-400-normal-JvkpT0Av.woff +0 -0
  158. package/dist/assets/francois-one-vietnamese-400-normal-BLIKeG5Y.woff2 +0 -0
  159. package/dist/assets/francois-one-vietnamese-400-normal-CuWeHlXs.woff +0 -0
  160. package/dist/assets/index-CNcrTYN-.css +0 -1
  161. package/dist/assets/index-DNPchtK9.js +0 -844
  162. package/dist/assets/index-DNPchtK9.js.map +0 -1
  163. package/dist/assets/public-sans-latin-400-normal-8Rpg0ruU.woff2 +0 -0
  164. package/dist/assets/public-sans-latin-400-normal-SBbinRkI.woff +0 -0
  165. package/dist/assets/public-sans-latin-ext-400-normal-B02wwOdZ.woff +0 -0
  166. package/dist/assets/public-sans-latin-ext-400-normal-mk90oQqJ.woff2 +0 -0
  167. package/dist/assets/public-sans-vietnamese-400-normal-BO1meqcx.woff +0 -0
  168. package/dist/assets/public-sans-vietnamese-400-normal-TxZB8OSn.woff2 +0 -0
  169. package/src/fontsource.d.ts +0 -3
@@ -1,7 +1,5 @@
1
1
  import { useEffect, useRef, useState } from 'react'
2
2
 
3
- import { faMars, faVenus } from '@fortawesome/free-solid-svg-icons'
4
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
5
3
  import Button from '@mui/material/Button/index.js'
6
4
  import Card from '@mui/material/Card/index.js'
7
5
  import CardActions from '@mui/material/CardActions/index.js'
@@ -10,7 +8,6 @@ import TextField from '@mui/material/TextField/index.js'
10
8
  import Tooltip from '@mui/material/Tooltip/index.js'
11
9
  import Typography from '@mui/material/Typography/index.js'
12
10
  import classNames from 'classnames'
13
- import { array, bool, func, number, object, string } from 'prop-types'
14
11
  import { useIsMounted } from 'usehooks-ts'
15
12
 
16
13
  import { PURCHASEABLE_COW_PENS } from '../../constants.js'
@@ -29,13 +26,14 @@ import { isCowInBreedingPen } from '../../utils/isCowInBreedingPen.js'
29
26
  import { isInViewport } from '../../utils/isInViewport.js'
30
27
  import { A } from '../Elements/index.js'
31
28
  import FarmhandContext, { BoundHandlers } from '../Farmhand/Farmhand.context.js'
29
+ import { FemaleIcon, MaleIcon } from '../PixelIcon/index.js'
32
30
 
33
31
  import Subheader from './Subheader/index.js'
34
32
 
35
33
  const genderIcons = {
36
- [genders.FEMALE as string]: faVenus,
37
- [genders.MALE as string]: faMars,
38
- } as Record<string, typeof faVenus>
34
+ [genders.FEMALE as string]: FemaleIcon,
35
+ [genders.MALE as string]: MaleIcon,
36
+ } as Record<string, typeof FemaleIcon>
39
37
 
40
38
  export interface CowCardProps {
41
39
  allowCustomPeerCowNames: farmhand.state['allowCustomPeerCowNames']
@@ -157,6 +155,8 @@ export const CowCard = ({
157
155
  }
158
156
  }, [isSelected])
159
157
 
158
+ const GenderIcon = genderIcons[cow.gender]
159
+
160
160
  return (
161
161
  <>
162
162
  <A
@@ -233,11 +233,7 @@ export const CowCard = ({
233
233
  ) : (
234
234
  displayName
235
235
  )}{' '}
236
- <FontAwesomeIcon
237
- {...{
238
- icon: genderIcons[cow.gender],
239
- }}
240
- />
236
+ <GenderIcon fontSize="inherit" />
241
237
  </>
242
238
  ),
243
239
  subheader: (
@@ -279,7 +275,6 @@ export const CowCard = ({
279
275
  {canCowBeTradedFor && (
280
276
  <Tooltip
281
277
  {...{
282
- arrow: true,
283
278
  placement: 'top',
284
279
  title: 'The game will be saved when the trade is completed.',
285
280
  }}
@@ -312,7 +307,6 @@ export const CowCard = ({
312
307
  (cowIdOfferedForTrade === cow.id ? (
313
308
  <Tooltip
314
309
  {...{
315
- arrow: true,
316
310
  placement: 'top',
317
311
  title: WITHDRAW_COW_FROM_TRADE('', cowDisplayName),
318
312
  }}
@@ -333,7 +327,6 @@ export const CowCard = ({
333
327
  ) : (
334
328
  <Tooltip
335
329
  {...{
336
- arrow: true,
337
330
  placement: 'top',
338
331
  title: (
339
332
  <Typography>
@@ -374,31 +367,6 @@ export const CowCard = ({
374
367
  )
375
368
  }
376
369
 
377
- CowCard.propTypes = {
378
- allowCustomPeerCowNames: bool.isRequired,
379
- cow: object.isRequired,
380
- cowBreedingPen: object.isRequired,
381
- cowIdOfferedForTrade: string.isRequired,
382
- cowInventory: array.isRequired,
383
- debounced: object,
384
- handleCowAutomaticHugChange: func,
385
- handleCowBreedChange: func,
386
- handleCowHugClick: func,
387
- handleCowNameInputChange: func,
388
- handleCowOfferClick: func,
389
- handleCowPurchaseClick: func,
390
- handleCowWithdrawClick: func,
391
- handleCowSellClick: func,
392
- handleCowTradeClick: func,
393
- playerId: string.isRequired,
394
- inventory: array.isRequired,
395
- isCowOfferedForTradeByPeer: bool,
396
- isOnline: bool.isRequired,
397
- isSelected: bool,
398
- money: number.isRequired,
399
- purchasedCowPen: number.isRequired,
400
- }
401
-
402
370
  export default function Consumer(
403
371
  props: Pick<CowCardProps, 'cow' | 'isCowOfferedForTradeByPeer' | 'isSelected'>
404
372
  ) {
@@ -1,12 +1,8 @@
1
- import { faHeart as faEmptyHeart } from '@fortawesome/free-regular-svg-icons'
2
- import { faHeart as faFullHeart } from '@fortawesome/free-solid-svg-icons'
3
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
4
1
  import Checkbox from '@mui/material/Checkbox/index.js'
5
2
  import FormControlLabel from '@mui/material/FormControlLabel/index.js'
6
3
  import Tooltip from '@mui/material/Tooltip/index.js'
7
4
  import Typography from '@mui/material/Typography/index.js'
8
5
  import classNames from 'classnames'
9
- import { array, bool, func, object, string } from 'prop-types'
10
6
 
11
7
  import { huggingMachine } from '../../../data/items.js'
12
8
  import { genders } from '../../../enums.js'
@@ -19,6 +15,7 @@ import { isCowInBreedingPen } from '../../../utils/isCowInBreedingPen.js'
19
15
  import { memoize } from '../../../utils/memoize.js'
20
16
  import { moneyString } from '../../../utils/moneyString.js'
21
17
  import { nullArray } from '../../../utils/nullArray.js'
18
+ import { HeartIcon, HeartOutlineIcon } from '../../PixelIcon/index.js'
22
19
  import Bloodline from '../Bloodline/index.js'
23
20
  import { CowCardProps } from '../CowCard.js'
24
21
 
@@ -37,18 +34,17 @@ const getCowMapById = memoize((cowInventory: farmhand.state['cowInventory']) =>
37
34
  )
38
35
  )
39
36
 
40
- export interface SubheaderProps
41
- extends Pick<
42
- CowCardProps,
43
- | 'cow'
44
- | 'cowBreedingPen'
45
- | 'cowIdOfferedForTrade'
46
- | 'cowInventory'
47
- | 'handleCowAutomaticHugChange'
48
- | 'handleCowBreedChange'
49
- | 'huggingMachinesRemain'
50
- | 'playerId'
51
- > {
37
+ export interface SubheaderProps extends Pick<
38
+ CowCardProps,
39
+ | 'cow'
40
+ | 'cowBreedingPen'
41
+ | 'cowIdOfferedForTrade'
42
+ | 'cowInventory'
43
+ | 'handleCowAutomaticHugChange'
44
+ | 'handleCowBreedChange'
45
+ | 'huggingMachinesRemain'
46
+ | 'playerId'
47
+ > {
52
48
  canCowBeTradedFor: boolean
53
49
  cowValue: number
54
50
  isCowPurchased: boolean
@@ -116,25 +112,20 @@ const Subheader = ({
116
112
  <ol className="hearts">
117
113
  {nullArray(10).map((_null: null, i: number) => (
118
114
  <li key={`${cow.id}_${i}`}>
119
- <FontAwesomeIcon
120
- {...{
121
- icon: isHeartFull(i, numberOfFullHearts)
122
- ? faFullHeart
123
- : faEmptyHeart,
124
- color: isHeartFull(i, numberOfFullHearts)
125
- ? colors.heart
126
- : undefined,
127
- className: classNames('heart', {
128
- 'is-full': isHeartFull(i, numberOfFullHearts),
129
- }),
130
- }}
131
- />
115
+ {isHeartFull(i, numberOfFullHearts) ? (
116
+ <HeartIcon
117
+ className="heart is-full"
118
+ fontSize="inherit"
119
+ htmlColor={colors.heart}
120
+ />
121
+ ) : (
122
+ <HeartOutlineIcon className="heart" fontSize="inherit" />
123
+ )}
132
124
  </li>
133
125
  ))}
134
126
  </ol>
135
127
  <Tooltip
136
128
  {...{
137
- arrow: true,
138
129
  placement: 'top',
139
130
  title: (
140
131
  <Typography>
@@ -165,7 +156,6 @@ const Subheader = ({
165
156
  </Tooltip>
166
157
  <Tooltip
167
158
  {...{
168
- arrow: true,
169
159
  placement: 'top',
170
160
  disableFocusListener: disableBreedingControlTooltip,
171
161
  disableHoverListener: disableBreedingControlTooltip,
@@ -210,16 +200,3 @@ const Subheader = ({
210
200
  }
211
201
 
212
202
  export default Subheader
213
-
214
- Subheader.propTypes = {
215
- canCowBeTradedFor: bool.isRequired,
216
- cow: object.isRequired,
217
- cowBreedingPen: object.isRequired,
218
- cowIdOfferedForTrade: string.isRequired,
219
- cowInventory: array.isRequired,
220
- handleCowAutomaticHugChange: func,
221
- handleCowBreedChange: func,
222
- huggingMachinesRemain: bool.isRequired,
223
- playerId: string.isRequired,
224
- isCowPurchased: bool,
225
- }
@@ -1,5 +1,3 @@
1
- import { faHeart } from '@fortawesome/free-solid-svg-icons'
2
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
3
1
  import Tooltip from '@mui/material/Tooltip/index.js'
4
2
  import Typography from '@mui/material/Typography/index.js'
5
3
  import classNames from 'classnames'
@@ -12,6 +10,7 @@ import { LEFT, RIGHT } from '../../constants.js'
12
10
  import { pixel } from '../../img/index.js'
13
11
  import { getCowDisplayName } from '../../utils/getCowDisplayName.js'
14
12
  import { getCowImage } from '../../utils/getCowImage.js'
13
+ import { HeartIcon } from '../PixelIcon/index.js'
15
14
 
16
15
  // Only moves the cow within the middle 80% of the pen
17
16
  const randomPosition = () => 10 + random() * 80
@@ -249,7 +248,6 @@ export const Cow = ({
249
248
  )}
250
249
  <Tooltip
251
250
  {...{
252
- arrow: true,
253
251
  placement: 'top',
254
252
  title: <Typography>{cowDisplayName}</Typography>,
255
253
  open: isSelected,
@@ -265,12 +263,12 @@ export const Cow = ({
265
263
  }}
266
264
  alt={cowDisplayName}
267
265
  />
268
- <FontAwesomeIcon
266
+ <HeartIcon
269
267
  {...{
270
- className: classNames('animation', {
268
+ className: classNames('heart-icon', 'animation', {
271
269
  'is-animating': showHugAnimation,
272
270
  }),
273
- icon: faHeart,
271
+ fontSize: 'inherit',
274
272
  }}
275
273
  />
276
274
  </div>
@@ -278,11 +276,7 @@ export const Cow = ({
278
276
  <ol {...{ className: 'happiness-boosts-today' }}>
279
277
  {new Array(cow.happinessBoostsToday).fill(undefined).map((_, i) => (
280
278
  <li {...{ key: i }}>
281
- <FontAwesomeIcon
282
- {...{
283
- icon: faHeart,
284
- }}
285
- />
279
+ <HeartIcon className="heart-icon" fontSize="inherit" />
286
280
  </li>
287
281
  ))}
288
282
  </ol>
@@ -94,7 +94,7 @@ describe('Cow', () => {
94
94
 
95
95
  render(<Cow {...defaultCowProps} cow={happyCow} />)
96
96
 
97
- expect(document.querySelector('.fa-heart')).toBeInTheDocument()
97
+ expect(document.querySelector('.heart-icon')).toBeInTheDocument()
98
98
  })
99
99
 
100
100
  test('does not show happiness indicator when cow is not happy', () => {
@@ -214,7 +214,7 @@ describe('Cow', () => {
214
214
  />
215
215
  )
216
216
 
217
- const heart = () => container.querySelector('.fa-heart.animation')
217
+ const heart = () => container.querySelector('.heart-icon.animation')
218
218
 
219
219
  rerender(
220
220
  <Cow
@@ -234,7 +234,7 @@ describe('Cow', () => {
234
234
  />
235
235
  )
236
236
 
237
- const heart = () => container.querySelector('.fa-heart.animation')
237
+ const heart = () => container.querySelector('.heart-icon.animation')
238
238
 
239
239
  rerender(
240
240
  <Cow
@@ -258,7 +258,7 @@ describe('Cow', () => {
258
258
  />
259
259
  )
260
260
 
261
- const heart = () => container.querySelector('.fa-heart.animation')
261
+ const heart = () => container.querySelector('.heart-icon.animation')
262
262
 
263
263
  // Midnight: the daily reset brings the boost count back down.
264
264
  rerender(
@@ -1,5 +1,4 @@
1
1
  import { Theme } from '@mui/material/styles/index.js'
2
- import { array, bool, func, string } from 'prop-types'
3
2
  import { useEffect } from 'react'
4
3
 
5
4
  import { fillSx } from '../../styles/sx.js'
@@ -10,11 +9,10 @@ import FarmhandContext from '../Farmhand/Farmhand.context.js'
10
9
  import { Cow } from './Cow.js'
11
10
  import { Tumbleweeds } from './Tumbleweeds.js'
12
11
 
13
- export interface CowPenProps
14
- extends Pick<
15
- farmhand.state,
16
- 'allowCustomPeerCowNames' | 'cowInventory' | 'playerId' | 'selectedCowId'
17
- > {
12
+ export interface CowPenProps extends Pick<
13
+ farmhand.state,
14
+ 'allowCustomPeerCowNames' | 'cowInventory' | 'playerId' | 'selectedCowId'
15
+ > {
18
16
  handleCowPenUnmount: () => void
19
17
  handleCowClick: (cow: farmhand.cow) => void
20
18
  }
@@ -72,7 +70,7 @@ export const CowPen = ({
72
70
  easing: theme.transitions.easing.easeOut,
73
71
  }),
74
72
  },
75
- '& .fa-heart': {
73
+ '& .heart-icon': {
76
74
  color: colors.heart,
77
75
  '&.animation': {
78
76
  opacity: 0,
@@ -170,15 +168,6 @@ export const CowPen = ({
170
168
  )
171
169
  }
172
170
 
173
- CowPen.propTypes = {
174
- allowCustomPeerCowNames: bool.isRequired,
175
- cowInventory: array.isRequired,
176
- handleCowClick: func.isRequired,
177
- handleCowPenUnmount: func.isRequired,
178
- playerId: string.isRequired,
179
- selectedCowId: string.isRequired,
180
- }
181
-
182
171
  export default function Consumer(props: Partial<CowPenProps>) {
183
172
  return (
184
173
  <FarmhandContext.Consumer>
@@ -1,14 +1,13 @@
1
- import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward.js'
2
- import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward.js'
3
1
  import Fab from '@mui/material/Fab/index.js'
4
2
  import MenuItem from '@mui/material/MenuItem/index.js'
5
3
  import Select from '@mui/material/Select/index.js'
6
4
  import Tab from '@mui/material/Tab/index.js'
7
5
  import Tabs from '@mui/material/Tabs/index.js'
8
6
  import sortBy from 'lodash.sortby'
9
- import { array, func, number, object, string } from 'prop-types'
10
7
  import { useEffect, useState } from 'react'
11
8
 
9
+ import { ArrowDownwardIcon, ArrowUpwardIcon } from '../PixelIcon/index.js'
10
+
12
11
  import { PURCHASEABLE_COW_PENS } from '../../constants.js'
13
12
  import cowShopInventory from '../../data/shop-inventory-cow.js'
14
13
  import uiEventHandlers from '../../handlers/ui-events.js'
@@ -327,21 +326,6 @@ export const CowPenContextMenu = ({
327
326
  )
328
327
  }
329
328
 
330
- CowPenContextMenu.propTypes = {
331
- cowForSale: object.isRequired,
332
- cowInventory: array.isRequired,
333
- handleCowAutomaticHugChange: func.isRequired,
334
- handleCowBreedChange: func.isRequired,
335
- handleCowHugClick: func.isRequired,
336
- handleCowNameInputChange: func.isRequired,
337
- handleCowOfferClick: func.isRequired,
338
- handleCowSelect: func.isRequired,
339
- handleCowSellClick: func.isRequired,
340
- handleCowWithdrawClick: func.isRequired,
341
- purchasedCowPen: number.isRequired,
342
- selectedCowId: string.isRequired,
343
- }
344
-
345
329
  export default function Consumer() {
346
330
  return (
347
331
  <FarmhandContext.Consumer>
@@ -1,5 +1,4 @@
1
1
  import React from 'react'
2
- import { node, number } from 'prop-types'
3
2
 
4
3
  export const TabPanel = (
5
4
  props: React.PropsWithChildren<
@@ -21,12 +20,6 @@ export const TabPanel = (
21
20
  )
22
21
  }
23
22
 
24
- TabPanel.propTypes = {
25
- children: node,
26
- index: number.isRequired,
27
- value: number.isRequired,
28
- }
29
-
30
23
  export const a11yProps = (index: number) => ({
31
24
  id: `cow-context-tab-${index}`,
32
25
  'aria-controls': `cow-context-tabpanel-${index}`,
@@ -12,6 +12,7 @@ import {
12
12
  import uiEventHandlers from '../../handlers/ui-events.js'
13
13
  import { generateCow } from '../../utils/generateCow.js'
14
14
  import { scarecrow } from '../../data/items.js'
15
+ import { NOTIFICATION_DURATION_DEFAULT } from '../../constants.js'
15
16
 
16
17
  /**
17
18
  * A utility type that transforms a type containing functions with an explicit `this` parameter
@@ -159,6 +160,7 @@ export const createContextData = (): ContextData => {
159
160
  latestNotification: null,
160
161
  newDayNotifications: [],
161
162
  notificationLog: [],
163
+ notificationDuration: NOTIFICATION_DURATION_DEFAULT,
162
164
  peers: {}, // empty object for now
163
165
  peerRoom: null,
164
166
  pendingPeerMessages: [],
@@ -217,8 +219,7 @@ export const createContextData = (): ContextData => {
217
219
  }
218
220
  }
219
221
 
220
- const FarmhandContext: import('react').Context<ContextData> = createContext<
221
- ContextData
222
- >(createContextData())
222
+ const FarmhandContext: import('react').Context<ContextData> =
223
+ createContext<ContextData>(createContextData())
223
224
 
224
225
  export default FarmhandContext
@@ -1,7 +1,3 @@
1
- import HotelIcon from '@mui/icons-material/Hotel.js'
2
- import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft.js'
3
- import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight.js'
4
- import MenuIcon from '@mui/icons-material/Menu.js'
5
1
  import CssBaseline from '@mui/material/CssBaseline/index.js'
6
2
  import Drawer from '@mui/material/Drawer/index.js'
7
3
  import Fab from '@mui/material/Fab/index.js'
@@ -11,10 +7,16 @@ import Tooltip from '@mui/material/Tooltip/index.js'
11
7
  import classNames from 'classnames'
12
8
  import localforage from 'localforage'
13
9
  import { SnackbarProvider } from 'notistack'
14
- import { object } from 'prop-types'
15
10
  import { GlobalHotKeys } from 'react-hotkeys'
16
11
  import { Redirect } from 'react-router-dom'
17
12
 
13
+ import {
14
+ HotelIcon,
15
+ KeyboardArrowLeftIcon as KeyboardArrowLeft,
16
+ KeyboardArrowRightIcon as KeyboardArrowRight,
17
+ MenuIcon,
18
+ } from '../PixelIcon/index.js'
19
+
18
20
  import { Z_INDEX } from '../../constants.js'
19
21
  import theme, { blueStripeBg } from '../../mui-theme.js'
20
22
  import { Div } from '../Elements/index.js'
@@ -103,9 +105,10 @@ const Farmhand = (props: FarmhandProps) => {
103
105
  pointerEvents: 'none',
104
106
  },
105
107
  }),
106
- [`@media (min-width: ${breakpoints.smallPhone}px) and (orientation: landscape)`]: {
107
- paddingTop: '3em',
108
- },
108
+ [`@media (min-width: ${breakpoints.smallPhone}px) and (orientation: landscape)`]:
109
+ {
110
+ paddingTop: '3em',
111
+ },
109
112
  [`@media (min-width: ${breakpoints.sm}px)`]: {
110
113
  paddingTop: '4em',
111
114
  },
@@ -282,11 +285,4 @@ Farmhand.defaultProps = {
282
285
  match: { path: '', params: {} },
283
286
  }
284
287
 
285
- Farmhand.propTypes = {
286
- features: object,
287
- history: object,
288
- location: object,
289
- match: object.isRequired,
290
- }
291
-
292
288
  export default Farmhand
@@ -193,8 +193,7 @@ export class FarmhandReducers extends Component<FarmhandProps, FarmhandState> {
193
193
 
194
194
  for (const reducerName of reducerNames) {
195
195
  const reducer = reducers[reducerName as keyof typeof reducers] as
196
- | ((state: farmhand.state, ...args: any[]) => farmhand.state)
197
- | undefined
196
+ ((state: farmhand.state, ...args: any[]) => farmhand.state) | undefined
198
197
 
199
198
  if (!reducer) {
200
199
  if (import.meta.env?.MODE === 'development') {
@@ -50,9 +50,8 @@ describe('FarmhandService', () => {
50
50
  { id: 'carrot-seed', quantity: 1 },
51
51
  { id: 'weed', quantity: 1 },
52
52
  ]
53
- const plantableCropInventory = FarmhandService.getPlantableCropInventory(
54
- inventory
55
- )
53
+ const plantableCropInventory =
54
+ FarmhandService.getPlantableCropInventory(inventory)
56
55
 
57
56
  expect(plantableCropInventory).toEqual([{ ...carrotSeed, quantity: 1 }])
58
57
  })
@@ -64,9 +63,8 @@ describe('FarmhandService', () => {
64
63
  { id: 'apple-sapling', quantity: 1 },
65
64
  { id: 'weed', quantity: 1 },
66
65
  ]
67
- const plantableTreeInventory = FarmhandService.getPlantableTreeInventory(
68
- inventory
69
- )
66
+ const plantableTreeInventory =
67
+ FarmhandService.getPlantableTreeInventory(inventory)
70
68
 
71
69
  expect(plantableTreeInventory).toEqual([{ ...appleSapling, quantity: 1 }])
72
70
  })
@@ -76,9 +74,8 @@ describe('FarmhandService', () => {
76
74
  { id: 'apple-sapling', quantity: 1 },
77
75
  { id: 'not-a-real-item-id', quantity: 1 },
78
76
  ]
79
- const plantableTreeInventory = FarmhandService.getPlantableTreeInventory(
80
- inventory
81
- )
77
+ const plantableTreeInventory =
78
+ FarmhandService.getPlantableTreeInventory(inventory)
82
79
 
83
80
  expect(plantableTreeInventory).toEqual([{ ...appleSapling, quantity: 1 }])
84
81
  })
@@ -50,12 +50,8 @@ export const useFarmhandDayAdvancement = (
50
50
  let serverValueAdjustments: Record<string, number> | undefined
51
51
 
52
52
  if (stateRef.current.isOnline) {
53
- const {
54
- inventory,
55
- room,
56
- todaysPurchases,
57
- todaysStartingInventory,
58
- } = stateRef.current
53
+ const { inventory, room, todaysPurchases, todaysStartingInventory } =
54
+ stateRef.current
59
55
 
60
56
  const positions = computeMarketPositions(
61
57
  todaysStartingInventory,
@@ -58,14 +58,14 @@ const setup = () => {
58
58
  const sendCowTradeRequest = vitest.fn()
59
59
  const showNotification = vitest.fn()
60
60
 
61
- const fakeState = ({
61
+ const fakeState = {
62
62
  peers: {
63
63
  [peerId]: { playerId: ownerId } as farmhand.peerMetadata,
64
64
  },
65
65
  sendCowTradeRequest,
66
66
  cowInventory: [cowOfferedForTrade],
67
67
  cowIdOfferedForTrade: cowOfferedForTrade.id,
68
- } as unknown) as farmhand.state
68
+ } as unknown as farmhand.state
69
69
 
70
70
  const instanceProxyRef: React.MutableRefObject<any> = {
71
71
  current: { state: { ...fakeState } },
@@ -83,12 +83,8 @@ export const useFarmhandNetwork = (
83
83
  const tradeForPeerCow = useCallback(
84
84
  (peerPlayerCow: farmhand.cow) => {
85
85
  const latestState = instanceProxyRef.current?.state ?? state
86
- const {
87
- cowIdOfferedForTrade,
88
- cowInventory,
89
- peers,
90
- sendCowTradeRequest,
91
- } = latestState
86
+ const { cowIdOfferedForTrade, cowInventory, peers, sendCowTradeRequest } =
87
+ latestState
92
88
 
93
89
  if (!sendCowTradeRequest) return
94
90
 
@@ -139,7 +135,7 @@ export const useFarmhandNetwork = (
139
135
 
140
136
  setState(previous => ({
141
137
  ...previous,
142
- cowTradeTimeoutId: (cowTradeTimeoutId as unknown) as number,
138
+ cowTradeTimeoutId: cowTradeTimeoutId as unknown as number,
143
139
  isAwaitingCowTradeRequest: true,
144
140
  }))
145
141
  },
@@ -153,26 +149,20 @@ export const useFarmhandNetwork = (
153
149
  return previous
154
150
  })
155
151
 
156
- const timeoutId = (window.setTimeout(() => {
152
+ const timeoutId = window.setTimeout(() => {
157
153
  setState((previous: farmhand.state) => ({
158
154
  ...previous,
159
155
  money: moneyTotal(previous.money, previous.activePlayers ?? 0),
160
156
  }))
161
157
  scheduleHeartbeat()
162
- }, HEARTBEAT_INTERVAL_PERIOD) as unknown) as number
158
+ }, HEARTBEAT_INTERVAL_PERIOD) as unknown as number
163
159
 
164
160
  setState(previous => ({ ...previous, heartbeatTimeoutId: timeoutId }))
165
161
  }, [setState])
166
162
 
167
163
  const syncToRoom = useCallback(async () => {
168
- const {
169
- isOnline,
170
- priceCrashes,
171
- priceSurges,
172
- room,
173
- playerId,
174
- peerRoom,
175
- } = instanceProxyRef.current.state
164
+ const { isOnline, priceCrashes, priceSurges, room, playerId, peerRoom } =
165
+ instanceProxyRef.current.state
176
166
 
177
167
  if (!isOnline) return
178
168
 
@@ -308,27 +298,22 @@ export const useFarmhandNetwork = (
308
298
  boundReducersRef.current.removePeer(id)
309
299
  )
310
300
 
311
- const [
312
- sendPeerMetadata,
313
- getPeerMetadataFunc,
314
- ] = statePeerRoom.makeAction('peerMetadata')
301
+ const [sendPeerMetadata, getPeerMetadataFunc] =
302
+ statePeerRoom.makeAction('peerMetadata')
315
303
 
316
304
  getPeerMetadataFunc((...args: any[]) =>
317
305
  handlePeerMetadataRequest(instanceProxyRef.current, args[0], args[1])
318
306
  )
319
307
 
320
- const [
321
- sendCowTradeRequest,
322
- getCowTradeRequest,
323
- ] = statePeerRoom.makeAction('cowTrade')
308
+ const [sendCowTradeRequest, getCowTradeRequest] =
309
+ statePeerRoom.makeAction('cowTrade')
324
310
 
325
311
  getCowTradeRequest((...args: any[]) =>
326
312
  handleCowTradeRequest(instanceProxyRef.current, args[0], args[1])
327
313
  )
328
314
 
329
- const [sendCowAccept, getCowAccept] = statePeerRoom.makeAction(
330
- 'cowAccept'
331
- )
315
+ const [sendCowAccept, getCowAccept] =
316
+ statePeerRoom.makeAction('cowAccept')
332
317
 
333
318
  getCowAccept((...args: any[]) =>
334
319
  handleCowTradeRequestAccept(
@@ -338,9 +323,8 @@ export const useFarmhandNetwork = (
338
323
  )
339
324
  )
340
325
 
341
- const [sendCowReject, getCowReject] = statePeerRoom.makeAction(
342
- 'cowReject'
343
- )
326
+ const [sendCowReject, getCowReject] =
327
+ statePeerRoom.makeAction('cowReject')
344
328
 
345
329
  getCowReject((...args: any[]) =>
346
330
  handleCowTradeRequestReject(instanceProxyRef.current, args[0])