@rpg-engine/long-bow 0.4.8 → 0.4.9

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.4.8",
3
+ "version": "0.4.9",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -1,114 +1,114 @@
1
- import React, { useEffect, useState } from 'react';
2
- import styled from 'styled-components';
3
- import { v4 as uuidv4 } from 'uuid';
4
-
5
- export interface IOptionsProps {
6
- id: number;
7
- value: string;
8
- option: string | JSX.Element;
9
- }
10
-
11
- export interface IDropdownProps {
12
- options: IOptionsProps[];
13
- width?: string;
14
- onChange: (value: string) => void;
15
- }
16
-
17
- export const Dropdown: React.FC<IDropdownProps> = ({
18
- options,
19
- width,
20
- onChange,
21
- }) => {
22
- const dropdownId = uuidv4();
23
-
24
- const [selectedValue, setSelectedValue] = useState<string>('');
25
- const [selectedOption, setSelectedOption] = useState<string | JSX.Element>(
26
- ''
27
- );
28
- const [opened, setOpened] = useState<boolean>(false);
29
-
30
- useEffect(() => {
31
- const firstOption = options[0];
32
-
33
- if (firstOption) {
34
- let change = !selectedValue;
35
- if (!change) {
36
- change = options.filter(o => o.value === selectedValue).length < 1;
37
- }
38
-
39
- /**
40
- * make a selection if there is no selected value already present
41
- * or if there is a selected value but its not in new options
42
- */
43
- if (change) {
44
- setSelectedValue(firstOption.value);
45
- setSelectedOption(firstOption.option);
46
- }
47
- }
48
- }, [options]);
49
-
50
- useEffect(() => {
51
- if (selectedValue) {
52
- onChange(selectedValue);
53
- }
54
- }, [selectedValue]);
55
-
56
- return (
57
- <Container onMouseLeave={() => setOpened(false)} width={width}>
58
- <DropdownSelect
59
- id={`dropdown-${dropdownId}`}
60
- className="rpgui-dropdown-imp rpgui-dropdown-imp-header"
61
- onPointerUp={() => setOpened(prev => !prev)}
62
- >
63
- <label>▼</label> {selectedOption}
64
- </DropdownSelect>
65
-
66
- <DropdownOptions className="rpgui-dropdown-imp" opened={opened}>
67
- {options.map(option => {
68
- return (
69
- <li
70
- key={option.id}
71
- onPointerUp={() => {
72
- setSelectedValue(option.value);
73
- setSelectedOption(option.option);
74
- setOpened(false);
75
- }}
76
- >
77
- {option.option}
78
- </li>
79
- );
80
- })}
81
- </DropdownOptions>
82
- </Container>
83
- );
84
- };
85
-
86
- const Container = styled.div<{ width: string | undefined }>`
87
- position: relative;
88
- width: ${props => props.width || '100%'};
89
- `;
90
-
91
- const DropdownSelect = styled.p`
92
- width: 100%;
93
- box-sizing: border-box;
94
-
95
- label {
96
- display: inline-block;
97
- transform: translateY(-2px);
98
- }
99
- `;
100
-
101
- const DropdownOptions = styled.ul<{
102
- opened: boolean;
103
- }>`
104
- position: absolute;
105
- width: 100%;
106
- max-height: 300px;
107
- overflow-y: auto;
108
- display: ${props => (props.opened ? 'block' : 'none')};
109
- box-sizing: border-box;
110
-
111
- @media (max-width: 768px) {
112
- padding: 8px 0;
113
- }
114
- `;
1
+ import React, { useEffect, useState } from 'react';
2
+ import styled from 'styled-components';
3
+ import { v4 as uuidv4 } from 'uuid';
4
+
5
+ export interface IOptionsProps {
6
+ id: number;
7
+ value: string;
8
+ option: string | JSX.Element;
9
+ }
10
+
11
+ export interface IDropdownProps {
12
+ options: IOptionsProps[];
13
+ width?: string;
14
+ onChange: (value: string) => void;
15
+ }
16
+
17
+ export const Dropdown: React.FC<IDropdownProps> = ({
18
+ options,
19
+ width,
20
+ onChange,
21
+ }) => {
22
+ const dropdownId = uuidv4();
23
+
24
+ const [selectedValue, setSelectedValue] = useState<string>('');
25
+ const [selectedOption, setSelectedOption] = useState<string | JSX.Element>(
26
+ ''
27
+ );
28
+ const [opened, setOpened] = useState<boolean>(false);
29
+
30
+ useEffect(() => {
31
+ const firstOption = options[0];
32
+
33
+ if (firstOption) {
34
+ let change = !selectedValue;
35
+ if (!change) {
36
+ change = options.filter(o => o.value === selectedValue).length < 1;
37
+ }
38
+
39
+ /**
40
+ * make a selection if there is no selected value already present
41
+ * or if there is a selected value but its not in new options
42
+ */
43
+ if (change) {
44
+ setSelectedValue(firstOption.value);
45
+ setSelectedOption(firstOption.option);
46
+ }
47
+ }
48
+ }, [options]);
49
+
50
+ useEffect(() => {
51
+ if (selectedValue) {
52
+ onChange(selectedValue);
53
+ }
54
+ }, [selectedValue]);
55
+
56
+ return (
57
+ <Container onMouseLeave={() => setOpened(false)} width={width}>
58
+ <DropdownSelect
59
+ id={`dropdown-${dropdownId}`}
60
+ className="rpgui-dropdown-imp rpgui-dropdown-imp-header"
61
+ onPointerUp={() => setOpened(prev => !prev)}
62
+ >
63
+ <label>▼</label> {selectedOption}
64
+ </DropdownSelect>
65
+
66
+ <DropdownOptions className="rpgui-dropdown-imp" opened={opened}>
67
+ {options.map(option => {
68
+ return (
69
+ <li
70
+ key={option.id}
71
+ onPointerUp={() => {
72
+ setSelectedValue(option.value);
73
+ setSelectedOption(option.option);
74
+ setOpened(false);
75
+ }}
76
+ >
77
+ {option.option}
78
+ </li>
79
+ );
80
+ })}
81
+ </DropdownOptions>
82
+ </Container>
83
+ );
84
+ };
85
+
86
+ const Container = styled.div<{ width: string | undefined }>`
87
+ position: relative;
88
+ width: ${props => props.width || '100%'};
89
+ `;
90
+
91
+ const DropdownSelect = styled.p`
92
+ width: 100%;
93
+ box-sizing: border-box;
94
+
95
+ label {
96
+ display: inline-block;
97
+ transform: translateY(-2px);
98
+ }
99
+ `;
100
+
101
+ const DropdownOptions = styled.ul<{
102
+ opened: boolean;
103
+ }>`
104
+ position: absolute;
105
+ width: 100%;
106
+ max-height: 300px;
107
+ overflow-y: auto;
108
+ display: ${props => (props.opened ? 'block' : 'none')};
109
+ box-sizing: border-box;
110
+
111
+ @media (max-width: 768px) {
112
+ padding: 8px 0;
113
+ }
114
+ `;
@@ -1,5 +1,5 @@
1
1
  import { IEquipmentSet, IMarketplaceItem } from '@rpg-engine/shared';
