@rpg-engine/long-bow 0.8.141 → 0.8.146

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 (64) hide show
  1. package/dist/components/Marketplace/BlueprintSearchModal.d.ts +17 -0
  2. package/dist/components/Marketplace/BlueprintTable.d.ts +9 -0
  3. package/dist/components/Marketplace/BuyOrderDetailsModal.d.ts +17 -0
  4. package/dist/components/Marketplace/BuyOrderPanel.d.ts +24 -0
  5. package/dist/components/Marketplace/BuyOrderRows.d.ts +13 -0
  6. package/dist/components/Marketplace/BuyPanel.d.ts +9 -1
  7. package/dist/components/Marketplace/HistoryPanel.d.ts +18 -0
  8. package/dist/components/Marketplace/ManagmentPanel.d.ts +3 -2
  9. package/dist/components/Marketplace/Marketplace.d.ts +35 -2
  10. package/dist/components/Marketplace/MarketplaceSettingsPanel.d.ts +2 -1
  11. package/dist/components/Store/PaymentMethodModal.d.ts +1 -0
  12. package/dist/components/shared/LabelPill/LabelPill.d.ts +9 -0
  13. package/dist/components/shared/LabelPill/index.d.ts +1 -0
  14. package/dist/components/shared/SegmentedToggle/SegmentedToggle.d.ts +12 -0
  15. package/dist/components/shared/SegmentedToggle/index.d.ts +1 -0
  16. package/dist/index.d.ts +4 -0
  17. package/dist/long-bow.cjs.development.js +11573 -1288
  18. package/dist/long-bow.cjs.development.js.map +1 -1
  19. package/dist/long-bow.cjs.production.min.js +1 -1
  20. package/dist/long-bow.cjs.production.min.js.map +1 -1
  21. package/dist/long-bow.esm.js +11562 -1290
  22. package/dist/long-bow.esm.js.map +1 -1
  23. package/dist/stories/Features/marketplace/BlueprintSearchModal.stories.d.ts +1 -0
  24. package/dist/stories/Features/marketplace/BuyOrderPanel.stories.d.ts +1 -0
  25. package/dist/stories/Features/marketplace/BuyOrderRows.stories.d.ts +1 -0
  26. package/dist/stories/Features/marketplace/HistoryPanel.stories.d.ts +1 -0
  27. package/dist/stories/Features/trading/MarketplaceRows.stories.d.ts +2 -1
  28. package/dist/stories/UI/buttonsAndInputs/SegmentedToggle.stories.d.ts +6 -0
  29. package/dist/stories/UI/text/LabelPill.stories.d.ts +7 -0
  30. package/dist/utils/atlasUtils.d.ts +2 -0
  31. package/package.json +2 -2
  32. package/src/components/Marketplace/BlueprintSearchModal.tsx +295 -0
  33. package/src/components/Marketplace/BlueprintTable.tsx +158 -0
  34. package/src/components/Marketplace/BuyOrderDetailsModal.tsx +306 -0
  35. package/src/components/Marketplace/BuyOrderPanel.tsx +284 -0
  36. package/src/components/Marketplace/BuyOrderRows.tsx +287 -0
  37. package/src/components/Marketplace/BuyPanel.tsx +406 -166
  38. package/src/components/Marketplace/HistoryPanel.tsx +422 -0
  39. package/src/components/Marketplace/ManagmentPanel.tsx +13 -15
  40. package/src/components/Marketplace/Marketplace.tsx +181 -30
  41. package/src/components/Marketplace/MarketplaceBuyModal.tsx +1 -0
  42. package/src/components/Marketplace/MarketplaceRows.tsx +41 -10
  43. package/src/components/Marketplace/MarketplaceSettingsPanel.tsx +4 -3
  44. package/src/components/Store/CartView.tsx +11 -0
  45. package/src/components/Store/PaymentMethodModal.tsx +26 -9
  46. package/src/components/shared/LabelPill/LabelPill.tsx +45 -0
  47. package/src/components/shared/LabelPill/index.ts +1 -0
  48. package/src/components/shared/SegmentedToggle/SegmentedToggle.tsx +61 -0
  49. package/src/components/shared/SegmentedToggle/index.ts +1 -0
  50. package/src/components/shared/SpriteFromAtlas.tsx +7 -2
  51. package/src/index.tsx +4 -0
  52. package/src/mocks/atlas/items/items.json +33998 -25238
  53. package/src/mocks/atlas/items/items.png +0 -0
  54. package/src/mocks/itemContainer.mocks.ts +31 -0
  55. package/src/stories/Features/marketplace/BlueprintSearchModal.stories.tsx +145 -0
  56. package/src/stories/Features/marketplace/BuyOrderPanel.stories.tsx +323 -0
  57. package/src/stories/Features/marketplace/BuyOrderRows.stories.tsx +116 -0
  58. package/src/stories/Features/marketplace/HistoryPanel.stories.tsx +157 -0
  59. package/src/stories/Features/trading/Marketplace.stories.tsx +130 -0
  60. package/src/stories/Features/trading/MarketplaceRows.stories.tsx +11 -0
  61. package/src/stories/UI/buttonsAndInputs/SegmentedToggle.stories.tsx +54 -0
  62. package/src/stories/UI/text/LabelPill.stories.tsx +43 -0
  63. package/src/utils/__test__/atlasUtils.spec.ts +26 -0
  64. package/src/utils/atlasUtils.ts +80 -0
