@rpg-engine/long-bow 0.6.8 → 0.6.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.
@@ -0,0 +1,5 @@
1
+ import { Meta } from '@storybook/react';
2
+ import { ITutorialStepperProps } from '../components/Tutorial/TutorialStepper';
3
+ declare const meta: Meta;
4
+ export default meta;
5
+ export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, ITutorialStepperProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.6.8",
3
+ "version": "0.6.9",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -16,7 +16,7 @@
16
16
  "src"
17
17
  ],
18
18
  "engines": {
19
- "node": ">=10"
19
+ "node": "^16.0.0"
20
20
  },
21
21
  "scripts": {
22
22
  "dev": "yarn install && start-storybook -p 6006",
Binary file
Binary file
@@ -18,12 +18,14 @@ interface IStepperProps {
18
18
  onClick: (() => void) | (() => Promise<void>) | ((e: any) => Promise<void>);
19
19
  };
20
20
  onError?: (message: string) => void;
21
+ useSideArrows?: boolean; // New prop to control arrow position
21
22
  }
22
23
 
23
24
  export const Stepper: React.FC<IStepperProps> = ({
24
25
  steps,
25
26
  finalCTAButton,
26
27
  onError,
28
+ useSideArrows = false, // Default to false for backwards compatibility
27
29
  }) => {
28
30
  const [currentStep, setCurrentStep] = useState(0);
29
31
 
@@ -36,7 +38,6 @@ export const Stepper: React.FC<IStepperProps> = ({
36
38
  try {
37
39
  const isValid = await steps[currentStep].validate!();
38
40
  if (!isValid) {
39
- // If the current step is not valid, prevent navigation and trigger onError
40
41
  if (onError) {
41
42
  onError(
42
43
  steps[currentStep].errorMessage ||
@@ -46,7 +47,6 @@ export const Stepper: React.FC<IStepperProps> = ({
46
47
  return;
47
48
  }
48
49
  } catch (error) {
49
- // Handle unexpected validation errors
50
50
  if (onError) {
51
51
  onError(
52
52
  `An error occurred during validation on step ${currentStep + 1}`
@@ -58,6 +58,42 @@ export const Stepper: React.FC<IStepperProps> = ({
58
58
  setCurrentStep(step);
59
59
  };
60
60
 
61
+ const renderArrows = () => {
62
+ const leftArrow = (
63
+ <SelectArrow
64
+ direction="left"
65
+ onPointerDown={() => onStepChange(Math.max(0, currentStep - 1))}
66
+ />
67
+ );
68
+
69
+ const rightArrow = (
70
+ <SelectArrow
71
+ direction="right"
72
+ onPointerDown={() =>
73
+ onStepChange(Math.min(totalSteps - 1, currentStep + 1))
74
+ }
75
+ />
76
+ );
77
+
78
+ if (useSideArrows) {
79
+ return (
80
+ <>
81
+ {currentStep > 0 && <ArrowContainer left>{leftArrow}</ArrowContainer>}
82
+ {currentStep < totalSteps - 1 && (
83
+ <ArrowContainer right>{rightArrow}</ArrowContainer>
84
+ )}
85
+ </>
86
+ );
87
+ } else {
88
+ return (
89
+ <>
90
+ {currentStep > 0 && leftArrow}
91
+ {currentStep < totalSteps - 1 && rightArrow}
92
+ </>
93
+ );
94
+ }
95
+ };
96
+
61
97
  return (
62
98
  <StepperContainer className="stepper-container">
63
99
  <StepperTop>
@@ -70,25 +106,13 @@ export const Stepper: React.FC<IStepperProps> = ({
70
106
  ))}
71
107
  </StepperTop>
72
108
 
73
- <StepperBody>{currentComponent}</StepperBody>
109
+ <StepperBodyContainer>
110
+ {useSideArrows && renderArrows()}
111
+ <StepperBody>{currentComponent}</StepperBody>
112
+ </StepperBodyContainer>
74
113
 
75
114
  <StepperFooter>
76
- {currentStep > 0 && (
77
- <SelectArrow
78
- direction="left"
79
- onPointerDown={() => onStepChange(Math.max(0, currentStep - 1))}
80
- />
81
- )}
82
-
83
- {currentStep < totalSteps - 1 && (
84
- <SelectArrow
85
- direction="right"
86
- onPointerDown={() =>
87
- onStepChange(Math.min(totalSteps - 1, currentStep + 1))
88
- }
89
- />
90
- )}
91
-
115
+ {!useSideArrows && renderArrows()}
92
116
  {currentStep === totalSteps - 1 && finalCTAButton && (
93
117
  <Button
94
118
  buttonType={ButtonTypes.RPGUIButton}
@@ -105,36 +129,48 @@ export const Stepper: React.FC<IStepperProps> = ({
105
129
  const StepperContainer = styled.div`
106
130
  display: flex;
107
131
  flex-direction: column;
108
- height: 100%; // Ensure the container takes up full height
132
+ height: 100%;
109
133
  `;
110
134
 
111
135
  const StepperTop = styled.div`
112
- flex: 1; // Small top
113
-
136
+ flex: 1;
114
137
  display: flex;
115
138
  flex-wrap: wrap;
116
139
  justify-content: center;
117
140
  align-items: center;
118
-
119
141
  margin-bottom: 1rem;
120
142
  `;
121
143
 
144
+ const StepperBodyContainer = styled.div`
145
+ flex: 8;
146
+ display: flex;
147
+ align-items: center;
148
+ position: relative;
149
+ `;
150
+
122
151
  const StepperBody = styled.div`
123
- flex: 8; // Big content space
152
+ flex: 1;
153
+ `;
154
+
155
+ const ArrowContainer = styled.div<{ left?: boolean; right?: boolean }>`
156
+ position: absolute;
157
+ top: 50%;
158
+ transform: translateY(-50%);
159
+ ${props => props.left && 'left: -30px;'}
160
+ ${props => props.right && 'right: -30px;'}
124
161
  `;
125
162
 
126
163
  const StepperFooter = styled.div`
127
164
  margin-top: 1rem;
128
- flex: 1; // Small footer
129
-
165
+ flex: 1;
130
166
  display: flex;
131
167
  justify-content: flex-end;
168
+ align-items: center;
132
169
  `;
133
170
 
134
171
  const ProgressIndicator = styled.div<{ isActive: boolean }>`
135
172
  width: 20px;
136
173
  height: 20px;
137
- border-radius: 50%;
138
174
  background-color: ${({ isActive }) =>
139
175
  isActive ? uiColors.orange : uiColors.lightGray};
140
176
  margin: 0 5px;
@@ -142,4 +178,13 @@ const ProgressIndicator = styled.div<{ isActive: boolean }>`
142
178
  opacity: ${({ isActive }) => (isActive ? 1 : 0.25)};
143
179
  border: 1px solid ${uiColors.raisinBlack};
144
180
  cursor: pointer;
181
+ clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
182
+ /* Create a diamond shape */
183
+ box-shadow: ${({ isActive }) =>
184
+ isActive
185
+ ? '0 0 0 1px black, 1px 1px 0 1px black, 2px 2px 0 1px black, -1px -1px 0 1px black'
186
+ : '0 0 0 1px black, 1px 1px 0 1px gray, 2px 2px 0 1px gray, -1px -1px 0 1px gray'};
187
+ /* Add pixel art border effect */
188
+ border-radius: 0;
189
+ /* Remove border-radius to make it square */
145
190
  `;
@@ -0,0 +1,72 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+ import { Stepper } from '../Stepper';
4
+ import { DynamicText } from '../typography/DynamicText';
5
+
6
+ export interface ITutorialLesson {
7
+ title: string;
8
+ body?: React.ReactNode | string;
9
+ text?: string;
10
+ image: string;
11
+ }
12
+
13
+ export interface ITutorialStepperProps {
14
+ lessons: ITutorialLesson[];
15
+ onLessonFinish: () => void;
16
+ }
17
+
18
+ export const TutorialStepper = ({
19
+ lessons,
20
+ onLessonFinish,
21
+ }: ITutorialStepperProps) => {
22
+ const generateLessons = () => {
23
+ return lessons.map((lesson, index) => ({
24
+ component: (
25
+ <div>
26
+ <h1>{lesson.title}</h1>
27
+ {lesson.image && (
28
+ <LessonImage>
29
+ <img src={lesson.image} alt={lesson.title} />
30
+ </LessonImage>
31
+ )}
32
+ {lesson.body && <LessonBody>{lesson.body}</LessonBody>}
33
+ {lesson.text && <DynamicText text={lesson.text} />}
34
+ </div>
35
+ ),
36
+ id: index,
37
+ }));
38
+ };
39
+
40
+ return (
41
+ <Container>
42
+ <Stepper
43
+ steps={generateLessons()}
44
+ finalCTAButton={{
45
+ label: 'Close',
46
+ onClick: () => {
47
+ onLessonFinish();
48
+ },
49
+ }}
50
+ useSideArrows
51
+ />
52
+ </Container>
53
+ );
54
+ };
55
+
56
+ const LessonBody = styled.div``;
57
+
58
+ const Container = styled.div`
59
+ margin: 2rem;
60
+ `;
61
+
62
+ const LessonImage = styled.div`
63
+ display: flex;
64
+ justify-content: center;
65
+ align-items: center;
66
+
67
+ img {
68
+ width: 600px;
69
+ height: 400px;
70
+ border-radius: 10px;
71
+ }
72
+ `;
package/src/index.tsx CHANGED
@@ -2,8 +2,8 @@ export * from './components/AsyncDropdown';
2
2
  export * from './components/Button';
3
3
  export * from './components/Character/CharacterSelection';
4
4
  export * from './components/Chat/Chat';
5
- export * from './components/ChatRevamp/ChatRevamp';
6
5
  export * from './components/Chatdeprecated/ChatDeprecated';
6
+ export * from './components/ChatRevamp/ChatRevamp';
7
7
  export * from './components/CheckButton';
8
8
  export * from './components/CheckItem';
9
9
  export * from './components/CircularController/CircularController';
@@ -20,6 +20,7 @@ export * from './components/Input';
20
20
  export { ErrorBoundary } from './components/Item/Inventory/ErrorBoundary';
21
21
  export * from './components/Item/Inventory/ItemContainer';
22
22
  export * from './components/Item/Inventory/ItemSlot';
23
+ export * from './components/itemSelector/ItemSelector';
23
24
  export * from './components/Leaderboard/Leaderboard';
24
25
  export * from './components/ListMenu';
25
26
  export * from './components/Marketplace/Marketplace';
@@ -34,10 +35,11 @@ export * from './components/ProgressBar';
34
35
  export * from './components/PropertySelect/PropertySelect';
35
36
  export * from './components/QuestInfo/QuestInfo';
36
37
  export * from './components/QuestList';
37
- export * from './components/RPGUI/RPGUIContainer';
38
- export * from './components/RPGUI/RPGUIRoot';
39
38
  export * from './components/RadioButton';
40
39
  export * from './components/RangeSlider';
40
+ export * from './components/RPGUI/RPGUIContainer';
41
+ export * from './components/RPGUI/RPGUIRoot';
42
+ export * from './components/shared/SpriteFromAtlas';
41
43
  export * from './components/Shortcuts/Shortcuts';
42
44
  export * from './components/SkillProgressBar';
43
45
  export * from './components/SkillsContainer';
@@ -47,7 +49,7 @@ export * from './components/TextArea';
47
49
  export * from './components/TimeWidget/TimeWidget';
48
50
  export * from './components/TradingMenu/TradingMenu';
49
51
  export * from './components/Truncate';
50
- export * from './components/itemSelector/ItemSelector';
51
- export * from './components/shared/SpriteFromAtlas';
52
+ export * from './components/Tutorial/TutorialStepper';
52
53
  export * from './components/typography/DynamicText';
54
+
53
55
  export { useEventListener } from './hooks/useEventListener';
@@ -0,0 +1,48 @@
1
+ import { Meta, Story } from '@storybook/react';
2
+ import React from 'react';
3
+ import { RPGUIRoot } from '..';
4
+ import {
5
+ ITutorialLesson,
6
+ ITutorialStepperProps,
7
+ TutorialStepper,
8
+ } from '../components/Tutorial/TutorialStepper';
9
+
10
+ import tutorialImg1 from '../assets/images/sewer.png';
11
+ import tutorialImg2 from '../assets/images/shortcuts.png';
12
+
13
+ const meta: Meta = {
14
+ title: 'Tutorial/TutorialStepper',
15
+ component: TutorialStepper,
16
+ };
17
+
18
+ export default meta;
19
+
20
+ const Template: Story<ITutorialStepperProps> = () => {
21
+ const lessons: ITutorialLesson[] = [
22
+ {
23
+ title: 'Sample Lesson 1',
24
+ text: 'This is the first lesson',
25
+ image: tutorialImg1,
26
+ },
27
+ {
28
+ title: 'Sample Lesson 2',
29
+ text: 'This is the second lesson',
30
+ image: tutorialImg2,
31
+ },
32
+ ];
33
+
34
+ return (
35
+ <RPGUIRoot>
36
+ <TutorialStepper
37
+ lessons={lessons}
38
+ onLessonFinish={() => {
39
+ console.log('finished lesson!');
40
+ }}
41
+ />
42
+ </RPGUIRoot>
43
+ );
44
+ };
45
+
46
+ export const Default = Template.bind({});
47
+
48
+ Default.args = {};