@nualang/nualang-ui-components 0.1.1410 → 0.1.1412

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.
Files changed (39) hide show
  1. package/dist/Assignments/AssignmentCard/AssignmentCard.js +1 -1
  2. package/dist/Cards/FeedbackCard/FeedbackCard.js +1 -1
  3. package/dist/Dialogs/BotPreview/BotPreview.js +1 -1
  4. package/dist/Dialogs/InviteDialog/InviteDialog.js +2 -2
  5. package/dist/Dialogs/QuickCreateClassroomDialog/QuickCreateClassroomDialog.js +2 -2
  6. package/dist/Dialogs/QuickCreateCourseDialog/QuickCreateCourseDialog.js +2 -2
  7. package/dist/Dialogs/QuickCreateTopicDialog/QuickCreateTopicDialog.js +2 -2
  8. package/dist/Editors/Bot/Bot.js +16 -21
  9. package/dist/Editors/Bot/Editor/Editor.js +2 -2
  10. package/dist/Editors/Roleplay/Roleplay.js +16 -11
  11. package/dist/Exercises/Bot/Bot.js +12 -8
  12. package/dist/Exercises/ListenAndSpeak/ListenAndSpeak.js +12 -20
  13. package/dist/Exercises/Listener/Listener.js +15 -22
  14. package/dist/Exercises/Meaning/Meaning.js +12 -8
  15. package/dist/Exercises/MeaningReadWrite/MeaningReadWriteGame.js +17 -20
  16. package/dist/Exercises/Pronouncer/Pronouncer.js +13 -8
  17. package/dist/Exercises/Roleplay/OriginalRoleplay.js +6 -3
  18. package/dist/Exercises/Roleplay/Roleplay.js +1 -0
  19. package/dist/Exercises/Translator/Translator.js +14 -8
  20. package/dist/Forms/ChipInput/ChipInput.js +17 -3
  21. package/dist/Forms/CreateClassroom/Steps/ClassroomSettings/ClassroomSettings.js +4 -1
  22. package/dist/Forms/FeedbackForm/FeedbackForm.js +2 -2
  23. package/dist/Forms/ImageSelector/ImageSelector.js +3 -3
  24. package/dist/Forms/PdfUploader/PdfUploader.js +2 -2
  25. package/dist/Forms/Settings/Settings.js +1 -1
  26. package/dist/Forms/UpdateClassroom/UpdateClassroom.js +3 -1
  27. package/dist/Lists/Courses/Courses.js +97 -7
  28. package/dist/Lists/Courses/Courses.test.js +61 -11
  29. package/dist/Live/Game/Game.js +12 -8
  30. package/dist/Live/GameMembers/GameMembers.js +3 -3
  31. package/dist/Live/GameSettings/GameSettings.js +1 -1
  32. package/dist/Live/HowToJoin/HowToJoin.js +28 -11
  33. package/dist/Live/LiveListener/LiveListener.js +1 -4
  34. package/dist/Misc/ImageLibrary/ImageLibrary.js +3 -3
  35. package/dist/Navigation/ResponsiveTabs/ResponsiveTabs.js +29 -15
  36. package/dist/hooks/useConfirm.js +1 -1
  37. package/dist/utils/courseSort.js +64 -0
  38. package/dist/utils/joyride.js +127 -0
  39. package/package.json +1 -1
@@ -167,7 +167,7 @@ export default function AssignmentCard({
167
167
  borderRadius: 1,
168
168
  fontWeight: "bold"
169
169
  },
170
- children: t("NEW")
170
+ children: t("new")
171
171
  })]
172
172
  })
173
173
  }), /*#__PURE__*/_jsx(Grid, {
@@ -514,7 +514,7 @@ export default function FeedbackCard({
514
514
  setHasBeenEdited(true);
515
515
  setIsSubmitted(false);
516
516
  },
517
- placeholder: t("Write your feedback here")
517
+ placeholder: t("write_your_feedback_here")
518
518
  })
519
519
  })]
