@rpg-engine/long-bow 0.8.8 → 0.8.10

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.8.8",
3
+ "version": "0.8.10",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -62,15 +62,6 @@ export interface IItemContainerProps {
62
62
  opacity?: number;
63
63
  }
64
64
 
65
- type onDragStart =
66
- | ((
67
- item: IItem,
68
- slotIndex: number,
69
- itemContainerType: ItemContainerType | null
70
- ) => void)
71
- | undefined;
72
- type onDragEnd = ((quantity?: number) => void) | undefined;
73
-
74
65
  const MIN_SLOTS_FOR_SCROLL = 20;
75
66
 
76
67
  export const ItemContainer: React.FC<IItemContainerProps> = React.memo(
@@ -154,7 +145,7 @@ export const ItemContainer: React.FC<IItemContainerProps> = React.memo(
154
145
  document.removeEventListener('pointermove', handleMouseMove);
155
146
  }, [handleMouseMove, stopScrolling]);
156
147
 
157
- const onDragStartHandler: onDragStart = useCallback(
148
+ const onDragStartHandler = useCallback(
158
149
  (
159
150
  item: IItem,
160
151
  slotIndex: number,
@@ -169,7 +160,7 @@ export const ItemContainer: React.FC<IItemContainerProps> = React.memo(
169
160
  [onItemDragStart, onDragStartScrollingEvents]
170
161
  );
171
162
 
172
- const onDragEndHandler: onDragEnd = useCallback(
163
+ const onDragEndHandler = useCallback(
173
164
  (quantity: number | undefined) => {
174
165
  if (onItemDragEnd) {
175
166
  onItemDragEnd(quantity);
@@ -179,16 +170,85 @@ export const ItemContainer: React.FC<IItemContainerProps> = React.memo(
179
170
  [onItemDragEnd, onDragEndScrollingEvents]
180
171
  );
181
172
 
182
- // Memoize handleSetShortcut to prevent unnecessary re-renders
183
- const memoizedHandleSetShortcut = useCallback(
184
- (item: IItem, index: number) => {
185
- handleSetShortcut(item, index);
173
+ const handleItemClick = useCallback(
174
+ (
175
+ itemType: IItem['type'],
176
+ containerType: ItemContainerType | null,
177
+ item: IItem
178
+ ) => {
179
+ if (settingShortcutIndex !== -1) {
180
+ setSettingShortcutIndex(-1);
181
+ handleSetShortcut(item, settingShortcutIndex);
182
+ } else if (onItemClick) {
183
+ onItemClick(item, itemType, containerType);
184
+ }
185
+ },
186
+ [settingShortcutIndex, handleSetShortcut, onItemClick]
187
+ );
188
+
189
+ const handlePlaceDrop = useCallback(
190
+ (
191
+ item: IItem | null,
192
+ slotIndex: number,
193
+ itemContainerType: ItemContainerType | null
194
+ ) => {
195
+ if (onItemPlaceDrop) {
196
+ onItemPlaceDrop(item, slotIndex, itemContainerType);
197
+ }
198
+ onDragEndScrollingEvents();
199
+ },
200
+ [onItemPlaceDrop, onDragEndScrollingEvents]
201
+ );
202
+
203
+ const handleOutsideDrop = useCallback(
204
+ (item: IItem, position: IPosition) => {
205
+ if (onOutsideDrop) {
206
+ onOutsideDrop(item, position);
207
+ }
208
+ onDragEndScrollingEvents();
186
209
  },
187
- [handleSetShortcut]
210
+ [onOutsideDrop, onDragEndScrollingEvents]
188
211
  );
189
212
 
190
- // Memoize onRenderSlots to prevent re-creating the slots array on every render
191
- const onRenderSlots = useMemo(() => {
213
+ const handleQuantitySelect = useCallback(
214
+ (maxQuantity: number, callback: (quantity: number) => void) => {
215
+ setQuantitySelect({
216
+ isOpen: true,
217
+ maxQuantity,
218
+ callback,
219
+ });
220
+ },
221
+ []
222
+ );
223
+
224
+ // Memoize slot rendering configuration
225
+ const slotConfig = useMemo(
226
+ () => ({
227
+ type,
228
+ atlasIMG,
229
+ atlasJSON,
230
+ scale,
231
+ equipmentSet,
232
+ isDepotSystem,
233
+ isSelectingShortcut: settingShortcutIndex !== -1,
234
+ checkIfItemCanBeMoved,
235
+ checkIfItemShouldDragEnd,
236
+ }),
237
+ [
238
+ type,
239
+ atlasIMG,
240
+ atlasJSON,
241
+ scale,
242
+ equipmentSet,
243
+ isDepotSystem,
244
+ settingShortcutIndex,
245
+ checkIfItemCanBeMoved,
246
+ checkIfItemShouldDragEnd,
247
+ ]
248
+ );
249
+
250
+ // Memoize slots rendering
251
+ const renderSlots = useMemo(() => {
192
252
  const slots = [];
193
253
 
194
254
  for (let i = 0; i < itemContainer.slotQty; i++) {
@@ -199,62 +259,27 @@ export const ItemContainer: React.FC<IItemContainerProps> = React.memo(
199
259
  key={i}
200
260
  slotIndex={i}
201
261
  item={currentItem}
202
- itemContainerType={type}
203
- onMouseOver={
204
- onMouseOver
205
- ? (event, slotIndex, item) =>
206
- onMouseOver(event, slotIndex, item)
207
- : undefined
208
- }
209
- onMouseOut={undefined} // Assuming you don't need onMouseOut here
210
- onPointerDown={(itemType, containerType, item) => {
211
- if (settingShortcutIndex !== -1) {
212
- setSettingShortcutIndex(-1);
213
- memoizedHandleSetShortcut(item, settingShortcutIndex);
214
- } else if (onItemClick) {
215
- onItemClick(item, itemType, containerType);
216
- }
217
- }}
262
+ itemContainerType={slotConfig.type}
263
+ onMouseOver={onMouseOver}
264
+ onPointerDown={handleItemClick}
218
265
  onDragStart={onDragStartHandler}
219
266
  onDragEnd={onDragEndHandler}
220
- dragScale={scale}
221
- checkIfItemCanBeMoved={checkIfItemCanBeMoved}
222
- checkIfItemShouldDragEnd={checkIfItemShouldDragEnd}
223
- openQuantitySelector={(maxQuantity, callback) => {
224
- setQuantitySelect({
225
- isOpen: true,
226
- maxQuantity,
227
- callback,
228
- });
229
- }}
230
- onPlaceDrop={(item, slotIndex, itemContainerType) => {
231
- if (onItemPlaceDrop) {
232
- onItemPlaceDrop(item, slotIndex, itemContainerType);
233
- }
234
-
235
- console.log('PLACE DROP');
236
-
237
- onDragEndScrollingEvents();
238
- }}
239
- onOutsideDrop={(item, position) => {
240
- if (onOutsideDrop) {
241
- onOutsideDrop(item, position);
242
- }
243
-
244
- console.log('OUTSIDE DROP');
245
-
246
- onDragEndScrollingEvents();
247
- }}
248
- atlasIMG={atlasIMG}
249
- atlasJSON={atlasJSON}
250
- isSelectingShortcut={settingShortcutIndex !== -1}
251
- equipmentSet={equipmentSet}
267
+ dragScale={slotConfig.scale}
268
+ checkIfItemCanBeMoved={slotConfig.checkIfItemCanBeMoved}
269
+ checkIfItemShouldDragEnd={slotConfig.checkIfItemShouldDragEnd}
270
+ openQuantitySelector={handleQuantitySelect}
271
+ onPlaceDrop={handlePlaceDrop}
272
+ onOutsideDrop={handleOutsideDrop}
273
+ atlasIMG={slotConfig.atlasIMG}
274
+ atlasJSON={slotConfig.atlasJSON}
275
+ isSelectingShortcut={slotConfig.isSelectingShortcut}
276
+ equipmentSet={slotConfig.equipmentSet}
252
277
  setItemShortcut={
253
278
  type === ItemContainerType.Inventory
254
- ? memoizedHandleSetShortcut
279
+ ? handleSetShortcut
255
280
  : undefined
256
281
  }
257
- isDepotSystem={isDepotSystem}
282
+ isDepotSystem={slotConfig.isDepotSystem}
258
283
  />
259
284
  );
260
285
  }
@@ -262,23 +287,16 @@ export const ItemContainer: React.FC<IItemContainerProps> = React.memo(
262
287
  }, [
263
288
  itemContainer.slotQty,
264
289
  itemContainer.slots,
265
- type,
290
+ slotConfig,
266
291
  onMouseOver,
267
- settingShortcutIndex,
268
- memoizedHandleSetShortcut,
269
- onItemClick,
292
+ handleItemClick,
270
293
  onDragStartHandler,
271
294
  onDragEndHandler,
272
- scale,
273
- checkIfItemCanBeMoved,
274
- checkIfItemShouldDragEnd,
275
- onItemPlaceDrop,
276
- onOutsideDrop,
277
- atlasIMG,
278
- atlasJSON,
279
- equipmentSet,
280
- isDepotSystem,
281
- onDragEndScrollingEvents,
295
+ handleQuantitySelect,
296
+ handlePlaceDrop,
297
+ handleOutsideDrop,
298
+ handleSetShortcut,
299
+ type,
282
300
  ]);
283
301
 
284
302
  return (
@@ -317,7 +335,7 @@ export const ItemContainer: React.FC<IItemContainerProps> = React.memo(
317
335
  isScrollable={itemContainer.slotQty > MIN_SLOTS_FOR_SCROLL}
318
336
  isFullScreen={isFullScreen}
319
337
  >
320
- {onRenderSlots}
338
+ {renderSlots}
321
339
  </ItemsContainer>
322
340
  </SlotsContainer>
323
341
  {quantitySelect.isOpen && (
@@ -37,42 +37,43 @@ export const SpriteFromAtlas: React.FC<IProps> = ({
37
37
  centered,
38
38
  borderRadius,
39
39
  }) => {
40
- //! If an item is not showing, remember that you MUST run yarn atlas:copy everytime you add a new item to the atlas (it will sync our public folder atlas with src/atlas).
41
- //!Due to React's limitations, we cannot import it from the public folder directly!
42
- const spriteData =
43
- atlasJSON?.frames?.[spriteKey] ||
44
- atlasJSON?.frames?.['others/no-image.png'];
40
+ //! If an item is not showing, remember that you MUST run yarn atlas:copy everytime you add a new item to the atlas (it will sync our public folder atlas with src/atlas).
41
+ //!Due to React's limitations, we cannot import it from the public folder directly!
45
42
 
46
- if (!spriteData) {
47
- console.error(
48
- `SpriteFromAtlas: Could not find sprite with key ${spriteKey} in atlasJSON.`
49
- );
50
- return null;
51
- }
43
+ const spriteData =
44
+ atlasJSON?.frames?.[spriteKey] ||
45
+ atlasJSON?.frames?.['others/no-image.png'];
52
46
 
53
- return (
54
- <Container
55
- width={width}
56
- height={height}
57
- hasHover={grayScale}
58
- onPointerDown={onPointerDown}
59
- style={containerStyle}
60
- >
61
- <ImgSprite
62
- className={`sprite-from-atlas-img ${imgClassname || ''}`}
63
- atlasIMG={atlasIMG}
64
- frame={spriteData.frame}
65
- scale={imgScale}
66
- grayScale={grayScale}
67
- opacity={opacity}
68
- style={imgStyle}
69
- centered={centered}
70
- borderRadius={borderRadius}
71
- tintColor={tintColor}
72
- />
73
- </Container>
74
- );
75
- };
47
+ if (!spriteData) {
48
+ console.error(
49
+ `SpriteFromAtlas: Could not find sprite with key ${spriteKey} in atlasJSON.`
50
+ );
51
+ return null;
52
+ }
53
+
54
+ return (
55
+ <Container
56
+ width={width}
57
+ height={height}
58
+ hasHover={grayScale}
59
+ onPointerDown={onPointerDown}
60
+ style={containerStyle}
61
+ >
62
+ <ImgSprite
63
+ className={`sprite-from-atlas-img ${imgClassname || ''}`}
64
+ atlasIMG={atlasIMG}
65
+ frame={spriteData.frame}
66
+ scale={imgScale}
67
+ grayScale={grayScale}
68
+ opacity={opacity}
69
+ style={imgStyle}
70
+ centered={centered}
71
+ borderRadius={borderRadius}
72
+ tintColor={tintColor}
73
+ />
74
+ </Container>
75
+ );
76
+ };
76
77
 
77
78
  interface IImgSpriteProps {
78
79
  atlasIMG: any;
@@ -111,30 +112,23 @@ const ImgSprite = styled.div<IImgSpriteProps>`
111
112
  width: ${props => props.frame.w}px;
112
113
  height: ${props => props.frame.h}px;
113
114
  background-image: url(${props => props.atlasIMG});
114
- background-position: -${props => props.frame.x}px -${props =>
115
- props.frame.y}px;
115
+ background-position: -${props => props.frame.x}px -${props => props.frame.y}px;
116
116
  transform: scale(${props => props.scale});
117
117
  position: relative;
118
118
  top: ${props => (props.centered ? '0' : '8px')};
119
119
  left: ${props => (props.centered ? '0' : '8px')};
120
- ${props =>
121
- props.tintColor &&
122
- `
123
- &::after {
124
- content: '';
125
- position: absolute;
126
- top: 0;
127
- left: 0;
128
- width: ${props.frame.w}px;
129
- height: ${props.frame.h}px;
130
- background-color: ${props.tintColor};
131
- mask-image: url(${props.atlasIMG});
132
- mask-position: -${props.frame.x}px -${props.frame.y}px;
133
- -webkit-mask-image: url(${props.atlasIMG});
134
- -webkit-mask-position: -${props.frame.x}px -${props.frame.y}px;
135
- mix-blend-mode: color;
136
- ${props.grayScale ? 'filter: grayscale(100%);' : 'none'}
137
- }
138
- `}
120
+ filter: ${props => {
121
+ const filters = [];
122
+ if (props.grayScale) filters.push('grayscale(100%)');
123
+ if (props.tintColor)
124
+ filters.push(
125
+ `brightness(0.8) contrast(1.2) sepia(100%) hue-rotate(${
126
+ props.tintColor === '#FFD700' ? '40deg' : '210deg'
127
+ }) saturate(400%)`
128
+ );
129
+ return filters.length ? filters.join(' ') : 'none';
130
+ }};
139
131
  opacity: ${props => props.opacity};
140
- `;
132
+ border-radius: ${props => props.borderRadius || '0'};
133
+ overflow: hidden;
134
+ `;