@rpg-engine/long-bow 0.6.69 → 0.6.71
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/dist/components/Friends/SearchFriend.d.ts +4 -4
- package/dist/components/QuestList.d.ts +2 -3
- package/dist/components/Table/Table.d.ts +5 -0
- package/dist/components/shared/Ellipsis.d.ts +1 -1
- package/dist/components/shared/SimpleTooltip.d.ts +12 -0
- package/dist/long-bow.cjs.development.js +402 -180
- package/dist/long-bow.cjs.development.js.map +1 -1
- package/dist/long-bow.cjs.production.min.js +1 -1
- package/dist/long-bow.cjs.production.min.js.map +1 -1
- package/dist/long-bow.esm.js +404 -183
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Friends/FriendList.tsx +6 -19
- package/src/components/Friends/SearchFriend.tsx +160 -107
- package/src/components/QuestList.tsx +144 -107
- package/src/components/Table/Table.tsx +19 -0
- package/src/components/shared/Ellipsis.tsx +2 -2
- package/src/components/shared/SimpleTooltip.tsx +198 -0
- package/src/stories/QuestList.stories.tsx +12 -42
|
@@ -11,6 +11,9 @@ export const TableRow = styled.tr`
|
|
|
11
11
|
&:nth-child(even) {
|
|
12
12
|
background-color: rgba(255, 255, 255, 0.05) !important;
|
|
13
13
|
}
|
|
14
|
+
&:hover {
|
|
15
|
+
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
16
|
+
}
|
|
14
17
|
`;
|
|
15
18
|
|
|
16
19
|
export const TableHeader = styled.th`
|
|
@@ -18,12 +21,14 @@ export const TableHeader = styled.th`
|
|
|
18
21
|
padding: 0.5rem;
|
|
19
22
|
color: ${uiColors.yellow} !important;
|
|
20
23
|
border-bottom: 1px solid ${uiColors.lightGray};
|
|
24
|
+
text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black;
|
|
21
25
|
`;
|
|
22
26
|
|
|
23
27
|
export const TableCell = styled.td`
|
|
24
28
|
padding: 0.5rem;
|
|
25
29
|
color: ${uiColors.white};
|
|
26
30
|
border-bottom: 1px solid ${uiColors.lightGray};
|
|
31
|
+
text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black;
|
|
27
32
|
`;
|
|
28
33
|
|
|
29
34
|
export const ActionButtons = styled.div`
|
|
@@ -31,3 +36,17 @@ export const ActionButtons = styled.div`
|
|
|
31
36
|
gap: 10px;
|
|
32
37
|
align-items: center;
|
|
33
38
|
`;
|
|
39
|
+
|
|
40
|
+
interface IUserActionProps {
|
|
41
|
+
color: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const UserActionLink = styled.span<IUserActionProps>`
|
|
45
|
+
color: ${({ color }) => color} !important;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
margin-right: 0.5rem;
|
|
48
|
+
|
|
49
|
+
&:hover {
|
|
50
|
+
text-decoration: underline;
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
@@ -3,7 +3,7 @@ import styled from 'styled-components';
|
|
|
3
3
|
|
|
4
4
|
interface IProps {
|
|
5
5
|
children: React.ReactNode;
|
|
6
|
-
maxLines
|
|
6
|
+
maxLines?: 1 | 2 | 3;
|
|
7
7
|
maxWidth: string;
|
|
8
8
|
fontSize?: string;
|
|
9
9
|
center?: boolean;
|
|
@@ -11,7 +11,7 @@ interface IProps {
|
|
|
11
11
|
|
|
12
12
|
export const Ellipsis = ({
|
|
13
13
|
children,
|
|
14
|
-
maxLines,
|
|
14
|
+
maxLines = 1,
|
|
15
15
|
maxWidth,
|
|
16
16
|
fontSize,
|
|
17
17
|
center,
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import React, { ReactNode, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import ReactDOM from 'react-dom';
|
|
3
|
+
import styled, { keyframes } from 'styled-components';
|
|
4
|
+
import { uiColors } from '../../constants/uiColors';
|
|
5
|
+
import { RPGUIRoot } from '../RPGUI/RPGUIRoot';
|
|
6
|
+
|
|
7
|
+
interface TooltipProps {
|
|
8
|
+
content: string | ReactNode;
|
|
9
|
+
direction?: 'top' | 'bottom' | 'left' | 'right';
|
|
10
|
+
backgroundColor?: string;
|
|
11
|
+
textColor?: string;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
showDelay?: number;
|
|
14
|
+
hideDelay?: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const SimpleTooltip: React.FC<TooltipProps> = ({
|
|
18
|
+
content,
|
|
19
|
+
direction = 'top',
|
|
20
|
+
backgroundColor = uiColors.raisinBlack,
|
|
21
|
+
textColor = uiColors.white,
|
|
22
|
+
children,
|
|
23
|
+
showDelay = 200,
|
|
24
|
+
hideDelay = 200,
|
|
25
|
+
}) => {
|
|
26
|
+
const [visible, setVisible] = useState(false);
|
|
27
|
+
const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 });
|
|
28
|
+
const tooltipRef = useRef<HTMLDivElement>(null);
|
|
29
|
+
const triggerRef = useRef<HTMLDivElement>(null);
|
|
30
|
+
const timeoutRef = useRef<NodeJS.Timeout>();
|
|
31
|
+
|
|
32
|
+
const calculatePosition = () => {
|
|
33
|
+
if (!triggerRef.current || !tooltipRef.current) return;
|
|
34
|
+
|
|
35
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
36
|
+
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
37
|
+
|
|
38
|
+
let top, left;
|
|
39
|
+
|
|
40
|
+
switch (direction) {
|
|
41
|
+
case 'top':
|
|
42
|
+
top = triggerRect.top - tooltipRect.height - 8;
|
|
43
|
+
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
|
|
44
|
+
break;
|
|
45
|
+
case 'bottom':
|
|
46
|
+
top = triggerRect.bottom + 8;
|
|
47
|
+
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
|
|
48
|
+
break;
|
|
49
|
+
case 'left':
|
|
50
|
+
top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
|
|
51
|
+
left = triggerRect.left - tooltipRect.width - 8;
|
|
52
|
+
break;
|
|
53
|
+
case 'right':
|
|
54
|
+
top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
|
|
55
|
+
left = triggerRect.right + 8;
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
top = triggerRect.top - tooltipRect.height - 8;
|
|
59
|
+
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Ensure the tooltip stays within the viewport
|
|
63
|
+
if (left < 8) left = 8;
|
|
64
|
+
if (left + tooltipRect.width > window.innerWidth)
|
|
65
|
+
left = window.innerWidth - tooltipRect.width - 8;
|
|
66
|
+
if (top < 8) top = 8;
|
|
67
|
+
if (top + tooltipRect.height > window.innerHeight)
|
|
68
|
+
top = window.innerHeight - tooltipRect.height - 8;
|
|
69
|
+
|
|
70
|
+
setTooltipPosition({ top: Math.round(top), left: Math.round(left) });
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const showTooltip = () => {
|
|
74
|
+
clearTimeout(timeoutRef.current);
|
|
75
|
+
timeoutRef.current = setTimeout(() => {
|
|
76
|
+
setVisible(true);
|
|
77
|
+
calculatePosition();
|
|
78
|
+
}, showDelay);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const hideTooltip = () => {
|
|
82
|
+
clearTimeout(timeoutRef.current);
|
|
83
|
+
timeoutRef.current = setTimeout(() => {
|
|
84
|
+
setVisible(false);
|
|
85
|
+
}, hideDelay);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
const handleMouseMove = (event: MouseEvent) => {
|
|
90
|
+
if (visible && tooltipRef.current && triggerRef.current) {
|
|
91
|
+
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
92
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
93
|
+
|
|
94
|
+
const isOutsideTooltip =
|
|
95
|
+
event.clientX < tooltipRect.left ||
|
|
96
|
+
event.clientX > tooltipRect.right ||
|
|
97
|
+
event.clientY < tooltipRect.top ||
|
|
98
|
+
event.clientY > tooltipRect.bottom;
|
|
99
|
+
|
|
100
|
+
const isOutsideTrigger =
|
|
101
|
+
event.clientX < triggerRect.left ||
|
|
102
|
+
event.clientX > triggerRect.right ||
|
|
103
|
+
event.clientY < triggerRect.top ||
|
|
104
|
+
event.clientY > triggerRect.bottom;
|
|
105
|
+
|
|
106
|
+
if (isOutsideTooltip && isOutsideTrigger) {
|
|
107
|
+
hideTooltip();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const handleScroll = () => {
|
|
113
|
+
if (visible) {
|
|
114
|
+
hideTooltip();
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const handleResize = () => {
|
|
119
|
+
if (visible) {
|
|
120
|
+
calculatePosition();
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
125
|
+
window.addEventListener('scroll', handleScroll);
|
|
126
|
+
window.addEventListener('resize', handleResize);
|
|
127
|
+
|
|
128
|
+
return () => {
|
|
129
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
130
|
+
window.removeEventListener('scroll', handleScroll);
|
|
131
|
+
window.removeEventListener('resize', handleResize);
|
|
132
|
+
clearTimeout(timeoutRef.current);
|
|
133
|
+
};
|
|
134
|
+
}, [visible]);
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<TooltipContainer
|
|
138
|
+
ref={triggerRef}
|
|
139
|
+
onMouseEnter={showTooltip}
|
|
140
|
+
onMouseLeave={hideTooltip}
|
|
141
|
+
onFocus={showTooltip}
|
|
142
|
+
onBlur={hideTooltip}
|
|
143
|
+
>
|
|
144
|
+
{children}
|
|
145
|
+
{visible &&
|
|
146
|
+
ReactDOM.createPortal(
|
|
147
|
+
<RPGUIRoot>
|
|
148
|
+
<TooltipBox
|
|
149
|
+
ref={tooltipRef}
|
|
150
|
+
direction={direction}
|
|
151
|
+
backgroundColor={backgroundColor}
|
|
152
|
+
textColor={textColor}
|
|
153
|
+
style={{ top: tooltipPosition.top, left: tooltipPosition.left }}
|
|
154
|
+
>
|
|
155
|
+
{content}
|
|
156
|
+
</TooltipBox>
|
|
157
|
+
</RPGUIRoot>,
|
|
158
|
+
document.body
|
|
159
|
+
)}
|
|
160
|
+
</TooltipContainer>
|
|
161
|
+
);
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const TooltipContainer = styled.div`
|
|
165
|
+
display: inline-block;
|
|
166
|
+
cursor: inherit;
|
|
167
|
+
`;
|
|
168
|
+
|
|
169
|
+
const fadeIn = keyframes`
|
|
170
|
+
from {
|
|
171
|
+
opacity: 0;
|
|
172
|
+
transform: scale(0.95);
|
|
173
|
+
}
|
|
174
|
+
to {
|
|
175
|
+
opacity: 1;
|
|
176
|
+
transform: scale(1);
|
|
177
|
+
}
|
|
178
|
+
`;
|
|
179
|
+
|
|
180
|
+
interface TooltipBoxProps {
|
|
181
|
+
direction: 'top' | 'bottom' | 'left' | 'right';
|
|
182
|
+
backgroundColor: string;
|
|
183
|
+
textColor: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const TooltipBox = styled.div<TooltipBoxProps>`
|
|
187
|
+
position: fixed;
|
|
188
|
+
z-index: 1000;
|
|
189
|
+
background-color: ${({ backgroundColor }) => backgroundColor};
|
|
190
|
+
color: ${({ textColor }) => textColor};
|
|
191
|
+
padding: 8px;
|
|
192
|
+
border-radius: 4px;
|
|
193
|
+
font-size: 0.65rem;
|
|
194
|
+
max-width: 250px;
|
|
195
|
+
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
|
|
196
|
+
animation: ${fadeIn} 0.2s ease-out;
|
|
197
|
+
line-height: 1.3;
|
|
198
|
+
`;
|
|
@@ -22,61 +22,31 @@ const IQuestMock = [
|
|
|
22
22
|
_id: '6317996c77f2420047a20b55',
|
|
23
23
|
rewards: [
|
|
24
24
|
{
|
|
25
|
-
id: '
|
|
26
|
-
itemKeys: ['
|
|
27
|
-
spellKeys: ['6317996c77f2420047a20b53'],
|
|
25
|
+
id: '66cd2b039b486b00436a4ace',
|
|
26
|
+
itemKeys: ['iron-armor'],
|
|
28
27
|
qty: 1,
|
|
29
28
|
},
|
|
30
29
|
],
|
|
31
30
|
objectives: [
|
|
32
31
|
{
|
|
33
|
-
id: '
|
|
34
|
-
type: QuestType.
|
|
32
|
+
id: '66cd2b049b486b00436a4b1a',
|
|
33
|
+
type: QuestType.Interaction,
|
|
35
34
|
status: QuestStatus.Pending,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
creatureKeys: ['6317996c77f2420047a20b53'],
|
|
35
|
+
targetNPCkey: 'durgan-miner',
|
|
36
|
+
items: [{ itemKey: 'iron-ingot', qty: 10 }],
|
|
39
37
|
},
|
|
40
38
|
],
|
|
41
39
|
npcId: '6317996b77f2420047a20825',
|
|
42
|
-
title: '
|
|
43
|
-
key: 'interaction-
|
|
40
|
+
title: 'Iron Ingot Craftsmanship',
|
|
41
|
+
key: 'interaction-durgan-miner',
|
|
44
42
|
description:
|
|
45
|
-
"
|
|
46
|
-
createdAt: '
|
|
47
|
-
updatedAt: '
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
_id: '6317996c77f2420047a20b55',
|
|
51
|
-
rewards: [
|
|
52
|
-
{
|
|
53
|
-
id: '6317996c77f2420047a20b53',
|
|
54
|
-
itemKeys: ['6317996c77f2420047a20b53'],
|
|
55
|
-
spellKeys: ['6317996c77f2420047a20b53'],
|
|
56
|
-
qty: 1,
|
|
57
|
-
},
|
|
58
|
-
],
|
|
59
|
-
objectives: [
|
|
60
|
-
{
|
|
61
|
-
id: '6317996c77f2420047a20b53',
|
|
62
|
-
type: QuestType.Kill,
|
|
63
|
-
status: QuestStatus.Pending,
|
|
64
|
-
killCount: 10,
|
|
65
|
-
killCountTarget: 30,
|
|
66
|
-
creatureKeys: ['6317996c77f2420047a20b53'],
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
npcId: '6317996b77f2420047a20825',
|
|
70
|
-
title: 'Deliver message to the trader2',
|
|
71
|
-
key: 'interaction-trader',
|
|
72
|
-
description:
|
|
73
|
-
"Need to send a message to my brother, the trader, about my father's health. I cannot do it because it is too dangerous out there. Please, help me by delivering this message to him.",
|
|
74
|
-
createdAt: '2022-09-06T19:03:08.285+0000',
|
|
75
|
-
updatedAt: '2022-09-06T19:03:08.304+0000',
|
|
43
|
+
"Employ your pickaxe to mine ore, followed by utilizing your blacksmith hammer. Select 'Use with,' then target an anvil to forge ingots. Provide me with 10 Iron Ingots, and I shall craft you an Iron Armor!",
|
|
44
|
+
createdAt: '2024-08-27T01:25:24.285+0000',
|
|
45
|
+
updatedAt: '2024-08-27T01:25:24.304+0000',
|
|
46
|
+
status: QuestStatus.Pending,
|
|
76
47
|
},
|
|
77
48
|
];
|
|
78
49
|
|
|
79
50
|
Default.args = {
|
|
80
51
|
quests: IQuestMock,
|
|
81
|
-
onClose: () => console.log('closing'),
|
|
82
52
|
};
|