@rpg-engine/long-bow 0.1.11 → 0.1.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.
Files changed (35) hide show
  1. package/dist/NPCDialog/NPCDialog.d.ts +1 -1
  2. package/{src/assets/npcDialog/npcThumbnails → dist}/alice.png +0 -0
  3. package/dist/hooks/useEventListener.d.ts +1 -1
  4. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +3 -0
  5. package/dist/long-bow.cjs.development.js +34 -43
  6. package/dist/long-bow.cjs.development.js.map +1 -1
  7. package/dist/long-bow.cjs.production.min.js +1 -1
  8. package/dist/long-bow.cjs.production.min.js.map +1 -1
  9. package/dist/long-bow.esm.js +35 -44
  10. package/dist/long-bow.esm.js.map +1 -1
  11. package/package.json +4 -2
  12. package/src/NPCDialog/NPCDialog.tsx +5 -7
  13. package/src/NPCDialog/NPCDialogText.tsx +13 -5
  14. package/src/NPCDialog/img/npcDialog/npcThumbnails/alice.png +0 -0
  15. package/src/{assets → NPCDialog/img}/space.gif +0 -0
  16. package/src/hooks/useEventListener.ts +18 -33
  17. package/src/hooks/useIsomorphicLayoutEffect.ts +6 -0
  18. package/src/types/index.d.ts +1 -0
  19. package/src/assets/npcDialog/npcThumbnails/tile000.png +0 -0
  20. package/src/assets/npcDialog/npcThumbnails/tile001.png +0 -0
  21. package/src/assets/npcDialog/npcThumbnails/tile002.png +0 -0
  22. package/src/assets/npcDialog/npcThumbnails/tile003.png +0 -0
  23. package/src/assets/npcDialog/npcThumbnails/tile004.png +0 -0
  24. package/src/assets/npcDialog/npcThumbnails/tile005.png +0 -0
  25. package/src/assets/npcDialog/npcThumbnails/tile006.png +0 -0
  26. package/src/assets/npcDialog/npcThumbnails/tile007.png +0 -0
  27. package/src/assets/npcDialog/npcThumbnails/tile008.png +0 -0
  28. package/src/assets/npcDialog/npcThumbnails/tile009.png +0 -0
  29. package/src/assets/npcDialog/npcThumbnails/tile010.png +0 -0
  30. package/src/assets/npcDialog/npcThumbnails/tile012.png +0 -0
  31. package/src/assets/npcDialog/npcThumbnails/tile013.png +0 -0
  32. package/src/assets/npcDialog/npcThumbnails/tile014.png +0 -0
  33. package/src/assets/npcDialog/npcThumbnails/tile015.png +0 -0
  34. package/src/assets/npcDialog/npcThumbnails/tile016.png +0 -0
  35. package/src/assets/npcDialog/npcThumbnails/tile017.png +0 -0
