UNPKG

@marshal604/react-game-dialogue

Version:

A React UI library for creating dialogue systems with a game-like interface | 一個專為 React 應用開發的對話系統 UI 套件,提供類遊戲風格的對話介面

2 lines (1 loc) 8.18 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),n=require("react"),t=function(){return t=Object.assign||function(e){for(var n,t=1,o=arguments.length;t<o;t++)for(var a in n=arguments[t])Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a]);return e},t.apply(this,arguments)};"function"==typeof SuppressedError&&SuppressedError;var o=new(function(){function e(){this.loadedImages=new Set,this.loadingPromises=new Map}return e.prototype.preloadImage=function(e){var n=this;if(this.loadedImages.has(e))return Promise.resolve();if(this.loadingPromises.has(e))return this.loadingPromises.get(e);var t=function(e){return new Promise((function(n,t){if(e){var o=new Image;o.onload=function(){return n()},o.onerror=function(){return t(new Error("Failed to load image: ".concat(e)))},o.src=e}else n()}))}(e).then((function(){n.loadedImages.add(e),n.loadingPromises.delete(e)}));return this.loadingPromises.set(e,t),t},e.prototype.preloadImages=function(e){var n=this,t=e.filter((function(e){return!!e}));return Promise.all(t.map((function(e){return n.preloadImage(e)})))},e.prototype.isImageLoaded=function(e){return this.loadedImages.has(e)},e.prototype.clearCache=function(){this.loadedImages.clear()},e}()),a=n.createContext({scene:null,item:null,character:null,background:null,handleNext:function(){},handleChoiceSelect:function(){},handleTypingComplete:function(){}}),r=function(r){var i=r.children,c=r.dialogue,s=r.characters,u=r.startScene,l=r.onMessageStart,d=r.onMessageEnd,f=r.onSceneEnd,m=r.onAllDialogueEnd,g=n.useState(null),h=g[0],p=g[1],x=n.useState(0),v=x[0],_=x[1],C=n.useState(!1),b=C[0],y=C[1],k=n.useMemo((function(){return h&&c[h]?c[h]:null}),[h,c]),j=n.useMemo((function(){return!k||!k.sequence||v>=k.sequence.length?null:k.sequence[v]}),[k,v]),S=n.useMemo((function(){return j&&j.speaker&&s[j.speaker]?s[j.speaker]:null}),[j,s]),E=n.useMemo((function(){return k&&(j&&j.background||k.background)||null}),[k,j]),N=n.useCallback((function(e,n){!function(e,n,t){var a=n[e];if(a){var r=[];a.background&&r.push(a.background),a.sequence.forEach((function(e){if(e.background&&r.push(e.background),e.speaker&&t[e.speaker]){var n=t[e.speaker],o=e.emotion||"default";n.images[o]&&r.push(n.images[o]),"default"!==o&&n.images.default&&r.push(n.images.default)}})),a.sequence.forEach((function(e){if(e.next&&n[e.next]){var t=n[e.next];t.background&&r.push(t.background)}e.choices&&e.choices.forEach((function(e){if(e.next&&n[e.next]){var t=n[e.next];t.background&&r.push(t.background)}}))})),o.preloadImages(r).catch((function(e){return console.error("Failed to preload images:",e)}))}}(e,c,s),p(e),_(n),y(!1);var t=c[e];t&&t.sequence&&t.sequence[n]&&l&&l(t.sequence[n])}),[c,s,l]),D=n.useCallback((function(){y(!0),j&&d&&d(j)}),[j,d]),I=n.useCallback((function(){k&&j&&(b?j.choices||(v<k.sequence.length-1?N(h,v+1):(f&&f(j),j.next?N(j.next,0):(p(null),_(0),y(!1),m&&m()))):D())}),[h,v,k,j,b,D,N,f,m]),M=n.useCallback((function(e){e?N(e,0):N(h,v+1)}),[N,h,v]);return n.useEffect((function(){u&&N(u,0)}),[u,c,N]),e.jsx(a.Provider,t({value:{scene:k,item:j,character:S,background:E,handleNext:I,handleChoiceSelect:M,handleTypingComplete:D}},{children:i}))},i="Character-module_character__WMx3-",c="Character-module_characterEnter__x7Q7O",s="Character-module_characterExit__yGDp3",u=function(o){var a=o.config,r=o.emotion,u=void 0===r?"default":r,l=o.position,d=void 0===l?"center":l,f=o.active,m=void 0===f||f,g=n.useMemo((function(){return a.images[u]||a.images.default}),[a.images,u]),h=n.useMemo((function(){switch(d){case"left":return{left:"var(--dialogic-character-side-margin, 1rem)",right:"auto",transform:"translateX(0)"};case"right":return{left:"auto",right:"var(--dialogic-character-side-margin, 1rem)",transform:"translateX(0)"};default:return{left:"0",right:"0",margin:"auto"}}}),[d]),p=m?"opacity-100":"opacity-50",x=m?c:s;return e.jsx("div",t({className:"".concat(i," ").concat(p," ").concat(x," pointer-events-auto"),style:t({position:"absolute",height:"center"===d?"auto":"100%",display:"flex",alignItems:"flex-end"},h)},{children:e.jsx("img",{src:g,alt:a.name,className:"center"===d?"w-full h-auto object-contain":void 0})}))};var l="DialogBox-module_dialogBox__--CNd",d="DialogBox-module_characterName__6UKbn",f="DialogBox-module_dialogText__APDO3",m="DialogBox-module_continueIndicator__ZJppK",g=function(o){var a=o.name,r=o.text,i=o.textColor,c=o.isTyping,s=void 0===c||c,u=o.typingSpeed,g=o.onTypingComplete,h=o.onNext,p=function(e,t){void 0===t&&(t={});var o=t.speed,a=void 0===o?30:o,r=t.startTyping,i=void 0===r||r,c=t.onComplete,s=t.punctuationDelay,u=void 0===s?{",":150,".":300,"!":300,"?":300,";":200,":":200}:s,l=n.useState(""),d=l[0],f=l[1],m=n.useState(!1),g=m[0],h=m[1],p=n.useState(0),x=p[0],v=p[1],_=n.useCallback((function(){f(e),v(e.length),h(!0),null==c||c()}),[e,c]);n.useEffect((function(){if(i&&!g){if(0===e.length)return h(!0),void(null==c||c());if(x>=e.length)return h(!0),void(null==c||c());var n=e[x],t=u[n]||a,o=setTimeout((function(){f(e.substring(0,x+1)),v((function(e){return e+1}))}),t);return function(){return clearTimeout(o)}}}),[e,x,a,i,g,c,u]);var C=n.useCallback((function(){f(""),v(0),h(!1)}),[]);return n.useEffect((function(){C()}),[e,C]),{displayText:d,isComplete:g,complete:_,reset:C}}(r,{speed:u||40,startTyping:s,onComplete:g}),x=p.displayText,v=p.isComplete,_=p.complete;n.useEffect((function(){s||_()}),[s,_]);var C=function(){v?null==h||h():_()};return e.jsxs("div",t({className:l,onClick:C,onKeyDown:function(e){"Enter"!==e.key&&" "!==e.key||C()},tabIndex:0,role:"button","aria-label":"繼續對話"},{children:[a&&e.jsx("div",t({className:d,style:i?{color:i}:void 0},{children:a})),e.jsx("div",t({className:f},{children:x})),v&&e.jsx("div",t({className:m},{children:"▼"}))]}))},h="ChoiceMenu-module_choices__uaEql",p="ChoiceMenu-module_choiceItem__4I3Fk",x=function(n){var o=n.choices,a=n.onSelect;return e.jsx("div",t({className:h},{children:o.map((function(n,o){return e.jsxs("button",t({className:p,onClick:function(){return a(n.next)}},{children:[n.icon&&e.jsx("span",t({className:"mr-2"},{children:n.icon})),e.jsx("span",{children:n.text})]}),"choice-".concat(o))}))}))},v="DialogicContainer-module_container__excEe",_="DialogicContainer-module_charactersContainer__JyNka",C="DialogicContainer-module_dialogArea__0hEYq",b="DialogicContainer-module_background__KDi75",y=function(o){var a=o.src,r=o.color,i=void 0===r?"transparent":r,c=o.transitionDuration,s=void 0===c?500:c,u=n.useState(a),l=u[0],d=u[1],f=n.useState(void 0),m=f[0],g=f[1],h=n.useState(!1),p=h[0],x=h[1];n.useEffect((function(){if(a!==l){g(l),d(a),x(!0);var e=setTimeout((function(){x(!1),g(void 0)}),s);return function(){return clearTimeout(e)}}}),[a,l,s]);var v=function(e){return{position:"absolute",inset:0,backgroundImage:e?"url(".concat(e,")"):"none",backgroundColor:e?void 0:i,backgroundSize:"cover",backgroundPosition:"center",transition:"opacity ".concat(s,"ms ease-in-out"),zIndex:-1}};return e.jsxs(e.Fragment,{children:[e.jsx("div",{className:b,style:t(t({},v(l)),{opacity:1})}),p&&m&&e.jsx("div",{className:b,style:t(t({},v(m)),{opacity:0})})]})},k=function(){var o=n.useContext(a),r=o.scene,i=o.item,c=o.character,s=o.background,l=o.handleNext,d=o.handleChoiceSelect,f=o.handleTypingComplete;if(!r||!i)return null;return e.jsxs("div",t({className:"".concat(v," flex flex-col"),style:{userSelect:"none"}},{children:[e.jsx(y,{src:s||void 0}),e.jsx("div",t({className:_},{children:c&&e.jsx(u,{config:c,emotion:i.emotion,position:i.position||c.defaultPosition,active:!0})})),i.choices&&e.jsx(x,{choices:i.choices,onSelect:d}),e.jsx("div",t({className:C},{children:e.jsx("div",t({className:"w-full max-w-5xl mx-auto px-4 mb-4"},{children:e.jsx(g,{name:null==c?void 0:c.name,text:i.text,textColor:null==c?void 0:c.textColor,onNext:function(){l()},onTypingComplete:f})}))}))]}))};exports.ReactGameDialogue=function(n){var o=n.characters,a=n.dialogue,i=n.startScene,c=n.onMessageStart,s=n.onMessageEnd,u=n.onSceneEnd,l=n.onAllDialogueEnd;return e.jsx(r,t({characters:o,dialogue:a,startScene:i,onMessageStart:c,onMessageEnd:s,onSceneEnd:u,onAllDialogueEnd:l},{children:e.jsx(k,{})}))};