@rpg-engine/long-bow 0.8.219 → 0.8.220

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 (35) hide show
  1. package/dist/components/DraggableContainer.d.ts +0 -6
  2. package/dist/components/Store/MetadataCollector.d.ts +2 -2
  3. package/dist/components/Store/Store.d.ts +10 -27
  4. package/dist/components/Store/StoreHeader.d.ts +14 -0
  5. package/dist/components/Store/hooks/useStoreCart.d.ts +2 -0
  6. package/dist/components/Store/hooks/useStoreMetadata.d.ts +4 -11
  7. package/dist/components/Store/hooks/useStoreTabs.d.ts +20 -0
  8. package/dist/components/Store/internal/packToBlueprint.d.ts +2 -0
  9. package/dist/components/Store/sections/StoreItemsSection.d.ts +5 -3
  10. package/dist/hooks/useStoreFiltering.d.ts +7 -4
  11. package/dist/long-bow.cjs.development.js +349 -396
  12. package/dist/long-bow.cjs.development.js.map +1 -1
  13. package/dist/long-bow.cjs.production.min.js +1 -1
  14. package/dist/long-bow.cjs.production.min.js.map +1 -1
  15. package/dist/long-bow.esm.js +351 -398
  16. package/dist/long-bow.esm.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/components/DraggableContainer.tsx +0 -24
  19. package/src/components/Store/CartView.tsx +7 -2
  20. package/src/components/Store/MetadataCollector.tsx +60 -40
  21. package/src/components/Store/Store.tsx +75 -282
  22. package/src/components/Store/StoreHeader.tsx +74 -0
  23. package/src/components/Store/__test__/MetadataCollector.spec.tsx +94 -164
  24. package/src/components/Store/__test__/Store.spec.tsx +4 -0
  25. package/src/components/Store/__test__/useStoreMetadata.spec.tsx +58 -156
  26. package/src/components/Store/__test__/useStoreTabs.spec.tsx +69 -0
  27. package/src/components/Store/hooks/useStoreCart.ts +5 -2
  28. package/src/components/Store/hooks/useStoreMetadata.ts +30 -48
  29. package/src/components/Store/hooks/useStoreTabs.ts +104 -0
  30. package/src/components/Store/internal/packToBlueprint.ts +21 -0
  31. package/src/components/Store/sections/StoreItemsSection.tsx +19 -60
  32. package/src/components/Store/sections/StorePacksSection.tsx +0 -1
  33. package/src/components/shared/ScrollableContent/ScrollableContent.tsx +3 -6
  34. package/src/hooks/useStoreFiltering.spec.tsx +79 -0
  35. package/src/hooks/useStoreFiltering.ts +27 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.219",
