@sage-rsc/talking-head-react 1.0.29 → 1.0.30
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-C_QSrujX.cjs → fbxAnimationLoader-BG4X_1Qa.cjs} +1 -1
- package/dist/{fbxAnimationLoader-Bsel7DtJ.js → fbxAnimationLoader-CO1F6v-w.js} +1 -1
- package/dist/index-BFQNNYmP.cjs +13 -0
- package/dist/{index-BvDk1TRw.js → index-V_d1NQ-5.js} +949 -953
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/CurriculumLearning.jsx +51 -30
- package/src/lib/talkinghead.mjs +1 -1
- package/dist/index-C3A1_CcE.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-BFQNNYmP.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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useRef, useEffect, forwardRef, useImperativeHandle, useCallback } from 'react';
|
|
1
|
+
import React, { useRef, useEffect, useLayoutEffect, forwardRef, useImperativeHandle, useCallback } from 'react';
|
|
2
2
|
import TalkingHeadAvatar from './TalkingHeadAvatar';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -55,6 +55,9 @@ const CurriculumLearning = forwardRef(({
|
|
|
55
55
|
const startTeachingRef = useRef(null);
|
|
56
56
|
const nextLessonRef = useRef(null);
|
|
57
57
|
const completeLessonRef = useRef(null);
|
|
58
|
+
const nextQuestionRef = useRef(null);
|
|
59
|
+
const completeCurriculumRef = useRef(null);
|
|
60
|
+
const startQuestionsRef = useRef(null);
|
|
58
61
|
|
|
59
62
|
// Update callbacks ref when they change
|
|
60
63
|
useEffect(() => {
|
|
@@ -127,7 +130,7 @@ const CurriculumLearning = forwardRef(({
|
|
|
127
130
|
let feedbackMessage = `Congratulations! You've completed this lesson`;
|
|
128
131
|
if (stateRef.current.totalQuestions > 0) {
|
|
129
132
|
feedbackMessage += ` with a score of ${stateRef.current.score} out of ${stateRef.current.totalQuestions} (${percentage}%). `;
|
|
130
|
-
|
|
133
|
+
} else {
|
|
131
134
|
feedbackMessage += `! `;
|
|
132
135
|
}
|
|
133
136
|
|
|
@@ -185,23 +188,22 @@ const CurriculumLearning = forwardRef(({
|
|
|
185
188
|
}, 1000);
|
|
186
189
|
}
|
|
187
190
|
});
|
|
188
|
-
|
|
191
|
+
} else {
|
|
189
192
|
// This is the last lesson, complete curriculum instead
|
|
190
193
|
avatarRef.current.speakText(feedbackMessage, {
|
|
191
194
|
lipsyncLang: defaultAvatarConfig.lipsyncLang,
|
|
192
195
|
onSpeechEnd: () => {
|
|
193
196
|
// Add a small delay after speech ends for natural flow
|
|
194
197
|
setTimeout(() => {
|
|
195
|
-
|
|
198
|
+
if (completeCurriculumRef.current) {
|
|
199
|
+
completeCurriculumRef.current();
|
|
200
|
+
}
|
|
196
201
|
}, 1000);
|
|
197
202
|
}
|
|
198
203
|
});
|
|
199
204
|
}
|
|
200
205
|
}
|
|
201
|
-
}, [animations.lessonComplete, curriculum,
|
|
202
|
-
|
|
203
|
-
// Assign ref immediately after function is defined
|
|
204
|
-
completeLessonRef.current = completeLesson;
|
|
206
|
+
}, [animations.lessonComplete, curriculum, defaultAvatarConfig]);
|
|
205
207
|
|
|
206
208
|
// Complete entire curriculum
|
|
207
209
|
const completeCurriculum = useCallback(() => {
|
|
@@ -211,8 +213,8 @@ const CurriculumLearning = forwardRef(({
|
|
|
211
213
|
modules: curriculum.modules.length,
|
|
212
214
|
totalLessons: curriculum.modules.reduce((sum, mod) => sum + mod.lessons.length, 0)
|
|
213
215
|
});
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
|
|
217
|
+
if (avatarRef.current) {
|
|
216
218
|
avatarRef.current.setMood("celebrating");
|
|
217
219
|
if (animations.curriculumComplete) {
|
|
218
220
|
try {
|
|
@@ -265,7 +267,7 @@ const CurriculumLearning = forwardRef(({
|
|
|
265
267
|
avatarRef.current.speakText(`Now let me ask you some questions. Here's the first one: ${firstQuestion.question}`, { lipsyncLang: defaultAvatarConfig.lipsyncLang });
|
|
266
268
|
} else if (firstQuestion.type === 'true_false') {
|
|
267
269
|
avatarRef.current.speakText(`Let's start with some true or false questions. First question: ${firstQuestion.question}`, { lipsyncLang: defaultAvatarConfig.lipsyncLang });
|
|
268
|
-
|
|
270
|
+
} else {
|
|
269
271
|
avatarRef.current.speakText(`Now let me ask you some questions. Here's the first one: ${firstQuestion.question}`, { lipsyncLang: defaultAvatarConfig.lipsyncLang });
|
|
270
272
|
}
|
|
271
273
|
} else if (avatarRef.current) {
|
|
@@ -294,14 +296,14 @@ const CurriculumLearning = forwardRef(({
|
|
|
294
296
|
}
|
|
295
297
|
|
|
296
298
|
if (avatarRef.current && nextQuestionObj) {
|
|
297
|
-
|
|
299
|
+
avatarRef.current.setMood("happy");
|
|
298
300
|
avatarRef.current.setBodyMovement("idle");
|
|
299
301
|
|
|
300
302
|
// Play custom animation if available
|
|
301
303
|
if (animations.nextQuestion) {
|
|
302
|
-
|
|
304
|
+
try {
|
|
303
305
|
avatarRef.current.playAnimation(animations.nextQuestion, true);
|
|
304
|
-
|
|
306
|
+
} catch (error) {
|
|
305
307
|
console.warn('Failed to play nextQuestion animation:', error);
|
|
306
308
|
}
|
|
307
309
|
}
|
|
@@ -364,12 +366,11 @@ const CurriculumLearning = forwardRef(({
|
|
|
364
366
|
}, 500);
|
|
365
367
|
}
|
|
366
368
|
} else {
|
|
367
|
-
|
|
369
|
+
if (completeCurriculumRef.current) {
|
|
370
|
+
completeCurriculumRef.current();
|
|
371
|
+
}
|
|
368
372
|
}
|
|
369
|
-
}, [curriculum
|
|
370
|
-
|
|
371
|
-
// Assign ref immediately after function is defined
|
|
372
|
-
nextLessonRef.current = nextLesson;
|
|
373
|
+
}, [curriculum]);
|
|
373
374
|
|
|
374
375
|
// Start teaching the lesson
|
|
375
376
|
const startTeaching = useCallback(() => {
|
|
@@ -415,7 +416,10 @@ const CurriculumLearning = forwardRef(({
|
|
|
415
416
|
setTimeout(() => {
|
|
416
417
|
stateRef.current.isTeaching = false;
|
|
417
418
|
if (currentLesson.questions && currentLesson.questions.length > 0) {
|
|
418
|
-
|
|
419
|
+
// Use ref to avoid circular dependency
|
|
420
|
+
if (startQuestionsRef.current) {
|
|
421
|
+
startQuestionsRef.current();
|
|
422
|
+
}
|
|
419
423
|
} else {
|
|
420
424
|
// No questions, complete the lesson using ref to avoid circular dependency
|
|
421
425
|
if (completeLessonRef.current) {
|
|
@@ -424,10 +428,7 @@ const CurriculumLearning = forwardRef(({
|
|
|
424
428
|
}
|
|
425
429
|
}, 8000);
|
|
426
430
|
}
|
|
427
|
-
}, [animations.teaching, getCurrentLesson,
|
|
428
|
-
|
|
429
|
-
// Assign ref immediately after function is defined
|
|
430
|
-
startTeachingRef.current = startTeaching;
|
|
431
|
+
}, [animations.teaching, getCurrentLesson, defaultAvatarConfig]);
|
|
431
432
|
|
|
432
433
|
// Handle answer selection
|
|
433
434
|
const handleAnswerSelect = useCallback((answer) => {
|
|
@@ -468,7 +469,9 @@ const CurriculumLearning = forwardRef(({
|
|
|
468
469
|
onSpeechEnd: () => {
|
|
469
470
|
// Add a small delay after speech ends for natural flow
|
|
470
471
|
setTimeout(() => {
|
|
471
|
-
|
|
472
|
+
if (nextQuestionRef.current) {
|
|
473
|
+
nextQuestionRef.current();
|
|
474
|
+
}
|
|
472
475
|
}, 500);
|
|
473
476
|
}
|
|
474
477
|
});
|
|
@@ -492,16 +495,20 @@ const CurriculumLearning = forwardRef(({
|
|
|
492
495
|
onSpeechEnd: () => {
|
|
493
496
|
// Add a small delay after speech ends for natural flow
|
|
494
497
|
setTimeout(() => {
|
|
495
|
-
|
|
498
|
+
if (nextQuestionRef.current) {
|
|
499
|
+
nextQuestionRef.current();
|
|
500
|
+
}
|
|
496
501
|
}, 500);
|
|
497
502
|
}
|
|
498
503
|
});
|
|
499
504
|
}
|
|
500
505
|
} else {
|
|
501
506
|
// If avatar not ready, move to next question immediately
|
|
502
|
-
|
|
507
|
+
if (nextQuestionRef.current) {
|
|
508
|
+
nextQuestionRef.current();
|
|
509
|
+
}
|
|
503
510
|
}
|
|
504
|
-
}, [animations.correct, animations.incorrect, getCurrentQuestion, checkAnswer,
|
|
511
|
+
}, [animations.correct, animations.incorrect, getCurrentQuestion, checkAnswer, defaultAvatarConfig]);
|
|
505
512
|
|
|
506
513
|
// Handle code test result submission
|
|
507
514
|
const handleCodeTestResult = useCallback((testResult) => {
|
|
@@ -542,8 +549,10 @@ const CurriculumLearning = forwardRef(({
|
|
|
542
549
|
});
|
|
543
550
|
|
|
544
551
|
// Handle answer using the same logic as regular questions
|
|
545
|
-
|
|
546
|
-
|
|
552
|
+
if (handleAnswerSelectRef.current) {
|
|
553
|
+
handleAnswerSelectRef.current(codeTestAnswer);
|
|
554
|
+
}
|
|
555
|
+
}, [getCurrentQuestion, checkAnswer, defaultAvatarConfig]);
|
|
547
556
|
|
|
548
557
|
// Reset curriculum
|
|
549
558
|
const resetCurriculum = useCallback(() => {
|
|
@@ -571,6 +580,18 @@ const CurriculumLearning = forwardRef(({
|
|
|
571
580
|
}
|
|
572
581
|
}, [autoStart, getCurrentLesson]);
|
|
573
582
|
|
|
583
|
+
// Set refs after all functions are defined - use useLayoutEffect for synchronous execution
|
|
584
|
+
// This ensures refs are set before React commits the render, avoiding initialization errors
|
|
585
|
+
useLayoutEffect(() => {
|
|
586
|
+
startTeachingRef.current = startTeaching;
|
|
587
|
+
nextLessonRef.current = nextLesson;
|
|
588
|
+
completeLessonRef.current = completeLesson;
|
|
589
|
+
nextQuestionRef.current = nextQuestion;
|
|
590
|
+
completeCurriculumRef.current = completeCurriculum;
|
|
591
|
+
startQuestionsRef.current = startQuestions;
|
|
592
|
+
handleAnswerSelectRef.current = handleAnswerSelect;
|
|
593
|
+
});
|
|
594
|
+
|
|
574
595
|
// Expose methods via ref (for external control)
|
|
575
596
|
useImperativeHandle(ref, () => ({
|
|
576
597
|
// Curriculum control methods
|
package/src/lib/talkinghead.mjs
CHANGED
|
@@ -3248,7 +3248,7 @@ class TalkingHead {
|
|
|
3248
3248
|
const module = LIPSYNC_MODULES[langLower];
|
|
3249
3249
|
|
|
3250
3250
|
if (module && module[className]) {
|
|
3251
|
-
|
|
3251
|
+
this.lipsync[lang] = new module[className];
|
|
3252
3252
|
console.log(`Loaded lip-sync module for ${lang}`);
|
|
3253
3253
|
} else {
|
|
3254
3254
|
console.warn(`Lip-sync module for ${lang} not found. Available modules:`, Object.keys(LIPSYNC_MODULES));
|