@charisma-ai/react
Version:
Charisma.ai chat component for React
247 lines (239 loc) • 9.44 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var React = require('react');
var React__default = _interopDefault(React);
var sdk = require('@charisma-ai/sdk');
const CharismaContext = React.createContext(undefined);
var __rest = (undefined && undefined.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
const useCharisma = ({ playthroughToken, charismaUrl, onConnect = () => { }, onReady = () => { }, onError = () => { }, isConnected = false }) => {
const [charisma, setCharisma] = React.useState();
const onConnectRef = React.useRef(onConnect);
React.useEffect(() => {
onConnectRef.current = onConnect;
}, [onConnect]);
const onReadyRef = React.useRef(onReady);
React.useEffect(() => {
onReadyRef.current = onReady;
}, [onReady]);
const onErrorRef = React.useRef(onError);
React.useEffect(() => {
onErrorRef.current = onError;
}, [onError]);
React.useEffect(() => {
if (playthroughToken) {
const newCharisma = new sdk.Charisma(playthroughToken, { charismaUrl });
newCharisma.on("connect", onConnectRef.current);
newCharisma.on("ready", onReadyRef.current);
newCharisma.on("error", onErrorRef.current);
setCharisma(newCharisma);
return () => {
newCharisma.cleanup();
};
}
return undefined;
}, [playthroughToken]);
React.useEffect(() => {
if (charisma) {
if (isConnected) {
charisma.connect();
}
else {
charisma.cleanup();
}
}
}, [isConnected, charisma]);
return charisma;
};
const Charisma = (_a) => {
var { children } = _a, props = __rest(_a, ["children"]);
const charisma = useCharisma(props);
return (React__default.createElement(CharismaContext.Provider, { value: charisma || null }, typeof children === "function" ? children(charisma) : children));
};
var __rest$1 = (undefined && undefined.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
(function (ChatMode) {
ChatMode["Tap"] = "tap";
ChatMode["Chat"] = "chat";
})(exports.ChatMode || (exports.ChatMode = {}));
const useConversation = ({ conversationId, onChangeCharacterMoods, onMessage, onStartTyping, onStopTyping, onSceneCompleted, onStart, onReply, onTap, speechConfig, stopOnSceneComplete }) => {
const charisma = React.useContext(CharismaContext);
if (charisma === undefined) {
throw new Error(`To use \`Conversation\`, you must wrap it within a \`Charisma\` instance.`);
}
const [inputValue, setInputValue] = React.useState("");
const [isTyping, setIsTyping] = React.useState(false);
const [messages, setMessages] = React.useState([]);
const [mode, setMode] = React.useState(exports.ChatMode.Chat);
const onMessageRef = React.useRef(() => { });
const onStartTypingRef = React.useRef(() => { });
const onStopTypingRef = React.useRef(() => { });
const onSceneCompletedRef = React.useRef(() => { });
const characterMoodsRef = React.useRef({});
React.useEffect(() => {
onMessageRef.current = (event) => {
setMessages([...messages, event]);
if (event.tapToContinue) {
setMode(exports.ChatMode.Tap);
}
else {
setMode(exports.ChatMode.Chat);
}
if (event.characterMoods.length > 0) {
const newCharacterMoods = Object.assign({}, characterMoodsRef.current);
event.characterMoods.forEach(({ id, mood }) => {
newCharacterMoods[id] = mood;
});
characterMoodsRef.current = newCharacterMoods;
if (onChangeCharacterMoods) {
onChangeCharacterMoods(newCharacterMoods);
}
}
if (onMessage) {
onMessage(event);
}
};
}, [onMessage, messages, onChangeCharacterMoods]);
React.useEffect(() => {
onStartTypingRef.current = (event) => {
setIsTyping(true);
if (onStartTyping) {
onStartTyping(event);
}
};
}, [onStartTyping]);
React.useEffect(() => {
onStopTypingRef.current = (event) => {
setIsTyping(false);
if (onStopTyping) {
onStopTyping(event);
}
};
}, [onStopTyping]);
React.useEffect(() => {
onSceneCompletedRef.current = (event) => {
if (onSceneCompleted) {
onSceneCompleted(event);
}
};
}, [onSceneCompleted]);
const conversationRef = React.useRef();
React.useEffect(() => {
if (conversationRef.current) {
conversationRef.current.setSpeechConfig(speechConfig);
if (typeof stopOnSceneComplete === "boolean") {
conversationRef.current.setStopOnSceneEnd(stopOnSceneComplete);
}
}
}, [speechConfig, stopOnSceneComplete]);
React.useEffect(() => {
(async function run() {
if (charisma && conversationId) {
const conversation = await charisma.joinConversation(conversationId);
conversation.on("message", event => {
onMessageRef.current(event);
});
conversation.on("start-typing", event => onStartTypingRef.current(event));
conversation.on("stop-typing", event => onStopTypingRef.current(event));
conversation.on("scene-completed", event => onSceneCompletedRef.current(event));
conversation.setSpeechConfig(speechConfig);
if (typeof stopOnSceneComplete === "boolean") {
conversation.setStopOnSceneEnd(stopOnSceneComplete);
}
conversationRef.current = conversation;
return () => {
charisma.leaveConversation(conversationId);
conversationRef.current = undefined;
};
}
return undefined;
})();
}, [charisma, conversationId]);
const onStartRef = React.useRef(onStart);
const onReplyRef = React.useRef(onReply);
const onTapRef = React.useRef(onTap);
React.useEffect(() => {
onStartRef.current = onStart;
}, [onStart]);
React.useEffect(() => {
onReplyRef.current = onReply;
}, [onReply]);
React.useEffect(() => {
onTapRef.current = onTap;
}, [onTap]);
const returnedValue = React.useMemo(() => {
return {
inputValue,
isTyping,
messages,
mode,
type: setInputValue,
start: event => {
if (onStartRef.current) {
onStartRef.current(event || {});
}
setMessages([]);
if (conversationRef.current) {
conversationRef.current.start(event);
}
},
reply: event => {
if (onReplyRef.current) {
onReplyRef.current(event);
}
setMessages([
...messages,
{
type: "player",
message: {
text: event.text
}
}
]);
setInputValue("");
if (conversationRef.current) {
conversationRef.current.reply(event);
}
},
tap: () => {
if (onTapRef.current) {
onTapRef.current();
}
if (conversationRef.current) {
conversationRef.current.tap();
}
}
};
}, [inputValue, isTyping, messages, mode]);
return returnedValue;
};
const Conversation = (_a) => {
var { children } = _a, props = __rest$1(_a, ["children"]);
const conversation = useConversation(props);
return React__default.createElement(React__default.Fragment, null, children(conversation));
};
exports.Charisma = Charisma;
exports.CharismaContext = CharismaContext;
exports.Conversation = Conversation;
exports.useCharisma = useCharisma;
exports.useConversation = useConversation;
//# sourceMappingURL=index.js.map