@rpg-engine/long-bow 0.3.39 → 0.3.40

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 { CircularControllerProps } from '../components/CircularController/CircularController';
3
+ declare const meta: Meta;
4
+ export default meta;
5
+ export declare const Default: import("@storybook/csf").AnnotatedStoryFn<import("@storybook/react").ReactFramework, CircularControllerProps>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.3.39",
3
+ "version": "0.3.40",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -83,7 +83,7 @@
83
83
  },
84
84
  "dependencies": {
85
85
  "@rollup/plugin-image": "^2.1.1",
86
- "@rpg-engine/shared": "^0.6.74",
86
+ "@rpg-engine/shared": "^0.6.73",
87
87
  "dayjs": "^1.11.2",
88
88
  "font-awesome": "^4.7.0",
89
89
  "fs-extra": "^10.1.0",
@@ -0,0 +1,162 @@
1
+ import { IRawSpell } from '@rpg-engine/shared';
2
+ import React from 'react';
3
+ import styled from 'styled-components';
4
+ import { uiColors } from '../../constants/uiColors';
5
+ import { SpellShortcut } from '../Spellbook/QuickSpells';
6
+
7
+ export type CircularControllerProps = {
8
+ onActionClick: () => void;
9
+ onCancelClick: () => void;
10
+ onSpellClick: (spellKey: string) => void;
11
+ mana: number;
12
+ spells: IRawSpell[];
13
+ };
14
+
15
+ export const CircularController: React.FC<CircularControllerProps> = ({
16
+ onActionClick,
17
+ onCancelClick,
18
+ onSpellClick,
19
+ mana,
20
+ spells,
21
+ }) => {
22
+ const onTouchStart = (e: React.TouchEvent<HTMLButtonElement>) => {
23
+ const target = e.target as HTMLButtonElement;
24
+ target?.classList.add('active');
25
+ };
26
+
27
+ const onTouchEnd = (
28
+ action: () => void,
29
+ e: React.TouchEvent<HTMLButtonElement>
30
+ ) => {
31
+ const target = e.target as HTMLButtonElement;
32
+ setTimeout(() => {
33
+ target?.classList.remove('active');
34
+ }, 100);
35
+ action();
36
+ };
37
+
38
+ return (
39
+ <ButtonsContainer>
40
+ <SpellsContainer>
41
+ {Array.from({ length: 4 }).map((_, i) => {
42
+ const variant = i === 0 ? 'top' : i === 3 ? 'bottom' : '';
43
+ const spell = spells[i];
44
+
45
+ const onSpellClickBinded = spell
46
+ ? onSpellClick.bind(null, spell.key)
47
+ : () => {};
48
+
49
+ return (
50
+ <StyledShortcut
51
+ key={i}
52
+ disabled={mana < spell?.manaCost}
53
+ onTouchStart={onTouchStart}
54
+ onTouchEnd={onTouchEnd.bind(null, onSpellClickBinded)}
55
+ className={variant}
56
+ >
57
+ <span className="mana">{spell?.key && spell?.manaCost}</span>
58
+ <span className="magicWords">
59
+ {spell?.magicWords.split(' ').map(word => word[0])}
60
+ </span>
61
+ </StyledShortcut>
62
+ );
63
+ })}
64
+ </SpellsContainer>
65
+ <Button
66
+ onTouchStart={onTouchStart}
67
+ onTouchEnd={onTouchEnd.bind(null, onActionClick)}
68
+ >
69
+ <div className="rpgui-icon sword" />
70
+ </Button>
71
+
72
+ <CancelButton
73
+ onTouchStart={onTouchStart}
74
+ onTouchEnd={onTouchEnd.bind(null, onCancelClick)}
75
+ >
76
+ <span>X</span>
77
+ </CancelButton>
78
+ </ButtonsContainer>
79
+ );
80
+ };
81
+
82
+ const Button = styled.button`
83
+ width: 4.3rem;
84
+ height: 4.3rem;
85
+ background-color: ${uiColors.lightGray};
86
+ border: 2px solid ${uiColors.darkGray};
87
+ border-radius: 50%;
88
+ text-transform: uppercase;
89
+ font-size: 0.7rem;
90
+ font-weight: bold;
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: center;
94
+ position: relative;
95
+ transition: background-color 0.1s;
96
+
97
+ &.active {
98
+ background-color: ${uiColors.gray};
99
+ }
100
+
101
+ .sword {
102
+ transform: rotate(-45deg);
103
+ height: 2.5rem;
104
+ width: 1.9rem;
105
+ pointer-events: none;
106
+ }
107
+ `;
108
+
109
+ const CancelButton = styled(Button)`
110
+ width: 3rem;
111
+ height: 3rem;
112
+ font-size: 0.8rem;
113
+
114
+ span {
115
+ margin-top: 4px;
116
+ margin-left: 2px;
117
+ pointer-events: none;
118
+ }
119
+ `;
120
+
121
+ const ButtonsContainer = styled.div`
122
+ display: flex;
123
+ align-items: center;
124
+ justify-content: center;
125
+ gap: 0.5rem;
126
+ `;
127
+
128
+ const SpellsContainer = styled.div`
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ gap: 0.4rem;
133
+ flex-direction: column;
134
+
135
+ .top {
136
+ transform: translate(93%, 25%);
137
+ }
138
+
139
+ .bottom {
140
+ transform: translate(93%, -25%);
141
+ }
142
+ `;
143
+
144
+ const StyledShortcut = styled(SpellShortcut)`
145
+ width: 2.5rem;
146
+ height: 2.5rem;
147
+ transition: background-color 0.1s;
148
+
149
+ .mana {
150
+ font-size: 0.5rem;
151
+ }
152
+
153
+ &:hover,
154
+ &:focus,
155
+ &:active {
156
+ background-color: ${uiColors.lightGray};
157
+ }
158
+
159
+ &.active {
160
+ background-color: ${uiColors.gray};
161
+ }
162
+ `;
@@ -57,7 +57,7 @@ export const QuickSpells: React.FC<QuickSpellsProps> = ({
57
57
  );
58
58
  };
59
59
 
60
- const SpellShortcut = styled.button`
60
+ export const SpellShortcut = styled.button`
61
61
  width: 3rem;
62
62
  height: 3rem;
63
63
  background-color: ${uiColors.lightGray};
@@ -71,6 +71,10 @@ const SpellShortcut = styled.button`
71
71
  justify-content: center;
72
72
  position: relative;
73
73
 
74
+ span {
75
+ pointer-events: none;
76
+ }
77
+
74
78
  .mana {
75
79
  position: absolute;
76
80
  top: -5px;
package/src/index.tsx CHANGED
@@ -3,6 +3,7 @@ export * from './components/Character/CharacterSelection';
3
3
  export * from './components/Chat/Chat';
4
4
  export * from './components/Chatdeprecated/ChatDeprecated';
5
5
  export * from './components/CheckButton';
6
+ export * from './components/CircularController/CircularController';
6
7
  export * from './components/CraftBook/CraftBook';
7
8
  export * from './components/DraggableContainer';
8
9
  export * from './components/Dropdown';
@@ -0,0 +1,33 @@
1
+ import { Meta, Story } from '@storybook/react';
2
+ import React from 'react';
3
+ import { RPGUIRoot } from '..';
4
+ import {
5
+ CircularController,
6
+ CircularControllerProps,
7
+ } from '../components/CircularController/CircularController';
8
+ import { SPELL_SHORTCUTS_STORAGE_KEY } from '../components/Spellbook/constants';
9
+
10
+ const meta: Meta = {
11
+ title: 'Circular Controller',
12
+ component: CircularController,
13
+ };
14
+
15
+ export default meta;
16
+
17
+ const Template: Story<CircularControllerProps> = args => (
18
+ <RPGUIRoot>
19
+ <CircularController {...args} />
20
+ </RPGUIRoot>
21
+ );
22
+
23
+ export const Default = Template.bind({});
24
+
25
+ Default.args = {
26
+ spells: JSON.parse(
27
+ localStorage.getItem(SPELL_SHORTCUTS_STORAGE_KEY) as string
28
+ ),
29
+ onSpellClick: key => console.log(key),
30
+ onActionClick: () => console.log('action'),
31
+ onCancelClick: () => console.log('cancel attack'),
32
+ mana: 100,
33
+ };