@rpg-engine/long-bow 0.8.25 → 0.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.25",
3
+ "version": "0.8.28",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -84,7 +84,7 @@
84
84
  "dependencies": {
85
85
  "@capacitor/core": "^6.1.0",
86
86
  "@rollup/plugin-image": "^2.1.1",
87
- "@rpg-engine/shared": "^0.9.101",
87
+ "@rpg-engine/shared": "^0.10.0",
88
88
  "dayjs": "^1.11.2",
89
89
  "font-awesome": "^4.7.0",
90
90
  "fs-extra": "^10.1.0",
@@ -368,7 +368,7 @@ const ContentContainer = styled.div`
368
368
  padding-bottom: 0;
369
369
  width: 100%;
370
370
  position: relative;
371
- min-height: 300px;
371
+ min-height: 250px;
372
372
  overflow: hidden;
373
373
  `;
374
374
 
@@ -9,9 +9,9 @@ import {
9
9
  } from '@rpg-engine/shared';
10
10
  import { DraggableContainer } from '../DraggableContainer';
11
11
  import { InternalTabs } from '../InternalTabs/InternalTabs';
12
+ import { RPGUIContainerTypes } from '../RPGUI/RPGUIContainer';
12
13
  import { InformationCenterBestiarySection } from './sections/bestiary/InformationCenterBestiarySection';
13
14
  import { InformationCenterFAQSection } from './sections/faq/InformationCenterFaqSection';
14
- import { InformationCenterItemDetails } from './sections/items/InformationCenterItemDetails';
15
15
  import { InformationCenterItemsSection } from './sections/items/InformationCenterItemsSection';
16
16
  import { InformationCenterTutorialsSection } from './sections/tutorials/InformationCenterTutorialsSection';
17
17
 
@@ -47,10 +47,6 @@ export const InformationCenter: React.FC<IInformationCenterProps> = ({
47
47
  initialSearchQuery = '',
48
48
  }) => {
49
49
  const [activeTab, setActiveTab] = useState('bestiary');
50
- const [
51
- selectedItem,
52
- setSelectedItem,
53
- ] = useState<IInformationCenterItem | null>(null);
54
50
 
55
51
  if (loading) {
56
52
  return <LoadingMessage>Loading...</LoadingMessage>;
@@ -117,7 +113,10 @@ export const InformationCenter: React.FC<IInformationCenterProps> = ({
117
113
  ];
118
114
 
119
115
  return (
120
- <DraggableContainer title="Information Center">
116
+ <DraggableContainer
117
+ title="Information Center"
118
+ type={RPGUIContainerTypes.Framed}
119
+ >
121
120
  <Container>
122
121
  <InternalTabs
123
122
  tabs={tabs}
@@ -129,19 +128,6 @@ export const InformationCenter: React.FC<IInformationCenterProps> = ({
129
128
  borderColor="#f59e0b"
130
129
  hoverColor="#fef3c7"
131
130
  />
132
- {selectedItem && (
133
- <InformationCenterItemDetails
134
- item={selectedItem}
135
- itemsAtlasJSON={itemsAtlasJSON}
136
- itemsAtlasIMG={itemsAtlasIMG}
137
- droppedBy={bestiaryItems.filter(npc =>
138
- npc.loots?.some(
139
- loot => loot.itemBlueprintKey === selectedItem.key
140
- )
141
- )}
142
- onBack={() => setSelectedItem(null)}
143
- />
144
- )}
145
131
  </Container>
146
132
  </DraggableContainer>
147
133
  );
@@ -1,4 +1,8 @@
1
- import { IInformationCenterNPC, NPCAlignment } from '@rpg-engine/shared';
1
+ import {
2
+ IInformationCenterNPC,
3
+ NPCAlignment,
4
+ isMobileOrTablet,
5
+ } from '@rpg-engine/shared';
2
6
  import React, { useMemo, useState } from 'react';
3
7
  import styled from 'styled-components';
4
8
  import { IOptionsProps } from '../../../Dropdown';
@@ -8,6 +12,7 @@ import { InformationCenterCell } from '../../InformationCenterCell';
8
12
  import { formatItemType } from '../items/InformationCenterItemsSection';
9
13
  import { InformationCenterNPCDetails } from './InformationCenterNPCDetails';
10
14
  import { InformationCenterNPCTooltip } from './InformationCenterNPCTooltip';
15
+
11
16
  interface IBestiarySectionProps {
12
17
  bestiaryItems: IInformationCenterNPC[];
13
18
  itemsAtlasJSON: Record<string, any>;
@@ -31,6 +36,7 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
31
36
  initialSearchQuery,
32
37
  tabId,
33
38
  }) => {
39
+ const isMobile = isMobileOrTablet();
34
40
  const [searchQuery, setSearchQuery] = useState(initialSearchQuery);
35
41
  const [tooltipData, setTooltipData] = useState<{
36
42
  npc: IInformationCenterNPC;
@@ -40,13 +46,12 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
40
46
  selectedMonster,
41
47
  setSelectedMonster,
42
48
  ] = useState<IInformationCenterNPC | null>(null);
43
- const [isTouchDevice] = useState('ontouchstart' in window);
44
49
 
45
50
  const handleMouseEnter = (
46
51
  monster: IInformationCenterNPC,
47
52
  event: React.MouseEvent
48
53
  ) => {
49
- if (!isTouchDevice && !selectedMonster) {
54
+ if (!isMobile && !selectedMonster) {
50
55
  setTooltipData({
51
56
  npc: monster,
52
57
  position: { x: event.clientX, y: event.clientY },
@@ -55,13 +60,13 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
55
60
  };
56
61
 
57
62
  const handleMouseLeave = () => {
58
- if (!isTouchDevice) {
63
+ if (!isMobile) {
59
64
  setTooltipData(null);
60
65
  }
61
66
  };
62
67
 
63
68
  const handleMouseMove = (event: React.MouseEvent) => {
64
- if (!isTouchDevice && tooltipData) {
69
+ if (!isMobile && tooltipData) {
65
70
  setTooltipData({
66
71
  ...tooltipData,
67
72
  position: { x: event.clientX, y: event.clientY },
@@ -73,18 +78,9 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
73
78
  monster: IInformationCenterNPC,
74
79
  event: React.TouchEvent
75
80
  ) => {
76
- if (isTouchDevice) {
77
- event.preventDefault();
78
- const touch = event.touches[0];
79
- if (tooltipData?.npc.id === monster.id) {
80
- setTooltipData(null);
81
- } else {
82
- setTooltipData({
83
- npc: monster,
84
- position: { x: touch.clientX, y: touch.clientY },
85
- });
86
- }
87
- }
81
+ event.preventDefault();
82
+ setSelectedMonster(monster);
83
+ setTooltipData(null);
88
84
  };
89
85
 
90
86
  const handleMonsterClick = (monster: IInformationCenterNPC) => {
@@ -170,7 +166,7 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
170
166
  dependencies={[selectedBestiaryCategory]}
171
167
  itemHeight="180px"
172
168
  />
173
- {tooltipData && (
169
+ {!isMobile && tooltipData && (
174
170
  <Portal>
175
171
  <TooltipWrapper
176
172
  style={{
@@ -188,16 +184,18 @@ export const InformationCenterBestiarySection: React.FC<IBestiarySectionProps> =
188
184
  </Portal>
189
185
  )}
190
186
  {selectedMonster && (
191
- <InformationCenterNPCDetails
192
- npc={selectedMonster}
193
- itemsAtlasJSON={itemsAtlasJSON}
194
- itemsAtlasIMG={itemsAtlasIMG}
195
- iconAtlasIMG={iconsAtlasIMG}
196
- iconAtlasJSON={iconsAtlasJSON}
197
- entitiesAtlasJSON={entitiesAtlasJSON}
198
- entitiesAtlasIMG={entitiesAtlasIMG}
199
- onBack={() => setSelectedMonster(null)}
200
- />
187
+ <Portal>
188
+ <InformationCenterNPCDetails
189
+ npc={selectedMonster}
190
+ itemsAtlasJSON={itemsAtlasJSON}
191
+ itemsAtlasIMG={itemsAtlasIMG}
192
+ iconAtlasIMG={iconsAtlasIMG}
193
+ iconAtlasJSON={iconsAtlasJSON}
194
+ entitiesAtlasJSON={entitiesAtlasJSON}
195
+ entitiesAtlasIMG={entitiesAtlasIMG}
196
+ onBack={() => setSelectedMonster(null)}
197
+ />
198
+ </Portal>
201
199
  )}
202
200
  </>
203
201
  );
@@ -2,11 +2,13 @@ import {
2
2
  IInformationCenterItem,
3
3
  IInformationCenterNPC,
4
4
  ItemType,
5
+ isMobileOrTablet,
5
6
  } from '@rpg-engine/shared';
6
7
  import React, { useState } from 'react';
7
8
  import styled from 'styled-components';
8
9
  import { IOptionsProps } from '../../../Dropdown';
9
10
  import { PaginatedContent } from '../../../shared/PaginatedContent/PaginatedContent';
11
+ import { Portal } from '../../../shared/Portal/Portal';
10
12
  import { InformationCenterCell } from '../../InformationCenterCell';
11
13
  import { InformationCenterItemDetails } from './InformationCenterItemDetails';
12
14
  import { InformationCenterItemTooltip } from './InformationCenterItemTooltip';
@@ -47,6 +49,7 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
47
49
  initialSearchQuery,
48
50
  tabId,
49
51
  }) => {
52
+ const isMobile = isMobileOrTablet();
50
53
  const [searchQuery, setSearchQuery] = useState(initialSearchQuery);
51
54
  const [selectedItemCategory, setSelectedItemCategory] = useState<string>(
52
55
  'all'
@@ -90,15 +93,17 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
90
93
  e: React.MouseEvent,
91
94
  item: IInformationCenterItem
92
95
  ) => {
93
- setTooltipPosition({
94
- x: e.clientX + TOOLTIP_OFFSET,
95
- y: e.clientY,
96
- });
97
- setHoveredItem(item);
96
+ if (!isMobile) {
97
+ setTooltipPosition({
98
+ x: e.clientX + TOOLTIP_OFFSET,
99
+ y: e.clientY,
100
+ });
101
+ setHoveredItem(item);
102
+ }
98
103
  };
99
104
 
100
105
  const handleMouseMove = (e: React.MouseEvent) => {
101
- if (hoveredItem) {
106
+ if (!isMobile && hoveredItem) {
102
107
  setTooltipPosition({
103
108
  x: e.clientX + TOOLTIP_OFFSET,
104
109
  y: e.clientY,
@@ -107,19 +112,17 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
107
112
  };
108
113
 
109
114
  const handleMouseLeave = () => {
110
- setHoveredItem(null);
115
+ if (!isMobile) {
116
+ setHoveredItem(null);
117
+ }
111
118
  };
112
119
 
113
120
  const handleTouchStart = (
114
121
  e: React.TouchEvent,
115
122
  item: IInformationCenterItem
116
123
  ) => {
117
- const touch = e.touches[0];
118
- setTooltipPosition({
119
- x: touch.clientX + TOOLTIP_OFFSET,
120
- y: touch.clientY,
121
- });
122
- setHoveredItem(item);
124
+ e.preventDefault();
125
+ setSelectedItem(item);
123
126
  };
124
127
 
125
128
  const handleItemClick = (item: IInformationCenterItem) => {
@@ -170,7 +173,7 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
170
173
  layout="grid"
171
174
  itemHeight="180px"
172
175
  />
173
- {hoveredItem && (
176
+ {!isMobile && hoveredItem && (
174
177
  <TooltipWrapper
175
178
  style={{ top: tooltipPosition.y, left: tooltipPosition.x }}
176
179
  >
@@ -178,13 +181,15 @@ export const InformationCenterItemsSection: React.FC<IItemsSectionProps> = ({
178
181
  </TooltipWrapper>
179
182
  )}
180
183
  {selectedItem && (
181
- <InformationCenterItemDetails
182
- item={selectedItem}
183
- itemsAtlasJSON={itemsAtlasJSON}
184
- itemsAtlasIMG={itemsAtlasIMG}
185
- droppedBy={getDroppedByNPCs(selectedItem.key, bestiaryItems)}
186
- onBack={() => setSelectedItem(null)}
187
- />
184
+ <Portal>
185
+ <InformationCenterItemDetails
186
+ item={selectedItem}
187
+ itemsAtlasJSON={itemsAtlasJSON}
188
+ itemsAtlasIMG={itemsAtlasIMG}
189
+ droppedBy={getDroppedByNPCs(selectedItem.key, bestiaryItems)}
190
+ onBack={() => setSelectedItem(null)}
191
+ />
192
+ </Portal>
188
193
  )}
189
194
  </>
190
195
  );
@@ -49,24 +49,29 @@ export const BaseInformationDetails: React.FC<IBaseInformationDetailsProps> = ({
49
49
  };
50
50
 
51
51
  const Container = styled.div`
52
- position: absolute;
52
+ position: fixed;
53
53
  inset: 0;
54
54
  display: flex;
55
55
  justify-content: center;
56
56
  align-items: center;
57
- z-index: 1000;
57
+ z-index: 9999;
58
58
  `;
59
59
 
60
60
  const Overlay = styled.div`
61
- position: absolute;
61
+ position: fixed;
62
62
  inset: 0;
63
63
  background-color: rgba(0, 0, 0, 0.8);
64
64
  `;
65
65
 
66
66
  const Modal = styled.div`
67
- position: relative;
68
- width: 90%;
69
- height: 90%;
67
+ position: fixed;
68
+ top: 50%;
69
+ left: 50%;
70
+ transform: translate(-50%, -50%);
71
+ width: 100%;
72
+ height: 100%;
73
+ max-width: 90%;
74
+ max-height: 90%;
70
75
  background-color: rgba(0, 0, 0, 0.95);
71
76
  border-radius: 4px;
72
77
  padding: 16px;
@@ -76,6 +81,12 @@ const Modal = styled.div`
76
81
  border: 1px solid ${uiColors.darkGray};
77
82
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
78
83
 
84
+ @media (max-width: 768px) {
85
+ max-width: 100%;
86
+ max-height: 100%;
87
+ border-radius: 0;
88
+ }
89
+
79
90
  &::-webkit-scrollbar {
80
91
  width: 2px;
81
92
  }