@rpg-engine/long-bow 0.8.231 → 0.8.233

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 (37) hide show
  1. package/dist/components/Quests/QuestInfo/QuestInfo.d.ts +3 -1
  2. package/dist/components/Quests/QuestInfo/QuestObjectivesSection.d.ts +8 -0
  3. package/dist/components/Quests/QuestInfo/QuestRequirementsSection.d.ts +8 -0
  4. package/dist/components/Quests/QuestInfo/QuestRewardsSection.d.ts +8 -0
  5. package/dist/components/Quests/QuestInfo/QuestSectionTypes.d.ts +8 -0
  6. package/dist/components/Quests/QuestList.d.ts +4 -5
  7. package/dist/components/Quests/QuestListRow.d.ts +15 -0
  8. package/dist/components/Store/CartView.d.ts +11 -1
  9. package/dist/components/Store/PaymentMethodModal.d.ts +1 -0
  10. package/dist/components/Store/Store.d.ts +2 -1
  11. package/dist/components/Store/hooks/useStoreCart.d.ts +2 -1
  12. package/dist/components/Tutorial/TutorialStepper.d.ts +2 -0
  13. package/dist/index.d.ts +1 -0
  14. package/dist/long-bow.cjs.development.js +491 -170
  15. package/dist/long-bow.cjs.development.js.map +1 -1
  16. package/dist/long-bow.cjs.production.min.js +1 -1
  17. package/dist/long-bow.cjs.production.min.js.map +1 -1
  18. package/dist/long-bow.esm.js +492 -172
  19. package/dist/long-bow.esm.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/Quests/QuestInfo/QuestInfo.tsx +57 -68
  22. package/src/components/Quests/QuestInfo/QuestObjectivesSection.tsx +114 -0
  23. package/src/components/Quests/QuestInfo/QuestRequirementsSection.tsx +74 -0
  24. package/src/components/Quests/QuestInfo/QuestRewardsSection.tsx +128 -0
  25. package/src/components/Quests/QuestInfo/QuestSectionTypes.ts +8 -0
  26. package/src/components/Quests/QuestList.tsx +12 -87
  27. package/src/components/Quests/QuestListRow.tsx +178 -0
  28. package/src/components/Store/CartView.tsx +26 -7
  29. package/src/components/Store/MetadataCollector.tsx +28 -1
  30. package/src/components/Store/PaymentMethodModal.tsx +19 -9
  31. package/src/components/Store/Store.tsx +2 -2
  32. package/src/components/Store/__test__/CartView.spec.tsx +190 -0
  33. package/src/components/Store/__test__/MetadataCollector.spec.tsx +12 -3
  34. package/src/components/Store/__test__/PaymentMethodModal.spec.tsx +108 -0
  35. package/src/components/Store/hooks/useStoreCart.ts +6 -4
  36. package/src/components/Tutorial/TutorialStepper.tsx +2 -0
  37. package/src/index.tsx +1 -1
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+ // @ts-nocheck
5
+ import React from 'react';
6
+ import ReactDOM from 'react-dom';
7
+ import { act } from 'react-dom/test-utils';
8
+ import { PaymentMethodModal } from '../PaymentMethodModal';
9
+
10
+ jest.mock('../../Abstractions/ModalPortal', () => ({
11
+ __esModule: true,
12
+ default: ({ children }) => <>{children}</>,
13
+ }));
14
+
15
+ jest.mock('../../Button', () => ({
16
+ ButtonTypes: { RPGUIButton: 'rpgui-button' },
17
+ Button: ({ children, disabled, onPointerDown }) => (
18
+ <button type="button" disabled={disabled} onPointerDown={onPointerDown}>
19
+ {children}
20
+ </button>
21
+ ),
22
+ }));
23
+
24
+ jest.mock('../../shared/MMORPGNumber', () => ({
25
+ MMORPGNumber: ({ value }) => <span>{value}</span>,
26
+ }));
27
+
28
+ jest.mock('pixelarticons/react/Cancel', () => ({
29
+ Cancel: () => <span>close</span>,
30
+ }));
31
+
32
+ jest.mock('styled-components', () => {
33
+ const withoutTransientProps = (props) =>
34
+ Object.fromEntries(
35
+ Object.entries(props).filter(([key]) => !key.startsWith('$'))
36
+ );
37
+ const createTag = (tag) => () => {
38
+ const Tag =
39
+ tag === 'button'
40
+ ? 'button'
41
+ : tag === 'h3'
42
+ ? 'h3'
43
+ : tag === 'span'
44
+ ? 'span'
45
+ : 'div';
46
+ return ({ children, ...props }) => (
47
+ <Tag {...withoutTransientProps(props)}>{children}</Tag>
48
+ );
49
+ };
50
+ const styled = new Proxy(() => {}, {
51
+ get: (_target, prop) => {
52
+ if (prop === '__esModule') return true;
53
+ return createTag(prop);
54
+ },
55
+ apply: () => createTag('div'),
56
+ });
57
+ return { __esModule: true, default: styled };
58
+ });
59
+
60
+ describe('PaymentMethodModal processing guard', () => {
61
+ afterEach(() => {
62
+ ReactDOM.unmountComponentAtNode(document.body.lastElementChild);
63
+ document.body.innerHTML = '';
64
+ });
65
+
66
+ it('blocks close, backdrop, and confirm while checkout is processing', () => {
67
+ const onClose = jest.fn();
68
+ const onPayWithCard = jest.fn();
69
+ const container = document.createElement('div');
70
+ document.body.appendChild(container);
71
+
72
+ act(() => {
73
+ ReactDOM.render(
74
+ <PaymentMethodModal
75
+ dcBalance={0}
76
+ onPayWithDC={jest.fn()}
77
+ onPayWithCard={onPayWithCard}
78
+ onPayWithPix={jest.fn()}
79
+ onClose={onClose}
80
+ isProcessing
81
+ />,
82
+ container
83
+ );
84
+ });
85
+
86
+ const closeButton = container.querySelector('button[aria-label="Close"]');
87
+ const confirmButton = Array.from(container.querySelectorAll('button')).find(
88
+ (button) => button.textContent === 'Processing...'
89
+ );
90
+ const overlay = container.firstElementChild;
91
+
92
+ expect(closeButton.disabled).toBe(true);
93
+ expect(confirmButton.disabled).toBe(true);
94
+
95
+ act(() => {
96
+ closeButton.dispatchEvent(
97
+ new MouseEvent('pointerdown', { bubbles: true })
98
+ );
99
+ confirmButton.dispatchEvent(
100
+ new MouseEvent('pointerdown', { bubbles: true })
101
+ );
102
+ overlay.dispatchEvent(new MouseEvent('pointerdown', { bubbles: true }));
103
+ });
104
+
105
+ expect(onClose).not.toHaveBeenCalled();
106
+ expect(onPayWithCard).not.toHaveBeenCalled();
107
+ });
108
+ });
@@ -6,6 +6,7 @@ import {
6
6
  PurchaseType
7
7
  } from '@rpg-engine/shared';