520
520
  })
@@ -237,7 +237,7 @@ function BotPreview({
237
237
  textAlign: "center",
238
238
  mb: 1
239
239
  },
240
- children: t("Preview")
240
+ children: t("preview")
241
241
  }), bot && bot.picture && /*#__PURE__*/_jsx(Box, {
242
242
  sx: {
243
243
  textAlign: "center"
@@ -200,11 +200,11 @@ function InviteDialog({
200
200
  return /*#__PURE__*/_jsx(ResponsiveDialog, {
201
201
  open: open,
202
202
  handleClose: handleClose,
203
- dialogTitle: t("Invite Students"),
203
+ dialogTitle: t("invite_students"),
204
204
  handleSubmit: isWaysideClassroom ? () => {
205
205
  window.open(learningSiteURL, "wayside-window");
206
206
  } : null,
207
- submitText: isWaysideClassroom ? t("Visit Learning Site") : null,
207
+ submitText: isWaysideClassroom ? t("visit_learning_site") : null,
208
208
  children: isWaysideClassroom ? /*#__PURE__*/_jsx(_Fragment, {
209
209
  children: /*#__PURE__*/_jsxs(DialogContentText, {
210
210
  sx: {
@@ -133,7 +133,7 @@ export default function QuickCreateClassroomDialog({
133
133
  return String(Math.floor(Math.random() * 90000) + 10000);
134
134
  };
135
135
  const handleSubmit = async () => {
136
- if (!classroomName.trim() || !classroomDescription.trim()) return;
136
+ if (!classroomName.trim() || !classroomDescription.trim() || !classroomLearnLang || !classroomForLang) return;
137
137
  setIsLoading(true);
138
138
  try {
139
139
  const createdClassroom = await handleCreate({
@@ -187,7 +187,7 @@ export default function QuickCreateClassroomDialog({
187
187
  handleClose: isLoading ? undefined : resetAndClose,
188
188
  handleSubmit: handleSubmit,
189
189
  dialogTitle: t("create_classroom") || "Create Classroom",
190
- isSubmitDisabled: !classroomName.trim() || !classroomDescription.trim() || isLoading,
190
+ isSubmitDisabled: !classroomName.trim() || !classroomDescription.trim() || !classroomLearnLang || !classroomForLang || isLoading,
191
191
  closeText: t("cancel") || "Cancel",
192
192
  submitText: t("create") || "Create",
193
193
  PaperComponent: ClassroomDialogPaper,
@@ -133,7 +133,7 @@ export default function QuickCreateCourseDialog({
133
133
  return String(Math.floor(Math.random() * 90000) + 10000);
134
134
  };
135
135
  const handleSubmit = async () => {
136
- if (!courseName.trim() || !courseDescription.trim() || !difficulty) return;
136
+ if (!courseName.trim() || !courseDescription.trim() || !difficulty || !courseLearnLang || !courseForLang) return;
137
137
  setIsLoading(true);
138
138
  try {
139
139
  const createdCourse = await handleCreate({
@@ -185,7 +185,7 @@ export default function QuickCreateCourseDialog({
185
185
  handleClose: isLoading ? undefined : resetAndClose,
186
186
  handleSubmit: handleSubmit,
187
187
  dialogTitle: t("create_course") || "Create Course",
188
- isSubmitDisabled: !courseName.trim() || !difficulty || isLoading,
188
+ isSubmitDisabled: !courseName.trim() || !courseDescription.trim() || !difficulty || !courseLearnLang || !courseForLang || isLoading,
189
189
  closeText: t("cancel") || "Cancel",
190
190
  submitText: t("create") || "Create",
191
191
  PaperComponent: CourseDialogPaper,
@@ -142,7 +142,7 @@ export default function QuickCreateTopicDialog({
142
142
  setPicture(inheritCourseImage ? coursePicture : "");
143
143
  };
144
144
  const handleSubmit = async () => {
145
- if (!topicName.trim() || !topicDifficulty) return;
145
+ if (!topicName.trim() || !topicDifficulty || !learnLang || !forLang) return;
146
146
  setIsLoading(true);
147
147
  try {
148
148
  const createdTopic = await handleCreate({
@@ -190,7 +190,7 @@ export default function QuickCreateTopicDialog({
190
190
  handleClose: isLoading ? undefined : resetAndClose,
191
191
  handleSubmit: handleSubmit,
192
192
  dialogTitle: t("create_topic") || "Create Topic",
193
- isSubmitDisabled: !topicName.trim() || !topicDifficulty || isLoading,
193
+ isSubmitDisabled: !topicName.trim() || !topicDifficulty || !learnLang || !forLang || isLoading,
194
194
  closeText: t("cancel") || "Cancel",
195
195
  submitText: t("create") || "Create",
196
196
  PaperComponent: TopicDialogPaper,
@@ -26,6 +26,7 @@ import Editor from "./Editor/Editor";
26
26
 
27
27
  // utils
28
28
  import { jsonToRivescript, rivescriptToJson } from "../../utils/index";
29
+ import { startJoyrideWhenReady } from "../../utils/joyride";
29
30
  import useDebounce from "../../hooks/useDebounce";
30
31
  import useRecognition from "../../hooks/useRecognition";
31
32
  import { botErrorMessage } from "../../utils/constants";
@@ -217,16 +218,6 @@ function Bot({
217
218
  }),
218
219
  spotlightPadding: 8,
219
220
  target: "#editorSidebar"
220
- }, {
221
- content: /*#__PURE__*/_jsxs("div", {
222
- children: [/*#__PURE__*/_jsx("h2", {
223
- children: t("bot_editor_flow_chart")
224
- }), /*#__PURE__*/_jsx("br", {}), /*#__PURE__*/_jsx("p", {
225
- children: t("bot_editor_flow_chart_desc")
226
- })]
227
- }),
228
- spotlightPadding: 8,
229
- target: "#editorFlowChart"
230
221
  }, {
231
222
  content: /*#__PURE__*/_jsx("h2", {
232
223
  children: t("bot_editor_share")
@@ -260,10 +251,11 @@ function Bot({
260
251
  };
261
252
  useEffect(() => {
262
253
  if (open && !localStorage.getItem("bot-editor-tour-completed")) {
263
- setJoyrideState(prevState => ({
254
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
264
255
  ...prevState,
265
- run: true
266
- }));
256
+ run: true,
257
+ steps
258
+ })));
267
259
  }
268
260
  }, [open]);
269
261
  useEffect(() => {
@@ -303,10 +295,11 @@ function Bot({
303
295
  }));
304
296
  }
305
297
  if (tabValue === 0 && !localStorage.getItem(`bot-editor-tour-completed`)) {
306
- setJoyrideState(prevState => ({
298
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
307
299
  ...prevState,
308
- run: true
309
- }));
300
+ run: true,
301
+ steps
302
+ })));
310
303
  }
311
304
  }, [tabValue]);
312
305
  const handleChangeTab = (event, newValue) => {
@@ -670,13 +663,14 @@ function Bot({
670
663
  }), /*#__PURE__*/_jsx("div", {
671
664
  className: "grow-1"
672
665
  }), /*#__PURE__*/_jsx(Tooltip, {
673
- title: t("Rewatch tutorial"),
666
+ title: t("rewatch_tutorial"),
674
667
  children: /*#__PURE__*/_jsx(IconButton, {
675
668
  color: "inherit",
676
- onClick: () => setJoyrideState({
677
- ...joyrideState,
678
- run: true
679
- }),
669
+ onClick: () => startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
670
+ ...prevState,
671
+ run: true,
672
+ steps
673
+ }))),
680
674
  size: "large",
681
675
  children: /*#__PURE__*/_jsx(LightbulbIcon, {})
682
676
  })
@@ -825,6 +819,7 @@ function Bot({
825
819
  close: t("close"),
826
820
  last: t("last"),
827
821
  next: t("next"),
822
+ nextWithProgress: t("next_with_progress"),
828
823
  skip: t("skip")
829
824
  },
830
825
  options: {
@@ -475,7 +475,7 @@ function Editor({
475
475
  width: "100%"
476
476
  },
477
477
  children: [/*#__PURE__*/_jsx(Tooltip, {
478
- title: isDisabled ? t("Please select a textfield") : t("formatting_options"),
478
+ title: isDisabled ? t("please_select_a_textfield") : t("formatting_options"),
479
479
  children: /*#__PURE__*/_jsx("span", {
480
480
  children: /*#__PURE__*/_jsx(IconButton, {
481
481
  color: "inherit",
@@ -489,7 +489,7 @@ function Editor({
489
489
  })
490
490
  })
491
491
  }), /*#__PURE__*/_jsx(Tooltip, {
492
- title: isDisabled ? t("Please select a textfield") : t("insert_link"),
492
+ title: isDisabled ? t("please_select_a_textfield") : t("insert_link"),
493
493
  children: /*#__PURE__*/_jsx("span", {
494
494
  children: /*#__PURE__*/_jsx(IconButton, {
495
495
  color: "inherit",
@@ -26,6 +26,7 @@ import useExerciseState from "../../hooks/useExerciseState";
26
26
  import useConfirm from "../../hooks/useConfirm";
27
27
  import { handleScriptDownload } from "../../hooks/handleScriptDownload";
28
28
  import { formatMarkdownNewlines } from "../../utils";
29
+ import { startJoyrideWhenReady } from "../../utils/joyride";
29
30
  import DefaultButton from "../../Misc/DefaultColourButton/DefaultColourButton";
30
31
  import { removeExtraWhiteSpaces } from "../../utils/index";
31
32
  import GenerateQuestion from "../../Dialogs/GenerateQuestion/GenerateQuestion";
@@ -388,18 +389,20 @@ function Roleplay({
388
389
  }));
389
390
  }
390
391
  if (tabValue === 0 && !localStorage.getItem(`roleplay-editor-tour-completed`)) {
391
- setJoyrideState(prevState => ({
392
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
392
393
  ...prevState,
393
- run: true
394
- }));
394
+ run: true,
395
+ steps
396
+ })));
395
397
  }
396
398
  }, [tabValue]);
397
399
  useEffect(() => {
398
400
  if (open && !localStorage.getItem(`roleplay-editor-tour-completed`)) {
399
- setJoyrideState(prevState => ({
401
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
400
402
  ...prevState,
401
- run: true
402
- }));
403
+ run: true,
404
+ steps
405
+ })));
403
406
  }
404
407
  }, [open]);
405
408
 
@@ -719,13 +722,14 @@ function Roleplay({
719
722
  },
720
723
  children: roleplay.roleplayName
721
724
  }), /*#__PURE__*/_jsx(Tooltip, {
722
- title: t("Rewatch tutorial"),
725
+ title: t("rewatch_tutorial"),
723
726
  children: /*#__PURE__*/_jsx(IconButton, {
724
727
  color: "inherit",
725
- onClick: () => setJoyrideState({
726
- ...joyrideState,
727
- run: true
728
- }),
728
+ onClick: () => startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
729
+ ...prevState,
730
+ run: true,
731
+ steps
732
+ }))),
729
733
  size: "large",
730
734
  children: /*#__PURE__*/_jsx(LightbulbIcon, {})
731
735
  })
@@ -937,6 +941,7 @@ function Roleplay({
937
941
  close: t("close"),
938
942
  last: t("last"),
939
943
  next: t("next"),
944
+ nextWithProgress: t("next_with_progress"),
940
945
  skip: t("skip")
941
946
  },
942
947
  options: {
@@ -21,6 +21,7 @@ import useExerciseState from "../../hooks/useExerciseState";
21
21
  import VoiceSpeedSelector from "../../Misc/VoiceSpeed/VoiceSpeed";
22
22
  import ReportProblem from "../../Misc/ReportProblem/ReportProblem";
23
23
  import NualaSignInImage from "../../img/nuala_sign_in.svg";
24
+ import { startJoyrideWhenReady } from "../../utils/joyride";
24
25
  import { useTheme } from "@mui/material/styles";
25
26
  import config from "../../config";
26
27
  import { useNavigate } from "react-router";
@@ -393,10 +394,11 @@ function Bot({
393
394
  }, [currentPhrase, bot, isSpeaking]);
394
395
  useEffect(() => {
395
396
  if (open && !run && !localStorage.getItem(`bot-exercise-tour-completed`)) {
396
- setJoyrideState(prevState => ({
397
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
397
398
  ...prevState,
398
- run: true
399
- }));
399
+ run: true,
400
+ steps
401
+ })));
400
402
  } else {
401
403
  if (open && !joyrideRewatched && !run && bot.studentInstructions && bot.studentInstructions !== "") {
402
404
  handleClickOpenInstructions();
@@ -424,15 +426,16 @@ function Bot({
424
426
 
425
427
  const topBarActions = /*#__PURE__*/_jsxs(_Fragment, {
426
428
  children: [/*#__PURE__*/_jsx(Tooltip, {
427
- title: t("Rewatch tutorial"),
429
+ title: t("rewatch_tutorial"),
428
430
  children: /*#__PURE__*/_jsx(IconButton, {
429
431
  color: "inherit",
430
432
  onClick: () => {
431
433
  setJoyrideRewatched(true);
432
- setJoyrideState({
433
- ...joyrideState,
434
- run: true
435
- });
434
+ startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
435
+ ...prevState,
436
+ run: true,
437
+ steps
438
+ })));
436
439
  },
437
440
  size: "large",
438
441
  children: /*#__PURE__*/_jsx(LightbulbIcon, {})
@@ -698,6 +701,7 @@ function Bot({
698
701
  close: t("close"),
699
702
  last: t("last"),
700
703
  next: t("next"),
704
+ nextWithProgress: t("next_with_progress"),
701
705
  skip: t("skip")
702
706
  },
703
707
  options: {
@@ -22,12 +22,11 @@ import ExerciseBottomBar from "../../Misc/ExerciseBottomBar/ExerciseBottomBar";
22
22
  import useExerciseState from "../../hooks/useExerciseState";
23
23
  import useExerciseDocumentTitle from "../../hooks/useExerciseDocumentTitle";
24
24
  import useRecognition from "../../hooks/useRecognition";
25
- import MoreHorizIcon from "@mui/icons-material/MoreHoriz";
26
25
  import VoiceSpeedSelector from "../../Misc/VoiceSpeed/VoiceSpeed";
27
26
  import ReportProblem from "../../Misc/ReportProblem/ReportProblem";
28
- import ChatBubble from "../../Misc/ChatBubble/ChatBubble";
29
27
  import WaveFormLite from "../../Misc/WaveFormLite/WaveFormLite";
30
28
  import { removeExtraWhiteSpaces, removeAllSymbols } from "../../utils";
29
+ import { startJoyrideWhenReady } from "../../utils/joyride";
31
30
  import getVoiceImages from "../../utils/voiceImages";
32
31
  import { useNavigate } from "react-router";
33
32
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -340,16 +339,6 @@ function ListenAndSpeak({
340
339
  }),
341
340
  placement: "center",
342
341
  target: "body"
343
- }, {
344
- content: /*#__PURE__*/_jsxs("div", {
345
- children: [/*#__PURE__*/_jsx("h2", {
346
- children: t("pronunciation_exercise_speak")
347
- }), /*#__PURE__*/_jsx("br", {}), /*#__PURE__*/_jsx("p", {
348
- children: t("listen_and_speak_exercise_speak_desc")
349
- })]
350
- }),
351
- spotlightPadding: 8,
352
- target: "#speakButton"
353
342
  }, {
354
343
  content: /*#__PURE__*/_jsx("div", {
355
344
  children: /*#__PURE__*/_jsx("h2", {
@@ -429,10 +418,11 @@ function ListenAndSpeak({
429
418
  }, [isSpeaking, isSocketConnected]);
430
419
  useEffect(() => {
431
420
  if (open && !localStorage.getItem(`meaning-listen-and-speak-exercise-tour-completed`)) {
432
- setJoyrideState(prevState => ({
421
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
433
422
  ...prevState,
434
- run: true
435
- }));
423
+ run: true,
424
+ steps
425
+ })));
436
426
  } else if (open && !run && !joyrideRewatched && localStorage.getItem(`meaning-listen-and-speak-exercise-tour-completed`)) {
437
427
  handlePronunciationTourFinished();
438
428
  }
@@ -524,15 +514,16 @@ function ListenAndSpeak({
524
514
  children: t("meaning")
525
515
  })
526
516
  }), /*#__PURE__*/_jsx(Tooltip, {
527
- title: t("Rewatch tutorial"),
517
+ title: t("rewatch_tutorial"),
528
518
  children: /*#__PURE__*/_jsx(IconButton, {
529
519
  color: "inherit",
530
520
  onClick: () => {
531
521
  setJoyrideRewatched(true);
532
- setJoyrideState({
533
- ...joyrideState,
534
- run: true
535
- });
522
+ startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
523
+ ...prevState,
524
+ run: true,
525
+ steps
526
+ })));
536
527
  },
537
528
  size: "large",
538
529
  children: /*#__PURE__*/_jsx(LightbulbIcon, {})
@@ -950,6 +941,7 @@ function ListenAndSpeak({
950
941
  close: t("close"),
951
942
  last: t("last"),
952
943
  next: t("next"),
944
+ nextWithProgress: t("next_with_progress"),
953
945
  skip: t("skip")
954
946
  },
955
947
  options: {
@@ -30,6 +30,7 @@ import { Sortable, SortableGridDndContextWrapper } from "../../utils/dragAndDrop
30
30
 
31
31
  // utils
32
32
  import { capitalize, removeExtraWhiteSpaces } from "../../utils/index";
33
+ import { startJoyrideWhenReady } from "../../utils/joyride";
33
34
  import useWordBankFocus from "../../hooks/useWordBankFocus";
34
35
  import getVoiceImages from "../../utils/voiceImages";
35
36
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
@@ -379,16 +380,6 @@ function Listener({
379
380
  }),
380
381
  spotlightPadding: 8,
381
382
  target: "#speakButton"
382
- }, {
383
- content: /*#__PURE__*/_jsxs("div", {
384
- children: [/*#__PURE__*/_jsx("h2", {
385
- children: t("listening_exercise_voice_options")
386
- }), /*#__PURE__*/_jsx("br", {}), /*#__PURE__*/_jsx("p", {
387
- children: t("listening_exercise_voice_options_desc")
388
- })]
389
- }),
390
- spotlightPadding: 8,
391
- target: "#voiceOptions"
392
383
  }, {
393
384
  content: /*#__PURE__*/_jsxs("div", {
394
385
  children: [/*#__PURE__*/_jsx("h2", {
@@ -480,10 +471,11 @@ function Listener({
480
471
  }, [useWordBank]);
481
472
  useEffect(() => {
482
473
  if (open && !run && !localStorage.getItem(`listening-exercise-tour-completed`)) {
483
- setJoyrideState(prevState => ({
474
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
484
475
  ...prevState,
485
- run: true
486
- }));
476
+ run: true,
477
+ steps
478
+ })));
487
479
  } else if (open && !run && !joyrideRewatched && localStorage.getItem(`listening-exercise-tour-completed`)) {
488
480
  handleListeningTourFinished();
489
481
  setTimeout(() => setWordBankTooltipOpen(true), 1000);
@@ -586,15 +578,16 @@ function Listener({
586
578
  },
587
579
  children: t("listening")
588
580
  }), /*#__PURE__*/_jsx(Tooltip, {
589
- title: t("Rewatch tutorial"),
581
+ title: t("rewatch_tutorial"),
590
582
  children: /*#__PURE__*/_jsx(IconButton, {
591
583
  color: "inherit",
592
584
  onClick: () => {
593
585
  setJoyrideRewatched(true);
594
- setJoyrideState({
595
- ...joyrideState,
596
- run: true
597
- });
586
+ startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
587
+ ...prevState,
588
+ run: true,
589
+ steps
590
+ })));
598
591
  },
599
592
  size: "large",
600
593
  children: /*#__PURE__*/_jsx(LightbulbIcon, {})
@@ -735,6 +728,7 @@ function Listener({
735
728
  marginLeft: 1
736
729
  },
737
730
  children: learnLang !== "irish" && /*#__PURE__*/_jsx(Box, {
731
+ id: "speakButton",
738
732
  sx: theme => ({
739
733
  [theme.breakpoints.down("md")]: {
740
734
  minWidth: 185
@@ -886,6 +880,7 @@ function Listener({
886
880
  })
887
881
  })
888
882
  }), isWordBankEnabled && /*#__PURE__*/_jsx(Grid, {
883
+ id: "useWordBank",
889
884
  children: /*#__PURE__*/_jsx(Tooltip, {
890
885
  title: t("use_wordbank_if_stuck"),
891
886
  enterDelay: 500,
@@ -909,10 +904,7 @@ function Listener({
909
904
  run: false
910
905
  }));
911
906
  },
912
- startIcon: /*#__PURE__*/_jsx(Bank, {})
913
- // Commented out to fix lint warning - jsx-no-duplicate-props
914
- // id="useWordBank"
915
- ,
907
+ startIcon: /*#__PURE__*/_jsx(Bank, {}),
916
908
  children: t("use_word_bank")
917
909
  })
918
910
  })
@@ -1010,6 +1002,7 @@ function Listener({
1010
1002
  close: t("close"),
1011
1003
  last: t("last"),
1012
1004
  next: t("next"),
1005
+ nextWithProgress: t("next_with_progress"),
1013
1006
  skip: t("skip")
1014
1007
  },
1015
1008
  options: {
@@ -26,6 +26,7 @@ import { useTheme } from "@mui/material/styles";
26
26
  import getVoiceImages from "../../utils/voiceImages";
27
27
  import { useNavigate } from "react-router";
28
28
  import { removeExtraWhiteSpaces, shuffle } from "../../utils/index";
29
+ import { startJoyrideWhenReady } from "../../utils/joyride";
29
30
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
30
31
  const useStyles = makeStyles()(theme => ({
31
32
  appBar: {
@@ -335,10 +336,11 @@ function Meaning({
335
336
  };
336
337
  useEffect(() => {
337
338
  if (open && !run && !localStorage.getItem("meaning-exercise-tour-completed")) {
338
- setJoyrideState(prev => ({
339
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prev => ({
339
340
  ...prev,
340
- run: true
341
- }));
341
+ run: true,
342
+ steps
343
+ })));
342
344
  } else if (open && !run && !joyrideRewatched && localStorage.getItem("meaning-exercise-tour-completed")) {
343
345
  handleTranslationTourFinished();
344
346
  }
@@ -454,15 +456,16 @@ function Meaning({
454
456
  },
455
457
  children: t("meaning")
456
458
  }), /*#__PURE__*/_jsx(Tooltip, {
457
- title: t("Rewatch tutorial"),
459
+ title: t("rewatch_tutorial"),
458
460
  children: /*#__PURE__*/_jsx(IconButton, {
459
461
  color: "inherit",
460
462
  onClick: () => {
461
463
  setJoyrideRewatched(true);
462
- setJoyrideState({
463
- ...joyrideState,
464
- run: true
465
- });
464
+ startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
465
+ ...prevState,
466
+ run: true,
467
+ steps
468
+ })));
466
469
  },
467
470
  size: "large",
468
471
  children: /*#__PURE__*/_jsx(LightbulbIcon, {})
@@ -787,6 +790,7 @@ function Meaning({
787
790
  close: t("close"),
788
791
  last: t("last"),
789
792
  next: t("next"),
793
+ nextWithProgress: t("next_with_progress"),
790
794
  skip: t("skip")
791
795
  },
792
796
  options: {
@@ -5,6 +5,7 @@ import { useTheme } from "@mui/material/styles";
5
5
  import { makeStyles } from "tss-react/mui";
6
6
  import useExerciseState from "../../hooks/useExerciseState";
7
7
  import { removeExtraWhiteSpaces } from "../../utils/index";
8
+ import { startJoyrideWhenReady } from "../../utils/joyride";
8
9
  import { Grid, Slide, IconButton, Dialog, AppBar, Toolbar, Tooltip, Typography, Box } from "@mui/material";
9
10
  import { styled } from "@mui/system";
10
11
  import LightbulbIcon from "@mui/icons-material/Lightbulb";
@@ -268,19 +269,12 @@ export default function MeaningReadWrite({
268
269
  }),
269
270
  spotlightPadding: 8,
270
271
  target: "#skipButton"
271
- }, {
272
- content: /*#__PURE__*/_jsx("h2", {
273
- children: t("change_voice_speed")
274
- }),
275
- spotlightPadding: 8,
276
- target: "#change-voice-speed"
277
- }, {
278
- content: /*#__PURE__*/_jsx("h2", {
279
- children: t("exercise_mute")
280
- }),
281
- spotlightPadding: 8,
282
- target: "#mute"
283
- }, {
272
+ },
273
+ // No change_voice_speed or exercise_mute step: this exercise has neither control.
274
+ // It speaks only through the answer result dialogs, and that path calls the raw
275
+ // handleSpeak prop rather than the muteSound-aware speak() from useExerciseState,
276
+ // so a mute button here would not silence anything the learner hears.
277
+ {
284
278
  content: /*#__PURE__*/_jsx("h2", {
285
279
  children: t("exercise_restart")
286
280
  }),
@@ -298,10 +292,11 @@ export default function MeaningReadWrite({
298
292
  } = joyrideState;
299
293
  useEffect(() => {
300
294
  if (open && !run && !localStorage.getItem("meaning-read-write-exercise-tour-completed")) {
301
- setJoyrideState(prev => ({
295
+ return startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prev => ({
302
296
  ...prev,
303
- run: true
304
- }));
297
+ run: true,
298
+ steps
299
+ })));
305
300
  } else if (open && !run && !joyrideRewatched && localStorage.getItem("meaning-read-write-exercise-tour-completed")) {
306
301
  handleTranslationTourFinished();
307
302
  }
@@ -429,10 +424,11 @@ export default function MeaningReadWrite({
429
424
  color: "inherit",
430
425
  onClick: () => {
431
426
  setJoyrideRewatched(true);
432
- setJoyrideState({
433
- ...joyrideState,
434
- run: true
435
- });
427
+ startJoyrideWhenReady(joyrideSteps, steps => setJoyrideState(prevState => ({
428
+ ...prevState,
429
+ run: true,
430
+ steps
431
+ })));
436
432
  },
437
433
  size: "large",
438
434
  children: /*#__PURE__*/_jsx(LightbulbIcon, {})
@@ -714,6 +710,7 @@ export default function MeaningReadWrite({
714
710
  close: t("close"),
715
711
  last: t("last"),
716
712
  next: t("next"),
713
+ nextWithProgress: t("next_with_progress"),
717
714
  skip: t("skip")
718
715
  },
719
716
  options: {