@sage-rsc/talking-head-react 1.0.26 → 1.0.28
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/{fbxAnimationLoader-DYwX3TQf.cjs → fbxAnimationLoader-BAdAJQ7P.cjs} +1 -1
- package/dist/{fbxAnimationLoader-BEp5N4LW.js → fbxAnimationLoader-xd44uqKF.js} +1 -1
- package/dist/index-Dx7mDKJm.cjs +13 -0
- package/dist/{index-R68Q6EcC.js → index-zMY6cyU2.js} +1407 -1377
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +92 -13
- package/dist/index-BAyfuKmk.cjs +0 -13
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./index-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("./index-Dx7mDKJm.cjs");exports.CurriculumLearning=i.CurriculumLearning;exports.TalkingHeadAvatar=i.TalkingHeadAvatar;exports.TalkingHeadComponent=i.TalkingHeadComponent;exports.animations=i.animations;exports.getActiveTTSConfig=i.getActiveTTSConfig;exports.getAnimation=i.getAnimation;exports.getVoiceOptions=i.getVoiceOptions;exports.hasAnimation=i.hasAnimation;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -51,6 +51,11 @@ const CurriculumLearning = forwardRef(({
|
|
|
51
51
|
onCustomAction
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
// Refs for functions to avoid circular dependencies
|
|
55
|
+
const startTeachingRef = useRef(null);
|
|
56
|
+
const nextLessonRef = useRef(null);
|
|
57
|
+
const completeLessonRef = useRef(null);
|
|
58
|
+
|
|
54
59
|
// Update callbacks ref when they change
|
|
55
60
|
useEffect(() => {
|
|
56
61
|
callbacksRef.current = {
|
|
@@ -111,13 +116,20 @@ const CurriculumLearning = forwardRef(({
|
|
|
111
116
|
return false;
|
|
112
117
|
}, []);
|
|
113
118
|
|
|
114
|
-
// Complete current lesson
|
|
119
|
+
// Complete current lesson - defined before it's used to avoid circular dependency
|
|
115
120
|
const completeLesson = useCallback(() => {
|
|
116
121
|
stateRef.current.lessonCompleted = true;
|
|
117
122
|
stateRef.current.isQuestionMode = false;
|
|
118
123
|
|
|
119
|
-
const percentage =
|
|
120
|
-
|
|
124
|
+
const percentage = stateRef.current.totalQuestions > 0
|
|
125
|
+
? Math.round((stateRef.current.score / stateRef.current.totalQuestions) * 100)
|
|
126
|
+
: 100;
|
|
127
|
+
let feedbackMessage = `Congratulations! You've completed this lesson`;
|
|
128
|
+
if (stateRef.current.totalQuestions > 0) {
|
|
129
|
+
feedbackMessage += ` with a score of ${stateRef.current.score} out of ${stateRef.current.totalQuestions} (${percentage}%). `;
|
|
130
|
+
} else {
|
|
131
|
+
feedbackMessage += `! `;
|
|
132
|
+
}
|
|
121
133
|
|
|
122
134
|
if (percentage >= 80) {
|
|
123
135
|
feedbackMessage += "Excellent work! You have a great understanding of this topic.";
|
|
@@ -135,6 +147,16 @@ const CurriculumLearning = forwardRef(({
|
|
|
135
147
|
percentage: percentage
|
|
136
148
|
});
|
|
137
149
|
|
|
150
|
+
// Trigger custom action for lesson completion
|
|
151
|
+
callbacksRef.current.onCustomAction({
|
|
152
|
+
type: 'lessonComplete',
|
|
153
|
+
moduleIndex: stateRef.current.currentModuleIndex,
|
|
154
|
+
lessonIndex: stateRef.current.currentLessonIndex,
|
|
155
|
+
score: stateRef.current.score,
|
|
156
|
+
totalQuestions: stateRef.current.totalQuestions,
|
|
157
|
+
percentage: percentage
|
|
158
|
+
});
|
|
159
|
+
|
|
138
160
|
if (avatarRef.current) {
|
|
139
161
|
avatarRef.current.setMood("happy");
|
|
140
162
|
if (animations.lessonComplete) {
|
|
@@ -144,9 +166,39 @@ const CurriculumLearning = forwardRef(({
|
|
|
144
166
|
avatarRef.current.playCelebration();
|
|
145
167
|
}
|
|
146
168
|
}
|
|
147
|
-
|
|
169
|
+
|
|
170
|
+
// Check if there's a next lesson available
|
|
171
|
+
const currentModule = curriculum.modules[stateRef.current.currentModuleIndex];
|
|
172
|
+
const hasNextLesson = stateRef.current.currentLessonIndex < (currentModule?.lessons?.length || 0) - 1;
|
|
173
|
+
|
|
174
|
+
if (hasNextLesson) {
|
|
175
|
+
// Wait for speech to finish, then automatically move to next lesson
|
|
176
|
+
avatarRef.current.speakText(feedbackMessage, {
|
|
177
|
+
lipsyncLang: defaultAvatarConfig.lipsyncLang,
|
|
178
|
+
onSpeechEnd: () => {
|
|
179
|
+
// Add a small delay after speech ends for natural flow
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
// Use ref to avoid circular dependency
|
|
182
|
+
if (nextLessonRef.current) {
|
|
183
|
+
nextLessonRef.current();
|
|
184
|
+
}
|
|
185
|
+
}, 1000);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
} else {
|
|
189
|
+
// This is the last lesson, complete curriculum instead
|
|
190
|
+
avatarRef.current.speakText(feedbackMessage, {
|
|
191
|
+
lipsyncLang: defaultAvatarConfig.lipsyncLang,
|
|
192
|
+
onSpeechEnd: () => {
|
|
193
|
+
// Add a small delay after speech ends for natural flow
|
|
194
|
+
setTimeout(() => {
|
|
195
|
+
completeCurriculum();
|
|
196
|
+
}, 1000);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
148
200
|
}
|
|
149
|
-
}, [animations.lessonComplete, defaultAvatarConfig]);
|
|
201
|
+
}, [animations.lessonComplete, curriculum, completeCurriculum, defaultAvatarConfig]);
|
|
150
202
|
|
|
151
203
|
// Complete entire curriculum
|
|
152
204
|
const completeCurriculum = useCallback(() => {
|
|
@@ -246,7 +298,7 @@ const CurriculumLearning = forwardRef(({
|
|
|
246
298
|
if (animations.nextQuestion) {
|
|
247
299
|
try {
|
|
248
300
|
avatarRef.current.playAnimation(animations.nextQuestion, true);
|
|
249
|
-
|
|
301
|
+
} catch (error) {
|
|
250
302
|
console.warn('Failed to play nextQuestion animation:', error);
|
|
251
303
|
}
|
|
252
304
|
}
|
|
@@ -282,16 +334,33 @@ const CurriculumLearning = forwardRef(({
|
|
|
282
334
|
stateRef.current.currentLessonIndex += 1;
|
|
283
335
|
stateRef.current.currentQuestionIndex = 0;
|
|
284
336
|
stateRef.current.lessonCompleted = false;
|
|
337
|
+
stateRef.current.isQuestionMode = false;
|
|
338
|
+
stateRef.current.isTeaching = false;
|
|
285
339
|
stateRef.current.score = 0;
|
|
286
340
|
stateRef.current.totalQuestions = 0;
|
|
287
341
|
|
|
342
|
+
// Clear current question in UI
|
|
343
|
+
callbacksRef.current.onCustomAction({
|
|
344
|
+
type: 'lessonStart',
|
|
345
|
+
moduleIndex: stateRef.current.currentModuleIndex,
|
|
346
|
+
lessonIndex: stateRef.current.currentLessonIndex
|
|
347
|
+
});
|
|
348
|
+
|
|
288
349
|
if (avatarRef.current) {
|
|
289
|
-
|
|
350
|
+
avatarRef.current.setMood("happy");
|
|
351
|
+
avatarRef.current.setBodyMovement("idle");
|
|
352
|
+
|
|
353
|
+
// Automatically start teaching the next lesson after a brief pause
|
|
354
|
+
setTimeout(() => {
|
|
355
|
+
if (startTeachingRef.current) {
|
|
356
|
+
startTeachingRef.current();
|
|
357
|
+
}
|
|
358
|
+
}, 500);
|
|
290
359
|
}
|
|
291
360
|
} else {
|
|
292
361
|
completeCurriculum();
|
|
293
362
|
}
|
|
294
|
-
}, [curriculum, completeCurriculum
|
|
363
|
+
}, [curriculum, completeCurriculum]);
|
|
295
364
|
|
|
296
365
|
// Start teaching the lesson
|
|
297
366
|
const startTeaching = useCallback(() => {
|
|
@@ -339,11 +408,14 @@ const CurriculumLearning = forwardRef(({
|
|
|
339
408
|
if (currentLesson.questions && currentLesson.questions.length > 0) {
|
|
340
409
|
startQuestions();
|
|
341
410
|
} else {
|
|
342
|
-
|
|
411
|
+
// No questions, complete the lesson using ref to avoid circular dependency
|
|
412
|
+
if (completeLessonRef.current) {
|
|
413
|
+
completeLessonRef.current();
|
|
414
|
+
}
|
|
343
415
|
}
|
|
344
416
|
}, 8000);
|
|
345
417
|
}
|
|
346
|
-
}, [animations.teaching, getCurrentLesson, startQuestions,
|
|
418
|
+
}, [animations.teaching, getCurrentLesson, startQuestions, defaultAvatarConfig]);
|
|
347
419
|
|
|
348
420
|
// Handle answer selection
|
|
349
421
|
const handleAnswerSelect = useCallback((answer) => {
|
|
@@ -365,9 +437,9 @@ const CurriculumLearning = forwardRef(({
|
|
|
365
437
|
|
|
366
438
|
if (avatarRef.current) {
|
|
367
439
|
if (isCorrect) {
|
|
368
|
-
|
|
440
|
+
avatarRef.current.setMood("happy");
|
|
369
441
|
if (animations.correct) {
|
|
370
|
-
|
|
442
|
+
try {
|
|
371
443
|
avatarRef.current.playReaction("happy");
|
|
372
444
|
} catch (error) {
|
|
373
445
|
avatarRef.current.setBodyMovement("happy");
|
|
@@ -388,7 +460,7 @@ const CurriculumLearning = forwardRef(({
|
|
|
388
460
|
}, 500);
|
|
389
461
|
}
|
|
390
462
|
});
|
|
391
|
-
|
|
463
|
+
} else {
|
|
392
464
|
avatarRef.current.setMood("sad");
|
|
393
465
|
if (animations.incorrect) {
|
|
394
466
|
try {
|
|
@@ -485,6 +557,13 @@ const CurriculumLearning = forwardRef(({
|
|
|
485
557
|
}
|
|
486
558
|
}, [autoStart, getCurrentLesson, startTeaching]);
|
|
487
559
|
|
|
560
|
+
// Update refs after all functions are defined to avoid circular dependency issues
|
|
561
|
+
useEffect(() => {
|
|
562
|
+
startTeachingRef.current = startTeaching;
|
|
563
|
+
nextLessonRef.current = nextLesson;
|
|
564
|
+
completeLessonRef.current = completeLesson;
|
|
565
|
+
}, [startTeaching, nextLesson, completeLesson]);
|
|
566
|
+
|
|
488
567
|
// Expose methods via ref (for external control)
|
|
489
568
|
useImperativeHandle(ref, () => ({
|
|
490
569
|
// Curriculum control methods
|