@rpg-engine/long-bow 0.8.32 → 0.8.34

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.8.32",
3
+ "version": "0.8.34",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -10,6 +10,7 @@ import { IOptionsProps } from '../../../Dropdown';
10
10
  import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
11
11
  import { Portal } from '../../../shared/Portal/Portal';
12
12
  import { InformationCenterCell } from '../../InformationCenterCell';
13
+ import { BaseInformationDetails } from '../../shared/BaseInformationDetails';
13
14
  import { formatItemType } from '../items/InformationCenterItemsSection';
14
15
  import { BestiaryAdvancedFilters } from './BestiaryAdvancedFilters';
15
16
  import { InformationCenterNPCDetails } from './InformationCenterNPCDetails';
@@ -222,16 +223,24 @@ export const InformationCenterBestiarySection = ({
222
223
  )}
223
224
  {selectedMonster && (
224
225
  <Portal>
225
- <InformationCenterNPCDetails
226
- npc={selectedMonster}
227
- itemsAtlasJSON={itemsAtlasJSON}
228
- itemsAtlasIMG={itemsAtlasIMG}
229
- iconAtlasIMG={iconsAtlasIMG}
230
- iconAtlasJSON={iconsAtlasJSON}
231
- entitiesAtlasJSON={entitiesAtlasJSON}
232
- entitiesAtlasIMG={entitiesAtlasIMG}
226
+ <BaseInformationDetails
227
+ name={selectedMonster.name}
228
+ spriteKey={selectedMonster.key}
229
+ atlasJSON={entitiesAtlasJSON}
230
+ atlasIMG={entitiesAtlasIMG}
233
231
  onBack={() => setSelectedMonster(null)}
234
- />
232
+ >
233
+ <InformationCenterNPCDetails
234
+ npc={selectedMonster}
235
+ itemsAtlasJSON={itemsAtlasJSON}
236
+ itemsAtlasIMG={itemsAtlasIMG}
237
+ iconAtlasIMG={iconsAtlasIMG}
238
+ iconAtlasJSON={iconsAtlasJSON}
239
+ entitiesAtlasJSON={entitiesAtlasJSON}
240
+ entitiesAtlasIMG={entitiesAtlasIMG}
241
+ onBack={() => setSelectedMonster(null)}
242
+ />
243
+ </BaseInformationDetails>
235
244
  </Portal>
236
245
  )}
237
246
  </>
@@ -1,18 +1,23 @@
1
1
  import {
2
+ IInformationCenterItem,
2
3
  IInformationCenterNPC,
3
4
  isMobileOrTablet,
5
+ ItemRarities,
6
+ ItemSubType,
7
+ ItemType,
4
8
  MovementSpeed,
5
9
  RangeTypes,
6
10
  } from '@rpg-engine/shared';
7
- import React, { useState } from 'react';
11
+ import React, { useEffect, useState } from 'react';
8
12
  import styled from 'styled-components';
9
13
  import { uiColors } from '../../../../constants/uiColors';
10
14
  import { Collapsible } from '../../../shared/Collapsible/Collapsible';
11
15
  import { Pagination } from '../../../shared/Pagination/Pagination';
16
+ import { Portal } from '../../../shared/Portal/Portal';
12
17
  import { SearchBar } from '../../../shared/SearchBar/SearchBar';
13
18
  import { SpriteFromAtlas } from '../../../shared/SpriteFromAtlas';
14
-
15
19
  import { BaseInformationDetails } from '../../shared/BaseInformationDetails';
20
+ import { InformationCenterItemDetails } from '../items/InformationCenterItemDetails';
16
21
 
