@rpg-engine/long-bow 0.4.81 → 0.4.82

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.
Files changed (176) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +181 -181
  3. package/dist/components/Marketplace/BuyPanel.d.ts +1 -0
  4. package/dist/components/Marketplace/ManagmentPanel.d.ts +1 -0
  5. package/dist/long-bow.cjs.development.js +1297 -1256
  6. package/dist/long-bow.cjs.development.js.map +1 -1
  7. package/dist/long-bow.cjs.production.min.js +1 -1
  8. package/dist/long-bow.cjs.production.min.js.map +1 -1
  9. package/dist/long-bow.esm.js +1187 -1146
  10. package/dist/long-bow.esm.js.map +1 -1
  11. package/package.json +100 -100
  12. package/src/components/Abstractions/ModalPortal.tsx +22 -22
  13. package/src/components/Abstractions/SlotsContainer.tsx +62 -62
  14. package/src/components/Arrow/SelectArrow.tsx +69 -69
  15. package/src/components/Arrow/img/arrow01-left-clicked.png +0 -0
  16. package/src/components/Arrow/img/arrow01-left.png +0 -0
  17. package/src/components/Arrow/img/arrow01-right-clicked.png +0 -0
  18. package/src/components/Arrow/img/arrow01-right.png +0 -0
  19. package/src/components/Arrow/img/arrow02-left-clicked.png +0 -0
  20. package/src/components/Arrow/img/arrow02-left.png +0 -0
  21. package/src/components/Arrow/img/arrow02-right-clicked.png +0 -0
  22. package/src/components/Arrow/img/arrow02-right.png +0 -0
  23. package/src/components/Button.tsx +40 -40
  24. package/src/components/Character/CharacterSelection.tsx +98 -98
  25. package/src/components/CharacterStatus/CharacterStatus.tsx +120 -120
  26. package/src/components/Chat/Chat.tsx +196 -196
  27. package/src/components/Chatdeprecated/ChatDeprecated.tsx +198 -198
  28. package/src/components/CheckButton.tsx +65 -65
  29. package/src/components/CircularController/CircularController.tsx +282 -282
  30. package/src/components/ConfirmModal.tsx +87 -87
  31. package/src/components/CraftBook/CraftBook.tsx +286 -286
  32. package/src/components/CraftBook/CraftingRecipe.tsx +161 -161
  33. package/src/components/CraftBook/MockItems.ts +101 -101
  34. package/src/components/DraggableContainer.tsx +183 -183
  35. package/src/components/Dropdown.tsx +114 -114
  36. package/src/components/DropdownSelectorContainer.tsx +42 -42
  37. package/src/components/Equipment/EquipmentSet.tsx +199 -199
  38. package/src/components/HistoryDialog.tsx +104 -104
  39. package/src/components/Input.tsx +15 -15
  40. package/src/components/InputRadio.tsx +41 -41
  41. package/src/components/Item/Cards/ItemInfo.tsx +298 -298
  42. package/src/components/Item/Cards/ItemInfoDisplay.tsx +135 -135
  43. package/src/components/Item/Cards/ItemInfoWrapper.tsx +62 -62
  44. package/src/components/Item/Cards/ItemTooltip.tsx +83 -83
  45. package/src/components/Item/Cards/MobileItemTooltip.tsx +149 -149
  46. package/src/components/Item/Inventory/ErrorBoundary.tsx +42 -42
  47. package/src/components/Item/Inventory/ItemContainer.tsx +231 -231
  48. package/src/components/Item/Inventory/ItemContainerTypes.ts +6 -6
  49. package/src/components/Item/Inventory/ItemQuantitySelector.tsx +138 -138
  50. package/src/components/Item/Inventory/ItemSlot.tsx +595 -595
  51. package/src/components/Item/Inventory/itemContainerHelper.ts +175 -175
  52. package/src/components/ListMenu.tsx +63 -63
  53. package/src/components/Marketplace/BuyPanel.tsx +304 -296
  54. package/src/components/Marketplace/ManagmentPanel.tsx +255 -247
  55. package/src/components/Marketplace/Marketplace.tsx +106 -106
  56. package/src/components/Marketplace/MarketplaceRows.tsx +177 -161
  57. package/src/components/Marketplace/filters/index.tsx +67 -67
  58. package/src/components/Multitab/Tab.tsx +66 -66
  59. package/src/components/Multitab/TabBody.tsx +13 -13
  60. package/src/components/Multitab/TabsContainer.tsx +97 -97
  61. package/src/components/NPCDialog/NPCDialog.tsx +121 -121
  62. package/src/components/NPCDialog/NPCDialogText.tsx +113 -113
  63. package/src/components/NPCDialog/NPCMultiDialog.tsx +159 -159
  64. package/src/components/NPCDialog/QuestionDialog/QuestionDialog.tsx +237 -237
  65. package/src/components/Pager.tsx +94 -94
  66. package/src/components/ProgressBar.tsx +102 -102
  67. package/src/components/PropertySelect/PropertySelect.tsx +106 -106
  68. package/src/components/QuestInfo/QuestInfo.tsx +233 -233
  69. package/src/components/QuestList.tsx +135 -135
  70. package/src/components/RPGUIContainer.tsx +47 -47
  71. package/src/components/RPGUIForceRenderStart.tsx +45 -45
  72. package/src/components/RPGUIRoot.tsx +14 -14
  73. package/src/components/RadioButton.tsx +53 -53
  74. package/src/components/RadioInput/RadioButton.tsx +96 -96
  75. package/src/components/RadioInput/RadioInput.tsx +102 -102
  76. package/src/components/RadioInput/instruments.ts +15 -15
  77. package/src/components/RangeSlider.tsx +78 -78
  78. package/src/components/RelativeListMenu.tsx +90 -90
  79. package/src/components/ScrollList.tsx +79 -79
  80. package/src/components/Shortcuts/Shortcuts.tsx +193 -193
  81. package/src/components/Shortcuts/ShortcutsSetter.tsx +139 -139
  82. package/src/components/Shortcuts/SingleShortcut.ts +82 -82
  83. package/src/components/Shortcuts/useShortcutCooldown.ts +23 -23
  84. package/src/components/SimpleProgressBar.tsx +62 -62
  85. package/src/components/SkillProgressBar.tsx +206 -198
  86. package/src/components/SkillsContainer.tsx +213 -213
  87. package/src/components/Spellbook/Spell.tsx +235 -235
  88. package/src/components/Spellbook/Spellbook.tsx +145 -145
  89. package/src/components/Spellbook/cards/MobileSpellTooltip.tsx +137 -137
  90. package/src/components/Spellbook/cards/SpellInfo.tsx +134 -134
  91. package/src/components/Spellbook/cards/SpellInfoDisplay.tsx +31 -31
  92. package/src/components/Spellbook/cards/SpellInfoWrapper.tsx +48 -48
  93. package/src/components/Spellbook/cards/SpellTooltip.tsx +70 -70
  94. package/src/components/Spellbook/constants.ts +7 -7
  95. package/src/components/Spellbook/mockSpells.ts +84 -84
  96. package/src/components/StaticBook/StaticBook.tsx +103 -103
  97. package/src/components/TextArea.tsx +11 -11
  98. package/src/components/TimeWidget/DayNightPeriod/DayNightPeriod.tsx +35 -35
  99. package/src/components/TimeWidget/TimeWidget.tsx +65 -65
  100. package/src/components/TradingMenu/TradingItemRow.tsx +199 -199
  101. package/src/components/TradingMenu/TradingMenu.tsx +219 -219
  102. package/src/components/TradingMenu/items.mock.ts +48 -48
  103. package/src/components/Truncate.tsx +25 -25
  104. package/src/components/itemSelector/ItemSelector.tsx +136 -136
  105. package/src/components/shared/Column.tsx +16 -16
  106. package/src/components/shared/Ellipsis.tsx +76 -76
  107. package/src/components/shared/SpriteFromAtlas.tsx +104 -104
  108. package/src/components/typography/DynamicText.tsx +49 -49
  109. package/src/constants/uiColors.ts +20 -20
  110. package/src/constants/uiDevices.ts +3 -3
  111. package/src/constants/uiFonts.ts +12 -12
  112. package/src/hooks/useEventListener.ts +21 -21
  113. package/src/hooks/useOutsideAlerter.ts +25 -25
  114. package/src/index.tsx +42 -42
  115. package/src/libs/CastingTypeHelper.ts +7 -7
  116. package/src/libs/StringHelpers.ts +3 -3
  117. package/src/libs/itemCounter.ts +21 -21
  118. package/src/mocks/atlas/entities/entities.json +20215 -20215
  119. package/src/mocks/atlas/icons/icons.json +735 -735
  120. package/src/mocks/atlas/items/items.json +12086 -12086
  121. package/src/mocks/equipmentSet.mocks.ts +391 -391
  122. package/src/mocks/itemContainer.mocks.ts +605 -605
  123. package/src/mocks/skills.mocks.ts +130 -130
  124. package/src/stories/Arrow.stories.tsx +26 -26
  125. package/src/stories/Button.stories.tsx +36 -36
  126. package/src/stories/CharacterSelection.stories.tsx +44 -44
  127. package/src/stories/CharacterStatus.stories.tsx +29 -29
  128. package/src/stories/Chat.stories.tsx +187 -187
  129. package/src/stories/ChatDeprecated.stories.tsx +170 -170
  130. package/src/stories/CheckButton.stories.tsx +48 -48
  131. package/src/stories/CircullarController.stories.tsx +37 -37
  132. package/src/stories/CraftBook.stories.tsx +42 -42
  133. package/src/stories/DayNightPeriod.stories.tsx +27 -27
  134. package/src/stories/DraggableContainer.stories.tsx +28 -28
  135. package/src/stories/Dropdown.stories.tsx +46 -46
  136. package/src/stories/DropdownSelectorContainer.stories.tsx +41 -41
  137. package/src/stories/EquipmentSet.stories.tsx +65 -65
  138. package/src/stories/HistoryDialog.stories.tsx +61 -61
  139. package/src/stories/ItemContainer.stories.tsx +201 -201
  140. package/src/stories/ItemInfoDisplay.stories.tsx +33 -33
  141. package/src/stories/ItemQuantitySelector.stories.tsx +26 -26
  142. package/src/stories/ItemSelector.stories.tsx +77 -77
  143. package/src/stories/ItemTradingComponent.stories.tsx +35 -35
  144. package/src/stories/ListMenu.stories.tsx +56 -56
  145. package/src/stories/Marketplace.stories.tsx +57 -53
  146. package/src/stories/MarketplaceRows.stories.tsx +27 -27
  147. package/src/stories/Multitab.stories.tsx +51 -51
  148. package/src/stories/NPCDialog.stories.tsx +130 -130
  149. package/src/stories/NPCMultiDialog.stories.tsx +71 -71
  150. package/src/stories/ProgressBar.stories.tsx +24 -24
  151. package/src/stories/PropertySelect.stories.tsx +40 -40
  152. package/src/stories/QuestInfo.stories.tsx +107 -107
  153. package/src/stories/QuestList.stories.tsx +82 -82
  154. package/src/stories/RPGUIContainers.stories.tsx +42 -42
  155. package/src/stories/RadioButton.stories.tsx +49 -49
  156. package/src/stories/RadioInput.stories.tsx +34 -34
  157. package/src/stories/RangeSlider.stories.tsx +64 -64
  158. package/src/stories/ScrollList.stories.tsx +85 -85
  159. package/src/stories/Shortcuts.stories.tsx +39 -39
  160. package/src/stories/SimpleProgressBar.stories.tsx +22 -22
  161. package/src/stories/SkillProgressBar.stories.tsx +34 -34
  162. package/src/stories/SkillsContainer.stories.tsx +35 -35
  163. package/src/stories/SpellInfoDisplay.stories.tsx +27 -27
  164. package/src/stories/Spellbook.stories.tsx +104 -104
  165. package/src/stories/StaticBook.stories.tsx +32 -32
  166. package/src/stories/Text.stories.tsx +42 -42
  167. package/src/stories/TimeWidget.stories.tsx +27 -27
  168. package/src/stories/TradingMenu.stories.tsx +47 -47
  169. package/src/types/eventTypes.ts +4 -4
  170. package/src/types/index.d.ts +2 -2
  171. package/src/.DS_Store +0 -0
  172. package/src/components/.DS_Store +0 -0
  173. package/src/components/NPCDialog/.DS_Store +0 -0
  174. package/src/components/NPCDialog/img/.DS_Store +0 -0
  175. package/src/mocks/.DS_Store +0 -0
  176. package/src/mocks/atlas/.DS_Store +0 -0
