@rpg-engine/long-bow 0.8.7 → 0.8.9

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 (70) hide show
  1. package/dist/components/InformationCenter/sections/bestiary/{BestiarySection.d.ts → InformationCenterBestiarySection.d.ts} +1 -1
  2. package/dist/components/InformationCenter/sections/faq/{FaqSection.d.ts → InformationCenterFaqSection.d.ts} +1 -1
  3. package/dist/components/InformationCenter/sections/items/{ItemsSection.d.ts → InformationCenterItemsSection.d.ts} +1 -1
  4. package/dist/components/InformationCenter/sections/tutorials/{TutorialsSection.d.ts → InformationCenterTutorialsSection.d.ts} +2 -1
  5. package/dist/components/Item/Inventory/ItemPropertyColorSelector.d.ts +10 -0
  6. package/dist/components/Item/Inventory/ItemPropertySimpleHandler.d.ts +10 -0
  7. package/dist/components/Store/CartView.d.ts +15 -0
  8. package/dist/components/Store/StoreItemDetails.d.ts +16 -0
  9. package/dist/components/Store/StoreItemRow.d.ts +1 -2
  10. package/dist/components/Store/StoreTypes.d.ts +33 -4
  11. package/dist/components/Store/hooks/useStoreCart.d.ts +14 -0
  12. package/dist/components/Store/sections/StoreItemsSection.d.ts +12 -0
  13. package/dist/components/Store/sections/StorePacksSection.d.ts +9 -0
  14. package/dist/components/shared/CTAButton/CTAButton.d.ts +13 -0
  15. package/dist/components/shared/Card/Card.d.ts +14 -0
  16. package/dist/components/shared/Ellipsis.d.ts +1 -1
  17. package/dist/components/shared/PaginatedContent/PaginatedContent.d.ts +3 -1
  18. package/dist/components/shared/ScrollableContent/ScrollableContent.d.ts +23 -0
  19. package/dist/components/shared/SearchBar/SearchBar.d.ts +2 -3
  20. package/dist/components/shared/SearchHeader/SearchHeader.d.ts +17 -0
  21. package/dist/components/shared/ShoppingCart/CartCard.d.ts +14 -0
  22. package/dist/components/shared/ShoppingCart/CartCardHorizontal.d.ts +13 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/long-bow.cjs.development.js +105 -39
  25. package/dist/long-bow.cjs.development.js.map +1 -1
  26. package/dist/long-bow.cjs.production.min.js +1 -1
  27. package/dist/long-bow.cjs.production.min.js.map +1 -1
  28. package/dist/long-bow.esm.js +105 -40
  29. package/dist/long-bow.esm.js.map +1 -1
  30. package/dist/stories/UI/buttonsAndInputs/CTAButton.stories.d.ts +18 -0
  31. package/dist/stories/UI/dropdownsAndSelectors/ItemPropertyColorSelector.stories.d.ts +3 -0
  32. package/package.json +3 -2
  33. package/src/components/InformationCenter/InformationCenter.tsx +8 -8
  34. package/src/components/InformationCenter/InformationCenterTabView.tsx +0 -1
  35. package/src/components/InformationCenter/sections/bestiary/{BestiarySection.tsx → InformationCenterBestiarySection.tsx} +2 -1
  36. package/src/components/InformationCenter/sections/faq/InformationCenterFaqSection.tsx +81 -0
  37. package/src/components/InformationCenter/sections/items/{ItemsSection.tsx → InformationCenterItemsSection.tsx} +2 -10
  38. package/src/components/InformationCenter/sections/tutorials/InformationCenterTutorialsSection.tsx +135 -0
  39. package/src/components/Item/Inventory/ItemPropertyColorSelector.tsx +75 -0
  40. package/src/components/Item/Inventory/ItemPropertySimpleHandler.tsx +26 -0
  41. package/src/components/Item/Inventory/itemContainerHelper.ts +10 -1
  42. package/src/components/Store/CartView.tsx +271 -0
  43. package/src/components/Store/Store.tsx +199 -96
  44. package/src/components/Store/StoreItemDetails.tsx +161 -0
  45. package/src/components/Store/StoreItemRow.tsx +24 -40
  46. package/src/components/Store/StoreTypes.ts +38 -4
  47. package/src/components/Store/hooks/useStoreCart.ts +121 -0
  48. package/src/components/Store/sections/StoreItemsSection.tsx +52 -0
  49. package/src/components/Store/sections/StorePacksSection.tsx +89 -0
  50. package/src/components/Store/sections/images/custom-skin.png +0 -0
  51. package/src/components/shared/CTAButton/CTAButton.tsx +127 -0
  52. package/src/components/shared/Card/Card.tsx +107 -0
  53. package/src/components/shared/Ellipsis.tsx +20 -22
  54. package/src/components/shared/PaginatedContent/PaginatedContent.tsx +48 -79
  55. package/src/components/shared/ScrollableContent/ScrollableContent.tsx +160 -0
  56. package/src/components/shared/SearchBar/SearchBar.tsx +43 -24
  57. package/src/components/shared/SearchHeader/SearchHeader.tsx +80 -0
  58. package/src/components/shared/ShoppingCart/CartCard.tsx +116 -0
  59. package/src/components/shared/ShoppingCart/CartCardHorizontal.tsx +120 -0
  60. package/src/components/shared/SpriteFromAtlas.tsx +2 -0
  61. package/src/index.tsx +1 -0
  62. package/src/stories/Features/store/Store.stories.tsx +54 -4
  63. package/src/stories/UI/buttonsAndInputs/CTAButton.stories.tsx +77 -0
  64. package/src/stories/UI/dropdownsAndSelectors/ItemPropertyColorSelector.stories.tsx +77 -0
  65. package/dist/components/Store/InternalStoreTab.d.ts +0 -15
  66. package/dist/components/Store/StoreTabContent.d.ts +0 -14
  67. package/src/components/InformationCenter/sections/faq/FaqSection.tsx +0 -51
  68. package/src/components/InformationCenter/sections/tutorials/TutorialsSection.tsx +0 -144
  69. package/src/components/Store/InternalStoreTab.tsx +0 -142
  70. package/src/components/Store/StoreTabContent.tsx +0 -46
