@rpg-engine/long-bow 0.7.93 → 0.7.95

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.7.93",
3
+ "version": "0.7.95",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -20,8 +20,12 @@ import { DraggableContainer } from '../DraggableContainer';
20
20
  import { Dropdown, IOptionsProps } from '../Dropdown';
21
21
  import { RPGUIContainerTypes } from '../RPGUI/RPGUIContainer';
22
22
  import { CraftingRecipe } from './CraftingRecipe';
23
+ import { useResponsiveSize } from './hooks/useResponsiveSize';
23
24
  import { calculateMaxCraftable } from './utils/calculateMaxCraftable';
24
25
 
26
+ const MOBILE_WIDTH = '500px';
27
+ const ITEMS_PER_PAGE = 8;
28
+
25
29
  export interface IItemCraftSelectorProps {
26
30
  atlasJSON: any;
27
31
  atlasIMG: any;
@@ -41,23 +45,6 @@ export interface ShowMessage {
41
45
  index: number;
42
46
  }
43
47
 
44
- const desktop = {
45
- width: 'min(900px, 80%)',
46
- height: 'min(700px, 80%)',
47
- };
48
-
49
- const mobileLanscape = {
50
- width: '800px',
51
- height: '500px',
52
- };
53
-
54
- const mobilePortrait = {
55
- width: '500px',
56
- height: '700px',
57
- };
58
-
59
- const ITEMS_PER_PAGE = 8;
60
-
61
48
  export const CraftBook: React.FC<IItemCraftSelectorProps> = ({
62
49
  atlasIMG,
63
50
  atlasJSON,
@@ -75,7 +62,7 @@ export const CraftBook: React.FC<IItemCraftSelectorProps> = ({
75
62
  const [selectedType, setSelectedType] = useState<string>(
76
63
  savedSelectedType ?? Object.keys(ItemSubType)[0]
77
64
  );
78
- const [size, setSize] = useState<{ width: string; height: string }>();
65
+ const size = useResponsiveSize(scale);
79
66
  const [searchTerm, setSearchTerm] = useState('');
80
67
  const [isSearchVisible, setIsSearchVisible] = useState(false);
81
68
  const [isCraftingDisabled, setIsCraftingDisabled] = useState(false);
@@ -90,30 +77,6 @@ export const CraftBook: React.FC<IItemCraftSelectorProps> = ({
90
77
  setItems(craftablesItems);
91
78
  }, [craftablesItems]);
92
79
 
93
- useEffect(() => {
94
- const handleResize = (): void => {
95
- if (
96
- window.innerWidth < 500 &&
97
- size?.width !== mobilePortrait.width &&
98
- (!scale || scale < 1)
99
- ) {
100
- setSize(mobilePortrait);
101
- } else if (
102
- (!scale || scale < 1) &&
103
- size?.width !== mobileLanscape.width
104
- ) {
105
- setSize(mobileLanscape);
106
- } else if (size?.width !== desktop.width) {
107
- setSize(desktop);
108
- }
109
- };
110
- handleResize();
111
-
112
- window.addEventListener('resize', handleResize);
113
-
114
- return () => window.removeEventListener('resize', handleResize);
115
- }, [scale]);
116
-
117
80
  const togglePinItem = (itemKey: string) => {
118
81
  setPinnedItems(current =>
119
82
  current.includes(itemKey)
@@ -123,23 +86,27 @@ export const CraftBook: React.FC<IItemCraftSelectorProps> = ({
123
86
  };
124
87
 
125
88
  const categoryOptions: IOptionsProps[] = [
126
- 'Suggested',
127
- ...(pinnedItems.length > 0 ? ['Pinned'] : []),
128
- ...Object.keys(ItemSubType),
129
- ]
130
- .filter(type => type !== 'DeadBody')
131
- .sort((a, b) => {
132
- if (a === 'Suggested') return -1;
133
- if (b === 'Suggested') return 1;
134
- if (a === 'Pinned') return -1;
135
- if (b === 'Pinned') return 1;
136
- return a.localeCompare(b);
137
- })
138
- .map((type, index) => ({
139
- id: index,
140
- value: type,
141
- option: type,
142
- }));
89
+ { id: 0, value: 'Suggested', option: 'Suggested' },
90
+ ...(pinnedItems.length > 0
91
+ ? [{ id: 1, value: 'Pinned', option: 'Pinned' }]
92
+ : []),
93
+ ...Object.keys(ItemSubType)
94
+ .filter(type => type !== 'DeadBody')
95
+ .map((type, index) => ({
96
+ id: index + (pinnedItems.length > 0 ? 2 : 1),
97
+ value: type,
98
+ option:
99
+ type === 'CraftingResources' || type === 'CraftingResource'
100
+ ? 'Resources'
101
+ : type,
102
+ })),
103
+ ].sort((a, b) => {
104
+ if (a.value === 'Suggested') return -1;
105
+ if (b.value === 'Suggested') return 1;
106
+ if (a.value === 'Pinned') return -1;
107
+ if (b.value === 'Pinned') return 1;
108
+ return a.value.localeCompare(b.value);
109
+ });
143
110
 
144
111
  const filteredCraftableItems = items?.filter(item => {
145
112
  const matchesSearch = item.name
@@ -246,29 +213,31 @@ export const CraftBook: React.FC<IItemCraftSelectorProps> = ({
246
213
  </RadioInputScroller>
247
214
  </ContentContainer>
248
215
 
249
- <PaginationContainer>
250
- <PaginationButton
251
- onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}
252
- disabled={currentPage === 1}
253
- >
254
- <FaChevronLeft size={12} />
255
- </PaginationButton>
256
- <PageInfo>
257
- Page {currentPage} of {totalPages}
258
- </PageInfo>
259
- <PaginationButton
260
- onClick={() =>
261
- setCurrentPage(prev => Math.min(totalPages, prev + 1))
262
- }
263
- disabled={currentPage === totalPages}
264
- >
265
- <FaChevronRight size={12} />
266
- </PaginationButton>
267
- </PaginationContainer>
216
+ {totalPages > 1 && (
217
+ <PaginationContainer>
218
+ <PaginationButton
219
+ onClick={() => setCurrentPage(prev => Math.max(1, prev - 1))}
220
+ disabled={currentPage === 1}
221
+ >
222
+ <FaChevronLeft size={12} />
223
+ </PaginationButton>
224
+ <PageInfo>
225
+ Page {currentPage} of {totalPages}
226
+ </PageInfo>
227
+ <PaginationButton
228
+ onClick={() =>
229
+ setCurrentPage(prev => Math.min(totalPages, prev + 1))
230
+ }
231
+ disabled={currentPage === totalPages}
232
+ >
233
+ <FaChevronRight size={12} />
234
+ </PaginationButton>
235
+ </PaginationContainer>
236
+ )}
268
237
 
269
238
  <Footer>
270
239
  <Button buttonType={ButtonTypes.RPGUIButton} onPointerDown={onClose}>
271
- Cancel
240
+ Close
272
241
  </Button>
273
242
  <Button
274
243
  disabled={!craftItemKey || isCraftingDisabled}
@@ -403,9 +372,9 @@ const RadioInputScroller = styled.div`
403
372
  display: grid;
404
373
  grid-template-columns: repeat(2, minmax(0, 1fr));
405
374
  gap: 16px;
406
- align-items: start;
375
+ align-content: start;
407
376
 
408
- @media (max-width: ${mobilePortrait.width}) {
377
+ @media (max-width: ${MOBILE_WIDTH}) {
409
378
  grid-template-columns: 1fr;
410
379
  }
411
380
  `;
@@ -457,7 +426,7 @@ const Footer = styled.div`
457
426
  min-width: 100px;
458
427
  }
459
428
 
460
- @media (max-width: ${mobilePortrait.width}) {
429
+ @media (max-width: ${MOBILE_WIDTH}) {
461
430
  justify-content: center;
462
431
  }
463
432
  `;
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
2
2
 
3
3
  const desktop = {
4
4
  width: 'min(900px, 80%)',
5
- height: 'min(700px, 80%)',
5
+ height: 'min(auto, 80%)',
6
6
  };
7
7
 
8
8
  const mobileLanscape = {
@@ -8,23 +8,23 @@ export function calculateMaxCraftable(
8
8
  return 0;
9
9
  }
10
10
 
11
- return recipe.ingredients.reduce((maxPossible, ingredient) => {
12
- const inventoryItem = Object.values(inventory.slots).find(
13
- (item): item is IItem => item?.key === ingredient.key
14
- );
11
+ return (
12
+ recipe.ingredients.reduce((maxPossible, ingredient) => {
13
+ const inventoryItem = Object.values(inventory.slots).find(
14
+ (item): item is IItem => item?.key === ingredient.key
15
+ );
15
16
 
16
- if (!inventoryItem) {
17
- return 0;
18
- }
17
+ if (!inventoryItem) {
18
+ return 0;
19
+ }
19
20
 
20
- const possibleWithThisIngredient = Math.floor(
21
- inventoryItem.stackQty ?? 0 / ingredient.qty
22
- );
21
+ const possibleWithThisIngredient = Math.floor(
22
+ (inventoryItem.stackQty ?? 0) / ingredient.qty
23
+ );
23
24
 
24
- if (maxPossible === -1) {
25
- return possibleWithThisIngredient;
26
- }
27
-
28
- return Math.min(maxPossible, possibleWithThisIngredient);
29
- }, -1);
25
+ return maxPossible === undefined
26
+ ? possibleWithThisIngredient
27
+ : Math.min(maxPossible, possibleWithThisIngredient);
28
+ }, undefined as number | undefined) ?? 0
29
+ );
30
30
  }