@rpg-engine/long-bow 0.8.140 → 0.8.145
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/dist/components/Marketplace/BlueprintSearchModal.d.ts +17 -0
- package/dist/components/Marketplace/BuyOrderDetailsModal.d.ts +17 -0
- package/dist/components/Marketplace/BuyOrderPanel.d.ts +24 -0
- package/dist/components/Marketplace/BuyOrderRows.d.ts +13 -0
- package/dist/components/Marketplace/BuyPanel.d.ts +9 -1
- package/dist/components/Marketplace/HistoryPanel.d.ts +18 -0
- package/dist/components/Marketplace/ManagmentPanel.d.ts +4 -3
- package/dist/components/Marketplace/Marketplace.d.ts +38 -2
- package/dist/components/Marketplace/MarketplaceRows.d.ts +13 -1
- package/dist/components/Marketplace/MarketplaceSettingsPanel.d.ts +8 -0
- package/dist/components/Store/PaymentMethodModal.d.ts +1 -0
- package/dist/components/shared/LabelPill/LabelPill.d.ts +9 -0
- package/dist/components/shared/LabelPill/index.d.ts +1 -0
- package/dist/components/shared/SegmentedToggle/SegmentedToggle.d.ts +12 -0
- package/dist/components/shared/SegmentedToggle/index.d.ts +1 -0
- package/dist/components/shared/Tabs/Tabs.d.ts +13 -0
- package/dist/components/shared/Tabs/index.d.ts +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/long-bow.cjs.development.js +12074 -1449
- package/dist/long-bow.cjs.development.js.map +1 -1
- package/dist/long-bow.cjs.production.min.js +1 -1
- package/dist/long-bow.cjs.production.min.js.map +1 -1
- package/dist/long-bow.esm.js +12060 -1450
- package/dist/long-bow.esm.js.map +1 -1
- package/dist/stories/Features/marketplace/BlueprintSearchModal.stories.d.ts +1 -0
- package/dist/stories/Features/marketplace/BuyOrderPanel.stories.d.ts +1 -0
- package/dist/stories/Features/marketplace/BuyOrderRows.stories.d.ts +1 -0
- package/dist/stories/Features/marketplace/HistoryPanel.stories.d.ts +1 -0
- package/dist/stories/Features/trading/MarketplaceRows.stories.d.ts +2 -1
- package/dist/stories/UI/buttonsAndInputs/SegmentedToggle.stories.d.ts +6 -0
- package/dist/stories/UI/text/LabelPill.stories.d.ts +7 -0
- package/dist/utils/atlasUtils.d.ts +2 -0
- package/package.json +3 -2
- package/src/components/ConfirmModal.tsx +50 -27
- package/src/components/Marketplace/BlueprintSearchModal.tsx +418 -0
- package/src/components/Marketplace/BuyOrderDetailsModal.tsx +307 -0
- package/src/components/Marketplace/BuyOrderPanel.tsx +266 -0
- package/src/components/Marketplace/BuyOrderRows.tsx +287 -0
- package/src/components/Marketplace/BuyPanel.tsx +486 -170
- package/src/components/Marketplace/HistoryPanel.tsx +422 -0
- package/src/components/Marketplace/ManagmentPanel.tsx +176 -98
- package/src/components/Marketplace/Marketplace.tsx +227 -40
- package/src/components/Marketplace/MarketplaceBuyModal.tsx +1 -0
- package/src/components/Marketplace/MarketplaceRows.tsx +274 -80
- package/src/components/Marketplace/MarketplaceSettingsPanel.tsx +128 -0
- package/src/components/Store/CartView.tsx +11 -0
- package/src/components/Store/PaymentMethodModal.tsx +26 -9
- package/src/components/shared/LabelPill/LabelPill.tsx +45 -0
- package/src/components/shared/LabelPill/index.ts +1 -0
- package/src/components/shared/SegmentedToggle/SegmentedToggle.tsx +61 -0
- package/src/components/shared/SegmentedToggle/index.ts +1 -0
- package/src/components/shared/SpriteFromAtlas.tsx +7 -2
- package/src/components/shared/Tabs/Tabs.tsx +60 -0
- package/src/components/shared/Tabs/index.ts +1 -0
- package/src/index.tsx +5 -0
- package/src/mocks/atlas/items/items.json +33998 -25238
- package/src/mocks/atlas/items/items.png +0 -0
- package/src/mocks/itemContainer.mocks.ts +31 -0
- package/src/stories/Features/marketplace/BlueprintSearchModal.stories.tsx +145 -0
- package/src/stories/Features/marketplace/BuyOrderPanel.stories.tsx +207 -0
- package/src/stories/Features/marketplace/BuyOrderRows.stories.tsx +116 -0
- package/src/stories/Features/marketplace/HistoryPanel.stories.tsx +157 -0
- package/src/stories/Features/trading/Marketplace.stories.tsx +109 -0
- package/src/stories/Features/trading/MarketplaceRows.stories.tsx +11 -0
- package/src/stories/UI/buttonsAndInputs/SegmentedToggle.stories.tsx +54 -0
- package/src/stories/UI/text/LabelPill.stories.tsx +43 -0
- package/src/utils/__test__/atlasUtils.spec.ts +26 -0
- package/src/utils/atlasUtils.ts +80 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -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>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpg-engine/long-bow",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.145",
|
|
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": "
|
|
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",
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
"lodash-es": "^4.17.21",
|
|
93
93
|
"mobx": "^6.6.0",
|
|
94
94
|
"mobx-react": "^7.5.0",
|
|
95
|
+
"pixelarticons": "^2.0.2",
|
|
95
96
|
"react-colorful": "^5.6.1",
|
|
96
97
|
"react-draggable": "^4.4.5",
|
|
97
98
|
"react-error-boundary": "^3.1.4",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { ReactNode, useCallback } from 'react';
|
|
2
|
+
import { FaTimes } from 'react-icons/fa';
|
|
2
3
|
import styled, { createGlobalStyle } from 'styled-components';
|
|
3
4
|
import ModalPortal from './Abstractions/ModalPortal';
|
|
4
5
|
import { Button, ButtonTypes } from './Button';
|
|
@@ -66,6 +67,13 @@ export const ConfirmModal: React.FC<IConfirmModalProps> = ({
|
|
|
66
67
|
onTouchMove={stopPropagationTouch}
|
|
67
68
|
onPointerDown={stopPropagationPointer}
|
|
68
69
|
>
|
|
70
|
+
<Header>
|
|
71
|
+
<Title>Confirm</Title>
|
|
72
|
+
<CloseButton onPointerDown={handleClose} aria-label="Close">
|
|
73
|
+
<FaTimes />
|
|
74
|
+
</CloseButton>
|
|
75
|
+
</Header>
|
|
76
|
+
|
|
69
77
|
<MessageContainer>
|
|
70
78
|
{typeof message === 'string' ? (
|
|
71
79
|
<Message>{message}</Message>
|
|
@@ -134,61 +142,76 @@ const ModalContainer = styled.div`
|
|
|
134
142
|
`;
|
|
135
143
|
|
|
136
144
|
const ModalContent = styled.div`
|
|
137
|
-
background
|
|
138
|
-
border: 2px solid #
|
|
145
|
+
background: #1a1a2e;
|
|
146
|
+
border: 2px solid #f59e0b;
|
|
139
147
|
border-radius: 8px;
|
|
140
|
-
padding: 20px;
|
|
148
|
+
padding: 20px 24px 24px;
|
|
141
149
|
min-width: 300px;
|
|
142
150
|
max-width: 90%;
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5), 0 0 40px rgba(0, 0, 0, 0.3);
|
|
151
|
+
display: flex;
|
|
152
|
+
flex-direction: column;
|
|
153
|
+
gap: 16px;
|
|
147
154
|
pointer-events: auto;
|
|
155
|
+
animation: scaleIn 0.15s ease-out;
|
|
148
156
|
|
|
149
157
|
@keyframes scaleIn {
|
|
150
|
-
from {
|
|
151
|
-
|
|
152
|
-
opacity: 0;
|
|
153
|
-
}
|
|
154
|
-
to {
|
|
155
|
-
transform: scale(1);
|
|
156
|
-
opacity: 1;
|
|
157
|
-
}
|
|
158
|
+
from { transform: scale(0.85); opacity: 0; }
|
|
159
|
+
to { transform: scale(1); opacity: 1; }
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
@media (max-width: 768px) {
|
|
161
|
-
padding: 25px;
|
|
162
163
|
width: 85%;
|
|
163
164
|
}
|
|
164
165
|
`;
|
|
165
166
|
|
|
167
|
+
const Header = styled.div`
|
|
168
|
+
display: flex;
|
|
169
|
+
align-items: center;
|
|
170
|
+
justify-content: space-between;
|
|
171
|
+
`;
|
|
172
|
+
|
|
173
|
+
const Title = styled.h3`
|
|
174
|
+
margin: 0;
|
|
175
|
+
font-family: 'Press Start 2P', cursive;
|
|
176
|
+
font-size: 0.7rem;
|
|
177
|
+
color: #fef08a;
|
|
178
|
+
`;
|
|
179
|
+
|
|
180
|
+
const CloseButton = styled.button`
|
|
181
|
+
background: none;
|
|
182
|
+
border: none;
|
|
183
|
+
color: rgba(255, 255, 255, 0.6);
|
|
184
|
+
cursor: pointer;
|
|
185
|
+
font-size: 1rem;
|
|
186
|
+
padding: 4px;
|
|
187
|
+
display: flex;
|
|
188
|
+
align-items: center;
|
|
189
|
+
|
|
190
|
+
&:hover {
|
|
191
|
+
color: #ffffff;
|
|
192
|
+
}
|
|
193
|
+
`;
|
|
194
|
+
|
|
166
195
|
const MessageContainer = styled.div`
|
|
167
|
-
margin-bottom: 20px;
|
|
168
196
|
text-align: center;
|
|
169
197
|
`;
|
|
170
198
|
|
|
171
199
|
const Message = styled.p`
|
|
172
200
|
margin: 0;
|
|
173
|
-
font-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
@media (max-width: 768px) {
|
|
178
|
-
font-size: 18px;
|
|
179
|
-
}
|
|
201
|
+
font-family: 'Press Start 2P', cursive;
|
|
202
|
+
font-size: 0.6rem;
|
|
203
|
+
color: rgba(255, 255, 255, 0.85);
|
|
204
|
+
line-height: 1.8;
|
|
180
205
|
`;
|
|
181
206
|
|
|
182
207
|
const ButtonsContainer = styled.div`
|
|
183
208
|
display: flex;
|
|
184
209
|
justify-content: center;
|
|
185
210
|
gap: 20px;
|
|
211
|
+
margin-top: 4px;
|
|
186
212
|
|
|
187
213
|
@media (max-width: 768px) {
|
|
188
214
|
gap: 30px;
|
|
189
|
-
/* Increase button size for better touch targets */
|
|
190
|
-
transform: scale(1.1);
|
|
191
|
-
margin-top: 5px;
|
|
192
215
|
}
|
|
193
216
|
`;
|
|
194
217
|
|
|
@@ -0,0 +1,418 @@
|
|
|
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 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 { SpriteFromAtlas } from '../shared/SpriteFromAtlas';
|
|
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 typeOptions: IOptionsProps[] = [
|
|
32
|
+
{ id: 1, value: '', option: 'All Types' },
|
|
33
|
+
...Object.keys(ItemSubType)
|
|
34
|
+
.filter((t) => t !== 'DeadBody')
|
|
35
|
+
.map((t, index) => ({ id: index + 2, value: t, option: t })),
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const subTypeOptions: IOptionsProps[] = [
|
|
39
|
+
{ id: 1, value: '', option: 'All Sub Types' },
|
|
40
|
+
...Object.keys(ItemSubType)
|
|
41
|
+
.filter((t) => t !== 'DeadBody')
|
|
42
|
+
.map((t, index) => ({ id: index + 2, value: t, option: t })),
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
export const BlueprintSearchModal: React.FC<IBlueprintSearchModalProps> = ({
|
|
46
|
+
isOpen,
|
|
47
|
+
onClose,
|
|
48
|
+
onSelect,
|
|
49
|
+
onSearch,
|
|
50
|
+
blueprints,
|
|
51
|
+
totalCount,
|
|
52
|
+
currentPage,
|
|
53
|
+
isLoading,
|
|
54
|
+
atlasJSON,
|
|
55
|
+
atlasIMG,
|
|
56
|
+
}) => {
|
|
57
|
+
const [searchName, setSearchName] = useState('');
|
|
58
|
+
const [selectedType, setSelectedType] = useState('');
|
|
59
|
+
const [selectedSubType, setSelectedSubType] = useState('');
|
|
60
|
+
|
|
61
|
+
if (!isOpen) return null;
|
|
62
|
+
|
|
63
|
+
const triggerSearch = (overrides?: Partial<{ name: string; itemType: string; itemSubType: string; page: number }>): void => {
|
|
64
|
+
onSearch({
|
|
65
|
+
npcId: '',
|
|
66
|
+
name: overrides?.name ?? searchName,
|
|
67
|
+
itemType: overrides?.itemType ?? selectedType,
|
|
68
|
+
itemSubType: overrides?.itemSubType ?? selectedSubType,
|
|
69
|
+
page: overrides?.page ?? 1,
|
|
70
|
+
limit: BLUEPRINTS_PER_PAGE,
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
|
|
75
|
+
setSearchName(e.target.value);
|
|
76
|
+
triggerSearch({ name: e.target.value, page: 1 });
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const handleTypeChange = (value: string): void => {
|
|
80
|
+
setSelectedType(value);
|
|
81
|
+
triggerSearch({ itemType: value, page: 1 });
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const handleSubTypeChange = (value: string): void => {
|
|
85
|
+
setSelectedSubType(value);
|
|
86
|
+
triggerSearch({ itemSubType: value, page: 1 });
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const handlePageChange = (page: number): void => {
|
|
90
|
+
triggerSearch({ page });
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const stopPropagation = (e: React.MouseEvent | React.PointerEvent): void => {
|
|
94
|
+
e.stopPropagation();
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const handleClose = (e: React.PointerEvent | React.MouseEvent): void => {
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
e.stopPropagation();
|
|
100
|
+
onClose();
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return (
|
|
104
|
+
<ModalPortal>
|
|
105
|
+
<Overlay onPointerDown={handleClose} />
|
|
106
|
+
<ModalContainer>
|
|
107
|
+
<ModalContent
|
|
108
|
+
onClick={stopPropagation as React.MouseEventHandler}
|
|
109
|
+
onPointerDown={stopPropagation as React.PointerEventHandler}
|
|
110
|
+
>
|
|
111
|
+
<Header>
|
|
112
|
+
<Title>Select Item</Title>
|
|
113
|
+
<CloseButton onPointerDown={handleClose} aria-label="Close">
|
|
114
|
+
<FaTimes />
|
|
115
|
+
</CloseButton>
|
|
116
|
+
</Header>
|
|
117
|
+
|
|
118
|
+
<InputWrapper>
|
|
119
|
+
<p>SEARCH</p>
|
|
120
|
+
<StyledInput
|
|
121
|
+
value={searchName}
|
|
122
|
+
onChange={handleNameChange}
|
|
123
|
+
placeholder="Search by name..."
|
|
124
|
+
/>
|
|
125
|
+
</InputWrapper>
|
|
126
|
+
|
|
127
|
+
<FiltersRow>
|
|
128
|
+
<StyledDropdown
|
|
129
|
+
key={`type-${selectedType}`}
|
|
130
|
+
options={typeOptions}
|
|
131
|
+
onChange={handleTypeChange}
|
|
132
|
+
width="100%"
|
|
133
|
+
/>
|
|
134
|
+
<StyledDropdown
|
|
135
|
+
key={`subtype-${selectedSubType}`}
|
|
136
|
+
options={subTypeOptions}
|
|
137
|
+
onChange={handleSubTypeChange}
|
|
138
|
+
width="100%"
|
|
139
|
+
/>
|
|
140
|
+
</FiltersRow>
|
|
141
|
+
|
|
142
|
+
<ResultsWrapper>
|
|
143
|
+
{isLoading ? (
|
|
144
|
+
<EmptyState>Loading...</EmptyState>
|
|
145
|
+
) : blueprints.length === 0 ? (
|
|
146
|
+
<EmptyState>No blueprints found</EmptyState>
|
|
147
|
+
) : (
|
|
148
|
+
<>
|
|
149
|
+
<ResultsHeader>
|
|
150
|
+
<ColName>Name</ColName>
|
|
151
|
+
<ColType>Type</ColType>
|
|
152
|
+
<ColTier>Tier</ColTier>
|
|
153
|
+
</ResultsHeader>
|
|
154
|
+
{blueprints.map((blueprint) => (
|
|
155
|
+
<ResultRow
|
|
156
|
+
key={blueprint.key}
|
|
157
|
+
onPointerDown={() => onSelect(blueprint)}
|
|
158
|
+
>
|
|
159
|
+
<SpriteWrapper>
|
|
160
|
+
<SpriteFromAtlas
|
|
161
|
+
atlasJSON={atlasJSON}
|
|
162
|
+
atlasIMG={atlasIMG}
|
|
163
|
+
spriteKey={blueprint.texturePath || blueprint.key}
|
|
164
|
+
width={32}
|
|
165
|
+
height={32}
|
|
166
|
+
imgScale={2}
|
|
167
|
+
centered
|
|
168
|
+
/>
|
|
169
|
+
</SpriteWrapper>
|
|
170
|
+
<ColName>
|
|
171
|
+
<BlueprintName>{blueprint.name}</BlueprintName>
|
|
172
|
+
<BlueprintKey>{blueprint.key}</BlueprintKey>
|
|
173
|
+
</ColName>
|
|
174
|
+
<ColType>
|
|
175
|
+
<TypeText>{blueprint.type}</TypeText>
|
|
176
|
+
{blueprint.subType && blueprint.subType !== blueprint.type && (
|
|
177
|
+
<SubTypeText>{blueprint.subType}</SubTypeText>
|
|
178
|
+
)}
|
|
179
|
+
</ColType>
|
|
180
|
+
<ColTier>T{blueprint.tier}</ColTier>
|
|
181
|
+
</ResultRow>
|
|
182
|
+
))}
|
|
183
|
+
</>
|
|
184
|
+
)}
|
|
185
|
+
</ResultsWrapper>
|
|
186
|
+
|
|
187
|
+
<PagerContainer>
|
|
188
|
+
<Pager
|
|
189
|
+
totalItems={totalCount}
|
|
190
|
+
currentPage={currentPage}
|
|
191
|
+
itemsPerPage={BLUEPRINTS_PER_PAGE}
|
|
192
|
+
onPageChange={handlePageChange}
|
|
193
|
+
/>
|
|
194
|
+
</PagerContainer>
|
|
195
|
+
</ModalContent>
|
|
196
|
+
</ModalContainer>
|
|
197
|
+
</ModalPortal>
|
|
198
|
+
);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const Overlay = styled.div`
|
|
202
|
+
position: fixed;
|
|
203
|
+
inset: 0;
|
|
204
|
+
background: rgba(0, 0, 0, 0.7);
|
|
205
|
+
z-index: 1000;
|
|
206
|
+
`;
|
|
207
|
+
|
|
208
|
+
const ModalContainer = styled.div`
|
|
209
|
+
position: fixed;
|
|
210
|
+
inset: 0;
|
|
211
|
+
display: flex;
|
|
212
|
+
align-items: center;
|
|
213
|
+
justify-content: center;
|
|
214
|
+
z-index: 1001;
|
|
215
|
+
pointer-events: none;
|
|
216
|
+
`;
|
|
217
|
+
|
|
218
|
+
const ModalContent = styled.div`
|
|
219
|
+
background: #1a1a2e;
|
|
220
|
+
border: 2px solid #f59e0b;
|
|
221
|
+
border-radius: 8px;
|
|
222
|
+
padding: 20px 24px;
|
|
223
|
+
width: 600px;
|
|
224
|
+
max-width: 90%;
|
|
225
|
+
display: flex;
|
|
226
|
+
flex-direction: column;
|
|
227
|
+
gap: 12px;
|
|
228
|
+
pointer-events: auto;
|
|
229
|
+
animation: scaleIn 0.15s ease-out;
|
|
230
|
+
|
|
231
|
+
@keyframes scaleIn {
|
|
232
|
+
from { transform: scale(0.85); opacity: 0; }
|
|
233
|
+
to { transform: scale(1); opacity: 1; }
|
|
234
|
+
}
|
|
235
|
+
`;
|
|
236
|
+
|
|
237
|
+
const Header = styled.div`
|
|
238
|
+
display: flex;
|
|
239
|
+
align-items: center;
|
|
240
|
+
justify-content: space-between;
|
|
241
|
+
`;
|
|
242
|
+
|
|
243
|
+
const Title = styled.h3`
|
|
244
|
+
margin: 0;
|
|
245
|
+
font-family: 'Press Start 2P', cursive;
|
|
246
|
+
font-size: 0.7rem;
|
|
247
|
+
color: #fef08a;
|
|
248
|
+
`;
|
|
249
|
+
|
|
250
|
+
const CloseButton = styled.button`
|
|
251
|
+
background: none;
|
|
252
|
+
border: none;
|
|
253
|
+
color: rgba(255, 255, 255, 0.6);
|
|
254
|
+
cursor: pointer;
|
|
255
|
+
font-size: 1rem;
|
|
256
|
+
padding: 4px;
|
|
257
|
+
display: flex;
|
|
258
|
+
align-items: center;
|
|
259
|
+
pointer-events: auto;
|
|
260
|
+
|
|
261
|
+
&:hover {
|
|
262
|
+
color: #ffffff;
|
|
263
|
+
}
|
|
264
|
+
`;
|
|
265
|
+
|
|
266
|
+
const InputWrapper = styled.div`
|
|
267
|
+
display: flex;
|
|
268
|
+
align-items: center;
|
|
269
|
+
gap: 12px;
|
|
270
|
+
padding: 8px 12px;
|
|
271
|
+
background: rgba(0, 0, 0, 0.2);
|
|
272
|
+
border-radius: 4px;
|
|
273
|
+
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
274
|
+
|
|
275
|
+
p {
|
|
276
|
+
margin: 0;
|
|
277
|
+
font-size: 0.7rem;
|
|
278
|
+
color: #ccc;
|
|
279
|
+
text-transform: uppercase;
|
|
280
|
+
letter-spacing: 1px;
|
|
281
|
+
white-space: nowrap;
|
|
282
|
+
}
|
|
283
|
+
`;
|
|
284
|
+
|
|
285
|
+
const StyledInput = styled(Input)`
|
|
286
|
+
flex: 1;
|
|
287
|
+
height: 10px;
|
|
288
|
+
`;
|
|
289
|
+
|
|
290
|
+
const FiltersRow = styled.div`
|
|
291
|
+
display: grid;
|
|
292
|
+
grid-template-columns: 1fr 1fr;
|
|
293
|
+
gap: 8px;
|
|
294
|
+
`;
|
|
295
|
+
|
|
296
|
+
const StyledDropdown = styled(Dropdown)`
|
|
297
|
+
margin: 0px !important;
|
|
298
|
+
width: 100% !important;
|
|
299
|
+
`;
|
|
300
|
+
|
|
301
|
+
const ResultsWrapper = styled.div`
|
|
302
|
+
overflow-y: auto;
|
|
303
|
+
max-height: 320px;
|
|
304
|
+
background: rgba(0, 0, 0, 0.2);
|
|
305
|
+
border: 1px solid rgba(255, 255, 255, 0.05);
|
|
306
|
+
border-radius: 4px;
|
|
307
|
+
`;
|
|
308
|
+
|
|
309
|
+
const tableRowBase = `
|
|
310
|
+
display: grid;
|
|
311
|
+
grid-template-columns: 32px 1fr 120px 60px;
|
|
312
|
+
align-items: center;
|
|
313
|
+
gap: 8px;
|
|
314
|
+
padding: 6px 12px;
|
|
315
|
+
`;
|
|
316
|
+
|
|
317
|
+
const ResultsHeader = styled.div`
|
|
318
|
+
${tableRowBase}
|
|
319
|
+
background: rgba(0, 0, 0, 0.4);
|
|
320
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
|
321
|
+
position: sticky;
|
|
322
|
+
top: 0;
|
|
323
|
+
z-index: 1;
|
|
324
|
+
|
|
325
|
+
> * {
|
|
326
|
+
font-size: 0.45rem;
|
|
327
|
+
color: #888;
|
|
328
|
+
text-transform: uppercase;
|
|
329
|
+
letter-spacing: 1px;
|
|
330
|
+
}
|
|
331
|
+
`;
|
|
332
|
+
|
|
333
|
+
const ResultRow = styled.div`
|
|
334
|
+
${tableRowBase}
|
|
335
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
|
336
|
+
cursor: pointer;
|
|
337
|
+
transition: background 0.1s;
|
|
338
|
+
|
|
339
|
+
&:hover {
|
|
340
|
+
background: rgba(245, 158, 11, 0.08);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
&:last-child {
|
|
344
|
+
border-bottom: none;
|
|
345
|
+
}
|
|
346
|
+
`;
|
|
347
|
+
|
|
348
|
+
const SpriteWrapper = styled.div`
|
|
349
|
+
display: flex;
|
|
350
|
+
align-items: center;
|
|
351
|
+
justify-content: center;
|
|
352
|
+
width: 32px;
|
|
353
|
+
height: 32px;
|
|
354
|
+
`;
|
|
355
|
+
|
|
356
|
+
const ColName = styled.div`
|
|
357
|
+
display: flex;
|
|
358
|
+
flex-direction: column;
|
|
359
|
+
gap: 2px;
|
|
360
|
+
overflow: hidden;
|
|
361
|
+
`;
|
|
362
|
+
|
|
363
|
+
const BlueprintName = styled.span`
|
|
364
|
+
font-size: 0.5rem;
|
|
365
|
+
color: #ddd;
|
|
366
|
+
overflow: hidden;
|
|
367
|
+
text-overflow: ellipsis;
|
|
368
|
+
white-space: nowrap;
|
|
369
|
+
`;
|
|
370
|
+
|
|
371
|
+
const BlueprintKey = styled.span`
|
|
372
|
+
font-size: 0.4rem;
|
|
373
|
+
color: #666;
|
|
374
|
+
overflow: hidden;
|
|
375
|
+
text-overflow: ellipsis;
|
|
376
|
+
white-space: nowrap;
|
|
377
|
+
`;
|
|
378
|
+
|
|
379
|
+
const ColType = styled.div`
|
|
380
|
+
display: flex;
|
|
381
|
+
flex-direction: column;
|
|
382
|
+
gap: 2px;
|
|
383
|
+
`;
|
|
384
|
+
|
|
385
|
+
const TypeText = styled.span`
|
|
386
|
+
font-size: 0.45rem;
|
|
387
|
+
color: #aaa;
|
|
388
|
+
`;
|
|
389
|
+
|
|
390
|
+
const SubTypeText = styled.span`
|
|
391
|
+
font-size: 0.4rem;
|
|
392
|
+
color: #666;
|
|
393
|
+
`;
|
|
394
|
+
|
|
395
|
+
const ColTier = styled.div`
|
|
396
|
+
font-size: 0.5rem;
|
|
397
|
+
color: #f59e0b;
|
|
398
|
+
text-align: center;
|
|
399
|
+
`;
|
|
400
|
+
|
|
401
|
+
const EmptyState = styled.div`
|
|
402
|
+
display: flex;
|
|
403
|
+
align-items: center;
|
|
404
|
+
justify-content: center;
|
|
405
|
+
height: 100px;
|
|
406
|
+
font-size: 0.55rem;
|
|
407
|
+
color: #666;
|
|
408
|
+
text-transform: uppercase;
|
|
409
|
+
letter-spacing: 1px;
|
|
410
|
+
`;
|
|
411
|
+
|
|
412
|
+
const PagerContainer = styled.div`
|
|
413
|
+
display: flex;
|
|
414
|
+
justify-content: center;
|
|
415
|
+
align-items: center;
|
|
416
|
+
`;
|
|
417
|
+
|
|
418
|
+
export { BLUEPRINTS_PER_PAGE };
|