@@ -1,4 +1,5 @@
1
- import { Meta } from '@storybook/react';
1
+ import { Meta, Story } from '@storybook/react';
2
2
  declare const meta: Meta;
3
3
  export default meta;
4
4
  export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, import("@storybook/react").Args>;
5
+ export declare const HighStackQuantity: Story;
@@ -0,0 +1,6 @@
1
+ import { Meta } from '@storybook/react';
2
+ import { ISegmentedToggleProps } from '../../../components/shared/SegmentedToggle';
3
+ declare const meta: Meta;
4
+ export default meta;
5
+ export declare const MarketplaceModes: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ISegmentedToggleProps>;
6
+ export declare const ShortOptions: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ISegmentedToggleProps>;
@@ -0,0 +1,7 @@
1
+ import { Meta } from '@storybook/react';
2
+ import { ILabelPillProps } from '../../../components/shared/LabelPill';
3
+ declare const meta: Meta;
4
+ export default meta;
5
+ export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ILabelPillProps>;
6
+ export declare const BuyRequest: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ILabelPillProps>;
7
+ export declare const Status: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ILabelPillProps>;
@@ -0,0 +1,2 @@
1
+ export declare const NO_IMAGE_SPRITE_KEY = "others/no-image.png";
2
+ export declare const resolveAtlasSpriteKey: (atlasJSON: any, spriteKey?: string | null | undefined) => string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.141",
3
+ "version": "0.8.146",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -84,7 +84,7 @@
84
84
  "dependencies": {
85
85
  "@capacitor/core": "^6.1.0",
86
86
  "@rollup/plugin-image": "^2.1.1",
87
- "@rpg-engine/shared": "0.10.83",
87
+ "@rpg-engine/shared": "file:../rpg-shared",
88
88
  "dayjs": "^1.11.2",
89
89
  "font-awesome": "^4.7.0",
90
90
  "fs-extra": "^10.1.0",
@@ -0,0 +1,295 @@
1
+ import {
2
+ IMarketplaceBlueprintSearchRequest,
3
+ IMarketplaceBlueprintSummary,
4
+ ItemSubType,
5
+ } from '@rpg-engine/shared';
6
+ import React, { useState } from 'react';
7
+ import { FaTimes } from 'react-icons/fa';
8
+ import styled, { keyframes } from 'styled-components';
9
+ import { Dropdown } from '../Dropdown';
10
+ import { IOptionsProps } from '../Dropdown';
11
+ import { Input } from '../Input';
12
+ import { Pager } from '../Pager';
13
+ import ModalPortal from '../Abstractions/ModalPortal';
14
+ import { BlueprintTable } from './BlueprintTable';
15
+
16
+ export interface IBlueprintSearchModalProps {
17
+ isOpen: boolean;
18
+ onClose: () => void;
19
+ onSelect: (blueprint: IMarketplaceBlueprintSummary) => void;
20
+ onSearch: (request: IMarketplaceBlueprintSearchRequest) => void;
21
+ blueprints: IMarketplaceBlueprintSummary[];
22
+ totalCount: number;
23
+ currentPage: number;
24
+ isLoading: boolean;
25
+ atlasJSON: any;
26
+ atlasIMG: any;
27
+ }
28
+
29
+ const BLUEPRINTS_PER_PAGE = 10;
30
+
31
+ const scaleIn = keyframes`
32
+ from { transform: scale(0.85); opacity: 0; }
33
+ to { transform: scale(1); opacity: 1; }
34
+ `;
35
+
36
+ const typeOptions: IOptionsProps[] = [
37
+ { id: 1, value: '', option: 'All Types' },
38
+ ...Object.keys(ItemSubType)
39
+ .filter((t) => t !== 'DeadBody')
40
+ .map((t, index) => ({ id: index + 2, value: t, option: t })),
41
+ ];
42
+
43
+ const subTypeOptions: IOptionsProps[] = [
44
+ { id: 1, value: '', option: 'All Sub Types' },
45
+ ...Object.keys(ItemSubType)
46
+ .filter((t) => t !== 'DeadBody')
47
+ .map((t, index) => ({ id: index + 2, value: t, option: t })),
48
+ ];
49
+
50
+ export const BlueprintSearchModal: React.FC<IBlueprintSearchModalProps> = ({
51
+ isOpen,
52
+ onClose,
53
+ onSelect,
54
+ onSearch,
55
+ blueprints,
56
+ totalCount,
57
+ currentPage,
58
+ isLoading,
59
+ atlasJSON,
60
+ atlasIMG,
61
+ }) => {
62
+ const [searchName, setSearchName] = useState('');
63
+ const [selectedType, setSelectedType] = useState('');
64
+ const [selectedSubType, setSelectedSubType] = useState('');
65
+
66
+ if (!isOpen) return null;
67
+
68
+ const triggerSearch = (overrides?: Partial<{ name: string; itemType: string; itemSubType: string; page: number }>): void => {
69
+ onSearch({
70
+ npcId: '',
71
+ name: overrides?.name ?? searchName,
72
+ itemType: overrides?.itemType ?? selectedType,
73
+ itemSubType: overrides?.itemSubType ?? selectedSubType,
74
+ page: overrides?.page ?? 1,
75
+ limit: BLUEPRINTS_PER_PAGE,
76
+ });
77
+ };
78
+
79
+ const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
80
+ setSearchName(e.target.value);
81
+ triggerSearch({ name: e.target.value, page: 1 });
82
+ };
83
+
84
+ const handleTypeChange = (value: string): void => {
85
+ setSelectedType(value);
86
+ triggerSearch({ itemType: value, page: 1 });
87
+ };
88
+
89
+ const handleSubTypeChange = (value: string): void => {
90
+ setSelectedSubType(value);
91
+ triggerSearch({ itemSubType: value, page: 1 });
92
+ };
93
+
94
+ const handlePageChange = (page: number): void => {
95
+ triggerSearch({ page });
96
+ };
97
+
98
+ const stopPropagation = (e: React.MouseEvent | React.PointerEvent): void => {
99
+ e.stopPropagation();
100
+ };
101
+
102
+ const handleClose = (e: React.PointerEvent | React.MouseEvent): void => {
103
+ e.preventDefault();
104
+ e.stopPropagation();
105
+ onClose();
106
+ };
107
+
108
+ return (
109
+ <ModalPortal>
110
+ <Overlay onPointerDown={handleClose} />
111
+ <ModalContainer>
112
+ <ModalContent
113
+ onClick={stopPropagation as React.MouseEventHandler}
114
+ onPointerDown={stopPropagation as React.PointerEventHandler}
115
+ >
116
+ <Header>
117
+ <Title>Select Item</Title>
118
+ <CloseButton onPointerDown={handleClose} aria-label="Close">
119
+ <FaTimes />
120
+ </CloseButton>
121
+ </Header>
122
+
123
+ <InputWrapper>
124
+ <p>SEARCH</p>
125
+ <StyledInput
126
+ value={searchName}
127
+ onChange={handleNameChange}
128
+ placeholder="Search by name..."
129
+ />
130
+ </InputWrapper>
131
+
132
+ <FiltersRow>
133
+ <StyledDropdown
134
+ key={`type-${selectedType}`}
135
+ options={typeOptions}
136
+ onChange={handleTypeChange}
137
+ width="100%"
138
+ />
139
+ <StyledDropdown
140
+ key={`subtype-${selectedSubType}`}
141
+ options={subTypeOptions}
142
+ onChange={handleSubTypeChange}
143
+ width="100%"
144
+ />
145
+ </FiltersRow>
146
+
147
+ <ResultsWrapper>
148
+ {isLoading ? (
149
+ <EmptyState>Loading...</EmptyState>
150
+ ) : blueprints.length === 0 ? (
151
+ <EmptyState>No blueprints found</EmptyState>
152
+ ) : (
153
+ <BlueprintTable
154
+ blueprints={blueprints}
155
+ atlasJSON={atlasJSON}
156
+ atlasIMG={atlasIMG}
157
+ onSelect={onSelect}
158
+ />
159
+ )}
160
+ </ResultsWrapper>
161
+
162
+ <PagerContainer>
163
+ <Pager
164
+ totalItems={totalCount}
165
+ currentPage={currentPage}
166
+ itemsPerPage={BLUEPRINTS_PER_PAGE}
167
+ onPageChange={handlePageChange}
168
+ />
169
+ </PagerContainer>
170
+ </ModalContent>
171
+ </ModalContainer>
172
+ </ModalPortal>
173
+ );
174
+ };
175
+
176
+ const Overlay = styled.div`
177
+ position: fixed;
178
+ inset: 0;
179
+ background: rgba(0, 0, 0, 0.7);
180
+ z-index: 1000;
181
+ `;
182
+
183
+ const ModalContainer = styled.div`
184
+ position: fixed;
185
+ inset: 0;
186
+ display: flex;
187
+ align-items: center;
188
+ justify-content: center;
189
+ z-index: 1001;
190
+ pointer-events: none;
191
+ `;
192
+
193
+ const ModalContent = styled.div`
194
+ background: #1a1a2e;
195
+ border: 2px solid #f59e0b;
196
+ border-radius: 8px;
197
+ padding: 20px 24px;
198
+ width: 600px;
199
+ max-width: 90%;
200
+ display: flex;
201
+ flex-direction: column;
202
+ gap: 12px;
203
+ pointer-events: auto;
204
+ animation: ${scaleIn} 0.15s ease-out;
205
+ `;
206
+
207
+ const Header = styled.div`
208
+ display: flex;
209
+ align-items: center;
210
+ justify-content: space-between;
211
+ `;
212
+
213
+ const Title = styled.h3`
214
+ margin: 0;
215
+ font-family: 'Press Start 2P', cursive;
216
+ font-size: 0.7rem;
217
+ color: #fef08a;
218
+ `;
219
+
220
+ const CloseButton = styled.button`
221
+ background: none;
222
+ border: none;
223
+ color: rgba(255, 255, 255, 0.6);
224
+ cursor: pointer;
225
+ font-size: 1rem;
226
+ padding: 4px;
227
+ display: flex;
228
+ align-items: center;
229
+ pointer-events: auto;
230
+
231
+ &:hover {
232
+ color: #ffffff;
233
+ }
234
+ `;
235
+
236
+ const InputWrapper = styled.div`
237
+ display: flex;
238
+ align-items: center;
239
+ gap: 12px;
240
+ padding: 8px 12px;
241
+ background: rgba(0, 0, 0, 0.2);
242
+ border-radius: 4px;
243
+ border: 1px solid rgba(255, 255, 255, 0.05);
244
+
245
+ p {
246
+ margin: 0;
247
+ font-size: 0.7rem;
248
+ color: #ccc;
249
+ text-transform: uppercase;
250
+ letter-spacing: 1px;
251
+ white-space: nowrap;
252
+ }
253
+ `;
254
+
255
+ const StyledInput = styled(Input)`
256
+ flex: 1;
257
+ `;
258
+
259
+ const FiltersRow = styled.div`
260
+ display: grid;
261
+ grid-template-columns: 1fr 1fr;
262
+ gap: 8px;
263
+ `;
264
+
265
+ const StyledDropdown = styled(Dropdown)`
266
+ margin: 0px !important;
267
+ width: 100% !important;
268
+ `;
269
+
270
+ const ResultsWrapper = styled.div`
271
+ overflow-y: auto;
272
+ max-height: 320px;
273
+ background: rgba(0, 0, 0, 0.2);
274
+ border: 1px solid rgba(255, 255, 255, 0.05);
275
+ border-radius: 4px;
276
+ `;
277
+
278
+ const EmptyState = styled.div`
279
+ display: flex;
280
+ align-items: center;
281
+ justify-content: center;
282
+ height: 100px;
283
+ font-size: 0.55rem;
284
+ color: #666;
285
+ text-transform: uppercase;
286
+ letter-spacing: 1px;
287
+ `;
288
+
289
+ const PagerContainer = styled.div`
290
+ display: flex;
291
+ justify-content: center;
292
+ align-items: center;
293
+ `;
294
+
295
+ export { BLUEPRINTS_PER_PAGE };
@@ -0,0 +1,158 @@
1
+ import { IMarketplaceBlueprintSummary } from '@rpg-engine/shared';
2
+ import React from 'react';
3
+ import styled from 'styled-components';
4
+ import { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
5
+
6
+ export interface IBlueprintTableProps {
7
+ blueprints: IMarketplaceBlueprintSummary[];
8
+ atlasJSON: any;
9
+ atlasIMG: any;
10
+ onSelect?: (blueprint: IMarketplaceBlueprintSummary) => void;
11
+ }
12
+
13
+ export const BlueprintTable: React.FC<IBlueprintTableProps> = ({
14
+ blueprints,
15
+ atlasJSON,
16
+ atlasIMG,
17
+ onSelect,
18
+ }) => {
19
+ return (
20
+ <>
21
+ <ResultsHeader>
22
+ <span />
23
+ <ColName>Name</ColName>
24
+ <ColType>Type</ColType>
25
+ <ColTier>Tier</ColTier>
26
+ </ResultsHeader>
27
+ {blueprints.map((blueprint) => (
28
+ <ResultRow
29
+ key={blueprint.key}
30
+ $selectable={!!onSelect}
31
+ onPointerDown={onSelect ? () => onSelect(blueprint) : undefined}
32
+ >
33
+ <SpriteWrapper>
34
+ <SpriteFromAtlas
35
+ atlasJSON={atlasJSON}
36
+ atlasIMG={atlasIMG}
37
+ spriteKey={blueprint.texturePath || blueprint.key}
38
+ width={32}
39
+ height={32}
40
+ imgScale={2}
41
+ centered
42
+ />
43
+ </SpriteWrapper>
44
+ <ColName>
45
+ <BlueprintName>{blueprint.name}</BlueprintName>
46
+ {(blueprint.type || blueprint.subType) && (
47
+ <BlueprintMeta>
48
+ {[blueprint.type, blueprint.subType]
49
+ .filter(Boolean)
50
+ .filter((v, i, arr) => arr.indexOf(v) === i)
51
+ .join(' · ')}
52
+ </BlueprintMeta>
53
+ )}
54
+ </ColName>
55
+ <ColType>
56
+ <TypeText>{blueprint.type}</TypeText>
57
+ {blueprint.subType && blueprint.subType !== blueprint.type && (
58
+ <SubTypeText>{blueprint.subType}</SubTypeText>
59
+ )}
60
+ </ColType>
61
+ <ColTier>T{blueprint.tier}</ColTier>
62
+ </ResultRow>
63
+ ))}
64
+ </>
65
+ );
66
+ };
67
+
68
+ const tableRowBase = `
69
+ display: grid;
70
+ grid-template-columns: 40px 1fr 120px 50px;
71
+ align-items: center;
72
+ gap: 8px;
73
+ padding: 6px 12px;
74
+ `;
75
+
76
+ const ResultsHeader = styled.div`
77
+ ${tableRowBase}
78
+ background: rgba(0, 0, 0, 0.4);
79
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
80
+ position: sticky;
81
+ top: 0;
82
+ z-index: 1;
83
+
84
+ > * {
85
+ font-size: 0.45rem;
86
+ color: #888;
87
+ text-transform: uppercase;
88
+ letter-spacing: 1px;
89
+ }
90
+ `;
91
+
92
+ const ResultRow = styled.div<{ $selectable: boolean }>`
93
+ ${tableRowBase}
94
+ border-bottom: 1px solid rgba(255, 255, 255, 0.04);
95
+ cursor: ${p => p.$selectable ? 'pointer' : 'default'};
96
+ transition: background 0.1s;
97
+
98
+ &:hover {
99
+ background: ${p => p.$selectable ? 'rgba(245, 158, 11, 0.08)' : 'none'};
100
+ }
101
+
102
+ &:last-child {
103
+ border-bottom: none;
104
+ }
105
+ `;
106
+
107
+ const SpriteWrapper = styled.div`
108
+ display: flex;
109
+ align-items: center;
110
+ justify-content: center;
111
+ width: 40px;
112
+ height: 32px;
113
+ `;
114
+
115
+ const ColName = styled.div`
116
+ display: flex;
117
+ flex-direction: column;
118
+ gap: 2px;
119
+ overflow: hidden;
120
+ `;
121
+
122
+ const BlueprintName = styled.span`
123
+ font-size: 0.5rem;
124
+ color: #ddd;
125
+ overflow: hidden;
126
+ text-overflow: ellipsis;
127
+ white-space: nowrap;
128
+ `;
129
+
130
+ const BlueprintMeta = styled.span`
131
+ font-size: 0.4rem;
132
+ color: #666;
133
+ overflow: hidden;
134
+ text-overflow: ellipsis;
135
+ white-space: nowrap;
136
+ `;
137
+
138
+ const ColType = styled.div`
139
+ display: flex;
140
+ flex-direction: column;
141
+ gap: 2px;
142
+ `;
143
+
144
+ const TypeText = styled.span`
145
+ font-size: 0.45rem;
146
+ color: #aaa;
147
+ `;
148
+
149
+ const SubTypeText = styled.span`
150
+ font-size: 0.4rem;
151
+ color: #666;
152
+ `;
153
+
154
+ const ColTier = styled.div`
155
+ font-size: 0.5rem;
156
+ color: #f59e0b;
157
+ text-align: center;
158
+ `;