8
8
  import { useEffect, useRef, useState } from 'react';
9
+ import { CartPurchaseResult } from '../CartView';
9
10
  import { useStoreMetadata } from './useStoreMetadata';
10
11
 
11
12
  interface ICartItem {
@@ -19,7 +20,7 @@ interface IUseStoreCart {
19
20
  isCartOpen: boolean;
20
21
  handleAddToCart: (item: IProductBlueprint, quantity: number, metadata?: Record<string, any>) => void;
21
22
  handleRemoveFromCart: (itemKey: string) => void;
22
- handlePurchase: (onPurchase: (purchase: IPurchase) => Promise<boolean>) => Promise<boolean>;
23
+ handlePurchase: (onPurchase: (purchase: IPurchase) => Promise<CartPurchaseResult>) => Promise<CartPurchaseResult>;
23
24
  openCart: () => void;
24
25
  closeCart: () => void;
25
26
  getTotalItems: () => number;
@@ -104,7 +105,7 @@ export const useStoreCart = (): IUseStoreCart => {
104
105
  );
105
106
  };
106
107
 
107
- const handlePurchase = async (onPurchase: (purchase: IPurchase) => Promise<boolean>): Promise<boolean> => {
108
+ const handlePurchase = async (onPurchase: (purchase: IPurchase) => Promise<CartPurchaseResult>): Promise<CartPurchaseResult> => {
108
109
  const purchaseUnits: IPurchaseUnit[] = cartItems.map(cartItem => ({
109
110
  purchaseKey: cartItem.item.key,
110
111
  qty: cartItem.quantity,
@@ -122,14 +123,15 @@ export const useStoreCart = (): IUseStoreCart => {
122
123
  purchases: purchaseUnits,
123
124
  };
124
125
 
125
- const success = await onPurchase(purchase);
126
+ const result = await onPurchase(purchase);
127
+ const success = typeof result === 'boolean' ? result : result.status === 'success';
126
128
 
127
129
  if (success && isMounted.current) {
128
130
  setCartItems([]);
129
131
  setIsCartOpen(false);
130
132
  }
131
133
 
132
- return success;
134
+ return result;
133
135
  };
134
136
 
135
137
  const openCart = () => setIsCartOpen(true);
@@ -9,6 +9,8 @@ export interface ITutorialLesson {
9
9
  title: string;
10
10
  body?: React.ReactNode | string;
11
11
  text?: string;
12
+ bodyHighlights?: string[];
13
+ textHighlights?: string[];
12
14
  image: string;
13
15
  imageUrl?: string;
14
16
  }
package/src/index.tsx CHANGED
@@ -62,6 +62,7 @@ export * from './components/PropertySelect/PropertySelect';
62
62
  export * from './components/QuantitySelector/QuantitySelectorModal';
63
63
  export * from './components/Quests/QuestInfo/QuestInfo';
64
64
  export * from './components/Quests/QuestList';
65
+ export * from './components/Quests/QuestListRow';
65
66
  export * from './components/RadioButton';
66
67
  export * from './components/RadioSelectCard/RadioSelectCard';
67
68
  export * from './components/RangeSlider';
@@ -98,4 +99,3 @@ export * from './components/Truncate';
98
99
  export * from './components/Tutorial/TutorialStepper';
99
100
  export * from './components/typography/DynamicText';
100
101
  export { useEventListener } from './hooks/useEventListener';
101
-