@@ -1,52 +1,71 @@
1
1
  import React from 'react';
2
+ import { FaSearch } from 'react-icons/fa';
2
3
  import styled from 'styled-components';
3
4
 
4
- interface SearchBarProps {
5
+ interface ISearchBarProps {
5
6
  value: string;
6
7
  onChange: (value: string) => void;
7
8
  placeholder?: string;
8
9
  className?: string;
9
- autoFocus?: boolean;
10
10
  }
11
11
 
12
- export const SearchBar: React.FC<SearchBarProps> = ({
12
+ export const SearchBar: React.FC<ISearchBarProps> = ({
13
13
  value,
14
14
  onChange,
15
- placeholder = 'Search...',
15
+ placeholder,
16
16
  className,
17
- autoFocus = false,
18
17
  }) => {
19
18
  return (
20
19
  <Container className={className}>
21
- <input
20
+ <Input
22
21
  type="text"
23
- className="rpgui-input"
24
- placeholder={placeholder}
25
22
  value={value}
26
23
  onChange={e => onChange(e.target.value)}
27
- autoFocus={autoFocus}
24
+ placeholder={placeholder}
25
+ className="rpgui-input"
28
26
  />
27
+ <IconContainer>
28
+ <SearchIcon />
29
+ </IconContainer>
29
30
  </Container>
30
31
  );
31
32
  };
32
33
 
33
34
  const Container = styled.div`
34
- input {
35
- width: 100%;
36
- font-size: 0.8rem;
37
- padding: 8px 12px;
38
- background-color: rgba(0, 0, 0, 0.3);
39
- border: none;
40
- color: white;
41
- border-radius: 4px;
35
+ position: relative;
36
+ width: 100%;
37
+ `;
42
38
 
43
- &::placeholder {
44
- color: rgba(255, 255, 255, 0.5);
45
- }
39
+ const Input = styled.input`
40
+ width: 100%;
41
+ padding-right: 2.5rem !important;
42
+ background: rgba(0, 0, 0, 0.2) !important;
43
+ border: 2px solid #f59e0b !important;
44
+ box-shadow: 0 0 10px rgba(245, 158, 11, 0.3);
45
+ color: #ffffff !important;
46
+ font-family: 'Press Start 2P', cursive !important;
47
+ font-size: 0.875rem !important;
46
48
 
47
- &:focus {
48
- outline: none;
49
- background-color: rgba(0, 0, 0, 0.4);
50
- }
49
+ &::placeholder {
50
+ color: rgba(255, 255, 255, 0.5) !important;
51
51
  }
52
52
  `;
53
+
54
+ const IconContainer = styled.div`
55
+ position: absolute;
56
+ right: 0.75rem;
57
+ top: 50%;
58
+ transform: translateY(-50%);
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ width: 24px;
63
+ height: 24px;
64
+ pointer-events: none;
65
+ `;
66
+
67
+ const SearchIcon = styled(FaSearch)`
68
+ font-size: 1rem;
69
+ color: #f59e0b;
70
+ filter: drop-shadow(0 0 2px rgba(245, 158, 11, 0.3));
71
+ `;
@@ -0,0 +1,80 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import { Dropdown, IOptionsProps } from '../../Dropdown';
4
+ import { SearchBar } from '../SearchBar/SearchBar';
5
+
6
+ interface ISearchHeaderProps {
7
+ searchOptions?: {
8
+ value: string;
9
+ onChange: (value: string) => void;
10
+ placeholder?: string;
11
+ };
12
+ filterOptions?: {
13
+ options: IOptionsProps[];
14
+ selectedOption: string;
15
+ onOptionChange: (value: string) => void;
16
+ };
17
+ className?: string;
18
+ }
19
+
20
+ export const SearchHeader: React.FC<ISearchHeaderProps> = ({
21
+ searchOptions,
22
+ filterOptions,
23
+ className,
24
+ }) => {
25
+ if (!searchOptions && !filterOptions) return null;
26
+
27
+ return (
28
+ <HeaderContainer className={className}>
29
+ <HeaderContent>
30
+ {searchOptions && (
31
+ <SearchContainer>
32
+ <StyledSearchBar
33
+ value={searchOptions.value}
34
+ onChange={searchOptions.onChange}
35
+ placeholder={searchOptions.placeholder || 'Search...'}
36
+ />
37
+ </SearchContainer>
38
+ )}
39
+ {filterOptions && (
40
+ <FilterContainer>
41
+ <StyledDropdown
42
+ options={filterOptions.options}
43
+ onChange={filterOptions.onOptionChange}
44
+ width="200px"
45
+ />
46
+ </FilterContainer>
47
+ )}
48
+ </HeaderContent>
49
+ </HeaderContainer>
50
+ );
51
+ };
52
+
53
+ const HeaderContainer = styled.div``;
54
+
55
+ const HeaderContent = styled.div`
56
+ display: flex;
57
+ justify-content: space-between;
58
+ align-items: center;
59
+ gap: 1rem;
60
+ background: rgba(0, 0, 0, 0.2);
61
+ padding: 1rem;
62
+ border-radius: 4px;
63
+ `;
64
+
65
+ const SearchContainer = styled.div`
66
+ flex: 1;
67
+ `;
68
+
69
+ const FilterContainer = styled.div`
70
+ display: flex;
71
+ justify-content: flex-end;
72
+ `;
73
+
74
+ const StyledSearchBar = styled(SearchBar)`
75
+ width: 100%;
76
+ `;
77
+
78
+ const StyledDropdown = styled(Dropdown)`
79
+ min-width: 150px;
80
+ `;
@@ -0,0 +1,116 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import { uiColors } from '../../../constants/uiColors';
4
+ import { Ellipsis } from '../Ellipsis';
5
+
6
+ export interface ICardProps {
7
+ title: string;
8
+ description: string;
9
+ imageUrl?: string | { src: string; default?: string };
10
+ category?: string;
11
+ onClick?: () => void;
12
+ footer?: React.ReactNode;
13
+ className?: string;
14
+ }
15
+
16
+ export const ShoppingCard: React.FC<ICardProps> = ({
17
+ title,
18
+ description,
19
+ imageUrl,
20
+ category,
21
+ onClick,
22
+ footer,
23
+ className,
24
+ }) => {
25
+ const getImageSrc = () => {
26
+ if (!imageUrl) return '/placeholder-thumbnail.png';
27
+ if (typeof imageUrl === 'string') return imageUrl;
28
+ return imageUrl.default || imageUrl.src;
29
+ };
30
+
31
+ return (
32
+ <CardContainer onClick={onClick} className={className}>
33
+ {imageUrl && (
34
+ <CardThumbnail>
35
+ <img src={getImageSrc()} alt={title} />
36
+ </CardThumbnail>
37
+ )}
38
+ <CardContent>
39
+ <CardTitle>
40
+ <Ellipsis maxLines={1} maxWidth="100%">
41
+ {title}
42
+ </Ellipsis>
43
+ </CardTitle>
44
+ <CardDescription>
45
+ <Ellipsis maxLines={5} maxWidth="100%">
46
+ {description}
47
+ </Ellipsis>
48
+ </CardDescription>
49
+ {category && <CardCategory>{category}</CardCategory>}
50
+ {footer && <CardFooter>{footer}</CardFooter>}
51
+ </CardContent>
52
+ </CardContainer>
53
+ );
54
+ };
55
+
56
+ const CardContainer = styled.div<{ onClick?: () => void }>`
57
+ background: rgba(0, 0, 0, 0.3);
58
+ border-radius: 4px;
59
+ overflow: hidden;
60
+ border: 1px solid ${uiColors.darkGray};
61
+ cursor: ${props => (props.onClick ? 'pointer' : 'default')};
62
+ transition: transform 0.2s ease;
63
+
64
+ &:hover {
65
+ transform: ${props => (props.onClick ? 'translateY(-2px)' : 'none')};
66
+ }
67
+ `;
68
+
69
+ const CardThumbnail = styled.div`
70
+ width: 100%;
71
+ height: 168px;
72
+ background: rgba(0, 0, 0, 0.2);
73
+ overflow: hidden;
74
+
75
+ img {
76
+ width: 100%;
77
+ height: 100%;
78
+ object-fit: cover;
79
+ }
80
+ `;
81
+
82
+ const CardContent = styled.div`
83
+ padding: 12px;
84
+ `;
85
+
86
+ const CardTitle = styled.h3`
87
+ margin: 0;
88
+ font-size: 0.6rem;
89
+ color: ${uiColors.yellow};
90
+ font-family: 'Press Start 2P', cursive;
91
+ margin-bottom: 8px;
92
+ `;
93
+
94
+ const CardDescription = styled.p`
95
+ margin: 0;
96
+ font-size: 0.55rem;
97
+ color: ${uiColors.lightGray};
98
+ font-family: 'Press Start 2P', cursive;
99
+ margin-bottom: 8px;
100
+ line-height: 1.4;
101
+ `;
102
+
103
+ const CardCategory = styled.span`
104
+ font-size: 0.5rem;
105
+ color: ${uiColors.yellow};
106
+ font-family: 'Press Start 2P', cursive;
107
+ background: rgba(255, 255, 255, 0.1);
108
+ padding: 4px 8px;
109
+ border-radius: 4px;
110
+ `;
111
+
112
+ const CardFooter = styled.div`
113
+ margin-top: 12px;
114
+ padding-top: 12px;
115
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
116
+ `;
@@ -0,0 +1,120 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import { uiColors } from '../../../constants/uiColors';
4
+ import { Ellipsis } from '../Ellipsis';
5
+
6
+ export interface ICardProps {
7
+ title: string;
8
+ description: string;
9
+ imageUrl?: string | { src: string; default?: string };
10
+ onClick?: () => void;
11
+ footer?: React.ReactNode;
12
+ className?: string;
13
+ }
14
+
15
+ export const ShoppingCardHorizontal: React.FC<ICardProps> = ({
16
+ title,
17
+ description,
18
+ imageUrl,
19
+ onClick,
20
+ footer,
21
+ className,
22
+ }) => {
23
+ const getImageSrc = () => {
24
+ if (!imageUrl) return '/placeholder-thumbnail.png';
25
+ if (typeof imageUrl === 'string') return imageUrl;
26
+ return imageUrl.default || imageUrl.src;
27
+ };
28
+
29
+ return (
30
+ <CardContainer onClick={onClick} className={className}>
31
+ <LeftSection>
32
+ {imageUrl && (
33
+ <CardThumbnail>
34
+ <img src={getImageSrc()} alt={title} />
35
+ </CardThumbnail>
36
+ )}
37
+ </LeftSection>
38
+ <RightSection>
39
+ <CardTitle>
40
+ <Ellipsis maxLines={1} maxWidth="100%">
41
+ {title}
42
+ </Ellipsis>
43
+ </CardTitle>
44
+ <CardDescription>
45
+ <Ellipsis maxLines={3} maxWidth="100%">
46
+ {description}
47
+ </Ellipsis>
48
+ </CardDescription>
49
+ {footer && (
50
+ <CardFooter onClick={e => e.stopPropagation()}>{footer}</CardFooter>
51
+ )}
52
+ </RightSection>
53
+ </CardContainer>
54
+ );
55
+ };
56
+
57
+ const CardContainer = styled.div<{ onClick?: () => void }>`
58
+ display: flex;
59
+ background: rgba(0, 0, 0, 0.3);
60
+ border-radius: 4px;
61
+ border: 1px solid ${uiColors.darkGray};
62
+ cursor: ${props => (props.onClick ? 'pointer' : 'default')};
63
+ transition: transform 0.2s ease;
64
+
65
+ &:hover {
66
+ transform: ${props => (props.onClick ? 'translateY(-2px)' : 'none')};
67
+ }
68
+
69
+ max-width: 380px;
70
+ `;
71
+
72
+ const LeftSection = styled.div`
73
+ width: 120px;
74
+ flex-shrink: 0;
75
+ `;
76
+
77
+ const RightSection = styled.div`
78
+ flex: 1;
79
+ display: flex;
80
+ flex-direction: column;
81
+ padding: 12px;
82
+ min-width: 0;
83
+ max-width: 100%;
84
+ `;
85
+
86
+ const CardThumbnail = styled.div`
87
+ width: 100%;
88
+ height: 100%;
89
+ background: rgba(0, 0, 0, 0.2);
90
+ overflow: hidden;
91
+
92
+ img {
93
+ width: 100%;
94
+ height: 100%;
95
+ object-fit: cover;
96
+ }
97
+ `;
98
+
99
+ const CardTitle = styled.h3`
100
+ margin: 0;
101
+ font-size: 0.6rem;
102
+ color: ${uiColors.yellow};
103
+ font-family: 'Press Start 2P', cursive;
104
+ margin-bottom: 8px;
105
+ `;
106
+
107
+ const CardDescription = styled.p`
108
+ margin: 0;
109
+ font-size: 0.55rem;
110
+ color: ${uiColors.lightGray};
111
+ font-family: 'Press Start 2P', cursive;
112
+ line-height: 1.4;
113
+ margin-bottom: 8px;
114
+ `;
115
+
116
+ const CardFooter = styled.div`
117
+ margin-top: auto;
118
+ padding-top: 8px;
119
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
120
+ `;
@@ -129,4 +129,6 @@ const ImgSprite = styled.div<IImgSpriteProps>`
129
129
  return filters.length ? filters.join(' ') : 'none';
130
130
  }};
131
131
  opacity: ${props => props.opacity};
132
+ border-radius: ${props => props.borderRadius || '0'};
133
+ overflow: hidden;
132
134
  `;
package/src/index.tsx CHANGED
@@ -22,6 +22,7 @@ export * from './components/Input';
22
22
  export * from './components/InternalTabs/InternalTabs';
23
23
  export { ErrorBoundary } from './components/Item/Inventory/ErrorBoundary';
24
24
  export * from './components/Item/Inventory/ItemContainer';
25
+ export * from './components/Item/Inventory/ItemPropertySimpleHandler';
25
26
  export * from './components/Item/Inventory/ItemQuantitySelectorModal';
26
27
  export * from './components/Item/Inventory/ItemSlot';
27
28
  export * from './components/itemSelector/ItemSelector';
@@ -2,8 +2,9 @@ import { UserAccountTypes } from '@rpg-engine/shared';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
3
  import React from 'react';
4
4
  import { RPGUIRoot } from '../../../components/RPGUI/RPGUIRoot';
5
+ import customSkinImage from '../../../components/Store/sections/images/custom-skin.png';
5
6
  import { Store } from '../../../components/Store/Store';
6
- import { IStoreItem } from '../../../components/Store/StoreTypes';
7
+ import { IItemPack, IPurchase, IStoreItem } from '../../../components/Store/StoreTypes';
7
8
  import itemsAtlasJSON from '../../../mocks/atlas/items/items.json';
8
9
  import itemsAtlasIMG from '../../../mocks/atlas/items/items.png';
9
10
  import { mockItems } from '../../../mocks/informationCenter.mocks';
@@ -85,15 +86,64 @@ const duplicatedItems: IStoreItem[] = [
85
86
  })),
86
87
  ];
