@rpg-engine/long-bow 0.8.14 → 0.8.15

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.
@@ -1,3 +1,6 @@
1
1
  declare const _default: import("@storybook/csf").ComponentAnnotations<import("@storybook/react").ReactFramework, import("@storybook/react").Args>;
2
2
  export default _default;
3
3
  export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, import("@storybook/react").Args>;
4
+ export declare const WithCostWarning: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, import("@storybook/react").Args>;
5
+ export declare const WithCustomCurrency: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, import("@storybook/react").Args>;
6
+ export declare const Closed: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, import("@storybook/react").Args>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.8.14",
3
+ "version": "0.8.15",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { ReactNode } from 'react';
2
2
  import styled from 'styled-components';
3
3
  import ModalPortal from './Abstractions/ModalPortal';
4
4
  import { Button, ButtonTypes } from './Button';
@@ -7,34 +7,46 @@ import { DraggableContainer } from './DraggableContainer';
7
7
  export interface IConfirmModalProps {
8
8
  onConfirm: () => void;
9
9
  onClose: () => void;
10
- message?: string;
10
+ message?: string | ReactNode;
11
11
  }
12
12
 
13
13
  export const ConfirmModal: React.FC<IConfirmModalProps> = ({
14
14
  onConfirm,
15
15
  onClose,
16
- message,
16
+ message = 'Are you sure?',
17
17
  }) => {
18
+ const handleConfirm = (e: React.MouseEvent) => {
19
+ e.preventDefault();
20
+ e.stopPropagation();
21
+ onConfirm();
22
+ };
23
+
24
+ const handleClose = (e: React.MouseEvent) => {
25
+ e.preventDefault();
26
+ e.stopPropagation();
27
+ onClose();
28
+ };
29
+
18
30
  return (
19
31
  <ModalPortal>
20
32
  <Background />
21
- <Container onPointerDown={onClose}>
33
+ <Container onClick={handleClose}>
22
34
  <DraggableContainer width="auto" dragDisabled>
23
- <Wrapper onPointerDown={e => e.stopPropagation()}>
24
- <p>{message ?? 'Are you sure?'}</p>
35
+ <Wrapper onClick={e => e.stopPropagation()}>
36
+ {typeof message === 'string' ? <p>{message}</p> : message}
25
37
 
26
38
  <ButtonsWrapper>
27
39
  <div className="cancel-button">
28
40
  <Button
29
41
  buttonType={ButtonTypes.RPGUIButton}
30
- onPointerDown={onClose}
42
+ onClick={handleClose}
31
43
  >
32
44
  No
33
45
  </Button>
34
46
  </div>
35
47
  <Button
36
48
  buttonType={ButtonTypes.RPGUIButton}
37
- onPointerDown={onConfirm}
49
+ onClick={handleConfirm}
38
50
  >
39
51
  Yes
40
52
  </Button>
@@ -1,75 +1,162 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { HexColorPicker } from 'react-colorful';
3
3
  import styled from 'styled-components';
4
+ import { uiColors } from '../../../constants/uiColors';
4
5
  import { Button, ButtonTypes } from '../../Button';
6
+ import { ConfirmModal } from '../../ConfirmModal';
5
7
  import { DraggableContainer } from '../../DraggableContainer';
6
8
  import { RPGUIContainerTypes } from '../../RPGUI/RPGUIContainer';
7
9
 
8
- interface Props {
10
+ interface IColorSelectorProps {
9
11
  selectedColor: string;
10
12
  isOpen: boolean;
11
13
  onClose: () => void;
12
14
  onConfirm: (color: string) => void;
13
15
  onChange: (color: string) => void;
16
+ costWarning?: {
17
+ cost: number;
18
+ currency?: string;
19
+ };
14
20
  }
15
21
 
16
- export const ColorSelector: React.FC<Props> = ({
22
+ export const ColorSelector: React.FC<IColorSelectorProps> = ({
17
23
  selectedColor,
18
24
  isOpen,
19
25
  onClose,
20
26
  onConfirm,
21
27
  onChange,
28
+ costWarning,
22
29
  }) => {
23
30
  const [currentColor, setCurrentColor] = useState(selectedColor);
31
+ const [showConfirmModal, setShowConfirmModal] = useState(false);
24
32
 
25
33
  useEffect(() => {
26
34
  if (isOpen) setCurrentColor(selectedColor);
27
35
  }, [isOpen, selectedColor]);
28
36
 
29
- const handleConfirm = () => {
37
+ const handleConfirm = (e: React.MouseEvent) => {
38
+ e.preventDefault();
39
+ if (costWarning) {
40
+ setShowConfirmModal(true);
41
+ } else {
42
+ onConfirm(currentColor);
43
+ onClose();
44
+ }
45
+ };
46
+
47
+ const handleConfirmCost = () => {
30
48
  onConfirm(currentColor);
49
+ setShowConfirmModal(false);
31
50
  onClose();
32
51
  };
33
52
 
53
+ const handleClose = () => {
54
+ setShowConfirmModal(false);
55
+ };
56
+
57
+ const renderConfirmMessage = () => (
58
+ <ConfirmContent>
59
+ <p>
60
+ Cost:
61
+ <CostDisplay>
62
+ {costWarning?.cost.toLocaleString()}
63
+ {costWarning?.currency || ' gold'}
64
+ </CostDisplay>
65
+ </p>
66
+ <p>Proceed with color change?</p>
67
+ </ConfirmContent>
68
+ );
69
+
34
70
  if (!isOpen) return null;
35
71
 
36
- return isOpen ? (
37
- <DraggableContainer
38
- type={RPGUIContainerTypes.Framed}
39
- cancelDrag=".react-colorful"
40
- width="20rem"
41
- onCloseButton={onClose}
42
- >
43
- <Container>
44
- <Header>Select Color</Header>
45
- <HexColorPicker
46
- color={currentColor}
47
- onChange={color => {
48
- setCurrentColor(color);
49
- onChange(color);
50
- }}
72
+ return (
73
+ <>
74
+ <DraggableContainer
75
+ type={RPGUIContainerTypes.Framed}
76
+ cancelDrag=".react-colorful"
77
+ width="25rem"
78
+ onCloseButton={onClose}
79
+ >
80
+ <Container>
81
+ <Header>Select Color</Header>
82
+ <ColorPickerWrapper>
83
+ <HexColorPicker
84
+ color={currentColor}
85
+ onChange={color => {
86
+ setCurrentColor(color);
87
+ onChange(color);
88
+ }}
89
+ />
90
+ </ColorPickerWrapper>
91
+ <ButtonContainer>
92
+ <Button
93
+ buttonType={ButtonTypes.RPGUIButton}
94
+ type="button"
95
+ onClick={handleConfirm}
96
+ >
97
+ Confirm
98
+ </Button>
99
+ </ButtonContainer>
100
+ </Container>
101
+ </DraggableContainer>
102
+
103
+ {showConfirmModal && costWarning && (
104
+ <ConfirmModal
105
+ message={renderConfirmMessage()}
106
+ onConfirm={handleConfirmCost}
107
+ onClose={handleClose}
51
108
  />
52
- <Button
53
- buttonType={ButtonTypes.RPGUIButton}
54
- type="button"
55
- onClick={handleConfirm}
56
- >
57
- Confirm
58
- </Button>
59
- </Container>
60
- </DraggableContainer>
61
- ) : null;
109
+ )}
110
+ </>
111
+ );
62
112
  };
63
113
 
64
114
  const Container = styled.div`
65
- padding: 2rem;
66
115
  text-align: center;
67
116
  background: inherit;
117
+ display: flex;
118
+ flex-direction: column;
119
+ gap: 1.5rem;
120
+ align-items: center;
121
+ width: 100%;
122
+ max-width: 24rem;
123
+ margin: 0 auto;
68
124
  `;
69
125
 
70
126
  const Header = styled.h2`
71
- font-family: 'Press Start 2P', cursive;
72
127
  color: white;
73
128
  font-size: 1rem;
74
- margin-bottom: 1rem;
129
+ margin: 0;
130
+ width: 100%;
131
+ text-align: center;
132
+ `;
133
+
134
+ const ColorPickerWrapper = styled.div`
135
+ display: flex;
136
+ justify-content: center;
137
+ width: 100%;
138
+
139
+ .react-colorful {
140
+ width: 100%;
141
+ max-width: 200px;
142
+ }
143
+ `;
144
+
145
+ const ButtonContainer = styled.div`
146
+ display: flex;
147
+ justify-content: center;
148
+ width: 100%;
149
+ `;
150
+
151
+ const ConfirmContent = styled.div`
152
+ display: flex;
153
+ flex-direction: column;
154
+ gap: 0.5rem;
155
+ text-align: center;
156
+ font-family: 'Press Start 2P', cursive;
157
+ font-size: 0.75rem;
158
+ `;
159
+
160
+ const CostDisplay = styled.span`
161
+ color: ${uiColors.yellow} !important;
75
162
  `;
@@ -1,39 +1,36 @@
1
1
  import { Meta, Story } from '@storybook/react';
2
2
  import React, { useState } from 'react';
3
- import { ItemPropertySimpleHandler } from '../../../components/Item/Inventory/ItemPropertySimpleHandler';
3
+ import { ColorSelector } from '../../../components/Item/Inventory/ItemPropertyColorSelector';
4
+ import { RPGUIRoot } from '../../../components/RPGUI/RPGUIRoot';
4
5
 
5
6
  export default {
6
- title: 'UI/Dropdowns & Selectors/ItemPropertySimpleHandler',
7
- component: ItemPropertySimpleHandler,
7
+ title: 'UI/Dropdowns & Selectors/Item Property Color Selector',
8
+ component: ColorSelector,
8
9
  parameters: {
10
+ layout: 'centered',
9
11
  docs: {
10
12
  description: {
11
13
  component:
12
- 'A simple handler for selecting and confirming item properties, including colors.',
14
+ 'A color selector component for items with optional cost warning.',
13
15
  },
14
16
  },
15
17
  },
16
18
  argTypes: {
17
- isOpen: {
18
- control: { type: 'boolean' },
19
- description: 'Controls whether the color selector is open.',
20
- },
21
19
  selectedColor: {
22
20
  control: { type: 'color' },
23
21
  description: 'Initial selected color.',
24
22
  },
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.',
23
+ isOpen: {
24
+ control: { type: 'boolean' },
25
+ description: 'Controls whether the color selector is open.',
32
26
  },
33
- onChange: {
34
- action: 'onChange',
35
- description: 'Callback when a color is being selected.',
27
+ costWarning: {
28
+ control: 'object',
29
+ description: 'Optional warning about the cost of changing colors.',
36
30
  },
31
+ onClose: { action: 'closed' },
32
+ onConfirm: { action: 'confirmed' },
33
+ onChange: { action: 'changed' },
37
34
  },
38
35
  } as Meta;
39
36
 
@@ -60,13 +57,16 @@ const Template: Story = args => {
60
57
  };
61
58
 
62
59
  return (
63
- <ItemPropertySimpleHandler
64
- isOpen={isOpen}
65
- selectedColor={currentColor}
66
- onClose={handleClose}
67
- onConfirm={handleConfirm}
68
- onChange={handleChange}
69
- />
60
+ <RPGUIRoot>
61
+ <ColorSelector
62
+ isOpen={isOpen}
63
+ selectedColor={currentColor}
64
+ onClose={handleClose}
65
+ onConfirm={handleConfirm}
66
+ onChange={handleChange}
67
+ {...args}
68
+ />
69
+ </RPGUIRoot>
70
70
  );
71
71
  };
72
72
 
@@ -75,3 +75,29 @@ Default.args = {
75
75
  isOpen: true,
76
76
  selectedColor: '#ff0000',
77
77
  };
78
+
79
+ export const WithCostWarning = Template.bind({});
80
+ WithCostWarning.args = {
81
+ isOpen: true,
82
+ selectedColor: '#ff0000',
83
+ costWarning: {
84
+ cost: 10000,
85
+ currency: ' gold',
86
+ },
87
+ };
88
+
89
+ export const WithCustomCurrency = Template.bind({});
90
+ WithCustomCurrency.args = {
91
+ isOpen: true,
92
+ selectedColor: '#ff0000',
93
+ costWarning: {
94
+ cost: 5000,
95
+ currency: ' crystals',
96
+ },
97
+ };
98
+
99
+ export const Closed = Template.bind({});
100
+ Closed.args = {
101
+ isOpen: false,
102
+ selectedColor: '#ff0000',
103
+ };