@@ -1,282 +1,282 @@
1
- import {
2
- getItemTextureKeyPath,
3
- IItem,
4
- IItemContainer,
5
- IRawSpell,
6
- IShortcut,
7
- ShortcutType,
8
- } from '@rpg-engine/shared';
9
- import React from 'react';
10
- import styled from 'styled-components';
11
- import { uiColors } from '../../constants/uiColors';
12
- import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
13
- import { SingleShortcut } from '../Shortcuts/SingleShortcut';
14
- import { useShortcutCooldown } from '../Shortcuts/useShortcutCooldown';
15
-
16
- export type CircularControllerProps = {
17
- onActionClick: () => void;
18
- onCancelClick: () => void;
19
- onShortcutClick: (index: number) => void;
20
- mana: number;
21
- shortcuts: IShortcut[];
22
- inventory?: IItemContainer | null;
23
- atlasIMG: any;
24
- atlasJSON: any;
25
- spellCooldowns?: Record<string, number>;
26
- };
27
-
28
- export const CircularController: React.FC<CircularControllerProps> = ({
29
- onActionClick,
30
- onCancelClick,
31
- onShortcutClick,
32
- mana,
33
- shortcuts,
34
- inventory,
35
- atlasIMG,
36
- atlasJSON,
37
- spellCooldowns,
38
- }) => {
39
- const { handleShortcutCast, shortcutCooldown } = useShortcutCooldown(
40
- onShortcutClick
41
- );
42
-
43
- const onTouchStart = (e: React.TouchEvent<HTMLButtonElement>) => {
44
- const target = e.target as HTMLButtonElement;
45
- target?.classList.add('active');
46
- };
47
-
48
- const onTouchEnd = (
49
- action: () => void,
50
- e: React.TouchEvent<HTMLButtonElement>
51
- ) => {
52
- const target = e.target as HTMLButtonElement;
53
- setTimeout(() => {
54
- target?.classList.remove('active');
55
- }, 100);
56
- action();
57
- };
58
-
59
- const renderShortcut = (i: number) => {
60
- const buildClassName = (classBase: string, isOnCooldown: boolean) => {
61
- return `${classBase} ${isOnCooldown ? 'onCooldown' : ''}`;
62
- };
63
-
64
- let variant = '';
65
-
66
- if (i === 0) variant = 'top';
67
- else if (i >= 3) variant = `bottom-${i - 3}`;
68
-
69
- const onShortcutClickBinded =
70
- shortcuts[i]?.type !== ShortcutType.None
71
- ? handleShortcutCast.bind(null, i)
72
- : () => {};
73
-
74
- const isOnShortcutCooldown = shortcutCooldown > 0;
75
-
76
- if (shortcuts[i]?.type === ShortcutType.Item) {
77
- const payload = shortcuts[i]?.payload as IItem | undefined;
78
-
79
- let itemsFromEquipment: (IItem | undefined | null)[] = [];
80
-
81
- if (inventory) {
82
- Object.keys(inventory.slots).forEach(i => {
83
- const index = parseInt(i);
84
-
85
- if (inventory.slots[index]?.key === payload?.key) {
86
- itemsFromEquipment.push(inventory.slots[index]);
87
- }
88
- });
89
- }
90
-
91
- const totalQty = itemsFromEquipment.reduce(
92
- (acc, item) => acc + (item?.stackQty || 1),
93
- 0
94
- );
95
-
96
- return (
97
- <StyledShortcut
98
- key={i}
99
- onTouchStart={onTouchStart}
100
- onTouchEnd={onTouchEnd.bind(null, onShortcutClickBinded)}
101
- disabled={false}
102
- className={variant}
103
- >
104
- {isOnShortcutCooldown && (
105
- <span className="cooldown">{shortcutCooldown.toFixed(1)}</span>
106
- )}
107
- {payload && (
108
- <SpriteFromAtlas
109
- atlasIMG={atlasIMG}
110
- atlasJSON={atlasJSON}
111
- spriteKey={getItemTextureKeyPath(
112
- {
113
- key: payload.texturePath,
114
- texturePath: payload.texturePath,
115
- stackQty: payload.stackQty || 1,
116
- isStackable: payload.isStackable,
117
- },
118
- atlasJSON
119
- )}
120
- width={32}
121
- height={32}
122
- imgScale={1.4}
123
- imgStyle={{ left: '4px' }}
124
- containerStyle={{ pointerEvents: 'none' }}
125
- />
126
- )}
127
- <span className={buildClassName('qty', isOnShortcutCooldown)}>
128
- {totalQty}
129
- </span>
130
- </StyledShortcut>
131
- );
132
- }
133
-
134
- const payload = shortcuts[i]?.payload as IRawSpell | undefined;
135
-
136
- const spellCooldown = !payload
137
- ? 0
138
- : spellCooldowns?.[payload.magicWords.replaceAll(' ', '_')] ??
139
- shortcutCooldown;
140
- const cooldown =
141
- spellCooldown > shortcutCooldown ? spellCooldown : shortcutCooldown;
142
- const isOnCooldown = cooldown > 0 && !!payload;
143
-
144
- return (
145
- <StyledShortcut
146
- key={i}
147
- onTouchStart={onTouchStart}
148
- onTouchEnd={onTouchEnd.bind(null, onShortcutClickBinded)}
149
- disabled={mana < (payload?.manaCost ?? 0)}
150
- className={variant}
151
- >
152
- {isOnCooldown && (
153
- <span className="cooldown">
154
- {cooldown.toFixed(cooldown < 10 ? 1 : 0)}
155
- </span>
156
- )}
157
- <span className={buildClassName('mana', isOnCooldown)}>
158
- {payload && payload.manaCost}
159
- </span>
160
- <span className="magicWords">
161
- {payload?.magicWords.split(' ').map(word => word[0])}
162
- </span>
163
- </StyledShortcut>
164
- );
165
- };
166
-
167
- return (
168
- <ButtonsContainer>
169
- <ShortcutsContainer>
170
- {Array.from({ length: 6 }).map((_, i) => renderShortcut(i))}
171
- </ShortcutsContainer>
172
- <Button
173
- onTouchStart={onTouchStart}
174
- onTouchEnd={onTouchEnd.bind(null, onActionClick)}
175
- >
176
- <div className="rpgui-icon sword" />
177
- </Button>
178
-
179
- <CancelButton
180
- onTouchStart={onTouchStart}
181
- onTouchEnd={onTouchEnd.bind(null, onCancelClick)}
182
- >
183
- <span>X</span>
184
- </CancelButton>
185
- </ButtonsContainer>
186
- );
187
- };
188
-
189
- const Button = styled.button`
190
- width: 4.3rem;
191
- height: 4.3rem;
192
- background-color: ${uiColors.lightGray};
193
- border: 2px solid ${uiColors.darkGray};
194
- border-radius: 50%;
195
- text-transform: uppercase;
196
- font-size: 0.7rem;
197
- font-weight: bold;
198
- display: flex;
199
- align-items: center;
200
- justify-content: center;
201
- position: relative;
202
- transition: all 0.1s;
203
- margin-top: -3rem;
204
-
205
- &.active {
206
- background-color: ${uiColors.gray};
207
- border-color: ${uiColors.yellow};
208
- }
209
-
210
- .sword {
211
- transform: rotate(-45deg);
212
- height: 2.5rem;
213
- width: 1.9rem;
214
- pointer-events: none;
215
- }
216
- `;
217
-
218
- const CancelButton = styled(Button)`
219
- width: 3rem;
220
- height: 3rem;
221
- font-size: 0.8rem;
222
-
223
- span {
224
- margin-top: 4px;
225
- margin-left: 2px;
226
- pointer-events: none;
227
- }
228
- `;
229
-
230
- const ButtonsContainer = styled.div`
231
- display: flex;
232
- align-items: center;
233
- justify-content: center;
234
- gap: 0.5rem;
235
- `;
236
-
237
- const ShortcutsContainer = styled.div`
238
- display: flex;
239
- align-items: center;
240
- justify-content: center;
241
- gap: 0.5rem;
242
- flex-direction: column;
243
- margin-top: 3rem;
244
-
245
- .top {
246
- transform: translate(93%, 25%);
247
- }
248
-
249
- .bottom-0 {
250
- transform: translate(93%, -25%);
251
- }
252
-
253
- .bottom-1 {
254
- transform: translate(-120%, calc(-5.5rem));
255
- }
256
-
257
- .bottom-2 {
258
- transform: translate(-30%, calc(-5.5rem - 25%));
259
- }
260
- `;
261
-
262
- const StyledShortcut = styled(SingleShortcut)`
263
- width: 2.5rem;
264
- height: 2.5rem;
265
- transition: all 0.1s;
266
-
267
- .mana,
268
- .qty {
269
- font-size: 0.5rem;
270
- }
271
-
272
- &:hover,
273
- &:focus,
274
- &:active {
275
- background-color: ${uiColors.lightGray};
276
- }
277
-
278
- &.active {
279
- background-color: ${uiColors.gray};
280
- border-color: ${uiColors.yellow};
281
- }
282
- `;
1
+ import {
2
+ getItemTextureKeyPath,
3
+ IItem,
4
+ IItemContainer,
5
+ IRawSpell,
6
+ IShortcut,
7
+ ShortcutType,
8
+ } from '@rpg-engine/shared';
9
+ import React from 'react';
10
+ import styled from 'styled-components';
11
+ import { uiColors } from '../../constants/uiColors';
12
+ import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
13
+ import { SingleShortcut } from '../Shortcuts/SingleShortcut';
14
+ import { useShortcutCooldown } from '../Shortcuts/useShortcutCooldown';
15
+
16
+ export type CircularControllerProps = {
17
+ onActionClick: () => void;
18
+ onCancelClick: () => void;
19
+ onShortcutClick: (index: number) => void;
20
+ mana: number;
21
+ shortcuts: IShortcut[];
22
+ inventory?: IItemContainer | null;
23
+ atlasIMG: any;
24
+ atlasJSON: any;
25
+ spellCooldowns?: Record<string, number>;
26
+ };
27
+
28
+ export const CircularController: React.FC<CircularControllerProps> = ({
29
+ onActionClick,
30
+ onCancelClick,
31
+ onShortcutClick,
32
+ mana,
33
+ shortcuts,
34
+ inventory,
35
+ atlasIMG,
36
+ atlasJSON,
37
+ spellCooldowns,
38
+ }) => {
39
+ const { handleShortcutCast, shortcutCooldown } = useShortcutCooldown(
40
+ onShortcutClick
41
+ );
42
+
43
+ const onTouchStart = (e: React.TouchEvent<HTMLButtonElement>) => {
44
+ const target = e.target as HTMLButtonElement;
45
+ target?.classList.add('active');
46
+ };
47
+
48
+ const onTouchEnd = (
49
+ action: () => void,
50
+ e: React.TouchEvent<HTMLButtonElement>
51
+ ) => {
52
+ const target = e.target as HTMLButtonElement;
53
+ setTimeout(() => {
54
+ target?.classList.remove('active');
55
+ }, 100);
56
+ action();
57
+ };
58
+
59
+ const renderShortcut = (i: number) => {
60
+ const buildClassName = (classBase: string, isOnCooldown: boolean) => {
61
+ return `${classBase} ${isOnCooldown ? 'onCooldown' : ''}`;
62
+ };
63
+
64
+ let variant = '';
65
+
66
+ if (i === 0) variant = 'top';
67
+ else if (i >= 3) variant = `bottom-${i - 3}`;
68
+
69
+ const onShortcutClickBinded =
70
+ shortcuts[i]?.type !== ShortcutType.None
71
+ ? handleShortcutCast.bind(null, i)
72
+ : () => {};
73
+
74
+ const isOnShortcutCooldown = shortcutCooldown > 0;
75
+
76
+ if (shortcuts[i]?.type === ShortcutType.Item) {
77
+ const payload = shortcuts[i]?.payload as IItem | undefined;
78
+
79
+ let itemsFromEquipment: (IItem | undefined | null)[] = [];
80
+
81
+ if (inventory) {
82
+ Object.keys(inventory.slots).forEach(i => {
83
+ const index = parseInt(i);
84
+
85
+ if (inventory.slots[index]?.key === payload?.key) {
86
+ itemsFromEquipment.push(inventory.slots[index]);
87
+ }
88
+ });
89
+ }
90
+
91
+ const totalQty = itemsFromEquipment.reduce(
92
+ (acc, item) => acc + (item?.stackQty || 1),
93
+ 0
94
+ );
95
+
96
+ return (
97
+ <StyledShortcut
98
+ key={i}
99
+ onTouchStart={onTouchStart}
100
+ onTouchEnd={onTouchEnd.bind(null, onShortcutClickBinded)}
101
+ disabled={false}
102
+ className={variant}
103
+ >
104
+ {isOnShortcutCooldown && (
105
+ <span className="cooldown">{shortcutCooldown.toFixed(1)}</span>
106
+ )}
107
+ {payload && (
108
+ <SpriteFromAtlas
109
+ atlasIMG={atlasIMG}
110
+ atlasJSON={atlasJSON}
111
+ spriteKey={getItemTextureKeyPath(
112
+ {
113
+ key: payload.texturePath,
114
+ texturePath: payload.texturePath,
115
+ stackQty: payload.stackQty || 1,
116
+ isStackable: payload.isStackable,
117
+ },
118
+ atlasJSON
119
+ )}
120
+ width={32}
121
+ height={32}
122
+ imgScale={1.4}
123
+ imgStyle={{ left: '4px' }}
124
+ containerStyle={{ pointerEvents: 'none' }}
125
+ />
126
+ )}
127
+ <span className={buildClassName('qty', isOnShortcutCooldown)}>
128
+ {totalQty}
129
+ </span>
130
+ </StyledShortcut>
131
+ );
132
+ }
133
+
134
+ const payload = shortcuts[i]?.payload as IRawSpell | undefined;
135
+
136
+ const spellCooldown = !payload
137
+ ? 0
138
+ : spellCooldowns?.[payload.magicWords.replaceAll(' ', '_')] ??
139
+ shortcutCooldown;
140
+ const cooldown =
141
+ spellCooldown > shortcutCooldown ? spellCooldown : shortcutCooldown;
142
+ const isOnCooldown = cooldown > 0 && !!payload;
143
+
144
+ return (
145
+ <StyledShortcut
146
+ key={i}
147
+ onTouchStart={onTouchStart}
148
+ onTouchEnd={onTouchEnd.bind(null, onShortcutClickBinded)}
149
+ disabled={mana < (payload?.manaCost ?? 0)}
150
+ className={variant}
151
+ >
152
+ {isOnCooldown && (
153
+ <span className="cooldown">
154
+ {cooldown.toFixed(cooldown < 10 ? 1 : 0)}
155
+ </span>
156
+ )}
157
+ <span className={buildClassName('mana', isOnCooldown)}>
158
+ {payload && payload.manaCost}
159
+ </span>
160
+ <span className="magicWords">
161
+ {payload?.magicWords.split(' ').map(word => word[0])}
162
+ </span>
163
+ </StyledShortcut>
164
+ );
165
+ };
166
+
167
+ return (
168
+ <ButtonsContainer>
169
+ <ShortcutsContainer>
170
+ {Array.from({ length: 6 }).map((_, i) => renderShortcut(i))}
171
+ </ShortcutsContainer>
172
+ <Button
173
+ onTouchStart={onTouchStart}
174
+ onTouchEnd={onTouchEnd.bind(null, onActionClick)}
175
+ >
176
+ <div className="rpgui-icon sword" />
177
+ </Button>
178
+
179
+ <CancelButton
180
+ onTouchStart={onTouchStart}
181
+ onTouchEnd={onTouchEnd.bind(null, onCancelClick)}
182
+ >
183
+ <span>X</span>
184
+ </CancelButton>
185
+ </ButtonsContainer>
186
+ );
187
+ };
188
+
189
+ const Button = styled.button`
190
+ width: 4.3rem;
191
+ height: 4.3rem;
192
+ background-color: ${uiColors.lightGray};
193
+ border: 2px solid ${uiColors.darkGray};
194
+ border-radius: 50%;
195
+ text-transform: uppercase;
196
+ font-size: 0.7rem;
197
+ font-weight: bold;
198
+ display: flex;
199
+ align-items: center;
200
+ justify-content: center;
201
+ position: relative;
202
+ transition: all 0.1s;
203
+ margin-top: -3rem;
204
+
205
+ &.active {
206
+ background-color: ${uiColors.gray};
207
+ border-color: ${uiColors.yellow};
208
+ }
209
+
210
+ .sword {
211
+ transform: rotate(-45deg);
212
+ height: 2.5rem;
213
+ width: 1.9rem;
214
+ pointer-events: none;
215
+ }
216
+ `;
217
+
218
+ const CancelButton = styled(Button)`
219
+ width: 3rem;
220
+ height: 3rem;
221
+ font-size: 0.8rem;
222
+
223
+ span {
224
+ margin-top: 4px;
225
+ margin-left: 2px;
226
+ pointer-events: none;
227
+ }
228
+ `;
229
+
230
+ const ButtonsContainer = styled.div`
231
+ display: flex;
232
+ align-items: center;
233
+ justify-content: center;
234
+ gap: 0.5rem;
235
+ `;
236
+
237
+ const ShortcutsContainer = styled.div`
238
+ display: flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ gap: 0.5rem;
242
+ flex-direction: column;
243
+ margin-top: 3rem;
244
+
245
+ .top {
246
+ transform: translate(93%, 25%);
247
+ }
248
+
249
+ .bottom-0 {
250
+ transform: translate(93%, -25%);
251
+ }
252
+
253
+ .bottom-1 {
254
+ transform: translate(-120%, calc(-5.5rem));
255
+ }
256
+
257
+ .bottom-2 {
258
+ transform: translate(-30%, calc(-5.5rem - 25%));
259
+ }
260
+ `;
261
+
262
+ const StyledShortcut = styled(SingleShortcut)`
263
+ width: 2.5rem;
264
+ height: 2.5rem;
265
+ transition: all 0.1s;
266
+
267
+ .mana,
268
+ .qty {
269
+ font-size: 0.5rem;
270
+ }
271
+
272
+ &:hover,
273
+ &:focus,
274
+ &:active {
275
+ background-color: ${uiColors.lightGray};
276
+ }
277
+
278
+ &.active {
279
+ background-color: ${uiColors.gray};
280
+ border-color: ${uiColors.yellow};
281
+ }
282
+ `;