@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.
@@ -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 { ICharacterProps } from '../../../components/Character/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
- }
2
+ import { ICharacterSkinSelectionModalProps } from '../../../components/Character/CharacterSkinSelectionModal';
12
3
  declare const meta: Meta;
13
4
  export default meta;
14
- export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ICharacterSkinSelectionModalProps>;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.45",
3
+ "version": "0.8.46",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -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, { useEffect, useState } from 'react';
3
- import styled from 'styled-components';
2
+ import React from 'react';
4
3
  import { RPGUIRoot } from '../../..';
5
- import { Button, ButtonTypes } from '../../../components/Button';
6
- import CharacterSelection, { ICharacterProps } from '../../../components/Character/CharacterSelection';
7
- import { DraggableContainer } from '../../../components/DraggableContainer';
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 Modal',
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 Default = Template.bind({});
115
- export const EmptySelection = Template.bind({});
23
+ export const KnightSkins = Template.bind({});
116
24
 
117
- // Dados de exemplo para os personagens disponíveis
118
- const availableCharacters = [
25
+ // Example of different knight skins
26
+ const knightCharacters = [
119
27
  {
120
- name: 'Woman',
121
- textureKey: 'woman-1',
28
+ name: 'Black Knight',
29
+ textureKey: 'black-knight',
122
30
  },
123
31
  {
124
- name: 'Kid',
125
- textureKey: 'kid-1',
32
+ name: 'Dragon Knight',
33
+ textureKey: 'dragon-knight',
126
34
  },
127
35
  {
128
- name: 'Purple Hair Hero 1',
129
- textureKey: 'purple-hair-hero-1',
130
- },
36
+ name: 'Senior Knight',
37
+ textureKey: 'senior-knight-1',
38
+ }
131
39
  ];
132
40
 
133
- Default.args = {
41
+ KnightSkins.args = {
134
42
  isOpen: true,
135
- onClose: () => console.log('Modal fechado'),
136
- onConfirm: (textureKey: string) => console.log('Skin selecionada:', textureKey),
137
- availableCharacters: 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: 'woman-1',
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
+ };