87
88
 
89
+ // Mock packs data
90
+ const mockPacks: IItemPack[] = [
91
+ // Regular Packs
92
+ {
93
+ key: 'starter-pack',
94
+ title: 'Starter Pack',
95
+ description: 'Perfect for beginners! Get essential items to start your adventure.',
96
+ priceUSD: 4.99,
97
+ image: customSkinImage,
98
+ },
99
+ {
100
+ key: 'custom-skin-pack',
101
+ title: 'Custom Skin Pack',
102
+ description: 'Get a unique look with this custom skin pack! Stand out from the crowd.',
103
+ priceUSD: 7.99,
104
+ image: customSkinImage,
105
+ },
106
+
107
+ {
108
+ key: 'ultimate-pack',
109
+ title: '👑 Ultimate Premium Pack',
110
+ description: 'The most exclusive collection of items, effects, and perks. Includes everything from previous tiers plus legendary items!',
111
+ priceUSD: 99.99,
112
+ image: customSkinImage,
113
+ },
114
+ {
115
+ key: 'gold-pack',
116
+ title: '🥇 Gold Premium Pack',
117
+ description: 'The ultimate premium experience with rare items, unique effects, and exclusive content. For true champions!',
118
+ priceUSD: 49.99,
119
+ image: customSkinImage,
120
+ },
121
+ {
122
+ key: 'silver-pack',
123
+ title: '🥈 Silver Premium Pack',
124
+ description: 'Enhanced premium features with more exclusive items and special effects. For dedicated adventurers.',
125
+ priceUSD: 24.99,
126
+ image: customSkinImage,
127
+ },
128
+ {
129
+ key: 'bronze-pack',
130
+ title: '🥉 Bronze Premium Pack',
131
+ description: 'Start your premium journey with exclusive items and basic perks. Perfect for casual players.',
132
+ priceUSD: 14.99,
133
+ image: customSkinImage,
134
+ },
135
+
136
+ ];
137
+
88
138
  // Create the story with the static mock data