17
22
  interface INPCDetailsProps {
18
23
  npc: IInformationCenterNPC;
@@ -54,6 +59,14 @@ export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
54
59
  const isMobile = isMobileOrTablet();
55
60
  const [lootSearchQuery, setLootSearchQuery] = useState('');
56
61
  const [currentLootPage, setCurrentLootPage] = useState(1);
62
+ const [
63
+ selectedItem,
64
+ setSelectedItem,
65
+ ] = useState<IInformationCenterItem | null>(null);
66
+
67
+ useEffect(() => {
68
+ setCurrentLootPage(1);
69
+ }, [lootSearchQuery]);
57
70
 
58
71
  const formatText = (text: string | RangeTypes | MovementSpeed): string => {
59
72
  if (typeof text === 'number') {
@@ -101,6 +114,26 @@ export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
101
114
  currentLootPage * ITEMS_PER_PAGE
102
115
  );
103
116
 
117
+ const handleItemClick = (loot: any) => {
118
+ const item: IInformationCenterItem = {
119
+ key: loot.itemBlueprintKey,
120
+ name: formatItemName(loot.itemBlueprintKey),
121
+ texturePath: loot.itemBlueprintKey,
122
+ textureAtlas: 'items',
123
+ type: ItemType.Weapon,
124
+ subType: ItemSubType.Sword,
125
+ tier: 1,
126
+ rarity: ItemRarities.Common,
127
+ weight: 0,
128
+ maxStackSize: loot.quantityRange ? loot.quantityRange[1] : 1,
129
+ canSell: true,
130
+ description: 'A basic item.',
131
+ basePrice: 100,
132
+ allowedEquipSlotType: [],
133
+ };
134
+ setSelectedItem(item);
135
+ };
136
+
104
137
  return (
105
138
  <BaseInformationDetails
106
139
  name={npc.name}
@@ -153,13 +186,19 @@ export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
153
186
  <LootSearchContainer>
154
187
  <StyledSearchBar
155
188
  value={lootSearchQuery}
156
- onChange={setLootSearchQuery}
189
+ onChange={(query: string) => {
190
+ setLootSearchQuery(query);
191
+ setCurrentLootPage(1);
192
+ }}
157
193
  placeholder="Search loot..."
158
194
  />
159
195
  </LootSearchContainer>
160
196
  <LootGrid>
161
197
  {paginatedLoots.map((loot, index) => (
162
- <LootItem key={index}>
198
+ <LootItem
199
+ key={`${loot.itemBlueprintKey}-${index}`}
200
+ onClick={() => handleItemClick(loot)}
201
+ >
163
202
  <SpriteFromAtlas
164
203
  atlasJSON={itemsAtlasJSON}
165
204
  atlasIMG={itemsAtlasIMG}
@@ -232,6 +271,18 @@ export const InformationCenterNPCDetails: React.FC<INPCDetailsProps> = ({
232
271
  </SpellsList>
233
272
  </StyledCollapsible>
234
273
  )}
274
+
275
+ {selectedItem && (
276
+ <Portal>
277
+ <InformationCenterItemDetails
278
+ item={selectedItem}
279
+ itemsAtlasJSON={itemsAtlasJSON}
280
+ itemsAtlasIMG={itemsAtlasIMG}
281
+ droppedBy={[npc]}
282
+ onBack={() => setSelectedItem(null)}
283
+ />
284
+ </Portal>
285
+ )}
235
286
  </BaseInformationDetails>
236
287
  );
237
288
  };
@@ -399,6 +450,13 @@ const LootItem = styled.div`
399
450
  padding: 4px;
400
451
  border-radius: 4px;
401
452
  min-width: 0;
453
+ cursor: pointer;
454
+ user-select: none;
455
+ transition: background-color 0.2s ease;
456
+
457
+ &:hover {
458
+ background: rgba(255, 255, 255, 0.1);
459
+ }
402
460
  `;
403
461
 
404
462
  const LootDetails = styled.div`
@@ -406,27 +464,32 @@ const LootDetails = styled.div`
406
464
  display: flex;
407
465
  flex-direction: column;
408
466
  gap: 4px;
467
+ user-select: none;
409
468
  `;
410
469
 
411
470
  const LootName = styled.div`
412
471
  color: ${uiColors.white};
413
472
  font-size: 0.5rem;
473
+ user-select: none;
414
474
  `;
415
475
 
416
476
  const LootInfo = styled.div`
417
477
  display: flex;
418
478
  align-items: center;
419
479
  gap: 8px;
480
+ user-select: none;
420
481
  `;
421
482
 
422
483
  const LootChance = styled.span`
423
484
  color: ${uiColors.yellow};
424
485
  font-size: 0.45rem;
486
+ user-select: none;
425
487
  `;
426
488
 
427
489
  const LootQuantity = styled.span`
428
490
  color: ${uiColors.lightGray};
429
491
  font-size: 0.45rem;
492
+ user-select: none;
430
493
  `;
431
494
 
432
495
  const PaginationContainer = styled.div`
@@ -9,6 +9,7 @@ import { useTooltipPosition } from '../../../../hooks/useTooltipPosition';
9
9
  import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
10
10
  import { Portal } from '../../../shared/Portal/Portal';
11
11
  import { InformationCenterCell } from '../../InformationCenterCell';
12
+ import { BaseInformationDetails } from '../../shared/BaseInformationDetails';
12
13
  import { InformationCenterItemDetails } from './InformationCenterItemDetails';
13
14
  import { InformationCenterItemTooltip } from './InformationCenterItemTooltip';
14
15
  import { ItemsAdvancedFilters } from './ItemsAdvancedFilters';
@@ -170,13 +171,21 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
170
171
  )}
171
172
  {selectedItem && (
172
173
  <Portal>
173
- <InformationCenterItemDetails
174
- item={selectedItem}
175
- itemsAtlasJSON={itemsAtlasJSON}
176
- itemsAtlasIMG={itemsAtlasIMG}
177
- droppedBy={getDroppedByNPCs(selectedItem.key, bestiaryItems)}
174
+ <BaseInformationDetails
175
+ name={selectedItem.name}
176
+ spriteKey={selectedItem.texturePath}
177
+ atlasJSON={itemsAtlasJSON}
178
+ atlasIMG={itemsAtlasIMG}
178
179
  onBack={() => setSelectedItem(null)}
179
- />
180
+ >
181
+ <InformationCenterItemDetails
182
+ item={selectedItem}
183
+ itemsAtlasJSON={itemsAtlasJSON}
184
+ itemsAtlasIMG={itemsAtlasIMG}
185
+ droppedBy={getDroppedByNPCs(selectedItem.key, bestiaryItems)}
186
+ onBack={() => setSelectedItem(null)}
187
+ />
188
+ </BaseInformationDetails>
180
189
  </Portal>
181
190
  )}
182
191
  </>
@@ -64,7 +64,7 @@ const Overlay = styled.div`
64
64
  `;
65
65
 
66
66
  const Modal = styled.div`
67
- position: fixed;
67
+ position: relative;
68
68
  background-color: rgba(0, 0, 0, 0.95);
69
69
  border-radius: 4px;
70
70
  padding: 12px;
@@ -74,17 +74,13 @@ const Modal = styled.div`
74
74
  border: 1px solid ${uiColors.darkGray};
75
75
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
76
76
  width: 90%;
77
- height: 90%;
78
- top: 5%;
79
- left: 5%;
77
+ height: 90vh;
80
78
  max-width: 800px;
81
- margin: 0 auto;
79
+ max-height: 800px;
82
80
 
83
81
  @media (max-width: 768px) {
84
82
  width: 100%;
85
83
  height: 100%;
86
- top: 0;
87
- left: 0;
88
84
  border-radius: 0;
89
85
  padding: 8px;
90
86
  }