3
+ "version": "0.8.220",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -12,12 +12,6 @@ export interface IDraggableContainerProps {
12
12
  height?: string;
13
13
  minWidth?: string;
14
14
  minHeight?: string;
15
- /** CSS override for width applied below `mobileBreakpoint`. Useful for responsive sizing without JS detection. */
16
- mobileWidth?: string;
17
- /** CSS override for height applied below `mobileBreakpoint`. Useful for responsive sizing without JS detection. */
18
- mobileHeight?: string;
19
- /** Viewport width in px under which mobile overrides apply. Defaults to 768. */
20
- mobileBreakpoint?: number;
21
15
  className?: string;
22
16
  type?: RPGUIContainerTypes;
23
17
  title?: string;
@@ -42,9 +36,6 @@ export const DraggableContainer: React.FC<IDraggableContainerProps> = ({
42
36
  height,
43
37
  minHeight,
44
38
  minWidth,
45
- mobileWidth,
46
- mobileHeight,
47
- mobileBreakpoint = 768,
48
39
  className,
49
40
  type = RPGUIContainerTypes.FramedGold,
50
41
  onCloseButton,
@@ -126,9 +117,6 @@ export const DraggableContainer: React.FC<IDraggableContainerProps> = ({
126
117
  height={height || 'auto'}
127
118
  minWidth={minWidth}
128
119
  minHeight={minHeight}
129
- mobileWidth={mobileWidth}
130
- mobileHeight={mobileHeight}
131
- mobileBreakpoint={mobileBreakpoint}
132
120
  className={`rpgui-container ${type} ${className}`}
133
121
  isFullScreen={isFullScreen}
134
122
  opacity={opacity}
@@ -161,9 +149,6 @@ interface IContainerProps {
161
149
  height: string;
162
150
  minWidth?: string;
163
151
  minHeight?: string;
164
- mobileWidth?: string;
165
- mobileHeight?: string;
166
- mobileBreakpoint?: number;
167
152
  isFullScreen?: boolean;
168
153
  opacity?: number;
169
154
  }
@@ -193,15 +178,6 @@ const Container = styled.div<IContainerProps>`
193
178
  align-content: flex-start;
194
179
  `}
195
180
 
196
- ${({ mobileWidth, mobileHeight, mobileBreakpoint }) =>
197
- (mobileWidth || mobileHeight) &&
198
- css`
199
- @media (max-width: ${mobileBreakpoint ?? 768}px) {
200
- ${mobileWidth && `width: ${mobileWidth}; min-width: unset;`}
201
- ${mobileHeight && `height: ${mobileHeight}; min-height: unset;`}
202
- }
203
- `}
204
-
205
181
  &.rpgui-container {
206
182
  padding-top: 1.5rem;
207
183
  }
@@ -260,14 +260,17 @@ const Container = styled.div`
260
260
  display: flex;
261
261
  flex-direction: column;
262
262
  width: 100%;
263
- gap: 1rem;
263
+ height: 100%;
264
264
  padding: 1rem;
265
+ overflow: hidden;
266
+ box-sizing: border-box;
265
267
  `;
266
268
 
267
269
  const Header = styled.div`
268
270
  display: flex;
269
271
  justify-content: space-between;
270
272
  align-items: center;
273
+ flex-shrink: 0;
271
274
  `;
272
275
 
273
276
  const Title = styled.h2`
@@ -293,8 +296,10 @@ const CartItems = styled.div`
293
296
  display: flex;
294
297
  flex-direction: column;
295
298
  gap: 0.5rem;
299
+ flex: 1;
300
+ min-height: 0;
296
301
  overflow-y: auto;
297
- max-height: 250px;
302
+ margin: 1rem 0;
298
303
  padding-right: 0.5rem;
299
304
 
300
305
  &::-webkit-scrollbar {
@@ -1,48 +1,68 @@
1
- import { MetadataType } from "@rpg-engine/shared";
2
- import React, { useEffect } from "react";
3
- import { CharacterSkinSelectionModal } from "../Character/CharacterSkinSelectionModal";
1
+ import { MetadataType } from '@rpg-engine/shared';
2
+ import React, { useCallback, useEffect, useRef } from 'react';
3
+ import { CharacterSkinSelectionModal } from '../Character/CharacterSkinSelectionModal';
4
4
 
5
5
  export interface IMetadataCollectorProps {
6
- metadataType: MetadataType;
7
- config: Record<string, any>;
8
- onCollect: (metadata: Record<string, any>) => void;
9
- onCancel: () => void;
6
+ metadataType: MetadataType;
7
+ config: Record<string, any>;
8
+ onCollect: (metadata: Record<string, any>) => void;
9
+ onCancel: () => void;
10
10
  }
11
11
 
12
12
  export const MetadataCollector: React.FC<IMetadataCollectorProps> = ({
13
- metadataType,
14
- config,
15
- onCollect,
16
- onCancel,
13
+ metadataType,
14
+ config,
15
+ onCollect,
16
+ onCancel,
17
17
  }) => {
18
- // Make sure we clean up if unmounted without collecting
19
- useEffect(() => {
20
- return () => {
21
- // If we're unmounting without explicitly collecting or canceling,
22
- // make sure to call onCancel to prevent any hanging promises
23
- if (window.__metadataResolvers) {
24
- onCancel();
25
- }
26
- };
27
- }, [onCancel]);
28
-
29
- // Use string comparison instead of direct property access
30
- if (metadataType === 'CharacterSkin') {
31
- return (
32
- <CharacterSkinSelectionModal
33
- isOpen={true}
34
- onClose={onCancel}
35
- onConfirm={(selectedSkin: any) => onCollect({ selectedSkin })}
36
- availableCharacters={config.availableCharacters || []}
37
- atlasJSON={config.atlasJSON}
38
- atlasIMG={config.atlasIMG}
39
- initialSelectedSkin={config.initialSelectedSkin}
40
- />
41
- );
42
- } else {
43
- console.warn(`No collector implemented for metadata type: ${metadataType}`);
44
- // Auto-cancel for unhandled types to prevent hanging promises
45
- setTimeout(onCancel, 0);
46
- return null;
18
+ const isPendingRef = useRef(true);
19
+
20
+ const finalize = useCallback((callback: () => void) => {
21
+ if (!isPendingRef.current) {
22
+ return;
23
+ }
24
+
25
+ isPendingRef.current = false;
26
+ callback();
27
+ }, []);
28
+
29
+ const handleCollect = useCallback((metadata: Record<string, any>) => {
30
+ finalize(() => onCollect(metadata));
31
+ }, [finalize, onCollect]);
32
+
33
+ const handleCancel = useCallback(() => {
34
+ finalize(onCancel);
35
+ }, [finalize, onCancel]);
36
+
37
+ useEffect(() => {
38
+ return () => {
39
+ handleCancel();
40
+ };
41
+ }, [handleCancel]);
42
+
43
+ useEffect(() => {
44
+ if (metadataType === MetadataType.CharacterSkin) {
45
+ return undefined;
47
46
  }
47
+
48
+ const timer = window.setTimeout(handleCancel, 0);
49
+ return () => window.clearTimeout(timer);
50
+ }, [handleCancel, metadataType]);
51
+
52
+ if (metadataType === MetadataType.CharacterSkin) {
53
+ return (
54
+ <CharacterSkinSelectionModal
55
+ isOpen
56
+ onClose={handleCancel}
57
+ onConfirm={(selectedSkin: any) => handleCollect({ selectedSkin })}
58
+ availableCharacters={config.availableCharacters || []}
59
+ atlasJSON={config.atlasJSON}
60
+ atlasIMG={config.atlasIMG}
61
+ initialSelectedSkin={config.initialSelectedSkin}
62
+ />
63
+ );
64
+ }
65
+
66
+ console.warn(`No collector implemented for metadata type: ${metadataType}`);
67
+ return null;
48
68
  };