@rpg-engine/long-bow 0.8.45 → 0.8.46
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/Character/CharacterSkinSelectionModal.d.ts +13 -0
- package/dist/index.d.ts +1 -0
- package/dist/stories/Character/character/CharacterSkinSelectionModal.stories.d.ts +2 -12
- package/package.json +1 -1
- package/src/components/Character/CharacterSkinSelectionModal.tsx +157 -0
- package/src/index.tsx +1 -0
- package/src/stories/Character/character/CharacterSkinSelectionModal.stories.tsx +21 -160
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ICharacterProps } from './CharacterSelection';
|
|
3
|
+
export interface ICharacterSkinSelectionModalProps {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
onConfirm: (textureKey: string) => void;
|
|
7
|
+
availableCharacters: ICharacterProps[];
|
|
8
|
+
atlasJSON: any;
|
|
9
|
+
atlasIMG: any;
|
|
10
|
+
initialSelectedSkin?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const CharacterSkinSelectionModal: React.FC<ICharacterSkinSelectionModalProps>;
|
|
13
|
+
export default CharacterSkinSelectionModal;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './components/Arrow/SelectArrow';
|
|
|
2
2
|
export * from './components/AsyncDropdown';
|
|
3
3
|
export * from './components/Button';
|
|
4
4
|
export * from './components/Character/CharacterSelection';
|
|
5
|
+
export * from './components/Character/CharacterSkinSelectionModal';
|
|
5
6
|
export * from './components/Chat/Chat';
|
|
6
7
|
export * from './components/Chatdeprecated/ChatDeprecated';
|
|
7
8
|
export * from './components/ChatRevamp/ChatRevamp';
|
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
import { Meta } from '@storybook/react';
|
|
2
|
-
import {
|
|
3
|
-
export interface ICharacterSkinSelectionModalProps {
|
|
4
|
-
isOpen: boolean;
|
|
5
|
-
onClose: () => void;
|
|
6
|
-
onConfirm: (textureKey: string) => void;
|
|
7
|
-
availableCharacters: ICharacterProps[];
|
|
8
|
-
atlasJSON: any;
|
|
9
|
-
atlasIMG: any;
|
|
10
|
-
initialSelectedSkin?: string;
|
|
11
|
-
}
|
|
2
|
+
import { ICharacterSkinSelectionModalProps } from '../../../components/Character/CharacterSkinSelectionModal';
|
|
12
3
|
declare const meta: Meta;
|
|
13
4
|
export default meta;
|
|
14
|
-
export declare const
|
|
15
|
-
export declare const EmptySelection: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ICharacterSkinSelectionModalProps>;
|
|
5
|
+
export declare const KnightSkins: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ICharacterSkinSelectionModalProps>;
|
package/package.json
CHANGED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import styled from 'styled-components';
|
|
3
|
+
import { Button, ButtonTypes } from '../Button';
|
|
4
|
+
import { ErrorBoundary } from '../Item/Inventory/ErrorBoundary';
|
|
5
|
+
import PropertySelect, { IPropertiesProps } from '../PropertySelect/PropertySelect';
|
|
6
|
+
import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
|
|
7
|
+
import { ICharacterProps } from './CharacterSelection';
|
|
8
|
+
|
|
9
|
+
export interface ICharacterSkinSelectionModalProps {
|
|
10
|
+
isOpen: boolean;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
onConfirm: (textureKey: string) => void;
|
|
13
|
+
availableCharacters: ICharacterProps[];
|
|
14
|
+
atlasJSON: any;
|
|
15
|
+
atlasIMG: any;
|
|
16
|
+
initialSelectedSkin?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const CharacterSkinSelectionModal: React.FC<ICharacterSkinSelectionModalProps> = ({
|
|
20
|
+
isOpen,
|
|
21
|
+
onClose,
|
|
22
|
+
onConfirm,
|
|
23
|
+
availableCharacters,
|
|
24
|
+
atlasJSON,
|
|
25
|
+
atlasIMG,
|
|
26
|
+
initialSelectedSkin = '',
|
|
27
|
+
}) => {
|
|
28
|
+
// Convert availableCharacters to the format used by PropertySelect
|
|
29
|
+
const propertySelectValues = availableCharacters.map((item) => ({
|
|
30
|
+
id: item.textureKey,
|
|
31
|
+
name: item.name,
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
// State to store the selected skin and the sprite key
|
|
35
|
+
const [selectedValue, setSelectedValue] = useState<IPropertiesProps | undefined>();
|
|
36
|
+
const [selectedSpriteKey, setSelectedSpriteKey] = useState('');
|
|
37
|
+
|
|
38
|
+
// Update sprite when the selected value changes
|
|
39
|
+
const updateSelectedSpriteKey = () => {
|
|
40
|
+
const textureKey = selectedValue ? selectedValue.id : '';
|
|
41
|
+
const spriteKey = textureKey ? textureKey + '/down/standing/0.png' : '';
|
|
42
|
+
|
|
43
|
+
if (spriteKey === selectedSpriteKey) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setSelectedSpriteKey(spriteKey);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// Update sprite when selectedValue changes
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
updateSelectedSpriteKey();
|
|
53
|
+
}, [selectedValue]);
|
|
54
|
+
|
|
55
|
+
// Initialize selectedValue
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (initialSelectedSkin) {
|
|
58
|
+
const initialProperty = propertySelectValues.find(
|
|
59
|
+
(prop) => prop.id === initialSelectedSkin
|
|
60
|
+
);
|
|
61
|
+
setSelectedValue(initialProperty || propertySelectValues[0]);
|
|
62
|
+
} else if (propertySelectValues.length > 0) {
|
|
63
|
+
setSelectedValue(propertySelectValues[0]);
|
|
64
|
+
}
|
|
65
|
+
}, [initialSelectedSkin, availableCharacters]);
|
|
66
|
+
|
|
67
|
+
// Functions to handle confirmation and cancellation
|
|
68
|
+
const handleConfirm = () => {
|
|
69
|
+
if (selectedValue) {
|
|
70
|
+
onConfirm(selectedValue.id);
|
|
71
|
+
onClose();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const handleCancel = () => {
|
|
76
|
+
onClose();
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
if (!isOpen) return null;
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
|
|
83
|
+
<Container>
|
|
84
|
+
{selectedSpriteKey && atlasIMG && atlasJSON && (
|
|
85
|
+
<ErrorBoundary>
|
|
86
|
+
<SpriteFromAtlas
|
|
87
|
+
spriteKey={selectedSpriteKey}
|
|
88
|
+
atlasIMG={atlasIMG}
|
|
89
|
+
atlasJSON={atlasJSON}
|
|
90
|
+
imgScale={4}
|
|
91
|
+
height={80}
|
|
92
|
+
width={64}
|
|
93
|
+
containerStyle={{
|
|
94
|
+
display: 'flex',
|
|
95
|
+
alignItems: 'center',
|
|
96
|
+
paddingBottom: '15px',
|
|
97
|
+
}}
|
|
98
|
+
imgStyle={{
|
|
99
|
+
left: '22px',
|
|
100
|
+
}}
|
|
101
|
+
/>
|
|
102
|
+
</ErrorBoundary>
|
|
103
|
+
)}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
<PropertySelect
|
|
107
|
+
availableProperties={propertySelectValues}
|
|
108
|
+
onChange={(value) => {
|
|
109
|
+
setSelectedValue(value);
|
|
110
|
+
}}
|
|
111
|
+
/>
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
<ButtonsContainer>
|
|
116
|
+
<Button
|
|
117
|
+
buttonType={ButtonTypes.RPGUIButton}
|
|
118
|
+
onClick={handleCancel}
|
|
119
|
+
>
|
|
120
|
+
Cancel
|
|
121
|
+
</Button>
|
|
122
|
+
<Button
|
|
123
|
+
buttonType={ButtonTypes.RPGUIButton}
|
|
124
|
+
onClick={handleConfirm}
|
|
125
|
+
disabled={!selectedValue}
|
|
126
|
+
>
|
|
127
|
+
Confirm
|
|
128
|
+
</Button>
|
|
129
|
+
</ButtonsContainer>
|
|
130
|
+
</Container>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// Styled components
|
|
135
|
+
|
|
136
|
+
const Container = styled.div`
|
|
137
|
+
display: flex;
|
|
138
|
+
flex-direction: column;
|
|
139
|
+
align-items: center;
|
|
140
|
+
image-rendering: pixelated;
|
|
141
|
+
`;
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
const ButtonsContainer = styled.div`
|
|
145
|
+
display: flex;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
gap: 0.8rem;
|
|
148
|
+
width: 100%;
|
|
149
|
+
margin: 3rem 0 0.75rem;
|
|
150
|
+
|
|
151
|
+
button {
|
|
152
|
+
min-width: 95px;
|
|
153
|
+
font-size: 0.9rem;
|
|
154
|
+
}
|
|
155
|
+
`;
|
|
156
|
+
|
|
157
|
+
export default CharacterSkinSelectionModal;
|
package/src/index.tsx
CHANGED
|
@@ -2,6 +2,7 @@ export * from './components/Arrow/SelectArrow';
|
|
|
2
2
|
export * from './components/AsyncDropdown';
|
|
3
3
|
export * from './components/Button';
|
|
4
4
|
export * from './components/Character/CharacterSelection';
|
|
5
|
+
export * from './components/Character/CharacterSkinSelectionModal';
|
|
5
6
|
export * from './components/Chat/Chat';
|
|
6
7
|
export * from './components/Chatdeprecated/ChatDeprecated';
|
|
7
8
|
export * from './components/ChatRevamp/ChatRevamp';
|
|
@@ -1,105 +1,14 @@
|
|
|
1
1
|
import { Meta, Story } from '@storybook/react';
|
|
2
|
-
import React
|
|
3
|
-
import styled from 'styled-components';
|
|
2
|
+
import React from 'react';
|
|
4
3
|
import { RPGUIRoot } from '../../..';
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import { RPGUIContainerTypes } from '../../../components/RPGUI/RPGUIContainer';
|
|
4
|
+
import CharacterSkinSelectionModal, {
|
|
5
|
+
ICharacterSkinSelectionModalProps
|
|
6
|
+
} from '../../../components/Character/CharacterSkinSelectionModal';
|
|
9
7
|
import atlasJSON from '../../../mocks/atlas/entities/entities.json';
|
|
10
8
|
import atlasIMG from '../../../mocks/atlas/entities/entities.png';
|
|
11
9
|
|
|
12
|
-
// Create the missing interface
|
|
13
|
-
export interface ICharacterSkinSelectionModalProps {
|
|
14
|
-
isOpen: boolean;
|
|
15
|
-
onClose: () => void;
|
|
16
|
-
onConfirm: (textureKey: string) => void;
|
|
17
|
-
availableCharacters: ICharacterProps[];
|
|
18
|
-
atlasJSON: any;
|
|
19
|
-
atlasIMG: any;
|
|
20
|
-
initialSelectedSkin?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Temporary component to replace the missing one
|
|
24
|
-
const CharacterSkinSelectionModal: React.FC<ICharacterSkinSelectionModalProps> = ({
|
|
25
|
-
isOpen,
|
|
26
|
-
onClose,
|
|
27
|
-
onConfirm,
|
|
28
|
-
availableCharacters,
|
|
29
|
-
atlasJSON,
|
|
30
|
-
atlasIMG,
|
|
31
|
-
initialSelectedSkin = '',
|
|
32
|
-
}) => {
|
|
33
|
-
const [selectedSkin, setSelectedSkin] = useState<string>(initialSelectedSkin);
|
|
34
|
-
|
|
35
|
-
// Determine if we have a valid skin selection to enable/disable confirm button
|
|
36
|
-
const isConfirmEnabled = Boolean(selectedSkin);
|
|
37
|
-
|
|
38
|
-
// Reset selected skin when initial value changes or component mounts
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
// Allow for empty strings but not undefined
|
|
41
|
-
if (initialSelectedSkin !== undefined) {
|
|
42
|
-
setSelectedSkin(initialSelectedSkin);
|
|
43
|
-
} else if (availableCharacters.length > 0) {
|
|
44
|
-
// Default to first skin if none provided
|
|
45
|
-
setSelectedSkin(availableCharacters[0].textureKey);
|
|
46
|
-
}
|
|
47
|
-
}, [initialSelectedSkin, availableCharacters]);
|
|
48
|
-
|
|
49
|
-
const handleConfirm = (): void => {
|
|
50
|
-
if (selectedSkin) {
|
|
51
|
-
onConfirm(selectedSkin);
|
|
52
|
-
onClose();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const handleCancel = (): void => {
|
|
57
|
-
onClose();
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
if (!isOpen) return null;
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<ModalOverlay>
|
|
64
|
-
<DraggableContainer
|
|
65
|
-
type={RPGUIContainerTypes.Framed}
|
|
66
|
-
width="30rem"
|
|
67
|
-
onCloseButton={onClose}
|
|
68
|
-
title="Selecionar Skin"
|
|
69
|
-
>
|
|
70
|
-
<ModalContent>
|
|
71
|
-
<CharacterSelectionWrapper>
|
|
72
|
-
<CharacterSelection
|
|
73
|
-
availableCharacters={availableCharacters}
|
|
74
|
-
atlasJSON={atlasJSON}
|
|
75
|
-
atlasIMG={atlasIMG}
|
|
76
|
-
onChange={(textureKey) => setSelectedSkin(textureKey)}
|
|
77
|
-
/>
|
|
78
|
-
</CharacterSelectionWrapper>
|
|
79
|
-
|
|
80
|
-
<ButtonsContainer>
|
|
81
|
-
<Button
|
|
82
|
-
buttonType={ButtonTypes.RPGUIButton}
|
|
83
|
-
onClick={handleCancel}
|
|
84
|
-
>
|
|
85
|
-
Cancelar
|
|
86
|
-
</Button>
|
|
87
|
-
<Button
|
|
88
|
-
buttonType={ButtonTypes.RPGUIButton}
|
|
89
|
-
onClick={handleConfirm}
|
|
90
|
-
disabled={!isConfirmEnabled}
|
|
91
|
-
>
|
|
92
|
-
Confirmar
|
|
93
|
-
</Button>
|
|
94
|
-
</ButtonsContainer>
|
|
95
|
-
</ModalContent>
|
|
96
|
-
</DraggableContainer>
|
|
97
|
-
</ModalOverlay>
|
|
98
|
-
);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
10
|
const meta: Meta = {
|
|
102
|
-
title: 'Character/Character/Skin Selection
|
|
11
|
+
title: 'Character/Character/Skin Selection',
|
|
103
12
|
component: CharacterSkinSelectionModal,
|
|
104
13
|
};
|
|
105
14
|
|
|
@@ -111,78 +20,30 @@ const Template: Story<ICharacterSkinSelectionModalProps> = (args: ICharacterSkin
|
|
|
111
20
|
</RPGUIRoot>
|
|
112
21
|
);
|
|
113
22
|
|
|
114
|
-
export const
|
|
115
|
-
export const EmptySelection = Template.bind({});
|
|
23
|
+
export const KnightSkins = Template.bind({});
|
|
116
24
|
|
|
117
|
-
//
|
|
118
|
-
const
|
|
25
|
+
// Example of different knight skins
|
|
26
|
+
const knightCharacters = [
|
|
119
27
|
{
|
|
120
|
-
name: '
|
|
121
|
-
textureKey: '
|
|
28
|
+
name: 'Black Knight',
|
|
29
|
+
textureKey: 'black-knight',
|
|
122
30
|
},
|
|
123
31
|
{
|
|
124
|
-
name: '
|
|
125
|
-
textureKey: '
|
|
32
|
+
name: 'Dragon Knight',
|
|
33
|
+
textureKey: 'dragon-knight',
|
|
126
34
|
},
|
|
127
35
|
{
|
|
128
|
-
name: '
|
|
129
|
-
textureKey: '
|
|
130
|
-
}
|
|
36
|
+
name: 'Senior Knight',
|
|
37
|
+
textureKey: 'senior-knight-1',
|
|
38
|
+
}
|
|
131
39
|
];
|
|
132
40
|
|
|
133
|
-
|
|
41
|
+
KnightSkins.args = {
|
|
134
42
|
isOpen: true,
|
|
135
|
-
onClose: () => console.log('Modal
|
|
136
|
-
onConfirm: (textureKey: string) => console.log('
|
|
137
|
-
availableCharacters:
|
|
43
|
+
onClose: () => console.log('Modal closed'),
|
|
44
|
+
onConfirm: (textureKey: string) => console.log('Selected skin:', textureKey),
|
|
45
|
+
availableCharacters: knightCharacters,
|
|
138
46
|
atlasJSON: atlasJSON,
|
|
139
47
|
atlasIMG: atlasIMG,
|
|
140
|
-
initialSelectedSkin: '
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
EmptySelection.args = {
|
|
144
|
-
isOpen: true,
|
|
145
|
-
onClose: () => console.log('Modal fechado'),
|
|
146
|
-
onConfirm: (textureKey: string) => console.log('Skin selecionada:', textureKey),
|
|
147
|
-
availableCharacters: availableCharacters,
|
|
148
|
-
atlasJSON: atlasJSON,
|
|
149
|
-
atlasIMG: atlasIMG,
|
|
150
|
-
initialSelectedSkin: '',
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// Componentes estilizados
|
|
154
|
-
const ModalOverlay = styled.div`
|
|
155
|
-
position: fixed;
|
|
156
|
-
top: 0;
|
|
157
|
-
left: 0;
|
|
158
|
-
right: 0;
|
|
159
|
-
bottom: 0;
|
|
160
|
-
display: flex;
|
|
161
|
-
align-items: center;
|
|
162
|
-
justify-content: center;
|
|
163
|
-
z-index: 100;
|
|
164
|
-
`;
|
|
165
|
-
|
|
166
|
-
const ModalContent = styled.div`
|
|
167
|
-
padding: 20px;
|
|
168
|
-
display: flex;
|
|
169
|
-
flex-direction: column;
|
|
170
|
-
align-items: center;
|
|
171
|
-
min-width: 300px;
|
|
172
|
-
`;
|
|
173
|
-
|
|
174
|
-
const CharacterSelectionWrapper = styled.div`
|
|
175
|
-
width: 100%;
|
|
176
|
-
margin-bottom: 20px;
|
|
177
|
-
`;
|
|
178
|
-
|
|
179
|
-
const ButtonsContainer = styled.div`
|
|
180
|
-
display: flex;
|
|
181
|
-
justify-content: space-between;
|
|
182
|
-
width: 100%;
|
|
183
|
-
margin-top: 20px;
|
|
184
|
-
|
|
185
|
-
button {
|
|
186
|
-
margin: 0 10px;
|
|
187
|
-
}
|
|
188
|
-
`;
|
|
48
|
+
initialSelectedSkin: 'black-knight',
|
|
49
|
+
};
|