@@ -6,7 +6,7 @@ export declare enum NPCDialogType {
6
6
  export interface INPCDialogProps {
7
7
  text: string;
8
8
  type: NPCDialogType;
9
- npcKey: string;
9
+ imagePath?: string;
10
10
  onClose?: () => void;
11
11
  }
12
12
  export declare const NPCDialog: React.FC<INPCDialogProps>;
@@ -1 +1 @@
1
- export declare function useEventListener(eventName: string, handler: (e: any) => void, element?: Window & typeof globalThis): void;
1
+ export declare const useEventListener: (type: any, handler: any, el?: Window & typeof globalThis) => void;
@@ -0,0 +1,3 @@
1
+ import { useLayoutEffect } from 'react';
2
+ declare const useIsomorphicLayoutEffect: typeof useLayoutEffect;
3
+ export default useIsomorphicLayoutEffect;
@@ -10,8 +10,6 @@ var styled = _interopDefault(require('styled-components'));
10
10
  require('rpgui/rpgui.css');
11
11
  require('rpgui/rpgui.js');
12
12
 
13
- const img = require('./space.gif');
14
-
15
13
  var RPGUI = function RPGUI(_ref) {
16
14
  var children = _ref.children;
17
15
  return React__default.createElement("div", {
@@ -37,41 +35,31 @@ var Container = /*#__PURE__*/styled.div.withConfig({
37
35
  return width;
38
36
  });
39
37
 
40
- function useEventListener(eventName, handler, element) {
41
- if (element === void 0) {
42
- element = window;
43
- }
38
+ const img = require('./alice.png');
44
39
 
45
- // Create a ref that stores handler
46
- var savedHandler = React.useRef(); // Update ref.current value if handler changes.
47
- // This allows our effect below to always get latest handler ...
48
- // ... without us needing to pass it in effect deps array ...
49
- // ... and potentially cause effect to re-run every render.
40
+ const img$1 = require('./space.gif');
50
41
 
51
- React.useEffect(function () {
52
- //@ts-ignore
42
+ var useEventListener = function useEventListener(type, handler, el) {
43
+ if (el === void 0) {
44
+ el = window;
45
+ }
46
+
47
+ var savedHandler = React__default.useRef();
48
+ React__default.useEffect(function () {
53
49
  savedHandler.current = handler;
54
50
  }, [handler]);
55
- React.useEffect(function () {
56
- // Make sure element supports addEventListener
57
- // On
58
- var isSupported = element && element.addEventListener;
59
- if (!isSupported) return; // Create event listener that calls handler function stored in ref
51
+ React__default.useEffect(function () {
60
52
  //@ts-ignore
53
+ var listener = function listener(e) {
54
+ return savedHandler.current(e);
55
+ };
61
56
 
62
- var eventListener = function eventListener(event) {
63
- return savedHandler.current(event);
64
- }; // Add event listener
65
-
66
-
67
- element.addEventListener(eventName, eventListener); // Remove event listener on cleanup
68
-
57
+ el.addEventListener(type, listener);
69
58
  return function () {
70
- element.removeEventListener(eventName, eventListener);
59
+ el.removeEventListener(type, listener);
71
60
  };
72
- }, [eventName, element] // Re-run if eventName or element changes
73
- );
74
- }
61
+ }, [type, el]);
62
+ };
75
63
 
76
64
  var chunkString = function chunkString(str, length) {
77
65
  return str.match(new RegExp('.{1,' + length + '}', 'g'));
@@ -129,20 +117,26 @@ var NPCDialogText = function NPCDialogText(_ref) {
129
117
  chunkIndex = _useState[0],
130
118
  setChunkIndex = _useState[1];
131
119
 
132
- useEventListener('keydown', function (event) {
120
+ var onHandleSpacePress = function onHandleSpacePress(event) {
133
121
  if (event.code === 'Space') {
134
122
  if (textChunks != null && textChunks[chunkIndex + 1]) {
135
- setChunkIndex(function (prev) {
136
- return prev + 1;
137
- });
123
+ setChunkIndex(chunkIndex + 1);
138
124
  } else {
139
125
  // if there's no more text chunks, close the dialog
140
126
  onClose();
141
127
  }
142
128
  }
143
- });
129
+ };
130
+
131
+ React.useEffect(function () {
132
+ window.addEventListener('keydown', onHandleSpacePress);
133
+ return function () {
134
+ return window.removeEventListener('keydown', onHandleSpacePress);
135
+ };
136
+ }, [chunkIndex]);
137
+ useEventListener('keydown', onHandleSpacePress);
144
138
  return React__default.createElement(Container$1, null, React__default.createElement(DynamicText, {
145
- text: textChunks == null ? void 0 : textChunks[chunkIndex],
139
+ text: (textChunks == null ? void 0 : textChunks[chunkIndex]) || '',
146
140
  onFinish: onEndStep,
147
141
  onStart: onStartStep
148
142
  }));
@@ -160,8 +154,8 @@ var Container$1 = /*#__PURE__*/styled.div.withConfig({
160
154
  var NPCDialog = function NPCDialog(_ref) {
161
155
  var text = _ref.text,
162
156
  type = _ref.type,
163
- npcKey = _ref.npcKey,
164
- _onClose = _ref.onClose;
157
+ _onClose = _ref.onClose,
158
+ imagePath = _ref.imagePath;
165
159
 
166
160
  var _useState = React.useState(true),
167
161
  isOpen = _useState[0],
@@ -169,10 +163,7 @@ var NPCDialog = function NPCDialog(_ref) {
169
163
 
170
164
  var _useState2 = React.useState(false),
171
165
  showGoNextIndicator = _useState2[0],
172
- setShowGoNextIndicator = _useState2[1]; //dynamically require npc thumbnail
173
-
174
-
175
- var npcThumbnail = require("../assets/npcDialog/npcThumbnails/" + npcKey + ".png");
166
+ setShowGoNextIndicator = _useState2[1];
176
167
 
177
168
  return isOpen ? React__default.createElement(RPGUI, null, React__default.createElement(RPGUIContainer, {
178
169
  type: "framed-golden"
@@ -194,10 +185,10 @@ var NPCDialog = function NPCDialog(_ref) {
194
185
  }
195
186
  }
196
187
  })), type === exports.NPCDialogType.TextAndThumbnail && React__default.createElement(ThumbnailContainer, null, React__default.createElement(NPCThumbnail, {
197
- src: npcThumbnail
188
+ src: imagePath || img
198
189
  }))), showGoNextIndicator && React__default.createElement(PressSpaceIndicator, {
199
190
  right: type === exports.NPCDialogType.TextOnly ? '1rem' : '10.5rem',
200
- src: img
191
+ src: img$1
201
192
  }))) : null;
202
193
  };
203
194
  var Container$2 = /*#__PURE__*/styled.div.withConfig({
@@ -1 +1 @@
1
- {"version":3,"file":"long-bow.cjs.development.js","sources":["../src/assets/space.gif","../src/RPGUI/RPGUI.tsx","../src/RPGUI/RPGUIContainer.tsx","../src/hooks/useEventListener.ts","../src/libs/StringHelpers.ts","../src/typography/DynamicText.tsx","../src/NPCDialog/NPCDialogText.tsx","../src/NPCDialog/NPCDialog.tsx"],"sourcesContent":["const img = require('./space.gif'); export default img;","import React from 'react';\nimport 'rpgui/rpgui.css';\nimport 'rpgui/rpgui.js';\n\ninterface IProps {\n children: React.ReactNode;\n}\n\nexport const RPGUI: React.FC<IProps> = ({ children }) => {\n return <div className=\"rpgui-content\">{children}</div>;\n};\n","import React from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n type: 'framed' | 'framed-golden' | 'framed-golden-2' | 'framed-grey';\n children: React.ReactNode;\n width?: string;\n}\n\nexport const RPGUIContainer: React.FC<IProps> = ({\n children,\n type,\n width = '50%',\n}) => {\n return (\n <Container width={width} className={`rpgui-container ${type}`}>\n {children}\n </Container>\n );\n};\n\ninterface IContainerProps {\n width: string;\n}\n\nconst Container = styled.div<IContainerProps>`\n max-width: ${({ width }) => width};\n`;\n","import { useEffect, useRef } from 'react';\n\nexport function useEventListener(\n eventName: string,\n handler: (e: any) => void,\n element = window\n) {\n // Create a ref that stores handler\n const savedHandler = useRef();\n // Update ref.current value if handler changes.\n // This allows our effect below to always get latest handler ...\n // ... without us needing to pass it in effect deps array ...\n // ... and potentially cause effect to re-run every render.\n useEffect(() => {\n //@ts-ignore\n savedHandler.current = handler;\n }, [handler]);\n useEffect(\n () => {\n // Make sure element supports addEventListener\n // On\n const isSupported = element && element.addEventListener;\n if (!isSupported) return;\n // Create event listener that calls handler function stored in ref\n //@ts-ignore\n const eventListener = (event: any) => savedHandler.current(event);\n // Add event listener\n element.addEventListener(eventName, eventListener);\n // Remove event listener on cleanup\n return () => {\n element.removeEventListener(eventName, eventListener);\n };\n },\n [eventName, element] // Re-run if eventName or element changes\n );\n}\n","export const chunkString = (str: string, length: number) => {\n return str.match(new RegExp('.{1,' + length + '}', 'g'));\n};\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n text: string;\n onFinish?: () => void;\n onStart?: () => void;\n}\n\nexport const DynamicText: React.FC<IProps> = ({ text, onFinish, onStart }) => {\n const [textState, setTextState] = useState<string>('');\n\n useEffect(() => {\n let i = 0;\n const interval = setInterval(() => {\n // on every interval, show one more character\n\n if (i === 0) {\n if (onStart) {\n onStart();\n }\n }\n\n if (i < text.length) {\n setTextState(text.substring(0, i + 1));\n i++;\n } else {\n clearInterval(interval);\n if (onFinish) {\n onFinish();\n }\n }\n }, 50);\n\n return () => {\n clearInterval(interval);\n };\n }, [text]);\n\n return <TextContainer>{textState}</TextContainer>;\n};\n\nconst TextContainer = styled.p`\n font-size: 0.7rem !important;\n color: white;\n text-shadow: 1px 1px 0px #000000;\n letter-spacing: 1.2px;\n`;\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { useEventListener } from '../hooks/useEventListener';\nimport { chunkString } from '../libs/StringHelpers';\nimport { DynamicText } from '../typography/DynamicText';\n\ninterface IProps {\n text: string;\n onClose: () => void;\n onEndStep: () => void;\n onStartStep: () => void;\n}\n\nexport const NPCDialogText: React.FC<IProps> = ({\n text,\n onClose,\n onEndStep,\n onStartStep,\n}) => {\n const textChunks = chunkString(text, 85);\n\n const [chunkIndex, setChunkIndex] = useState<number>(0);\n\n useEventListener('keydown', (event: KeyboardEvent) => {\n if (event.code === 'Space') {\n if (textChunks?.[chunkIndex + 1]) {\n setChunkIndex((prev) => prev + 1);\n } else {\n // if there's no more text chunks, close the dialog\n onClose();\n }\n }\n });\n\n return (\n <Container>\n <DynamicText\n text={textChunks?.[chunkIndex]!}\n onFinish={onEndStep}\n onStart={onStartStep}\n />\n </Container>\n );\n};\n\nconst Container = styled.div``;\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport pressSpaceGif from '../assets/space.gif';\nimport { RPGUI } from '../RPGUI/RPGUI';\nimport { RPGUIContainer } from '../RPGUI/RPGUIContainer';\nimport { NPCDialogText } from './NPCDialogText';\nexport enum NPCDialogType {\n TextOnly = 'TextOnly',\n TextAndThumbnail = 'TextAndThumbnail',\n}\n\nexport interface INPCDialogProps {\n text: string;\n type: NPCDialogType;\n npcKey: string;\n onClose?: () => void;\n}\n\nexport const NPCDialog: React.FC<INPCDialogProps> = ({\n text,\n type,\n npcKey,\n onClose,\n}) => {\n const [isOpen, setIsOpen] = useState<boolean>(true);\n const [showGoNextIndicator, setShowGoNextIndicator] =\n useState<boolean>(false);\n\n //dynamically require npc thumbnail\n const npcThumbnail = require(`../assets/npcDialog/npcThumbnails/${npcKey}.png`);\n\n return isOpen ? (\n <RPGUI>\n <RPGUIContainer type=\"framed-golden\">\n <Container>\n <TextContainer\n flex={type === NPCDialogType.TextAndThumbnail ? '70%' : '100%'}\n >\n <NPCDialogText\n onStartStep={() => setShowGoNextIndicator(false)}\n onEndStep={() => setShowGoNextIndicator(true)}\n text={text}\n onClose={() => {\n if (onClose) {\n onClose();\n setIsOpen(false);\n }\n }}\n />\n </TextContainer>\n {type === NPCDialogType.TextAndThumbnail && (\n <ThumbnailContainer>\n <NPCThumbnail src={npcThumbnail} />\n </ThumbnailContainer>\n )}\n </Container>\n {showGoNextIndicator && (\n <PressSpaceIndicator\n right={type === NPCDialogType.TextOnly ? '1rem' : '10.5rem'}\n src={pressSpaceGif}\n />\n )}\n </RPGUIContainer>\n </RPGUI>\n ) : null;\n};\n\nconst Container = styled.div`\n display: flex;\n width: 100%;\n height: 125px;\n box-sizing: border-box;\n justify-content: center;\n align-items: flex-start;\n position: relative;\n`;\n\ninterface ITextContainerProps {\n flex: string;\n}\n\nconst TextContainer = styled.div<ITextContainerProps>`\n flex: ${({ flex }) => flex} 0 0;\n width: 355px;\n`;\n\nconst ThumbnailContainer = styled.div`\n flex: 30% 0 0;\n display: flex;\n justify-content: flex-end;\n`;\n\nconst NPCThumbnail = styled.img`\n image-rendering: pixelated;\n height: 128px;\n width: 128px;\n`;\n\ninterface IPressSpaceIndicatorProps {\n right: string;\n}\n\nconst PressSpaceIndicator = styled.img<IPressSpaceIndicatorProps>`\n position: absolute;\n right: ${({ right }) => right};\n bottom: 1rem;\n height: 20.7px;\n image-rendering: -webkit-optimize-contrast;\n`;\n"],"names":["RPGUI","children","React","className","RPGUIContainer","type","width","Container","styled","div","useEventListener","eventName","handler","element","window","savedHandler","useRef","useEffect","current","isSupported","addEventListener","eventListener","event","removeEventListener","chunkString","str","length","match","RegExp","DynamicText","text","onFinish","onStart","useState","textState","setTextState","i","interval","setInterval","substring","clearInterval","TextContainer","p","NPCDialogText","onClose","onEndStep","onStartStep","textChunks","chunkIndex","setChunkIndex","code","prev","NPCDialogType","NPCDialog","npcKey","isOpen","setIsOpen","showGoNextIndicator","setShowGoNextIndicator","npcThumbnail","require","flex","TextAndThumbnail","ThumbnailContainer","NPCThumbnail","src","PressSpaceIndicator","right","TextOnly","pressSpaceGif","img"],"mappings":"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"}
1
+ {"version":3,"file":"long-bow.cjs.development.js","sources":["../src/RPGUI/RPGUI.tsx","../src/RPGUI/RPGUIContainer.tsx","../src/NPCDialog/img/npcDialog/npcThumbnails/alice.png","../src/NPCDialog/img/space.gif","../src/hooks/useEventListener.ts","../src/libs/StringHelpers.ts","../src/typography/DynamicText.tsx","../src/NPCDialog/NPCDialogText.tsx","../src/NPCDialog/NPCDialog.tsx"],"sourcesContent":["import React from 'react';\nimport 'rpgui/rpgui.css';\nimport 'rpgui/rpgui.js';\n\ninterface IProps {\n children: React.ReactNode;\n}\n\nexport const RPGUI: React.FC<IProps> = ({ children }) => {\n return <div className=\"rpgui-content\">{children}</div>;\n};\n","import React from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n type: 'framed' | 'framed-golden' | 'framed-golden-2' | 'framed-grey';\n children: React.ReactNode;\n width?: string;\n}\n\nexport const RPGUIContainer: React.FC<IProps> = ({\n children,\n type,\n width = '50%',\n}) => {\n return (\n <Container width={width} className={`rpgui-container ${type}`}>\n {children}\n </Container>\n );\n};\n\ninterface IContainerProps {\n width: string;\n}\n\nconst Container = styled.div<IContainerProps>`\n max-width: ${({ width }) => width};\n`;\n","const img = require('./alice.png'); export default img;","const img = require('./space.gif'); export default img;","import React from 'react';\n\n//@ts-ignore\nexport const useEventListener = (type, handler, el = window) => {\n const savedHandler = React.useRef();\n\n React.useEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n React.useEffect(() => {\n //@ts-ignore\n const listener = (e) => savedHandler.current(e);\n\n el.addEventListener(type, listener);\n\n return () => {\n el.removeEventListener(type, listener);\n };\n }, [type, el]);\n};\n","export const chunkString = (str: string, length: number) => {\n return str.match(new RegExp('.{1,' + length + '}', 'g'));\n};\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n text: string;\n onFinish?: () => void;\n onStart?: () => void;\n}\n\nexport const DynamicText: React.FC<IProps> = ({ text, onFinish, onStart }) => {\n const [textState, setTextState] = useState<string>('');\n\n useEffect(() => {\n let i = 0;\n const interval = setInterval(() => {\n // on every interval, show one more character\n\n if (i === 0) {\n if (onStart) {\n onStart();\n }\n }\n\n if (i < text.length) {\n setTextState(text.substring(0, i + 1));\n i++;\n } else {\n clearInterval(interval);\n if (onFinish) {\n onFinish();\n }\n }\n }, 50);\n\n return () => {\n clearInterval(interval);\n };\n }, [text]);\n\n return <TextContainer>{textState}</TextContainer>;\n};\n\nconst TextContainer = styled.p`\n font-size: 0.7rem !important;\n color: white;\n text-shadow: 1px 1px 0px #000000;\n letter-spacing: 1.2px;\n`;\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\nimport { useEventListener } from '../hooks/useEventListener';\nimport { chunkString } from '../libs/StringHelpers';\nimport { DynamicText } from '../typography/DynamicText';\n\ninterface IProps {\n text: string;\n onClose: () => void;\n onEndStep: () => void;\n onStartStep: () => void;\n}\n\nexport const NPCDialogText: React.FC<IProps> = ({\n text,\n onClose,\n onEndStep,\n onStartStep,\n}) => {\n const textChunks = chunkString(text, 85);\n\n const [chunkIndex, setChunkIndex] = useState<number>(0);\n\n const onHandleSpacePress = (event: KeyboardEvent) => {\n if (event.code === 'Space') {\n if (textChunks?.[chunkIndex + 1]) {\n setChunkIndex(chunkIndex + 1);\n } else {\n // if there's no more text chunks, close the dialog\n onClose();\n }\n }\n };\n\n useEffect(() => {\n window.addEventListener('keydown', onHandleSpacePress);\n\n return () => window.removeEventListener('keydown', onHandleSpacePress);\n }, [chunkIndex]);\n\n useEventListener('keydown', onHandleSpacePress);\n\n return (\n <Container>\n <DynamicText\n text={textChunks?.[chunkIndex] || ''}\n onFinish={onEndStep}\n onStart={onStartStep}\n />\n </Container>\n );\n};\n\nconst Container = styled.div``;\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { RPGUI } from '../RPGUI/RPGUI';\nimport { RPGUIContainer } from '../RPGUI/RPGUIContainer';\nimport aliceDefaultThumbnail from './img/npcDialog/npcThumbnails/alice.png';\nimport pressSpaceGif from './img/space.gif';\nimport { NPCDialogText } from './NPCDialogText';\nexport enum NPCDialogType {\n TextOnly = 'TextOnly',\n TextAndThumbnail = 'TextAndThumbnail',\n}\n\nexport interface INPCDialogProps {\n text: string;\n type: NPCDialogType;\n imagePath?: string;\n onClose?: () => void;\n}\n\nexport const NPCDialog: React.FC<INPCDialogProps> = ({\n text,\n type,\n onClose,\n imagePath,\n}) => {\n const [isOpen, setIsOpen] = useState<boolean>(true);\n const [showGoNextIndicator, setShowGoNextIndicator] =\n useState<boolean>(false);\n\n return isOpen ? (\n <RPGUI>\n <RPGUIContainer type=\"framed-golden\">\n <Container>\n <TextContainer\n flex={type === NPCDialogType.TextAndThumbnail ? '70%' : '100%'}\n >\n <NPCDialogText\n onStartStep={() => setShowGoNextIndicator(false)}\n onEndStep={() => setShowGoNextIndicator(true)}\n text={text}\n onClose={() => {\n if (onClose) {\n onClose();\n setIsOpen(false);\n }\n }}\n />\n </TextContainer>\n {type === NPCDialogType.TextAndThumbnail && (\n <ThumbnailContainer>\n <NPCThumbnail src={imagePath || aliceDefaultThumbnail} />\n </ThumbnailContainer>\n )}\n </Container>\n {showGoNextIndicator && (\n <PressSpaceIndicator\n right={type === NPCDialogType.TextOnly ? '1rem' : '10.5rem'}\n src={pressSpaceGif}\n />\n )}\n </RPGUIContainer>\n </RPGUI>\n ) : null;\n};\n\nconst Container = styled.div`\n display: flex;\n width: 100%;\n height: 125px;\n box-sizing: border-box;\n justify-content: center;\n align-items: flex-start;\n position: relative;\n`;\n\ninterface ITextContainerProps {\n flex: string;\n}\n\nconst TextContainer = styled.div<ITextContainerProps>`\n flex: ${({ flex }) => flex} 0 0;\n width: 355px;\n`;\n\nconst ThumbnailContainer = styled.div`\n flex: 30% 0 0;\n display: flex;\n justify-content: flex-end;\n`;\n\nconst NPCThumbnail = styled.img`\n image-rendering: pixelated;\n height: 128px;\n width: 128px;\n`;\n\ninterface IPressSpaceIndicatorProps {\n right: string;\n}\n\nconst PressSpaceIndicator = styled.img<IPressSpaceIndicatorProps>`\n position: absolute;\n right: ${({ right }) => right};\n bottom: 1rem;\n height: 20.7px;\n image-rendering: -webkit-optimize-contrast;\n`;\n"],"names":["RPGUI","children","React","className","RPGUIContainer","type","width","Container","styled","div","img","useEventListener","handler","el","window","savedHandler","useRef","useEffect","current","listener","e","addEventListener","removeEventListener","chunkString","str","length","match","RegExp","DynamicText","text","onFinish","onStart","useState","textState","setTextState","i","interval","setInterval","substring","clearInterval","TextContainer","p","NPCDialogText","onClose","onEndStep","onStartStep","textChunks","chunkIndex","setChunkIndex","onHandleSpacePress","event","code","NPCDialogType","NPCDialog","imagePath","isOpen","setIsOpen","showGoNextIndicator","setShowGoNextIndicator","flex","TextAndThumbnail","ThumbnailContainer","NPCThumbnail","src","aliceDefaultThumbnail","PressSpaceIndicator","right","TextOnly","pressSpaceGif"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),n=e(t),i=e(require("styled-components"));require("rpgui/rpgui.css"),require("rpgui/rpgui.js");const r=require("./space.gif");var o,a=function(e){return n.createElement("div",{className:"rpgui-content"},e.children)},l=function(e){var t=e.width;return n.createElement(c,{width:void 0===t?"50%":t,className:"rpgui-container "+e.type},e.children)},c=i.div.withConfig({displayName:"RPGUIContainer__Container",componentId:"sc-3xvrxc-0"})(["max-width:",";"],(function(e){return e.width})),u=function(e){var i=e.text,r=e.onFinish,o=e.onStart,a=t.useState(""),l=a[0],c=a[1];return t.useEffect((function(){var e=0,t=setInterval((function(){0===e&&o&&o(),e<i.length?(c(i.substring(0,e+1)),e++):(clearInterval(t),r&&r())}),50);return function(){clearInterval(t)}}),[i]),n.createElement(s,null,l)},s=i.p.withConfig({displayName:"DynamicText__TextContainer",componentId:"sc-acj2q5-0"})(["font-size:0.7rem !important;color:white;text-shadow:1px 1px 0px #000000;letter-spacing:1.2px;"]),p=function(e){var i=e.onClose,r=e.onEndStep,o=e.onStartStep,a=e.text.match(new RegExp(".{1,85}","g")),l=t.useState(0),c=l[0],s=l[1];return function(e,n,i){void 0===i&&(i=window);var r=t.useRef();t.useEffect((function(){r.current=n}),[n]),t.useEffect((function(){if(i&&i.addEventListener){var e=function(e){return r.current(e)};return i.addEventListener("keydown",e),function(){i.removeEventListener("keydown",e)}}}),["keydown",i])}(0,(function(e){"Space"===e.code&&(null!=a&&a[c+1]?s((function(e){return e+1})):i())})),n.createElement(m,null,n.createElement(u,{text:null==a?void 0:a[c],onFinish:r,onStart:o}))},m=i.div.withConfig({displayName:"NPCDialogText__Container",componentId:"sc-ahseq0-0"})([""]);(o=exports.NPCDialogType||(exports.NPCDialogType={})).TextOnly="TextOnly",o.TextAndThumbnail="TextAndThumbnail";var d=i.div.withConfig({displayName:"NPCDialog__Container",componentId:"sc-omm2zk-0"})(["display:flex;width:100%;height:125px;box-sizing:border-box;justify-content:center;align-items:flex-start;position:relative;"]),f=i.div.withConfig({displayName:"NPCDialog__TextContainer",componentId:"sc-omm2zk-1"})(["flex:"," 0 0;width:355px;"],(function(e){return e.flex})),x=i.div.withConfig({displayName:"NPCDialog__ThumbnailContainer",componentId:"sc-omm2zk-2"})(["flex:30% 0 0;display:flex;justify-content:flex-end;"]),g=i.img.withConfig({displayName:"NPCDialog__NPCThumbnail",componentId:"sc-omm2zk-3"})(["image-rendering:pixelated;height:128px;width:128px;"]),h=i.img.withConfig({displayName:"NPCDialog__PressSpaceIndicator",componentId:"sc-omm2zk-4"})(["position:absolute;right:",";bottom:1rem;height:20.7px;image-rendering:-webkit-optimize-contrast;"],(function(e){return e.right}));exports.DynamicText=u,exports.NPCDialog=function(e){var i=e.text,o=e.type,c=e.npcKey,u=e.onClose,s=t.useState(!0),m=s[0],y=s[1],C=t.useState(!1),v=C[0],w=C[1],T=require("../assets/npcDialog/npcThumbnails/"+c+".png");return m?n.createElement(a,null,n.createElement(l,{type:"framed-golden"},n.createElement(d,null,n.createElement(f,{flex:o===exports.NPCDialogType.TextAndThumbnail?"70%":"100%"},n.createElement(p,{onStartStep:function(){return w(!1)},onEndStep:function(){return w(!0)},text:i,onClose:function(){u&&(u(),y(!1))}})),o===exports.NPCDialogType.TextAndThumbnail&&n.createElement(x,null,n.createElement(g,{src:T}))),v&&n.createElement(h,{right:o===exports.NPCDialogType.TextOnly?"1rem":"10.5rem",src:r}))):null},exports.RPGUI=a,exports.RPGUIContainer=l;
1
+ "use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=require("react"),n=e(t),i=e(require("styled-components"));require("rpgui/rpgui.css"),require("rpgui/rpgui.js");var r=function(e){return n.createElement("div",{className:"rpgui-content"},e.children)},o=function(e){var t=e.width;return n.createElement(a,{width:void 0===t?"50%":t,className:"rpgui-container "+e.type},e.children)},a=i.div.withConfig({displayName:"RPGUIContainer__Container",componentId:"sc-3xvrxc-0"})(["max-width:",";"],(function(e){return e.width}));const l=require("./alice.png"),c=require("./space.gif");var u,s=function(e){var i=e.text,r=e.onFinish,o=e.onStart,a=t.useState(""),l=a[0],c=a[1];return t.useEffect((function(){var e=0,t=setInterval((function(){0===e&&o&&o(),e<i.length?(c(i.substring(0,e+1)),e++):(clearInterval(t),r&&r())}),50);return function(){clearInterval(t)}}),[i]),n.createElement(p,null,l)},p=i.p.withConfig({displayName:"DynamicText__TextContainer",componentId:"sc-acj2q5-0"})(["font-size:0.7rem !important;color:white;text-shadow:1px 1px 0px #000000;letter-spacing:1.2px;"]),d=function(e){var i=e.onClose,r=e.onEndStep,o=e.onStartStep,a=e.text.match(new RegExp(".{1,85}","g")),l=t.useState(0),c=l[0],u=l[1],p=function(e){"Space"===e.code&&(null!=a&&a[c+1]?u(c+1):i())};return t.useEffect((function(){return window.addEventListener("keydown",p),function(){return window.removeEventListener("keydown",p)}}),[c]),function(e,t,i){void 0===i&&(i=window);var r=n.useRef();n.useEffect((function(){r.current=t}),[t]),n.useEffect((function(){var e=function(e){return r.current(e)};return i.addEventListener("keydown",e),function(){i.removeEventListener("keydown",e)}}),["keydown",i])}(0,p),n.createElement(m,null,n.createElement(s,{text:(null==a?void 0:a[c])||"",onFinish:r,onStart:o}))},m=i.div.withConfig({displayName:"NPCDialogText__Container",componentId:"sc-ahseq0-0"})([""]);(u=exports.NPCDialogType||(exports.NPCDialogType={})).TextOnly="TextOnly",u.TextAndThumbnail="TextAndThumbnail";var f=i.div.withConfig({displayName:"NPCDialog__Container",componentId:"sc-omm2zk-0"})(["display:flex;width:100%;height:125px;box-sizing:border-box;justify-content:center;align-items:flex-start;position:relative;"]),x=i.div.withConfig({displayName:"NPCDialog__TextContainer",componentId:"sc-omm2zk-1"})(["flex:"," 0 0;width:355px;"],(function(e){return e.flex})),g=i.div.withConfig({displayName:"NPCDialog__ThumbnailContainer",componentId:"sc-omm2zk-2"})(["flex:30% 0 0;display:flex;justify-content:flex-end;"]),h=i.img.withConfig({displayName:"NPCDialog__NPCThumbnail",componentId:"sc-omm2zk-3"})(["image-rendering:pixelated;height:128px;width:128px;"]),y=i.img.withConfig({displayName:"NPCDialog__PressSpaceIndicator",componentId:"sc-omm2zk-4"})(["position:absolute;right:",";bottom:1rem;height:20.7px;image-rendering:-webkit-optimize-contrast;"],(function(e){return e.right}));exports.DynamicText=s,exports.NPCDialog=function(e){var i=e.text,a=e.type,u=e.onClose,s=e.imagePath,p=t.useState(!0),m=p[0],v=p[1],C=t.useState(!1),w=C[0],E=C[1];return m?n.createElement(r,null,n.createElement(o,{type:"framed-golden"},n.createElement(f,null,n.createElement(x,{flex:a===exports.NPCDialogType.TextAndThumbnail?"70%":"100%"},n.createElement(d,{onStartStep:function(){return E(!1)},onEndStep:function(){return E(!0)},text:i,onClose:function(){u&&(u(),v(!1))}})),a===exports.NPCDialogType.TextAndThumbnail&&n.createElement(g,null,n.createElement(h,{src:s||l}))),w&&n.createElement(y,{right:a===exports.NPCDialogType.TextOnly?"1rem":"10.5rem",src:c}))):null},exports.RPGUI=r,exports.RPGUIContainer=o;
2
2
  //# sourceMappingURL=long-bow.cjs.production.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"long-bow.cjs.production.min.js","sources":["../src/assets/space.gif","../src/NPCDialog/NPCDialog.tsx","../src/RPGUI/RPGUI.tsx","../src/RPGUI/RPGUIContainer.tsx","../src/typography/DynamicText.tsx","../src/NPCDialog/NPCDialogText.tsx","../src/libs/StringHelpers.ts","../src/hooks/useEventListener.ts"],"sourcesContent":["const img = require('./space.gif'); export default img;","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport pressSpaceGif from '../assets/space.gif';\nimport { RPGUI } from '../RPGUI/RPGUI';\nimport { RPGUIContainer } from '../RPGUI/RPGUIContainer';\nimport { NPCDialogText } from './NPCDialogText';\nexport enum NPCDialogType {\n TextOnly = 'TextOnly',\n TextAndThumbnail = 'TextAndThumbnail',\n}\n\nexport interface INPCDialogProps {\n text: string;\n type: NPCDialogType;\n npcKey: string;\n onClose?: () => void;\n}\n\nexport const NPCDialog: React.FC<INPCDialogProps> = ({\n text,\n type,\n npcKey,\n onClose,\n}) => {\n const [isOpen, setIsOpen] = useState<boolean>(true);\n const [showGoNextIndicator, setShowGoNextIndicator] =\n useState<boolean>(false);\n\n //dynamically require npc thumbnail\n const npcThumbnail = require(`../assets/npcDialog/npcThumbnails/${npcKey}.png`);\n\n return isOpen ? (\n <RPGUI>\n <RPGUIContainer type=\"framed-golden\">\n <Container>\n <TextContainer\n flex={type === NPCDialogType.TextAndThumbnail ? '70%' : '100%'}\n >\n <NPCDialogText\n onStartStep={() => setShowGoNextIndicator(false)}\n onEndStep={() => setShowGoNextIndicator(true)}\n text={text}\n onClose={() => {\n if (onClose) {\n onClose();\n setIsOpen(false);\n }\n }}\n />\n </TextContainer>\n {type === NPCDialogType.TextAndThumbnail && (\n <ThumbnailContainer>\n <NPCThumbnail src={npcThumbnail} />\n </ThumbnailContainer>\n )}\n </Container>\n {showGoNextIndicator && (\n <PressSpaceIndicator\n right={type === NPCDialogType.TextOnly ? '1rem' : '10.5rem'}\n src={pressSpaceGif}\n />\n )}\n </RPGUIContainer>\n </RPGUI>\n ) : null;\n};\n\nconst Container = styled.div`\n display: flex;\n width: 100%;\n height: 125px;\n box-sizing: border-box;\n justify-content: center;\n align-items: flex-start;\n position: relative;\n`;\n\ninterface ITextContainerProps {\n flex: string;\n}\n\nconst TextContainer = styled.div<ITextContainerProps>`\n flex: ${({ flex }) => flex} 0 0;\n width: 355px;\n`;\n\nconst ThumbnailContainer = styled.div`\n flex: 30% 0 0;\n display: flex;\n justify-content: flex-end;\n`;\n\nconst NPCThumbnail = styled.img`\n image-rendering: pixelated;\n height: 128px;\n width: 128px;\n`;\n\ninterface IPressSpaceIndicatorProps {\n right: string;\n}\n\nconst PressSpaceIndicator = styled.img<IPressSpaceIndicatorProps>`\n position: absolute;\n right: ${({ right }) => right};\n bottom: 1rem;\n height: 20.7px;\n image-rendering: -webkit-optimize-contrast;\n`;\n","import React from 'react';\nimport 'rpgui/rpgui.css';\nimport 'rpgui/rpgui.js';\n\ninterface IProps {\n children: React.ReactNode;\n}\n\nexport const RPGUI: React.FC<IProps> = ({ children }) => {\n return <div className=\"rpgui-content\">{children}</div>;\n};\n","import React from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n type: 'framed' | 'framed-golden' | 'framed-golden-2' | 'framed-grey';\n children: React.ReactNode;\n width?: string;\n}\n\nexport const RPGUIContainer: React.FC<IProps> = ({\n children,\n type,\n width = '50%',\n}) => {\n return (\n <Container width={width} className={`rpgui-container ${type}`}>\n {children}\n </Container>\n );\n};\n\ninterface IContainerProps {\n width: string;\n}\n\nconst Container = styled.div<IContainerProps>`\n max-width: ${({ width }) => width};\n`;\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n text: string;\n onFinish?: () => void;\n onStart?: () => void;\n}\n\nexport const DynamicText: React.FC<IProps> = ({ text, onFinish, onStart }) => {\n const [textState, setTextState] = useState<string>('');\n\n useEffect(() => {\n let i = 0;\n const interval = setInterval(() => {\n // on every interval, show one more character\n\n if (i === 0) {\n if (onStart) {\n onStart();\n }\n }\n\n if (i < text.length) {\n setTextState(text.substring(0, i + 1));\n i++;\n } else {\n clearInterval(interval);\n if (onFinish) {\n onFinish();\n }\n }\n }, 50);\n\n return () => {\n clearInterval(interval);\n };\n }, [text]);\n\n return <TextContainer>{textState}</TextContainer>;\n};\n\nconst TextContainer = styled.p`\n font-size: 0.7rem !important;\n color: white;\n text-shadow: 1px 1px 0px #000000;\n letter-spacing: 1.2px;\n`;\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { useEventListener } from '../hooks/useEventListener';\nimport { chunkString } from '../libs/StringHelpers';\nimport { DynamicText } from '../typography/DynamicText';\n\ninterface IProps {\n text: string;\n onClose: () => void;\n onEndStep: () => void;\n onStartStep: () => void;\n}\n\nexport const NPCDialogText: React.FC<IProps> = ({\n text,\n onClose,\n onEndStep,\n onStartStep,\n}) => {\n const textChunks = chunkString(text, 85);\n\n const [chunkIndex, setChunkIndex] = useState<number>(0);\n\n useEventListener('keydown', (event: KeyboardEvent) => {\n if (event.code === 'Space') {\n if (textChunks?.[chunkIndex + 1]) {\n setChunkIndex((prev) => prev + 1);\n } else {\n // if there's no more text chunks, close the dialog\n onClose();\n }\n }\n });\n\n return (\n <Container>\n <DynamicText\n text={textChunks?.[chunkIndex]!}\n onFinish={onEndStep}\n onStart={onStartStep}\n />\n </Container>\n );\n};\n\nconst Container = styled.div``;\n","export const chunkString = (str: string, length: number) => {\n return str.match(new RegExp('.{1,' + length + '}', 'g'));\n};\n","import { useEffect, useRef } from 'react';\n\nexport function useEventListener(\n eventName: string,\n handler: (e: any) => void,\n element = window\n) {\n // Create a ref that stores handler\n const savedHandler = useRef();\n // Update ref.current value if handler changes.\n // This allows our effect below to always get latest handler ...\n // ... without us needing to pass it in effect deps array ...\n // ... and potentially cause effect to re-run every render.\n useEffect(() => {\n //@ts-ignore\n savedHandler.current = handler;\n }, [handler]);\n useEffect(\n () => {\n // Make sure element supports addEventListener\n // On\n const isSupported = element && element.addEventListener;\n if (!isSupported) return;\n // Create event listener that calls handler function stored in ref\n //@ts-ignore\n const eventListener = (event: any) => savedHandler.current(event);\n // Add event listener\n element.addEventListener(eventName, eventListener);\n // Remove event listener on cleanup\n return () => {\n element.removeEventListener(eventName, eventListener);\n };\n },\n [eventName, element] // Re-run if eventName or element changes\n );\n}\n"],"names":["img","require","NPCDialogType","RPGUI","React","className","children","RPGUIContainer","width","Container","type","styled","div","DynamicText","text","onFinish","onStart","useState","textState","setTextState","useEffect","i","interval","setInterval","length","substring","clearInterval","TextContainer","p","NPCDialogText","onClose","onEndStep","onStartStep","textChunks","match","RegExp","chunkIndex","setChunkIndex","eventName","handler","element","window","savedHandler","useRef","current","addEventListener","eventListener","event","removeEventListener","useEventListener","code","prev","flex","ThumbnailContainer","NPCThumbnail","PressSpaceIndicator","right","npcKey","isOpen","setIsOpen","showGoNextIndicator","setShowGoNextIndicator","npcThumbnail","TextAndThumbnail","src","TextOnly","pressSpaceGif"],"mappings":"+PAAA,MAAMA,EAAMC,QAAQ,mBCMRC,ECECC,EAA0B,mBAC9BC,uBAAKC,UAAU,mBADkBC,WCC7BC,EAAmC,oBAG9CC,aAGEJ,gBAACK,GAAUD,iBAHL,QAGmBH,+BAJ3BK,QADAJ,WAeIG,EAAYE,EAAOC,mFAAPD,qBACH,qBAAGH,SCjBLK,EAAgC,gBAAGC,IAAAA,KAAMC,IAAAA,SAAUC,IAAAA,UAC5BC,WAAiB,IAA5CC,OAAWC,cAElBC,aAAU,eACJC,EAAI,EACFC,EAAWC,aAAY,WAGjB,IAANF,GACEL,GACFA,IAIAK,EAAIP,EAAKU,QACXL,EAAaL,EAAKW,UAAU,EAAGJ,EAAI,IACnCA,MAEAK,cAAcJ,GACVP,GACFA,OAGH,WAEI,WACLW,cAAcJ,MAEf,CAACR,IAEGV,gBAACuB,OAAeT,IAGnBS,EAAgBhB,EAAOiB,kFAAPjB,oGC7BTkB,EAAkC,gBAE7CC,IAAAA,QACAC,IAAAA,UACAC,IAAAA,YAEMC,IALNnB,KCbWoB,MAAM,IAAIC,OAAO,UAAuB,QDoBflB,WAAiB,GAA9CmB,OAAYC,uBElBnBC,EACAC,EACAC,YAAAA,IAAAA,EAAUC,YAGJC,EAAeC,WAKrBvB,aAAU,WAERsB,EAAaE,QAAUL,IACtB,CAACA,IACJnB,aACE,cAGsBoB,GAAWA,EAAQK,sBAIjCC,EAAgB,SAACC,UAAeL,EAAaE,QAAQG,WAE3DP,EAAQK,iBFJK,UEIuBC,GAE7B,WACLN,EAAQQ,oBFPG,UEO4BF,OAG3C,CFVe,UEUHN,IFVdS,CAAiB,GAAW,SAACF,GACR,UAAfA,EAAMG,aACJjB,GAAAA,EAAaG,EAAa,GAC5BC,GAAc,SAACc,UAASA,EAAO,KAG/BrB,QAMJ1B,gBAACK,OACCL,gBAACS,GACCC,WAAMmB,SAAAA,EAAaG,GACnBrB,SAAUgB,EACVf,QAASgB,MAMXvB,EAAYE,EAAOC,kFAAPD,QJvCNT,EAAAA,wBAAAA,+CAEVA,0CA2DIO,EAAYE,EAAOC,8EAAPD,kIAcZgB,EAAgBhB,EAAOC,kFAAPD,gCACZ,qBAAGyC,QAIPC,EAAqB1C,EAAOC,uFAAPD,0DAMrB2C,EAAe3C,EAAOX,iFAAPW,0DAUf4C,EAAsB5C,EAAOX,wFAAPW,uGAEjB,qBAAG6C,iDAtFsC,gBAClD1C,IAAAA,KACAJ,IAAAA,KACA+C,IAAAA,OACA3B,IAAAA,UAE4Bb,YAAkB,GAAvCyC,OAAQC,SAEb1C,YAAkB,GADb2C,OAAqBC,OAItBC,EAAe7D,6CAA6CwD,iBAE3DC,EACLtD,gBAACD,OACCC,gBAACG,GAAeG,KAAK,iBACnBN,gBAACK,OACCL,gBAACuB,GACCyB,KAAM1C,IAASR,sBAAc6D,iBAAmB,MAAQ,QAExD3D,gBAACyB,GACCG,YAAa,kBAAM6B,GAAuB,IAC1C9B,UAAW,kBAAM8B,GAAuB,IACxC/C,KAAMA,EACNgB,QAAS,WACHA,IACFA,IACA6B,GAAU,QAKjBjD,IAASR,sBAAc6D,kBACtB3D,gBAACiD,OACCjD,gBAACkD,GAAaU,IAAKF,MAIxBF,GACCxD,gBAACmD,GACCC,MAAO9C,IAASR,sBAAc+D,SAAW,OAAS,UAClDD,IAAKE,MAKX"}
1
+ {"version":3,"file":"long-bow.cjs.production.min.js","sources":["../src/RPGUI/RPGUI.tsx","../src/RPGUI/RPGUIContainer.tsx","../src/NPCDialog/img/npcDialog/npcThumbnails/alice.png","../src/NPCDialog/img/space.gif","../src/hooks/useEventListener.ts","../src/NPCDialog/NPCDialog.tsx","../src/typography/DynamicText.tsx","../src/NPCDialog/NPCDialogText.tsx","../src/libs/StringHelpers.ts"],"sourcesContent":["import React from 'react';\nimport 'rpgui/rpgui.css';\nimport 'rpgui/rpgui.js';\n\ninterface IProps {\n children: React.ReactNode;\n}\n\nexport const RPGUI: React.FC<IProps> = ({ children }) => {\n return <div className=\"rpgui-content\">{children}</div>;\n};\n","import React from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n type: 'framed' | 'framed-golden' | 'framed-golden-2' | 'framed-grey';\n children: React.ReactNode;\n width?: string;\n}\n\nexport const RPGUIContainer: React.FC<IProps> = ({\n children,\n type,\n width = '50%',\n}) => {\n return (\n <Container width={width} className={`rpgui-container ${type}`}>\n {children}\n </Container>\n );\n};\n\ninterface IContainerProps {\n width: string;\n}\n\nconst Container = styled.div<IContainerProps>`\n max-width: ${({ width }) => width};\n`;\n","const img = require('./alice.png'); export default img;","const img = require('./space.gif'); export default img;","import React from 'react';\n\n//@ts-ignore\nexport const useEventListener = (type, handler, el = window) => {\n const savedHandler = React.useRef();\n\n React.useEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n React.useEffect(() => {\n //@ts-ignore\n const listener = (e) => savedHandler.current(e);\n\n el.addEventListener(type, listener);\n\n return () => {\n el.removeEventListener(type, listener);\n };\n }, [type, el]);\n};\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { RPGUI } from '../RPGUI/RPGUI';\nimport { RPGUIContainer } from '../RPGUI/RPGUIContainer';\nimport aliceDefaultThumbnail from './img/npcDialog/npcThumbnails/alice.png';\nimport pressSpaceGif from './img/space.gif';\nimport { NPCDialogText } from './NPCDialogText';\nexport enum NPCDialogType {\n TextOnly = 'TextOnly',\n TextAndThumbnail = 'TextAndThumbnail',\n}\n\nexport interface INPCDialogProps {\n text: string;\n type: NPCDialogType;\n imagePath?: string;\n onClose?: () => void;\n}\n\nexport const NPCDialog: React.FC<INPCDialogProps> = ({\n text,\n type,\n onClose,\n imagePath,\n}) => {\n const [isOpen, setIsOpen] = useState<boolean>(true);\n const [showGoNextIndicator, setShowGoNextIndicator] =\n useState<boolean>(false);\n\n return isOpen ? (\n <RPGUI>\n <RPGUIContainer type=\"framed-golden\">\n <Container>\n <TextContainer\n flex={type === NPCDialogType.TextAndThumbnail ? '70%' : '100%'}\n >\n <NPCDialogText\n onStartStep={() => setShowGoNextIndicator(false)}\n onEndStep={() => setShowGoNextIndicator(true)}\n text={text}\n onClose={() => {\n if (onClose) {\n onClose();\n setIsOpen(false);\n }\n }}\n />\n </TextContainer>\n {type === NPCDialogType.TextAndThumbnail && (\n <ThumbnailContainer>\n <NPCThumbnail src={imagePath || aliceDefaultThumbnail} />\n </ThumbnailContainer>\n )}\n </Container>\n {showGoNextIndicator && (\n <PressSpaceIndicator\n right={type === NPCDialogType.TextOnly ? '1rem' : '10.5rem'}\n src={pressSpaceGif}\n />\n )}\n </RPGUIContainer>\n </RPGUI>\n ) : null;\n};\n\nconst Container = styled.div`\n display: flex;\n width: 100%;\n height: 125px;\n box-sizing: border-box;\n justify-content: center;\n align-items: flex-start;\n position: relative;\n`;\n\ninterface ITextContainerProps {\n flex: string;\n}\n\nconst TextContainer = styled.div<ITextContainerProps>`\n flex: ${({ flex }) => flex} 0 0;\n width: 355px;\n`;\n\nconst ThumbnailContainer = styled.div`\n flex: 30% 0 0;\n display: flex;\n justify-content: flex-end;\n`;\n\nconst NPCThumbnail = styled.img`\n image-rendering: pixelated;\n height: 128px;\n width: 128px;\n`;\n\ninterface IPressSpaceIndicatorProps {\n right: string;\n}\n\nconst PressSpaceIndicator = styled.img<IPressSpaceIndicatorProps>`\n position: absolute;\n right: ${({ right }) => right};\n bottom: 1rem;\n height: 20.7px;\n image-rendering: -webkit-optimize-contrast;\n`;\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n text: string;\n onFinish?: () => void;\n onStart?: () => void;\n}\n\nexport const DynamicText: React.FC<IProps> = ({ text, onFinish, onStart }) => {\n const [textState, setTextState] = useState<string>('');\n\n useEffect(() => {\n let i = 0;\n const interval = setInterval(() => {\n // on every interval, show one more character\n\n if (i === 0) {\n if (onStart) {\n onStart();\n }\n }\n\n if (i < text.length) {\n setTextState(text.substring(0, i + 1));\n i++;\n } else {\n clearInterval(interval);\n if (onFinish) {\n onFinish();\n }\n }\n }, 50);\n\n return () => {\n clearInterval(interval);\n };\n }, [text]);\n\n return <TextContainer>{textState}</TextContainer>;\n};\n\nconst TextContainer = styled.p`\n font-size: 0.7rem !important;\n color: white;\n text-shadow: 1px 1px 0px #000000;\n letter-spacing: 1.2px;\n`;\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\nimport { useEventListener } from '../hooks/useEventListener';\nimport { chunkString } from '../libs/StringHelpers';\nimport { DynamicText } from '../typography/DynamicText';\n\ninterface IProps {\n text: string;\n onClose: () => void;\n onEndStep: () => void;\n onStartStep: () => void;\n}\n\nexport const NPCDialogText: React.FC<IProps> = ({\n text,\n onClose,\n onEndStep,\n onStartStep,\n}) => {\n const textChunks = chunkString(text, 85);\n\n const [chunkIndex, setChunkIndex] = useState<number>(0);\n\n const onHandleSpacePress = (event: KeyboardEvent) => {\n if (event.code === 'Space') {\n if (textChunks?.[chunkIndex + 1]) {\n setChunkIndex(chunkIndex + 1);\n } else {\n // if there's no more text chunks, close the dialog\n onClose();\n }\n }\n };\n\n useEffect(() => {\n window.addEventListener('keydown', onHandleSpacePress);\n\n return () => window.removeEventListener('keydown', onHandleSpacePress);\n }, [chunkIndex]);\n\n useEventListener('keydown', onHandleSpacePress);\n\n return (\n <Container>\n <DynamicText\n text={textChunks?.[chunkIndex] || ''}\n onFinish={onEndStep}\n onStart={onStartStep}\n />\n </Container>\n );\n};\n\nconst Container = styled.div``;\n","export const chunkString = (str: string, length: number) => {\n return str.match(new RegExp('.{1,' + length + '}', 'g'));\n};\n"],"names":["RPGUI","React","className","children","RPGUIContainer","width","Container","type","styled","div","img","require","NPCDialogType","DynamicText","text","onFinish","onStart","useState","textState","setTextState","useEffect","i","interval","setInterval","length","substring","clearInterval","TextContainer","p","NPCDialogText","onClose","onEndStep","onStartStep","textChunks","match","RegExp","chunkIndex","setChunkIndex","onHandleSpacePress","event","code","window","addEventListener","removeEventListener","handler","el","savedHandler","useRef","current","listener","e","useEventListener","flex","ThumbnailContainer","NPCThumbnail","PressSpaceIndicator","right","imagePath","isOpen","setIsOpen","showGoNextIndicator","setShowGoNextIndicator","TextAndThumbnail","src","aliceDefaultThumbnail","TextOnly","pressSpaceGif"],"mappings":"mQAQaA,EAA0B,mBAC9BC,uBAAKC,UAAU,mBADkBC,WCC7BC,EAAmC,oBAG9CC,aAGEJ,gBAACK,GAAUD,iBAHL,QAGmBH,+BAJ3BK,QADAJ,WAeIG,EAAYE,EAAOC,mFAAPD,qBACH,qBAAGH,SC1BlB,MAAMK,EAAMC,QAAQ,eCAdD,EAAMC,QAAQ,eCGb,ICIKC,ECECC,EAAgC,gBAAGC,IAAAA,KAAMC,IAAAA,SAAUC,IAAAA,UAC5BC,WAAiB,IAA5CC,OAAWC,cAElBC,aAAU,eACJC,EAAI,EACFC,EAAWC,aAAY,WAGjB,IAANF,GACEL,GACFA,IAIAK,EAAIP,EAAKU,QACXL,EAAaL,EAAKW,UAAU,EAAGJ,EAAI,IACnCA,MAEAK,cAAcJ,GACVP,GACFA,OAGH,WAEI,WACLW,cAAcJ,MAEf,CAACR,IAEGb,gBAAC0B,OAAeT,IAGnBS,EAAgBnB,EAAOoB,kFAAPpB,oGC7BTqB,EAAkC,gBAE7CC,IAAAA,QACAC,IAAAA,UACAC,IAAAA,YAEMC,IALNnB,KCbWoB,MAAM,IAAIC,OAAO,UAAuB,QDoBflB,WAAiB,GAA9CmB,OAAYC,OAEbC,EAAqB,SAACC,GACP,UAAfA,EAAMC,aACJP,GAAAA,EAAaG,EAAa,GAC5BC,EAAcD,EAAa,GAG3BN,aAKNV,aAAU,kBACRqB,OAAOC,iBAAiB,UAAWJ,GAE5B,kBAAMG,OAAOE,oBAAoB,UAAWL,MAClD,CAACF,IHnC0B,SAAC7B,EAAMqC,EAASC,YAAAA,IAAAA,EAAKJ,YAC7CK,EAAe7C,EAAM8C,SAE3B9C,EAAMmB,WAAU,WACd0B,EAAaE,QAAUJ,IACtB,CAACA,IAEJ3C,EAAMmB,WAAU,eAER6B,EAAW,SAACC,UAAMJ,EAAaE,QAAQE,WAE7CL,EAAGH,iBG0BY,UH1BWO,GAEnB,WACLJ,EAAGF,oBGuBU,UHvBgBM,MAE9B,CGqBc,UHrBPJ,IGqBVM,CAAiB,EAAWb,GAG1BrC,gBAACK,OACCL,gBAACY,GACCC,YAAMmB,SAAAA,EAAaG,KAAe,GAClCrB,SAAUgB,EACVf,QAASgB,MAMX1B,EAAYE,EAAOC,kFAAPD,QF9CNI,EAAAA,wBAAAA,+CAEVA,0CAwDIN,EAAYE,EAAOC,8EAAPD,kIAcZmB,EAAgBnB,EAAOC,kFAAPD,gCACZ,qBAAG4C,QAIPC,EAAqB7C,EAAOC,uFAAPD,0DAMrB8C,EAAe9C,EAAOE,iFAAPF,0DAUf+C,EAAsB/C,EAAOE,wFAAPF,uGAEjB,qBAAGgD,iDAnFsC,gBAClD1C,IAAAA,KACAP,IAAAA,KACAuB,IAAAA,QACA2B,IAAAA,YAE4BxC,YAAkB,GAAvCyC,OAAQC,SAEb1C,YAAkB,GADb2C,OAAqBC,cAGrBH,EACLzD,gBAACD,OACCC,gBAACG,GAAeG,KAAK,iBACnBN,gBAACK,OACCL,gBAAC0B,GACCyB,KAAM7C,IAASK,sBAAckD,iBAAmB,MAAQ,QAExD7D,gBAAC4B,GACCG,YAAa,kBAAM6B,GAAuB,IAC1C9B,UAAW,kBAAM8B,GAAuB,IACxC/C,KAAMA,EACNgB,QAAS,WACHA,IACFA,IACA6B,GAAU,QAKjBpD,IAASK,sBAAckD,kBACtB7D,gBAACoD,OACCpD,gBAACqD,GAAaS,IAAKN,GAAaO,MAIrCJ,GACC3D,gBAACsD,GACCC,MAAOjD,IAASK,sBAAcqD,SAAW,OAAS,UAClDF,IAAKG,MAKX"}
@@ -1,10 +1,8 @@
1
- import React, { useRef, useEffect, useState } from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  import styled from 'styled-components';
3
3
  import 'rpgui/rpgui.css';
4
4
  import 'rpgui/rpgui.js';
5
5
 
6
- const img = require('./space.gif');
7
-
8
6
  var RPGUI = function RPGUI(_ref) {
9
7
  var children = _ref.children;
10
8
  return React.createElement("div", {
@@ -30,41 +28,31 @@ var Container = /*#__PURE__*/styled.div.withConfig({
30
28
  return width;
31
29
  });
32
30
 
33
- function useEventListener(eventName, handler, element) {
34
- if (element === void 0) {
35
- element = window;
36
- }
31
+ const img = require('./alice.png');
37
32
 
38
- // Create a ref that stores handler
39
- var savedHandler = useRef(); // Update ref.current value if handler changes.
40
- // This allows our effect below to always get latest handler ...
41
- // ... without us needing to pass it in effect deps array ...
42
- // ... and potentially cause effect to re-run every render.
33
+ const img$1 = require('./space.gif');
43
34
 
44
- useEffect(function () {
45
- //@ts-ignore
35
+ var useEventListener = function useEventListener(type, handler, el) {
36
+ if (el === void 0) {
37
+ el = window;
38
+ }
39
+
40
+ var savedHandler = React.useRef();
41
+ React.useEffect(function () {
46
42
  savedHandler.current = handler;
47
43
  }, [handler]);
48
- useEffect(function () {
49
- // Make sure element supports addEventListener
50
- // On
51
- var isSupported = element && element.addEventListener;
52
- if (!isSupported) return; // Create event listener that calls handler function stored in ref
44
+ React.useEffect(function () {
53
45
  //@ts-ignore
46
+ var listener = function listener(e) {
47
+ return savedHandler.current(e);
48
+ };
54
49
 
55
- var eventListener = function eventListener(event) {
56
- return savedHandler.current(event);
57
- }; // Add event listener
58
-
59
-
60
- element.addEventListener(eventName, eventListener); // Remove event listener on cleanup
61
-
50
+ el.addEventListener(type, listener);
62
51
  return function () {
63
- element.removeEventListener(eventName, eventListener);
52
+ el.removeEventListener(type, listener);
64
53
  };
65
- }, [eventName, element] // Re-run if eventName or element changes
66
- );
67
- }
54
+ }, [type, el]);
55
+ };
68
56
 
69
57
  var chunkString = function chunkString(str, length) {
70
58
  return str.match(new RegExp('.{1,' + length + '}', 'g'));
@@ -122,20 +110,26 @@ var NPCDialogText = function NPCDialogText(_ref) {
122
110
  chunkIndex = _useState[0],
123
111
  setChunkIndex = _useState[1];
124
112
 
125
- useEventListener('keydown', function (event) {
113
+ var onHandleSpacePress = function onHandleSpacePress(event) {
126
114
  if (event.code === 'Space') {
127
115
  if (textChunks != null && textChunks[chunkIndex + 1]) {
128
- setChunkIndex(function (prev) {
129
- return prev + 1;
130
- });
116
+ setChunkIndex(chunkIndex + 1);
131
117
  } else {
132
118
  // if there's no more text chunks, close the dialog
133
119
  onClose();
134
120
  }
135
121
  }
136
- });
122
+ };
123
+
124
+ useEffect(function () {
125
+ window.addEventListener('keydown', onHandleSpacePress);
126
+ return function () {
127
+ return window.removeEventListener('keydown', onHandleSpacePress);
128
+ };
129
+ }, [chunkIndex]);
130
+ useEventListener('keydown', onHandleSpacePress);
137
131
  return React.createElement(Container$1, null, React.createElement(DynamicText, {
138
- text: textChunks == null ? void 0 : textChunks[chunkIndex],
132
+ text: (textChunks == null ? void 0 : textChunks[chunkIndex]) || '',
139
133
  onFinish: onEndStep,
140
134
  onStart: onStartStep
141
135
  }));
@@ -155,8 +149,8 @@ var NPCDialogType;
155
149
  var NPCDialog = function NPCDialog(_ref) {
156
150
  var text = _ref.text,
157
151
  type = _ref.type,
158
- npcKey = _ref.npcKey,
159
- _onClose = _ref.onClose;
152
+ _onClose = _ref.onClose,
153
+ imagePath = _ref.imagePath;
160
154
 
161
155
  var _useState = useState(true),
162
156
  isOpen = _useState[0],
@@ -164,10 +158,7 @@ var NPCDialog = function NPCDialog(_ref) {
164
158
 
165
159
  var _useState2 = useState(false),
166
160
  showGoNextIndicator = _useState2[0],
167
- setShowGoNextIndicator = _useState2[1]; //dynamically require npc thumbnail
168
-
169
-
170
- var npcThumbnail = require("../assets/npcDialog/npcThumbnails/" + npcKey + ".png");
161
+ setShowGoNextIndicator = _useState2[1];
171
162
 
172
163
  return isOpen ? React.createElement(RPGUI, null, React.createElement(RPGUIContainer, {
173
164
  type: "framed-golden"
@@ -189,10 +180,10 @@ var NPCDialog = function NPCDialog(_ref) {
189
180
  }
190
181
  }
191
182
  })), type === NPCDialogType.TextAndThumbnail && React.createElement(ThumbnailContainer, null, React.createElement(NPCThumbnail, {
192
- src: npcThumbnail
183
+ src: imagePath || img
193
184
  }))), showGoNextIndicator && React.createElement(PressSpaceIndicator, {
194
185
  right: type === NPCDialogType.TextOnly ? '1rem' : '10.5rem',
195
- src: img
186
+ src: img$1
196
187
  }))) : null;
197
188
  };
198
189
  var Container$2 = /*#__PURE__*/styled.div.withConfig({
@@ -1 +1 @@
1
- {"version":3,"file":"long-bow.esm.js","sources":["../src/assets/space.gif","../src/RPGUI/RPGUI.tsx","../src/RPGUI/RPGUIContainer.tsx","../src/hooks/useEventListener.ts","../src/libs/StringHelpers.ts","../src/typography/DynamicText.tsx","../src/NPCDialog/NPCDialogText.tsx","../src/NPCDialog/NPCDialog.tsx"],"sourcesContent":["const img = require('./space.gif'); export default img;","import React from 'react';\nimport 'rpgui/rpgui.css';\nimport 'rpgui/rpgui.js';\n\ninterface IProps {\n children: React.ReactNode;\n}\n\nexport const RPGUI: React.FC<IProps> = ({ children }) => {\n return <div className=\"rpgui-content\">{children}</div>;\n};\n","import React from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n type: 'framed' | 'framed-golden' | 'framed-golden-2' | 'framed-grey';\n children: React.ReactNode;\n width?: string;\n}\n\nexport const RPGUIContainer: React.FC<IProps> = ({\n children,\n type,\n width = '50%',\n}) => {\n return (\n <Container width={width} className={`rpgui-container ${type}`}>\n {children}\n </Container>\n );\n};\n\ninterface IContainerProps {\n width: string;\n}\n\nconst Container = styled.div<IContainerProps>`\n max-width: ${({ width }) => width};\n`;\n","import { useEffect, useRef } from 'react';\n\nexport function useEventListener(\n eventName: string,\n handler: (e: any) => void,\n element = window\n) {\n // Create a ref that stores handler\n const savedHandler = useRef();\n // Update ref.current value if handler changes.\n // This allows our effect below to always get latest handler ...\n // ... without us needing to pass it in effect deps array ...\n // ... and potentially cause effect to re-run every render.\n useEffect(() => {\n //@ts-ignore\n savedHandler.current = handler;\n }, [handler]);\n useEffect(\n () => {\n // Make sure element supports addEventListener\n // On\n const isSupported = element && element.addEventListener;\n if (!isSupported) return;\n // Create event listener that calls handler function stored in ref\n //@ts-ignore\n const eventListener = (event: any) => savedHandler.current(event);\n // Add event listener\n element.addEventListener(eventName, eventListener);\n // Remove event listener on cleanup\n return () => {\n element.removeEventListener(eventName, eventListener);\n };\n },\n [eventName, element] // Re-run if eventName or element changes\n );\n}\n","export const chunkString = (str: string, length: number) => {\n return str.match(new RegExp('.{1,' + length + '}', 'g'));\n};\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n text: string;\n onFinish?: () => void;\n onStart?: () => void;\n}\n\nexport const DynamicText: React.FC<IProps> = ({ text, onFinish, onStart }) => {\n const [textState, setTextState] = useState<string>('');\n\n useEffect(() => {\n let i = 0;\n const interval = setInterval(() => {\n // on every interval, show one more character\n\n if (i === 0) {\n if (onStart) {\n onStart();\n }\n }\n\n if (i < text.length) {\n setTextState(text.substring(0, i + 1));\n i++;\n } else {\n clearInterval(interval);\n if (onFinish) {\n onFinish();\n }\n }\n }, 50);\n\n return () => {\n clearInterval(interval);\n };\n }, [text]);\n\n return <TextContainer>{textState}</TextContainer>;\n};\n\nconst TextContainer = styled.p`\n font-size: 0.7rem !important;\n color: white;\n text-shadow: 1px 1px 0px #000000;\n letter-spacing: 1.2px;\n`;\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { useEventListener } from '../hooks/useEventListener';\nimport { chunkString } from '../libs/StringHelpers';\nimport { DynamicText } from '../typography/DynamicText';\n\ninterface IProps {\n text: string;\n onClose: () => void;\n onEndStep: () => void;\n onStartStep: () => void;\n}\n\nexport const NPCDialogText: React.FC<IProps> = ({\n text,\n onClose,\n onEndStep,\n onStartStep,\n}) => {\n const textChunks = chunkString(text, 85);\n\n const [chunkIndex, setChunkIndex] = useState<number>(0);\n\n useEventListener('keydown', (event: KeyboardEvent) => {\n if (event.code === 'Space') {\n if (textChunks?.[chunkIndex + 1]) {\n setChunkIndex((prev) => prev + 1);\n } else {\n // if there's no more text chunks, close the dialog\n onClose();\n }\n }\n });\n\n return (\n <Container>\n <DynamicText\n text={textChunks?.[chunkIndex]!}\n onFinish={onEndStep}\n onStart={onStartStep}\n />\n </Container>\n );\n};\n\nconst Container = styled.div``;\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport pressSpaceGif from '../assets/space.gif';\nimport { RPGUI } from '../RPGUI/RPGUI';\nimport { RPGUIContainer } from '../RPGUI/RPGUIContainer';\nimport { NPCDialogText } from './NPCDialogText';\nexport enum NPCDialogType {\n TextOnly = 'TextOnly',\n TextAndThumbnail = 'TextAndThumbnail',\n}\n\nexport interface INPCDialogProps {\n text: string;\n type: NPCDialogType;\n npcKey: string;\n onClose?: () => void;\n}\n\nexport const NPCDialog: React.FC<INPCDialogProps> = ({\n text,\n type,\n npcKey,\n onClose,\n}) => {\n const [isOpen, setIsOpen] = useState<boolean>(true);\n const [showGoNextIndicator, setShowGoNextIndicator] =\n useState<boolean>(false);\n\n //dynamically require npc thumbnail\n const npcThumbnail = require(`../assets/npcDialog/npcThumbnails/${npcKey}.png`);\n\n return isOpen ? (\n <RPGUI>\n <RPGUIContainer type=\"framed-golden\">\n <Container>\n <TextContainer\n flex={type === NPCDialogType.TextAndThumbnail ? '70%' : '100%'}\n >\n <NPCDialogText\n onStartStep={() => setShowGoNextIndicator(false)}\n onEndStep={() => setShowGoNextIndicator(true)}\n text={text}\n onClose={() => {\n if (onClose) {\n onClose();\n setIsOpen(false);\n }\n }}\n />\n </TextContainer>\n {type === NPCDialogType.TextAndThumbnail && (\n <ThumbnailContainer>\n <NPCThumbnail src={npcThumbnail} />\n </ThumbnailContainer>\n )}\n </Container>\n {showGoNextIndicator && (\n <PressSpaceIndicator\n right={type === NPCDialogType.TextOnly ? '1rem' : '10.5rem'}\n src={pressSpaceGif}\n />\n )}\n </RPGUIContainer>\n </RPGUI>\n ) : null;\n};\n\nconst Container = styled.div`\n display: flex;\n width: 100%;\n height: 125px;\n box-sizing: border-box;\n justify-content: center;\n align-items: flex-start;\n position: relative;\n`;\n\ninterface ITextContainerProps {\n flex: string;\n}\n\nconst TextContainer = styled.div<ITextContainerProps>`\n flex: ${({ flex }) => flex} 0 0;\n width: 355px;\n`;\n\nconst ThumbnailContainer = styled.div`\n flex: 30% 0 0;\n display: flex;\n justify-content: flex-end;\n`;\n\nconst NPCThumbnail = styled.img`\n image-rendering: pixelated;\n height: 128px;\n width: 128px;\n`;\n\ninterface IPressSpaceIndicatorProps {\n right: string;\n}\n\nconst PressSpaceIndicator = styled.img<IPressSpaceIndicatorProps>`\n position: absolute;\n right: ${({ right }) => right};\n bottom: 1rem;\n height: 20.7px;\n image-rendering: -webkit-optimize-contrast;\n`;\n"],"names":["RPGUI","children","React","className","RPGUIContainer","type","width","Container","styled","div","useEventListener","eventName","handler","element","window","savedHandler","useRef","useEffect","current","isSupported","addEventListener","eventListener","event","removeEventListener","chunkString","str","length","match","RegExp","DynamicText","text","onFinish","onStart","useState","textState","setTextState","i","interval","setInterval","substring","clearInterval","TextContainer","p","NPCDialogText","onClose","onEndStep","onStartStep","textChunks","chunkIndex","setChunkIndex","code","prev","NPCDialogType","NPCDialog","npcKey","isOpen","setIsOpen","showGoNextIndicator","setShowGoNextIndicator","npcThumbnail","require","flex","TextAndThumbnail","ThumbnailContainer","NPCThumbnail","src","PressSpaceIndicator","right","TextOnly","pressSpaceGif","img"],"mappings":"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"}
1
+ {"version":3,"file":"long-bow.esm.js","sources":["../src/RPGUI/RPGUI.tsx","../src/RPGUI/RPGUIContainer.tsx","../src/NPCDialog/img/npcDialog/npcThumbnails/alice.png","../src/NPCDialog/img/space.gif","../src/hooks/useEventListener.ts","../src/libs/StringHelpers.ts","../src/typography/DynamicText.tsx","../src/NPCDialog/NPCDialogText.tsx","../src/NPCDialog/NPCDialog.tsx"],"sourcesContent":["import React from 'react';\nimport 'rpgui/rpgui.css';\nimport 'rpgui/rpgui.js';\n\ninterface IProps {\n children: React.ReactNode;\n}\n\nexport const RPGUI: React.FC<IProps> = ({ children }) => {\n return <div className=\"rpgui-content\">{children}</div>;\n};\n","import React from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n type: 'framed' | 'framed-golden' | 'framed-golden-2' | 'framed-grey';\n children: React.ReactNode;\n width?: string;\n}\n\nexport const RPGUIContainer: React.FC<IProps> = ({\n children,\n type,\n width = '50%',\n}) => {\n return (\n <Container width={width} className={`rpgui-container ${type}`}>\n {children}\n </Container>\n );\n};\n\ninterface IContainerProps {\n width: string;\n}\n\nconst Container = styled.div<IContainerProps>`\n max-width: ${({ width }) => width};\n`;\n","const img = require('./alice.png'); export default img;","const img = require('./space.gif'); export default img;","import React from 'react';\n\n//@ts-ignore\nexport const useEventListener = (type, handler, el = window) => {\n const savedHandler = React.useRef();\n\n React.useEffect(() => {\n savedHandler.current = handler;\n }, [handler]);\n\n React.useEffect(() => {\n //@ts-ignore\n const listener = (e) => savedHandler.current(e);\n\n el.addEventListener(type, listener);\n\n return () => {\n el.removeEventListener(type, listener);\n };\n }, [type, el]);\n};\n","export const chunkString = (str: string, length: number) => {\n return str.match(new RegExp('.{1,' + length + '}', 'g'));\n};\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\n\ninterface IProps {\n text: string;\n onFinish?: () => void;\n onStart?: () => void;\n}\n\nexport const DynamicText: React.FC<IProps> = ({ text, onFinish, onStart }) => {\n const [textState, setTextState] = useState<string>('');\n\n useEffect(() => {\n let i = 0;\n const interval = setInterval(() => {\n // on every interval, show one more character\n\n if (i === 0) {\n if (onStart) {\n onStart();\n }\n }\n\n if (i < text.length) {\n setTextState(text.substring(0, i + 1));\n i++;\n } else {\n clearInterval(interval);\n if (onFinish) {\n onFinish();\n }\n }\n }, 50);\n\n return () => {\n clearInterval(interval);\n };\n }, [text]);\n\n return <TextContainer>{textState}</TextContainer>;\n};\n\nconst TextContainer = styled.p`\n font-size: 0.7rem !important;\n color: white;\n text-shadow: 1px 1px 0px #000000;\n letter-spacing: 1.2px;\n`;\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\nimport { useEventListener } from '../hooks/useEventListener';\nimport { chunkString } from '../libs/StringHelpers';\nimport { DynamicText } from '../typography/DynamicText';\n\ninterface IProps {\n text: string;\n onClose: () => void;\n onEndStep: () => void;\n onStartStep: () => void;\n}\n\nexport const NPCDialogText: React.FC<IProps> = ({\n text,\n onClose,\n onEndStep,\n onStartStep,\n}) => {\n const textChunks = chunkString(text, 85);\n\n const [chunkIndex, setChunkIndex] = useState<number>(0);\n\n const onHandleSpacePress = (event: KeyboardEvent) => {\n if (event.code === 'Space') {\n if (textChunks?.[chunkIndex + 1]) {\n setChunkIndex(chunkIndex + 1);\n } else {\n // if there's no more text chunks, close the dialog\n onClose();\n }\n }\n };\n\n useEffect(() => {\n window.addEventListener('keydown', onHandleSpacePress);\n\n return () => window.removeEventListener('keydown', onHandleSpacePress);\n }, [chunkIndex]);\n\n useEventListener('keydown', onHandleSpacePress);\n\n return (\n <Container>\n <DynamicText\n text={textChunks?.[chunkIndex] || ''}\n onFinish={onEndStep}\n onStart={onStartStep}\n />\n </Container>\n );\n};\n\nconst Container = styled.div``;\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { RPGUI } from '../RPGUI/RPGUI';\nimport { RPGUIContainer } from '../RPGUI/RPGUIContainer';\nimport aliceDefaultThumbnail from './img/npcDialog/npcThumbnails/alice.png';\nimport pressSpaceGif from './img/space.gif';\nimport { NPCDialogText } from './NPCDialogText';\nexport enum NPCDialogType {\n TextOnly = 'TextOnly',\n TextAndThumbnail = 'TextAndThumbnail',\n}\n\nexport interface INPCDialogProps {\n text: string;\n type: NPCDialogType;\n imagePath?: string;\n onClose?: () => void;\n}\n\nexport const NPCDialog: React.FC<INPCDialogProps> = ({\n text,\n type,\n onClose,\n imagePath,\n}) => {\n const [isOpen, setIsOpen] = useState<boolean>(true);\n const [showGoNextIndicator, setShowGoNextIndicator] =\n useState<boolean>(false);\n\n return isOpen ? (\n <RPGUI>\n <RPGUIContainer type=\"framed-golden\">\n <Container>\n <TextContainer\n flex={type === NPCDialogType.TextAndThumbnail ? '70%' : '100%'}\n >\n <NPCDialogText\n onStartStep={() => setShowGoNextIndicator(false)}\n onEndStep={() => setShowGoNextIndicator(true)}\n text={text}\n onClose={() => {\n if (onClose) {\n onClose();\n setIsOpen(false);\n }\n }}\n />\n </TextContainer>\n {type === NPCDialogType.TextAndThumbnail && (\n <ThumbnailContainer>\n <NPCThumbnail src={imagePath || aliceDefaultThumbnail} />\n </ThumbnailContainer>\n )}\n </Container>\n {showGoNextIndicator && (\n <PressSpaceIndicator\n right={type === NPCDialogType.TextOnly ? '1rem' : '10.5rem'}\n src={pressSpaceGif}\n />\n )}\n </RPGUIContainer>\n </RPGUI>\n ) : null;\n};\n\nconst Container = styled.div`\n display: flex;\n width: 100%;\n height: 125px;\n box-sizing: border-box;\n justify-content: center;\n align-items: flex-start;\n position: relative;\n`;\n\ninterface ITextContainerProps {\n flex: string;\n}\n\nconst TextContainer = styled.div<ITextContainerProps>`\n flex: ${({ flex }) => flex} 0 0;\n width: 355px;\n`;\n\nconst ThumbnailContainer = styled.div`\n flex: 30% 0 0;\n display: flex;\n justify-content: flex-end;\n`;\n\nconst NPCThumbnail = styled.img`\n image-rendering: pixelated;\n height: 128px;\n width: 128px;\n`;\n\ninterface IPressSpaceIndicatorProps {\n right: string;\n}\n\nconst PressSpaceIndicator = styled.img<IPressSpaceIndicatorProps>`\n position: absolute;\n right: ${({ right }) => right};\n bottom: 1rem;\n height: 20.7px;\n image-rendering: -webkit-optimize-contrast;\n`;\n"],"names":["RPGUI","children","React","className","RPGUIContainer","type","width","Container","styled","div","img","useEventListener","handler","el","window","savedHandler","useRef","useEffect","current","listener","e","addEventListener","removeEventListener","chunkString","str","length","match","RegExp","DynamicText","text","onFinish","onStart","useState","textState","setTextState","i","interval","setInterval","substring","clearInterval","TextContainer","p","NPCDialogText","onClose","onEndStep","onStartStep","textChunks","chunkIndex","setChunkIndex","onHandleSpacePress","event","code","NPCDialogType","NPCDialog","imagePath","isOpen","setIsOpen","showGoNextIndicator","setShowGoNextIndicator","flex","TextAndThumbnail","ThumbnailContainer","NPCThumbnail","src","aliceDefaultThumbnail","PressSpaceIndicator","right","TextOnly","pressSpaceGif"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rpg-engine/long-bow",
3
- "version": "0.1.11",
3
+ "version": "0.1.15",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -19,6 +19,7 @@
19
19
  "node": ">=10"
20
20
  },
21
21
  "scripts": {
22
+ "dev": "start-storybook -p 6006",
22
23
  "start": "tsdx watch",
23
24
  "build": "tsdx build",
24
25
  "test": "tsdx test --passWithNoTests",
@@ -27,7 +28,8 @@
27
28
  "size": "size-limit",
28
29
  "analyze": "size-limit --why",
29
30
  "storybook": "start-storybook -p 6006",
30
- "build-storybook": "build-storybook"
31
+ "build-storybook": "build-storybook",
32
+ "configure": "./environment/download-credentials.sh"
31
33
  },
32
34
  "peerDependencies": {
33
35
  "react": ">=16"
@@ -1,8 +1,9 @@
1
1
  import React, { useState } from 'react';
2
2
  import styled from 'styled-components';
3
- import pressSpaceGif from '../assets/space.gif';
4
3
  import { RPGUI } from '../RPGUI/RPGUI';
5
4
  import { RPGUIContainer } from '../RPGUI/RPGUIContainer';
5
+ import aliceDefaultThumbnail from './img/npcDialog/npcThumbnails/alice.png';
6
+ import pressSpaceGif from './img/space.gif';
6
7
  import { NPCDialogText } from './NPCDialogText';
7
8
  export enum NPCDialogType {
8
9
  TextOnly = 'TextOnly',
@@ -12,23 +13,20 @@ export enum NPCDialogType {
12
13
  export interface INPCDialogProps {
13
14
  text: string;
14
15
  type: NPCDialogType;
15
- npcKey: string;
16
+ imagePath?: string;
16
17
  onClose?: () => void;
17
18
  }
18
19
 
19
20
  export const NPCDialog: React.FC<INPCDialogProps> = ({
20
21
  text,
21
22
  type,
22
- npcKey,
23
23
  onClose,
24
+ imagePath,
24
25
  }) => {
25
26
  const [isOpen, setIsOpen] = useState<boolean>(true);
26
27
  const [showGoNextIndicator, setShowGoNextIndicator] =
27
28
  useState<boolean>(false);
28
29
 
29
- //dynamically require npc thumbnail
30
- const npcThumbnail = require(`../assets/npcDialog/npcThumbnails/${npcKey}.png`);
31
-
32
30
  return isOpen ? (
33
31
  <RPGUI>
34
32
  <RPGUIContainer type="framed-golden">
@@ -50,7 +48,7 @@ export const NPCDialog: React.FC<INPCDialogProps> = ({
50
48
  </TextContainer>
51
49
  {type === NPCDialogType.TextAndThumbnail && (
52
50
  <ThumbnailContainer>
53
- <NPCThumbnail src={npcThumbnail} />
51
+ <NPCThumbnail src={imagePath || aliceDefaultThumbnail} />
54
52
  </ThumbnailContainer>
55
53
  )}
56
54
  </Container>
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import styled from 'styled-components';
3
3
  import { useEventListener } from '../hooks/useEventListener';
4
4
  import { chunkString } from '../libs/StringHelpers';
@@ -21,21 +21,29 @@ export const NPCDialogText: React.FC<IProps> = ({
21
21
 
22
22
  const [chunkIndex, setChunkIndex] = useState<number>(0);
23
23
 
24
- useEventListener('keydown', (event: KeyboardEvent) => {
24
+ const onHandleSpacePress = (event: KeyboardEvent) => {
25
25
  if (event.code === 'Space') {
26
26
  if (textChunks?.[chunkIndex + 1]) {
27
- setChunkIndex((prev) => prev + 1);
27
+ setChunkIndex(chunkIndex + 1);
28
28
  } else {
29
29
  // if there's no more text chunks, close the dialog
30
30
  onClose();
31
31
  }
32
32
  }
33
- });
33
+ };
34
+
35
+ useEffect(() => {
36
+ window.addEventListener('keydown', onHandleSpacePress);
37
+
38
+ return () => window.removeEventListener('keydown', onHandleSpacePress);
39
+ }, [chunkIndex]);
40
+
41
+ useEventListener('keydown', onHandleSpacePress);
34
42
 
35
43
  return (
36
44
  <Container>
37
45
  <DynamicText
38
- text={textChunks?.[chunkIndex]!}
46
+ text={textChunks?.[chunkIndex] || ''}
39
47
  onFinish={onEndStep}
40
48
  onStart={onStartStep}
41
49
  />
File without changes
@@ -1,36 +1,21 @@
1
- import { useEffect, useRef } from 'react';
1
+ import React from 'react';
2
2
 
3
- export function useEventListener(
4
- eventName: string,
5
- handler: (e: any) => void,
6
- element = window
7
- ) {
8
- // Create a ref that stores handler
9
- const savedHandler = useRef();
10
- // Update ref.current value if handler changes.
11
- // This allows our effect below to always get latest handler ...
12
- // ... without us needing to pass it in effect deps array ...
13
- // ... and potentially cause effect to re-run every render.
14
- useEffect(() => {
15
- //@ts-ignore
3
+ //@ts-ignore
4
+ export const useEventListener = (type, handler, el = window) => {
5
+ const savedHandler = React.useRef();
6
+
7
+ React.useEffect(() => {
16
8
  savedHandler.current = handler;
17
9
  }, [handler]);
18
- useEffect(
19
- () => {
20
- // Make sure element supports addEventListener
21
- // On
22
- const isSupported = element && element.addEventListener;
23
- if (!isSupported) return;
24
- // Create event listener that calls handler function stored in ref
25
- //@ts-ignore
26
- const eventListener = (event: any) => savedHandler.current(event);
27
- // Add event listener
28
- element.addEventListener(eventName, eventListener);
29
- // Remove event listener on cleanup
30
- return () => {
31
- element.removeEventListener(eventName, eventListener);
32
- };
33
- },
34
- [eventName, element] // Re-run if eventName or element changes
35
- );
36
- }
10
+
11
+ React.useEffect(() => {
12
+ //@ts-ignore
13
+ const listener = (e) => savedHandler.current(e);
14
+
15
+ el.addEventListener(type, listener);
16
+
17
+ return () => {
18
+ el.removeEventListener(type, listener);
19
+ };
20
+ }, [type, el]);
21
+ };
@@ -0,0 +1,6 @@
1
+ import { useEffect, useLayoutEffect } from 'react';
2
+
3
+ const useIsomorphicLayoutEffect =
4
+ typeof window !== 'undefined' ? useLayoutEffect : useEffect;
5
+
6
+ export default useIsomorphicLayoutEffect;
@@ -1 +1,2 @@
1
1
  declare module '*.gif';
2
+ declare module '*.png';