2
- import React, { useState } from 'react';
2
+ import React, { useEffect, useRef, useState } from 'react';
3
3
  import { AiFillCaretRight } from 'react-icons/ai';
4
4
  import styled from 'styled-components';
5
5
  import { ConfirmModal } from '../ConfirmModal';
@@ -30,6 +30,7 @@ export interface IBuyPanelProps {
30
30
  characterId: string;
31
31
  enableHotkeys?: () => void;
32
32
  disableHotkeys?: () => void;
33
+ currentPage: number;
33
34
  }
34
35
 
35
36
  export const BuyPanel: React.FC<IBuyPanelProps> = ({
@@ -48,6 +49,7 @@ export const BuyPanel: React.FC<IBuyPanelProps> = ({
48
49
  characterId,
49
50
  enableHotkeys,
50
51
  disableHotkeys,
52
+ currentPage,
51
53
  }) => {
52
54
  const [name, setName] = useState('');
53
55
  const [mainLevel, setMainLevel] = useState<
@@ -62,6 +64,12 @@ export const BuyPanel: React.FC<IBuyPanelProps> = ({
62
64
  ]);
63
65
  const [buyingItemId, setBuyingItemId] = useState<string | null>(null);
64
66
 
67
+ const itemsContainer = useRef<HTMLDivElement>(null);
68
+
69
+ useEffect(() => {
70
+ itemsContainer.current?.scrollTo(0, 0);
71
+ }, [currentPage]);
72
+
65
73
  return (
66
74
  <>
67
75
  {buyingItemId && (
@@ -200,7 +208,7 @@ export const BuyPanel: React.FC<IBuyPanelProps> = ({
200
208
  </WrapperContainer>
201
209
  </OptionsWrapper>
202
210
 
203
- <ItemComponentScrollWrapper id="MarketContainer">
211
+ <ItemComponentScrollWrapper id="MarketContainer" ref={itemsContainer}>
204
212
  {items?.map(({ item, price, _id, owner }, index) => (
205
213
  <MarketplaceRows
206
214
  key={`${item.key}_${index}`}
@@ -1,5 +1,5 @@
1
1
  import { IEquipmentSet, IItem, IMarketplaceItem } from '@rpg-engine/shared';
2
- import React, { useState } from 'react';
2
+ import React, { useEffect, useRef, useState } from 'react';
3
3
  import styled from 'styled-components';
4
4
  import { uiColors } from '../../constants/uiColors';
5
5
  import { uiFonts } from '../../constants/uiFonts';
@@ -23,6 +23,7 @@ export interface IManagmentPanelProps {
23
23
  enableHotkeys?: () => void;
24
24
  disableHotkeys?: () => void;
25
25
  onMoneyWithdraw: () => void;
26
+ currentPage: number;
26
27
  }
27
28
 
28
29
  export const ManagmentPanel: React.FC<IManagmentPanelProps> = ({
@@ -39,12 +40,19 @@ export const ManagmentPanel: React.FC<IManagmentPanelProps> = ({
39
40
  enableHotkeys,
40
41
  disableHotkeys,
41
42
  onMoneyWithdraw,
43
+ currentPage,
42
44
  }) => {
43
45
  const [name, setName] = useState('');
44
46
  const [price, setPrice] = useState('');
45
47
  const [isCreatingOffer, setIsCreatingOffer] = useState(false);
46
48
  const [removingItemId, setRemovingItemId] = useState<string | null>(null);
47
49
 
50
+ const itemsContainer = useRef<HTMLDivElement>(null);
51
+
52
+ useEffect(() => {
53
+ itemsContainer.current?.scrollTo(0, 0);
54
+ }, [currentPage]);
55
+
48
56
  return (
49
57
  <>
50
58
  {isCreatingOffer && (
@@ -144,7 +152,7 @@ export const ManagmentPanel: React.FC<IManagmentPanelProps> = ({
144
152
  </InnerOptionsWrapper>
145
153
  </OptionsWrapper>
146
154
 
147
- <ItemComponentScrollWrapper id="MarketContainer">
155
+ <ItemComponentScrollWrapper id="MarketContainer" ref={itemsContainer}>
148
156
  {items?.map(({ item, price, _id }, index) => (
149
157
  <MarketplaceRows
150
158
  key={`${item.key}_${index}`}
@@ -9,6 +9,7 @@ import { uiColors } from '../../constants/uiColors';
9
9
  import { uiFonts } from '../../constants/uiFonts';
10
10
  import { Button, ButtonTypes } from '../Button';
11
11
  import { ItemInfoWrapper } from '../Item/Cards/ItemInfoWrapper';
12
+ import { rarityColor } from '../Item/Inventory/ItemSlot';
12
13
  import { Ellipsis } from '../shared/Ellipsis';
13
14
  import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
14
15
 
@@ -37,54 +38,57 @@ export const MarketplaceRows: React.FC<IMarketPlaceRowsPropos> = ({
37
38
  }) => {
38
39
  return (
39
40
  <MarketplaceWrapper>
40
- <ItemInfoWrapper
41
- item={item}
42
- atlasIMG={atlasIMG}
43
- atlasJSON={atlasJSON}
44
- equipmentSet={equipmentSet}
45
- scale={scale}
46
- >
47
- <ItemIconContainer>
48
- <SpriteContainer>
49
- <SpriteFromAtlas
50
- atlasIMG={atlasIMG}
51
- atlasJSON={atlasJSON}
52
- spriteKey={getItemTextureKeyPath(
53
- {
54
- key: item.key,
55
- stackQty: item.stackQty || 1,
56
- texturePath: item.texturePath,
57
- isStackable: item.isStackable,
58
- },
59
- atlasJSON
60
- )}
61
- imgScale={2}
62
- />
41
+ <ItemIconContainer>
42
+ <SpriteContainer>
43
+ <ItemInfoWrapper
44
+ item={item}
45
+ atlasIMG={atlasIMG}
46
+ atlasJSON={atlasJSON}
47
+ equipmentSet={equipmentSet}
48
+ scale={scale}
49
+ >
50
+ <RarityContainer item={item}>
51
+ <SpriteFromAtlas
52
+ atlasIMG={atlasIMG}
53
+ atlasJSON={atlasJSON}
54
+ spriteKey={getItemTextureKeyPath(
55
+ {
56
+ key: item.key,
57
+ stackQty: item.stackQty || 1,
58
+ texturePath: item.texturePath,
59
+ isStackable: item.isStackable,
60
+ },
61
+ atlasJSON
62
+ )}
63
+ imgScale={2}
64
+ />
65
+ </RarityContainer>
63
66
  <QuantityContainer>
64
67
  {item.stackQty &&
65
68
  item.stackQty > 1 &&
66
69
  `x${Math.round(item.stackQty * 10) / 10}`}
67
70
  </QuantityContainer>
68
- </SpriteContainer>
69
- <PriceValue>
70
- <p>
71
- <Ellipsis maxLines={1} maxWidth="200px" fontSize="10px">
72
- {item.name}
73
- </Ellipsis>
74
- </p>
75
- </PriceValue>
76
- </ItemIconContainer>
77
- </ItemInfoWrapper>
71
+ </ItemInfoWrapper>
72
+ </SpriteContainer>
73
+ <PriceValue>
74
+ <p>
75
+ <Ellipsis maxLines={1} maxWidth="200px" fontSize="10px">
76
+ {item.name}
77
+ </Ellipsis>
78
+ </p>
79
+ </PriceValue>
80
+ </ItemIconContainer>
81
+
78
82
  <Flex>
79
83
  <ItemIconContainer>
80
- <SpriteContainer>
84
+ <GoldContainer>
81
85
  <SpriteFromAtlas
82
86
  atlasIMG={atlasIMG}
83
87
  atlasJSON={atlasJSON}
84
88
  spriteKey="others/gold-coin-qty-5.png"
85
89
  imgScale={2}
86
90
  />
87
- </SpriteContainer>
91
+ </GoldContainer>
88
92
  <PriceValue>
89
93
  <p>
90
94
  <Ellipsis maxLines={1} maxWidth="200px" fontSize="10px">
@@ -146,11 +150,15 @@ const ItemIconContainer = styled.div`
146
150
  align-items: center;
147
151
  `;
148
152
 
149
- const SpriteContainer = styled.div`
153
+ const GoldContainer = styled.div`
150
154
  position: relative;
151
155
  top: -0.5rem;
152
156
  left: 0.5rem;
153
157
  `;
158
+ const SpriteContainer = styled.div`
159
+ position: relative;
160
+ left: 0.5rem;
161
+ `;
154
162
 
155
163
  const PriceValue = styled.div`
156
164
  margin-left: 40px;
@@ -159,3 +167,11 @@ const PriceValue = styled.div`
159
167
  const ButtonContainer = styled.div`
160
168
  margin: auto;
161
169
  `;
170
+
171
+ const RarityContainer = styled.div<{ item: IItem }>`
172
+ border-color: ${({ item }) => rarityColor(item)};
173
+ box-shadow: ${({ item }) => `0 0 5px 8px ${rarityColor(item)}`} inset,
174
+ ${({ item }) => `0 0 8px 6px ${rarityColor(item)}`};
175
+ width: 32px;
176
+ height: 32px;
177
+ `;
@@ -14,40 +14,44 @@ const meta: Meta = {
14
14
 
15
15
  export default meta;
16
16
 
17
- const Template: Story = () => (
18
- <RPGUIRoot>
19
- <Marketplace
20
- onChangeOrder={value => console.log(value)}
21
- onChangeRarity={value => console.log(value)}
22
- onChangeType={value => console.log(value)}
23
- onChangeNameInput={event => console.log(event)}
24
- onChangePriceInput={value => console.log(value)}
25
- onChangeMainLevelInput={value => console.log(value)}
26
- onChangeSecondaryLevelInput={value => console.log(value)}
27
- atlasIMG={atlasIMG}
28
- atlasJSON={atlasJSON}
29
- onClose={() => console.log('close')}
30
- items={items.map(item => ({
31
- item,
32
- price: Math.round(Math.random() * 1000),
33
- _id: Math.random().toString(),
34
- owner: Math.random().toString(),
35
- }))}
36
- equipmentSet={equipmentSetMock}
37
- onMarketPlaceItemBuy={tradeId => console.log(tradeId)}
38
- availableGold={0}
39
- selectedItemToSell={null}
40
- onSelectedItemToSellRemove={() => console.log('click')}
41
- onYourPanelToggle={() => console.log('toggle')}
42
- onAddItemToMarketplace={() => console.log('add')}
43
- characterId="1"
44
- onMoneyWithdraw={() => console.log('withdraw')}
45
- totalItems={100}
46
- currentPage={1}
47
- itemsPerPage={30}
48
- onPageChange={page => console.log(page)}
49
- />
50
- </RPGUIRoot>
51
- );
17
+ const Template: Story = () => {
18
+ const [page, setPage] = React.useState(1);
19
+
20
+ return (
21
+ <RPGUIRoot>
22
+ <Marketplace
23
+ onChangeOrder={value => console.log(value)}
24
+ onChangeRarity={value => console.log(value)}
25
+ onChangeType={value => console.log(value)}
26
+ onChangeNameInput={event => console.log(event)}
27
+ onChangePriceInput={value => console.log(value)}
28
+ onChangeMainLevelInput={value => console.log(value)}
29
+ onChangeSecondaryLevelInput={value => console.log(value)}
30
+ atlasIMG={atlasIMG}
31
+ atlasJSON={atlasJSON}
32
+ onClose={() => console.log('close')}
33
+ items={items.map(item => ({
34
+ item,
35
+ price: Math.round(Math.random() * 1000),
36
+ _id: Math.random().toString(),
37
+ owner: Math.random().toString(),
38
+ }))}
39
+ equipmentSet={equipmentSetMock}
40
+ onMarketPlaceItemBuy={tradeId => console.log(tradeId)}
41
+ availableGold={0}
42
+ selectedItemToSell={null}
43
+ onSelectedItemToSellRemove={() => console.log('click')}
44
+ onYourPanelToggle={() => console.log('toggle')}
45
+ onAddItemToMarketplace={() => console.log('add')}
46
+ characterId="1"
47
+ onMoneyWithdraw={() => console.log('withdraw')}
48
+ totalItems={100}
49
+ currentPage={page}
50
+ itemsPerPage={30}
51
+ onPageChange={setPage}
52
+ />
53
+ </RPGUIRoot>
54
+ );
55
+ };
52
56
 
53
57
  export const Default = Template.bind({});
@@ -19,7 +19,6 @@ const Template: Story = () => (
19
19
  atlasIMG={atlasIMG}
20
20
  atlasJSON={atlasJSON}
21
21
  itemPrice={10}
22
- onHandleClick={value => console.log(value)}
23
22
  item={items[0]}
24
23
  />
25
24
  </RPGUIRoot>