@rpg-engine/long-bow 0.1.12 → 0.1.14
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.
- package/dist/hooks/useEventListener.d.ts +1 -1
- package/dist/hooks/useIsomorphicLayoutEffect.d.ts +3 -0
- package/dist/long-bow.cjs.development.js +19 -33
- package/dist/long-bow.cjs.development.js.map +1 -1
- package/dist/long-bow.cjs.production.min.js +1 -1
- package/dist/long-bow.cjs.production.min.js.map +1 -1
- package/dist/long-bow.esm.js +20 -34
- package/dist/long-bow.esm.js.map +1 -1
- package/package.json +4 -2
- package/src/NPCDialog/NPCDialogText.tsx +6 -4
- package/src/hooks/useEventListener.ts +18 -33
- package/src/hooks/useIsomorphicLayoutEffect.ts +6 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare const useEventListener: (type: any, handler: any, el?: Window & typeof globalThis) => void;
|
|
@@ -39,41 +39,27 @@ const img = require('./alice.png');
|
|
|
39
39
|
|
|
40
40
|
const img$1 = require('./space.gif');
|
|
41
41
|
|
|
42
|
-
function useEventListener(
|
|
43
|
-
if (
|
|
44
|
-
|
|
42
|
+
var useEventListener = function useEventListener(type, handler, el) {
|
|
43
|
+
if (el === void 0) {
|
|
44
|
+
el = window;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
// This allows our effect below to always get latest handler ...
|
|
50
|
-
// ... without us needing to pass it in effect deps array ...
|
|
51
|
-
// ... and potentially cause effect to re-run every render.
|
|
52
|
-
|
|
53
|
-
React.useEffect(function () {
|
|
54
|
-
//@ts-ignore
|
|
47
|
+
var savedHandler = React__default.useRef();
|
|
48
|
+
React__default.useEffect(function () {
|
|
55
49
|
savedHandler.current = handler;
|
|
56
50
|
}, [handler]);
|
|
57
|
-
|
|
58
|
-
// Make sure element supports addEventListener
|
|
59
|
-
// On
|
|
60
|
-
var isSupported = element && element.addEventListener;
|
|
61
|
-
if (!isSupported) return; // Create event listener that calls handler function stored in ref
|
|
51
|
+
React__default.useEffect(function () {
|
|
62
52
|
//@ts-ignore
|
|
53
|
+
var listener = function listener(e) {
|
|
54
|
+
return savedHandler.current(e);
|
|
55
|
+
};
|
|
63
56
|
|
|
64
|
-
|
|
65
|
-
return savedHandler.current(event);
|
|
66
|
-
}; // Add event listener
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
element.addEventListener(eventName, eventListener); // Remove event listener on cleanup
|
|
70
|
-
|
|
57
|
+
el.addEventListener(type, listener);
|
|
71
58
|
return function () {
|
|
72
|
-
|
|
59
|
+
el.removeEventListener(type, listener);
|
|
73
60
|
};
|
|
74
|
-
}, [
|
|
75
|
-
|
|
76
|
-
}
|
|
61
|
+
}, [type, el]);
|
|
62
|
+
};
|
|
77
63
|
|
|
78
64
|
var chunkString = function chunkString(str, length) {
|
|
79
65
|
return str.match(new RegExp('.{1,' + length + '}', 'g'));
|
|
@@ -131,20 +117,20 @@ var NPCDialogText = function NPCDialogText(_ref) {
|
|
|
131
117
|
chunkIndex = _useState[0],
|
|
132
118
|
setChunkIndex = _useState[1];
|
|
133
119
|
|
|
134
|
-
|
|
120
|
+
var onHandleSpacePress = function onHandleSpacePress(event) {
|
|
135
121
|
if (event.code === 'Space') {
|
|
136
122
|
if (textChunks != null && textChunks[chunkIndex + 1]) {
|
|
137
|
-
setChunkIndex(
|
|
138
|
-
return prev + 1;
|
|
139
|
-
});
|
|
123
|
+
setChunkIndex(chunkIndex + 1);
|
|
140
124
|
} else {
|
|
141
125
|
// if there's no more text chunks, close the dialog
|
|
142
126
|
onClose();
|
|
143
127
|
}
|
|
144
128
|
}
|
|
145
|
-
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
useEventListener('keydown', onHandleSpacePress);
|
|
146
132
|
return React__default.createElement(Container$1, null, React__default.createElement(DynamicText, {
|
|
147
|
-
text: textChunks == null ? void 0 : textChunks[chunkIndex],
|
|
133
|
+
text: (textChunks == null ? void 0 : textChunks[chunkIndex]) || '',
|
|
148
134
|
onFinish: onEndStep,
|
|
149
135
|
onStart: onStartStep
|
|
150
136
|
}));
|
|
@@ -1 +1 @@
|
|
|
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 { 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 { 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","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","imagePath","isOpen","setIsOpen","showGoNextIndicator","setShowGoNextIndicator","flex","TextAndThumbnail","ThumbnailContainer","NPCThumbnail","src","aliceDefaultThumbnail","PressSpaceIndicator","right","TextOnly","pressSpaceGif"],"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, { 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 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");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;"]),m=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];return function(e,
|
|
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;"]),m=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];return 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,(function(e){"Space"===e.code&&(null!=a&&a[c+1]?u(c+1):i())})),n.createElement(d,null,n.createElement(s,{text:(null==a?void 0:a[c])||"",onFinish:r,onStart:o}))},d=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;"]),C=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),d=p[0],y=p[1],v=t.useState(!1),w=v[0],N=v[1];return d?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(m,{onStartStep:function(){return N(!1)},onEndStep:function(){return N(!0)},text:i,onClose:function(){u&&(u(),y(!1))}})),a===exports.NPCDialogType.TextAndThumbnail&&n.createElement(g,null,n.createElement(h,{src:s||l}))),w&&n.createElement(C,{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/RPGUI/RPGUI.tsx","../src/RPGUI/RPGUIContainer.tsx","../src/NPCDialog/img/npcDialog/npcThumbnails/alice.png","../src/NPCDialog/img/space.gif","../src/NPCDialog/NPCDialog.tsx","../src/typography/DynamicText.tsx","../src/NPCDialog/NPCDialogText.tsx","../src/libs/StringHelpers.ts","../src/hooks/useEventListener.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, { 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, { 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":["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","eventName","handler","element","window","savedHandler","useRef","current","addEventListener","eventListener","event","removeEventListener","useEventListener","code","prev","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,mBCORC,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,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,QAMJ7B,gBAACK,OACCL,gBAACY,GACCC,WAAMmB,SAAAA,EAAaG,GACnBrB,SAAUgB,EACVf,QAASgB,MAMX1B,EAAYE,EAAOC,kFAAPD,QFtCNI,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
|
+
{"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, { 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 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","handler","el","window","savedHandler","useRef","current","listener","e","addEventListener","removeEventListener","useEventListener","event","code","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,cHlBW,SAAC9B,EAAM+B,EAASC,YAAAA,IAAAA,EAAKC,YAC7CC,EAAexC,EAAMyC,SAE3BzC,EAAMmB,WAAU,WACdqB,EAAaE,QAAUL,IACtB,CAACA,IAEJrC,EAAMmB,WAAU,eAERwB,EAAW,SAACC,UAAMJ,EAAaE,QAAQE,WAE7CN,EAAGO,iBGoBY,UHpBWF,GAEnB,WACLL,EAAGQ,oBGiBU,UHjBgBH,MAE9B,CGec,UHfPL,IGeVS,CAAiB,GAXU,SAACC,GACP,UAAfA,EAAMC,aACJjB,GAAAA,EAAaG,EAAa,GAC5BC,EAAcD,EAAa,GAG3BN,QAQJ7B,gBAACK,OACCL,gBAACY,GACCC,YAAMmB,SAAAA,EAAaG,KAAe,GAClCrB,SAAUgB,EACVf,QAASgB,MAMX1B,EAAYE,EAAOC,kFAAPD,QFxCNI,EAAAA,wBAAAA,+CAEVA,0CAwDIN,EAAYE,EAAOC,8EAAPD,kIAcZmB,EAAgBnB,EAAOC,kFAAPD,gCACZ,qBAAG2C,QAIPC,EAAqB5C,EAAOC,uFAAPD,0DAMrB6C,EAAe7C,EAAOE,iFAAPF,0DAUf8C,EAAsB9C,EAAOE,wFAAPF,uGAEjB,qBAAG+C,iDAnFsC,gBAClDzC,IAAAA,KACAP,IAAAA,KACAuB,IAAAA,QACA0B,IAAAA,YAE4BvC,YAAkB,GAAvCwC,OAAQC,SAEbzC,YAAkB,GADb0C,OAAqBC,cAGrBH,EACLxD,gBAACD,OACCC,gBAACG,GAAeG,KAAK,iBACnBN,gBAACK,OACCL,gBAAC0B,GACCwB,KAAM5C,IAASK,sBAAciD,iBAAmB,MAAQ,QAExD5D,gBAAC4B,GACCG,YAAa,kBAAM4B,GAAuB,IAC1C7B,UAAW,kBAAM6B,GAAuB,IACxC9C,KAAMA,EACNgB,QAAS,WACHA,IACFA,IACA4B,GAAU,QAKjBnD,IAASK,sBAAciD,kBACtB5D,gBAACmD,OACCnD,gBAACoD,GAAaS,IAAKN,GAAaO,MAIrCJ,GACC1D,gBAACqD,GACCC,MAAOhD,IAASK,sBAAcoD,SAAW,OAAS,UAClDF,IAAKG,MAKX"}
|
package/dist/long-bow.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import 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';
|
|
@@ -32,41 +32,27 @@ const img = require('./alice.png');
|
|
|
32
32
|
|
|
33
33
|
const img$1 = require('./space.gif');
|
|
34
34
|
|
|
35
|
-
function useEventListener(
|
|
36
|
-
if (
|
|
37
|
-
|
|
35
|
+
var useEventListener = function useEventListener(type, handler, el) {
|
|
36
|
+
if (el === void 0) {
|
|
37
|
+
el = window;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// This allows our effect below to always get latest handler ...
|
|
43
|
-
// ... without us needing to pass it in effect deps array ...
|
|
44
|
-
// ... and potentially cause effect to re-run every render.
|
|
45
|
-
|
|
46
|
-
useEffect(function () {
|
|
47
|
-
//@ts-ignore
|
|
40
|
+
var savedHandler = React.useRef();
|
|
41
|
+
React.useEffect(function () {
|
|
48
42
|
savedHandler.current = handler;
|
|
49
43
|
}, [handler]);
|
|
50
|
-
useEffect(function () {
|
|
51
|
-
// Make sure element supports addEventListener
|
|
52
|
-
// On
|
|
53
|
-
var isSupported = element && element.addEventListener;
|
|
54
|
-
if (!isSupported) return; // Create event listener that calls handler function stored in ref
|
|
44
|
+
React.useEffect(function () {
|
|
55
45
|
//@ts-ignore
|
|
46
|
+
var listener = function listener(e) {
|
|
47
|
+
return savedHandler.current(e);
|
|
48
|
+
};
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
return savedHandler.current(event);
|
|
59
|
-
}; // Add event listener
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
element.addEventListener(eventName, eventListener); // Remove event listener on cleanup
|
|
63
|
-
|
|
50
|
+
el.addEventListener(type, listener);
|
|
64
51
|
return function () {
|
|
65
|
-
|
|
52
|
+
el.removeEventListener(type, listener);
|
|
66
53
|
};
|
|
67
|
-
}, [
|
|
68
|
-
|
|
69
|
-
}
|
|
54
|
+
}, [type, el]);
|
|
55
|
+
};
|
|
70
56
|
|
|
71
57
|
var chunkString = function chunkString(str, length) {
|
|
72
58
|
return str.match(new RegExp('.{1,' + length + '}', 'g'));
|
|
@@ -124,20 +110,20 @@ var NPCDialogText = function NPCDialogText(_ref) {
|
|
|
124
110
|
chunkIndex = _useState[0],
|
|
125
111
|
setChunkIndex = _useState[1];
|
|
126
112
|
|
|
127
|
-
|
|
113
|
+
var onHandleSpacePress = function onHandleSpacePress(event) {
|
|
128
114
|
if (event.code === 'Space') {
|
|
129
115
|
if (textChunks != null && textChunks[chunkIndex + 1]) {
|
|
130
|
-
setChunkIndex(
|
|
131
|
-
return prev + 1;
|
|
132
|
-
});
|
|
116
|
+
setChunkIndex(chunkIndex + 1);
|
|
133
117
|
} else {
|
|
134
118
|
// if there's no more text chunks, close the dialog
|
|
135
119
|
onClose();
|
|
136
120
|
}
|
|
137
121
|
}
|
|
138
|
-
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
useEventListener('keydown', onHandleSpacePress);
|
|
139
125
|
return React.createElement(Container$1, null, React.createElement(DynamicText, {
|
|
140
|
-
text: textChunks == null ? void 0 : textChunks[chunkIndex],
|
|
126
|
+
text: (textChunks == null ? void 0 : textChunks[chunkIndex]) || '',
|
|
141
127
|
onFinish: onEndStep,
|
|
142
128
|
onStart: onStartStep
|
|
143
129
|
}));
|
package/dist/long-bow.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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 { 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 { 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","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","imagePath","isOpen","setIsOpen","showGoNextIndicator","setShowGoNextIndicator","flex","TextAndThumbnail","ThumbnailContainer","NPCThumbnail","src","aliceDefaultThumbnail","PressSpaceIndicator","right","TextOnly","pressSpaceGif"],"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, { 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 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":";;;;;IAQaA,KAAK,GAAqB,SAA1BA,KAA0B;MAAGC,gBAAAA;AACxC,SAAOC,mBAAA,MAAA;AAAKC,IAAAA,SAAS,EAAC;GAAf,EAAgCF,QAAhC,CAAP;AACD;;ICDYG,cAAc,GAAqB,SAAnCA,cAAmC;MAC9CH,gBAAAA;MACAI,YAAAA;wBACAC;MAAAA,gCAAQ;AAER,SACEJ,mBAAA,CAACK,SAAD;AAAWD,IAAAA,KAAK,EAAEA;AAAOH,IAAAA,SAAS,uBAAqBE;GAAvD,EACGJ,QADH,CADF;AAKD,CAVM;AAgBP,IAAMM,SAAS,gBAAGC,MAAM,CAACC,GAAV;AAAA;AAAA;AAAA,wBACA;AAAA,MAAGH,KAAH,SAAGA,KAAH;AAAA,SAAeA,KAAf;AAAA,CADA,CAAf;;ACzBA,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;;ACAnC,MAAMI,KAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;;ACG5B,IAAMC,gBAAgB,GAAG,SAAnBA,gBAAmB,CAACN,IAAD,EAAOO,OAAP,EAAgBC,EAAhB;MAAgBA;AAAAA,IAAAA,KAAKC;;;AACnD,MAAMC,YAAY,GAAGb,KAAK,CAACc,MAAN,EAArB;AAEAd,EAAAA,KAAK,CAACe,SAAN,CAAgB;AACdF,IAAAA,YAAY,CAACG,OAAb,GAAuBN,OAAvB;AACD,GAFD,EAEG,CAACA,OAAD,CAFH;AAIAV,EAAAA,KAAK,CAACe,SAAN,CAAgB;AACd;AACA,QAAME,QAAQ,GAAG,SAAXA,QAAW,CAACC,CAAD;AAAA,aAAOL,YAAY,CAACG,OAAb,CAAqBE,CAArB,CAAP;AAAA,KAAjB;;AAEAP,IAAAA,EAAE,CAACQ,gBAAH,CAAoBhB,IAApB,EAA0Bc,QAA1B;AAEA,WAAO;AACLN,MAAAA,EAAE,CAACS,mBAAH,CAAuBjB,IAAvB,EAA6Bc,QAA7B;AACD,KAFD;AAGD,GATD,EASG,CAACd,IAAD,EAAOQ,EAAP,CATH;AAUD,CAjBM;;ACHA,IAAMU,WAAW,GAAG,SAAdA,WAAc,CAACC,GAAD,EAAcC,MAAd;AACzB,SAAOD,GAAG,CAACE,KAAJ,CAAU,IAAIC,MAAJ,CAAW,SAASF,MAAT,GAAkB,GAA7B,EAAkC,GAAlC,CAAV,CAAP;AACD,CAFM;;ICSMG,WAAW,GAAqB,SAAhCA,WAAgC;MAAGC,YAAAA;MAAMC,gBAAAA;MAAUC,eAAAA;;AAC9D,kBAAkCC,QAAQ,CAAS,EAAT,CAA1C;AAAA,MAAOC,SAAP;AAAA,MAAkBC,YAAlB;;AAEAjB,EAAAA,SAAS,CAAC;AACR,QAAIkB,CAAC,GAAG,CAAR;AACA,QAAMC,QAAQ,GAAGC,WAAW,CAAC;AAC3B;AAEA,UAAIF,CAAC,KAAK,CAAV,EAAa;AACX,YAAIJ,OAAJ,EAAa;AACXA,UAAAA,OAAO;AACR;AACF;;AAED,UAAII,CAAC,GAAGN,IAAI,CAACJ,MAAb,EAAqB;AACnBS,QAAAA,YAAY,CAACL,IAAI,CAACS,SAAL,CAAe,CAAf,EAAkBH,CAAC,GAAG,CAAtB,CAAD,CAAZ;AACAA,QAAAA,CAAC;AACF,OAHD,MAGO;AACLI,QAAAA,aAAa,CAACH,QAAD,CAAb;;AACA,YAAIN,QAAJ,EAAc;AACZA,UAAAA,QAAQ;AACT;AACF;AACF,KAlB2B,EAkBzB,EAlByB,CAA5B;AAoBA,WAAO;AACLS,MAAAA,aAAa,CAACH,QAAD,CAAb;AACD,KAFD;AAGD,GAzBQ,EAyBN,CAACP,IAAD,CAzBM,CAAT;AA2BA,SAAO3B,mBAAA,CAACsC,aAAD,MAAA,EAAgBP,SAAhB,CAAP;AACD,CA/BM;AAiCP,IAAMO,aAAa,gBAAGhC,MAAM,CAACiC,CAAV;AAAA;AAAA;AAAA,qGAAnB;;AC7BO,IAAMC,aAAa,GAAqB,SAAlCA,aAAkC;MAC7Cb,YAAAA;MACAc,eAAAA;MACAC,iBAAAA;MACAC,mBAAAA;AAEA,MAAMC,UAAU,GAAGvB,WAAW,CAACM,IAAD,EAAO,EAAP,CAA9B;;AAEA,kBAAoCG,QAAQ,CAAS,CAAT,CAA5C;AAAA,MAAOe,UAAP;AAAA,MAAmBC,aAAnB;;AAEA,MAAMC,kBAAkB,GAAG,SAArBA,kBAAqB,CAACC,KAAD;AACzB,QAAIA,KAAK,CAACC,IAAN,KAAe,OAAnB,EAA4B;AAC1B,UAAIL,UAAJ,YAAIA,UAAU,CAAGC,UAAU,GAAG,CAAhB,CAAd,EAAkC;AAChCC,QAAAA,aAAa,CAACD,UAAU,GAAG,CAAd,CAAb;AACD,OAFD,MAEO;AACL;AACAJ,QAAAA,OAAO;AACR;AACF;AACF,GATD;;AAWAhC,EAAAA,gBAAgB,CAAC,SAAD,EAAYsC,kBAAZ,CAAhB;AAEA,SACE/C,mBAAA,CAACK,WAAD,MAAA,EACEL,mBAAA,CAAC0B,WAAD;AACEC,IAAAA,IAAI,EAAE,CAAAiB,UAAU,QAAV,YAAAA,UAAU,CAAGC,UAAH,CAAV,KAA4B;AAClCjB,IAAAA,QAAQ,EAAEc;AACVb,IAAAA,OAAO,EAAEc;GAHX,CADF,CADF;AASD,CAhCM;AAkCP,IAAMtC,WAAS,gBAAGC,MAAM,CAACC,GAAV;AAAA;AAAA;AAAA,QAAf;;ICxCY2C,aAAZ;;AAAA,WAAYA;AACVA,EAAAA,yBAAA,aAAA;AACAA,EAAAA,iCAAA,qBAAA;AACD,CAHD,EAAYA,aAAa,KAAbA,aAAa,KAAA,CAAzB;;AAYA,IAAaC,SAAS,GAA8B,SAAvCA,SAAuC;MAClDxB,YAAAA;MACAxB,YAAAA;MACAsC,gBAAAA;MACAW,iBAAAA;;AAEA,kBAA4BtB,QAAQ,CAAU,IAAV,CAApC;AAAA,MAAOuB,MAAP;AAAA,MAAeC,SAAf;;AACA,mBACExB,QAAQ,CAAU,KAAV,CADV;AAAA,MAAOyB,mBAAP;AAAA,MAA4BC,sBAA5B;;AAGA,SAAOH,MAAM,GACXrD,mBAAA,CAACF,KAAD,MAAA,EACEE,mBAAA,CAACE,cAAD;AAAgBC,IAAAA,IAAI,EAAC;GAArB,EACEH,mBAAA,CAACK,WAAD,MAAA,EACEL,mBAAA,CAACsC,eAAD;AACEmB,IAAAA,IAAI,EAAEtD,IAAI,KAAK+C,aAAa,CAACQ,gBAAvB,GAA0C,KAA1C,GAAkD;GAD1D,EAGE1D,mBAAA,CAACwC,aAAD;AACEG,IAAAA,WAAW,EAAE;AAAA,aAAMa,sBAAsB,CAAC,KAAD,CAA5B;AAAA;AACbd,IAAAA,SAAS,EAAE;AAAA,aAAMc,sBAAsB,CAAC,IAAD,CAA5B;AAAA;AACX7B,IAAAA,IAAI,EAAEA;AACNc,IAAAA,OAAO,EAAE;AACP,UAAIA,QAAJ,EAAa;AACXA,QAAAA,QAAO;;AACPa,QAAAA,SAAS,CAAC,KAAD,CAAT;AACD;AACF;GATH,CAHF,CADF,EAgBGnD,IAAI,KAAK+C,aAAa,CAACQ,gBAAvB,IACC1D,mBAAA,CAAC2D,kBAAD,MAAA,EACE3D,mBAAA,CAAC4D,YAAD;AAAcC,IAAAA,GAAG,EAAET,SAAS,IAAIU;GAAhC,CADF,CAjBJ,CADF,EAuBGP,mBAAmB,IAClBvD,mBAAA,CAAC+D,mBAAD;AACEC,IAAAA,KAAK,EAAE7D,IAAI,KAAK+C,aAAa,CAACe,QAAvB,GAAkC,MAAlC,GAA2C;AAClDJ,IAAAA,GAAG,EAAEK;GAFP,CAxBJ,CADF,CADW,GAiCT,IAjCJ;AAkCD,CA5CM;AA8CP,IAAM7D,WAAS,gBAAGC,MAAM,CAACC,GAAV;AAAA;AAAA;AAAA,mIAAf;AAcA,IAAM+B,eAAa,gBAAGhC,MAAM,CAACC,GAAV;AAAA;AAAA;AAAA,mCACT;AAAA,MAAGkD,IAAH,SAAGA,IAAH;AAAA,SAAcA,IAAd;AAAA,CADS,CAAnB;AAKA,IAAME,kBAAkB,gBAAGrD,MAAM,CAACC,GAAV;AAAA;AAAA;AAAA,2DAAxB;AAMA,IAAMqD,YAAY,gBAAGtD,MAAM,CAACE,GAAV;AAAA;AAAA;AAAA,2DAAlB;AAUA,IAAMuD,mBAAmB,gBAAGzD,MAAM,CAACE,GAAV;AAAA;AAAA;AAAA,0GAEd;AAAA,MAAGwD,KAAH,SAAGA,KAAH;AAAA,SAAeA,KAAf;AAAA,CAFc,CAAzB;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rpg-engine/long-bow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
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"
|
|
@@ -21,21 +21,23 @@ export const NPCDialogText: React.FC<IProps> = ({
|
|
|
21
21
|
|
|
22
22
|
const [chunkIndex, setChunkIndex] = useState<number>(0);
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
const onHandleSpacePress = (event: KeyboardEvent) => {
|
|
25
25
|
if (event.code === 'Space') {
|
|
26
26
|
if (textChunks?.[chunkIndex + 1]) {
|
|
27
|
-
setChunkIndex(
|
|
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
|
+
useEventListener('keydown', onHandleSpacePress);
|
|
34
36
|
|
|
35
37
|
return (
|
|
36
38
|
<Container>
|
|
37
39
|
<DynamicText
|
|
38
|
-
text={textChunks?.[chunkIndex]
|
|
40
|
+
text={textChunks?.[chunkIndex] || ''}
|
|
39
41
|
onFinish={onEndStep}
|
|
40
42
|
onStart={onStartStep}
|
|
41
43
|
/>
|
|
@@ -1,36 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
+
};
|