89
139
  export const Default: Story = {
90
140
  render: () => (
91
141
  <Store
92
142
  items={duplicatedItems}
93
- userGold={1000}
143
+ packs={mockPacks}
94
144
  userAccountType={UserAccountTypes.Free}
95
- onPurchase={(item: IStoreItem, quantity: number) => {
96
- console.log('Purchased', quantity, 'x', item.name);
145
+ onPurchase={(purchase: IPurchase) => {
146
+ console.log('Purchase details:', purchase);
97
147
  }}
98
148
  atlasJSON={itemsAtlasJSON}
99
149
  atlasIMG={itemsAtlasIMG}
@@ -0,0 +1,77 @@
1
+ import { Meta, Story } from '@storybook/react';
2
+ import React from 'react';
3
+ import { FaPlus, FaShoppingBag, FaShoppingCart, FaTrash } from 'react-icons/fa';
4
+ import { RPGUIRoot } from '../../../components/RPGUI/RPGUIRoot';
5
+ import { CTAButton } from '../../../components/shared/CTAButton/CTAButton';
6
+
7
+ interface ICTAButtonProps {
8
+ icon: React.ReactNode;
9
+ label?: React.ReactNode;
10
+ onClick?: () => void;
11
+ fullWidth?: boolean;
12
+ textColor?: string;
13
+ iconColor?: string;
14
+ disabled?: boolean;
15
+ }
16
+
17
+ const meta: Meta = {
18
+ title: 'UI/Buttons & Inputs/CTAButton',
19
+ component: CTAButton,
20
+ argTypes: {
21
+ icon: { control: false },
22
+ label: { control: 'text' },
23
+ fullWidth: { control: 'boolean' },
24
+ textColor: { control: 'color' },
25
+ iconColor: { control: 'color' },
26
+ disabled: { control: 'boolean' },
27
+ },
28
+ decorators: [
29
+ Story => (
30
+ <RPGUIRoot>
31
+ <div style={{ padding: '2rem', background: '#333' }}>
32
+ <Story />
33
+ </div>
34
+ </RPGUIRoot>
35
+ ),
36
+ ],
37
+ };
38
+
39
+ export default meta;
40
+
41
+ const Template: Story<ICTAButtonProps> = args => <CTAButton {...args} />;
42
+
43
+ export const CartButton = Template.bind({});
44
+ CartButton.args = {
45
+ icon: <FaShoppingCart />,
46
+ label: '3',
47
+ };
48
+
49
+ export const DeleteButton = Template.bind({});
50
+ DeleteButton.args = {
51
+ icon: <FaTrash />,
52
+ textColor: '#ef4444',
53
+ iconColor: '#ef4444',
54
+ };
55
+
56
+ export const AddButton = Template.bind({});
57
+ AddButton.args = {
58
+ icon: <FaPlus />,
59
+ label: 'Add Item',
60
+ textColor: '#22c55e',
61
+ iconColor: '#22c55e',
62
+ };
63
+
64
+ export const CheckoutButton = Template.bind({});
65
+ CheckoutButton.args = {
66
+ icon: <FaShoppingBag />,
67
+ label: 'Complete Purchase',
68
+ fullWidth: true,
69
+ };
70
+
71
+ export const DisabledCheckoutButton = Template.bind({});
72
+ DisabledCheckoutButton.args = {
73
+ icon: <FaShoppingBag />,
74
+ label: 'Complete Purchase',
75
+ fullWidth: true,
76
+ disabled: true,
77
+ };
@@ -0,0 +1,77 @@
1
+ import { Meta, Story } from '@storybook/react';
2
+ import React, { useState } from 'react';
3
+ import { ItemPropertySimpleHandler } from '../../../components/Item/Inventory/ItemPropertySimpleHandler';
4
+
5
+ export default {
6
+ title: 'UI/Dropdowns & Selectors/ItemPropertySimpleHandler',
7
+ component: ItemPropertySimpleHandler,
8
+ parameters: {
9
+ docs: {
10
+ description: {
11
+ component:
12
+ 'A simple handler for selecting and confirming item properties, including colors.',
13
+ },
14
+ },
15
+ },
16
+ argTypes: {
17
+ isOpen: {
18
+ control: { type: 'boolean' },
19
+ description: 'Controls whether the color selector is open.',
20
+ },
21
+ selectedColor: {
22
+ control: { type: 'color' },
23
+ description: 'Initial selected color.',
24
+ },
25
+ onClose: {
26
+ action: 'onClose',
27
+ description: 'Callback when the selector is closed.',
28
+ },
29
+ onConfirm: {
30
+ action: 'onConfirm',
31
+ description: 'Callback when a color is confirmed.',
32
+ },
33
+ onChange: {
34
+ action: 'onChange',
35
+ description: 'Callback when a color is being selected.',
36
+ },
37
+ },
38
+ } as Meta;
39
+
40
+ const Template: Story = args => {
41
+ const [isOpen, setIsOpen] = useState(args.isOpen ?? true);
42
+ const [currentColor, setCurrentColor] = useState(
43
+ args.selectedColor || '#000000'
44
+ );
45
+
46
+ const handleClose = () => {
47
+ setIsOpen(false);
48
+ args.onClose?.();
49
+ };
50
+
51
+ const handleConfirm = (color: string) => {
52
+ setCurrentColor(color);
53
+ setIsOpen(false);
54
+ args.onConfirm?.(color);
55
+ };
56
+
57
+ const handleChange = (color: string) => {
58
+ setCurrentColor(color);
59
+ args.onChange?.(color);
60
+ };
61
+
62
+ return (
63
+ <ItemPropertySimpleHandler
64
+ isOpen={isOpen}
65
+ selectedColor={currentColor}
66
+ onClose={handleClose}
67
+ onConfirm={handleConfirm}
68
+ onChange={handleChange}
69
+ />
70
+ );
71
+ };
72
+
73
+ export const Default = Template.bind({});
74
+ Default.args = {
75
+ isOpen: true,
76
+ selectedColor: '#ff0000',
77
+ };
@@ -1,15 +0,0 @@
1
- import { ItemType, UserAccountTypes } from '@rpg-engine/shared';
2
- import React from 'react';
3
- import { IStoreItem } from './StoreTypes';
4
- interface IInternalStoreTabProps {
5
- items: IStoreItem[];
6
- atlasJSON: Record<string, any>;
7
- atlasIMG: string;
8
- onPurchase: (item: IStoreItem, quantity: number) => void;
9
- userGold: number;
10
- userAccountType: UserAccountTypes;
11
- type?: ItemType | 'premium' | 'all';
12
- initialSearchQuery?: string;
13
- }
14
- export declare const InternalStoreTab: React.FC<IInternalStoreTabProps>;
15
- export {};
@@ -1,14 +0,0 @@
1
- import { UserAccountTypes } from '@rpg-engine/shared';
2
- import React from 'react';
3
- import { IStoreItem } from './StoreTypes';
4
- interface IStoreTabContentProps {
5
- items: IStoreItem[];
6
- atlasJSON: Record<string, any>;
7
- atlasIMG: string;
8
- onPurchase: (item: IStoreItem, quantity: number) => void;
9
- userGold: number;
10
- userAccountType: UserAccountTypes;
11
- tabId: string;
12
- }
13
- export declare const StoreTabContent: React.FC<IStoreTabContentProps>;
14
- export {};