@nualang/nualang-ui-components 0.1.1190 → 0.1.1192

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/Chat/Chat.js CHANGED
@@ -49,6 +49,7 @@ function Chat({
49
49
  moveScriptItem,
50
50
  handleRemoveMessage,
51
51
  learnLang,
52
+ voice,
52
53
  forLang,
53
54
  isPrimaryColor = false,
54
55
  handleKeyPress,
@@ -122,6 +123,7 @@ function Chat({
122
123
  speak: speak,
123
124
  stopSpeaking: stopSpeaking,
124
125
  learnLang: learnLang,
126
+ voice: voice,
125
127
  forLang: forLang,
126
128
  voiceSpeed: voiceSpeed,
127
129
  handleEditMessage: handleEditMessage,
@@ -60,6 +60,7 @@ function Messages({
60
60
  answerCounts,
61
61
  noAnswerCounts,
62
62
  moveScriptItem,
63
+ voice,
63
64
  ...otherProps
64
65
  }) {
65
66
  const {
@@ -175,6 +176,7 @@ function Messages({
175
176
  disableTranslation: disableTranslation,
176
177
  messageIndex: i,
177
178
  voiceSpeed: voiceSpeed,
179
+ voice: voice,
178
180
  messageCount: messages.length,
179
181
  isSpeaking: isSpeaking,
180
182
  isSpeakingTextContainer: isSpeakingTextContainer,
@@ -217,6 +219,7 @@ function Messages({
217
219
  disableTranslation: disableTranslation,
218
220
  messageIndex: i,
219
221
  voiceSpeed: voiceSpeed,
222
+ voice: voice,
220
223
  messageCount: messages.length,
221
224
  isSpeaking: isSpeaking,
222
225
  isSpeakingTextContainer: isSpeakingTextContainer,
@@ -219,9 +219,9 @@ function InviteDialog({
219
219
  component: "b",
220
220
  fontWeight: "bold",
221
221
  color: "primary"
222
- }, "Practice more with ", /*#__PURE__*/_react.default.createElement(NualangLogo, {
222
+ }, "Go to ", /*#__PURE__*/_react.default.createElement(NualangLogo, {
223
223
  src: _nualangLogoPrimary.default
224
- })), " ", "via the ", /*#__PURE__*/_react.default.createElement("b", null, "Learning Site"), ".")) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, teachClassroomsState.length > 0 && /*#__PURE__*/_react.default.createElement(_material.Tabs, {
224
+ }), " classroom"), " ", "via the ", /*#__PURE__*/_react.default.createElement("b", null, "Learning Site"), ".")) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, teachClassroomsState.length > 0 && /*#__PURE__*/_react.default.createElement(_material.Tabs, {
225
225
  value: tabValue,
226
226
  onChange: handleChangeTab,
227
227
  sx: {
@@ -87,6 +87,22 @@ const useStyles = (0, _mui.makeStyles)()(theme => ({
87
87
  paddingRight: `env(safe-area-inset-right)`
88
88
  }
89
89
  }));
90
+ function parsePhraseWithAlternatives(phraseString) {
91
+ const parts = phraseString.split("|").map(p => p.trim());
92
+ return {
93
+ primary: parts[0],
94
+ alternatives: parts.slice(1).filter(p => p && p.length > 0)
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Processes CSV data with the following format:
100
+ * - phrase: Primary phrase with optional alternatives separated by '|'
101
+ * Example: "Hello|Hi|Hey"
102
+ * - translations: Multiple translations separated by '|'
103
+ * - image: Optional image URL
104
+ */
105
+
90
106
  function UploadPhrases({
91
107
  t = text => text,
92
108
  open,
@@ -136,9 +152,14 @@ function UploadPhrases({
136
152
  if (data.phrase && data.translations) {
137
153
  setisError(false);
138
154
  setErrorMessage("");
155
+ const {
156
+ primary,
157
+ alternatives
158
+ } = parsePhraseWithAlternatives(data.phrase);
139
159
  const formattedTranslations = data.translations.split("|").map(t => t.trim());
140
160
  return {
141
- phrase: data.phrase.trim(),
161
+ phrase: primary,
162
+ alternativeVersions: alternatives,
142
163
  translations: formattedTranslations,
143
164
  image: data.image ? data.image.trim() : "",
144
165
  voices: [],
@@ -182,6 +182,9 @@ function Bot({
182
182
  const tabVariant = isSmallScreen ? "fullWidth" : null;
183
183
  const [tabValue, setTabValue] = (0, _react.useState)(0);
184
184
  const [simplified, setSimplified] = (0, _react.useState)(initialValues.editorMode === "advanced" ? false : true);
185
+ const {
186
+ voice
187
+ } = bot;
185
188
  const joyrideSteps = [{
186
189
  content: /*#__PURE__*/_react.default.createElement("h2", null, t("bot_editor_welcome")),
187
190
  placement: "center",
@@ -549,7 +552,8 @@ function Bot({
549
552
  speak: speak,
550
553
  stopSpeaking: stopSpeaking,
551
554
  isSpeaking: isSpeaking,
552
- isSpeakingTextContainer: isSpeakingTextContainer
555
+ isSpeakingTextContainer: isSpeakingTextContainer,
556
+ voice: voice
553
557
  });
554
558
  const tabs = [{
555
559
  label: t("editor")
@@ -243,15 +243,15 @@ function PhrasesEditor(props) {
243
243
  return rowEmpty;
244
244
  };
245
245
  const formatRowsToPhrases = rows => {
246
- const filtered = rows.filter(r => !isRowEmpty(r));
247
- return filtered.map((r, index) => {
248
- const newRow = {
246
+ return rows.filter(r => !isRowEmpty(r)).map(r => {
247
+ const newAlternatives = r.phrase.includes("|") ? r.phrase.split("|").slice(1).map(a => a.trim()).filter(Boolean) : [];
248
+ const updatedAlternativeVersions = [...(r.alternativeVersions || []), ...newAlternatives.filter(alt => !r.alternativeVersions?.map(v => v.toLowerCase()).includes(alt.toLowerCase()))];
249
+ return {
249
250
  ...r,
250
- idx: index,
251
- translations: r.translations.split("|").map(t => t.trim())
251
+ phrase: r.phrase.split("|")[0].trim() || '',
252
+ alternativeVersions: updatedAlternativeVersions,
253
+ translations: (r.translations || '').split("|").map(t => t.trim()).filter(Boolean)
252
254
  };
253
- delete newRow.id;
254
- return newRow;
255
255
  });
256
256
  };
257
257
 
@@ -311,8 +311,10 @@ function PhrasesEditor(props) {
311
311
  value: (row, {
312
312
  focus
313
313
  }) => {
314
+ const phraseDisplay = [row.phrase || '', ...(row.alternativeVersions || [])].filter(Boolean).join(" | ");
314
315
  return /*#__PURE__*/_react.default.createElement(_reactSpreadsheetGrid.Input, {
315
- value: row.phrase,
316
+ value: phraseDisplay,
317
+ placeholder: t("enter_phrase_with_alternatives"),
316
318
  focus: focus,
317
319
  onChange: onFieldChange(row.id, "phrase")
318
320
  });
@@ -393,27 +395,29 @@ function PhrasesEditor(props) {
393
395
  };
394
396
  const handleScriptDownload = () => {
395
397
  try {
398
+ const formattedRows = rows.map(row => ({
399
+ ...row,
400
+ phrase: [row.phrase || '', ...(row.alternativeVersions || [])].filter(Boolean).join(" | ")
401
+ }));
396
402
  const parser = new _plainjs.Parser({
397
403
  fields: ["phrase", "translations", "image"],
398
404
  defaultValue: ""
399
405
  });
400
- const csv = parser.parse(rows);
406
+ const csv = parser.parse(formattedRows);
401
407
  const element = document.createElement("a");
402
- const file = new Blob([csv.replace(",,", "").trim()], {
408
+ const file = new Blob([csv], {
403
409
  type: "text/plain"
404
410
  });
405
411
  element.href = URL.createObjectURL(file);
406
- const date = new Date();
407
- const dayOfDownload = date.getDate();
408
- const monthOfDownload = date.getMonth() + 1;
409
- const yearOfDownload = date.getFullYear();
410
- const formattedDate = `${dayOfDownload}-${monthOfDownload}-${yearOfDownload}`;
411
- element.download = `${topicName}-${formattedDate}.csv`;
412
- document.body.appendChild(element); // Required for this to work in Firefox
412
+ element.download = `${topicName}-${new Date().toLocaleDateString()}.csv`;
413
+ document.body.appendChild(element);
413
414
  element.click();
415
+ // Cleanup
416
+ document.body.removeChild(element);
417
+ URL.revokeObjectURL(element.href);
414
418
  } catch (err) {
415
419
  console.error(err);
416
- alert("There was a problem downloading");
420
+ alert(t("download_error"));
417
421
  }
418
422
  };
419
423
  const handleModeSelection = (event, mode) => {
@@ -848,14 +848,16 @@ function Listener({
848
848
  handleSubmit: () => handleContinue(false),
849
849
  handleSkip: () => handleContinue(true),
850
850
  isSubmitAnswerAllowed: true,
851
- isSubmitAnswerDisabled: !isWordBankAttemptChanged || !listeningWords || listeningWords.length === 0
851
+ isSubmitAnswerDisabled: !isWordBankAttemptChanged || !listeningWords || listeningWords.length === 0,
852
+ useWordBank: useWordBank
852
853
  }) : /*#__PURE__*/_react.default.createElement(_ExerciseBottomBar.default, {
853
854
  t: t,
854
855
  listeningWords: listeningWords,
855
856
  handleSubmit: () => handleContinue(false),
856
857
  handleSkip: () => handleContinue(true),
857
858
  isSubmitAnswerAllowed: true,
858
- isSubmitAnswerDisabled: !listeningText && (!listeningWords || listeningWords.length === 0)
859
+ isSubmitAnswerDisabled: !listeningText && (!listeningWords || listeningWords.length === 0),
860
+ useWordBank: useWordBank
859
861
  }), /*#__PURE__*/_react.default.createElement(_CompletedExcercise.default, {
860
862
  open: isCompletionModalOpen,
861
863
  restartExcercise: handleRestartExercise,
@@ -826,14 +826,16 @@ function Translator({
826
826
  handleSubmit: () => handleContinue(false),
827
827
  handleSkip: () => handleContinue(true),
828
828
  isSubmitAnswerAllowed: true,
829
- isSubmitAnswerDisabled: !isWordBankAttemptChanged || !translationWords || translationWords.length === 0
829
+ isSubmitAnswerDisabled: !isWordBankAttemptChanged || !translationWords || translationWords.length === 0,
830
+ useWordBank: useWordBank
830
831
  }) : /*#__PURE__*/_react.default.createElement(_ExerciseBottomBar.default, {
831
832
  t: t,
832
833
  translationWords: translationWords,
833
834
  handleSubmit: () => handleContinue(false),
834
835
  handleSkip: () => handleContinue(true),
835
836
  isSubmitAnswerAllowed: true,
836
- isSubmitAnswerDisabled: !translationText && (!translationWords || translationWords.length === 0)
837
+ isSubmitAnswerDisabled: !translationText && (!translationWords || translationWords.length === 0),
838
+ useWordBank: useWordBank
837
839
  }), /*#__PURE__*/_react.default.createElement(_AnswerResult.default, _extends({
838
840
  t: t,
839
841
  open: isCorrectResultOpen,
@@ -36,8 +36,9 @@ function ChipInput(props) {
36
36
  return /*#__PURE__*/_react.default.createElement(_CustomChipInput.default, _extends({
37
37
  label: label
38
38
  }, props, {
39
- onAdd: chip => handleAddChip(chip),
40
- onDelete: chip => deleteChip(chip)
39
+ onAdd: handleAddChip,
40
+ onDelete: deleteChip,
41
+ delimiter: delimiter
41
42
  }));
42
43
  }
43
44
  var _default = exports.default = ChipInput;
@@ -269,13 +269,17 @@ function FeedbackForm({
269
269
  }, /*#__PURE__*/_react.default.createElement(_material.Box, {
270
270
  key: attendee?.memberId,
271
271
  display: "flex",
272
- alignItems: "center"
272
+ alignItems: "center",
273
+ sx: {
274
+ marginBottom: 1,
275
+ marginTop: 1
276
+ }
273
277
  }, index !== 0 && /*#__PURE__*/_react.default.createElement(_material.Avatar, {
274
278
  alt: attendee,
275
279
  src: attendee.userImage,
276
280
  sx: {
277
- width: 24,
278
- height: 24,
281
+ width: 40,
282
+ height: 40,
279
283
  marginRight: "8px"
280
284
  }
281
285
  }), attendee.username, index === 0 &&
@@ -7,6 +7,11 @@ exports.default = FeedbackInfo;
7
7
  var _react = _interopRequireDefault(require("react"));
8
8
  var _material = require("@mui/material");
9
9
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ const getModeConditionalBackground = (dark, light) => theme => ({
11
+ backgroundColor: theme.palette.mode === "dark" ? dark // Using MUI's palette
12
+ : light,
13
+ padding: 2
14
+ });
10
15
  function FeedbackInfo({
11
16
  values = {
12
17
  feedback1: [{
@@ -79,10 +84,7 @@ function FeedbackInfo({
79
84
  }, gradingOption)))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
80
85
  container: true,
81
86
  alignItems: "flex-start",
82
- sx: {
83
- backgroundColor: "#f0f0f0",
84
- padding: 2
85
- }
87
+ sx: getModeConditionalBackground("#424242", "#f0f0f0")
86
88
  }, /*#__PURE__*/_react.default.createElement(_material.Grid, {
87
89
  item: true,
88
90
  xs: 4
@@ -98,10 +100,7 @@ function FeedbackInfo({
98
100
  }, feedback1.length > 0 ? feedback1[0]?.feedbackLevelName : "-"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
99
101
  container: true,
100
102
  alignItems: "flex-start",
101
- sx: {
102
- backgroundColor: "#e0e0e0",
103
- padding: 2
104
- }
103
+ sx: getModeConditionalBackground("#303030", "#e0e0e0")
105
104
  }, /*#__PURE__*/_react.default.createElement(_material.Grid, {
106
105
  item: true,
107
106
  xs: 4
@@ -117,10 +116,7 @@ function FeedbackInfo({
117
116
  }, feedback2.length > 0 ? feedback2[0]?.feedbackLevelName : "-"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
118
117
  container: true,
119
118
  alignItems: "flex-start",
120
- sx: {
121
- backgroundColor: "#f0f0f0",
122
- padding: 2
123
- }
119
+ sx: getModeConditionalBackground("#424242", "#f0f0f0")
124
120
  }, /*#__PURE__*/_react.default.createElement(_material.Grid, {
125
121
  item: true,
126
122
  xs: 4
@@ -136,10 +132,7 @@ function FeedbackInfo({
136
132
  }, feedback3.length > 0 ? feedback3[0]?.feedbackLevelName : "-"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
137
133
  container: true,
138
134
  alignItems: "flex-start",
139
- sx: {
140
- backgroundColor: "#e0e0e0",
141
- padding: 2
142
- }
135
+ sx: getModeConditionalBackground("#303030", "#e0e0e0")
143
136
  }, /*#__PURE__*/_react.default.createElement(_material.Grid, {
144
137
  item: true,
145
138
  xs: 4
@@ -155,10 +148,7 @@ function FeedbackInfo({
155
148
  }, feedback4.length > 0 ? feedback4[0]?.feedbackLevelName : "-"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
156
149
  container: true,
157
150
  alignItems: "flex-start",
158
- sx: {
159
- backgroundColor: "#f0f0f0",
160
- padding: 2
161
- }
151
+ sx: getModeConditionalBackground("#424242", "#f0f0f0")
162
152
  }, /*#__PURE__*/_react.default.createElement(_material.Grid, {
163
153
  item: true,
164
154
  xs: 4
@@ -174,10 +164,7 @@ function FeedbackInfo({
174
164
  }, feedback5.length > 0 ? feedback5[0]?.feedbackLevelName : "-"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
175
165
  container: true,
176
166
  alignItems: "flex-start",
177
- sx: {
178
- backgroundColor: "#e0e0e0",
179
- padding: 2
180
- }
167
+ sx: getModeConditionalBackground("#303030", "#e0e0e0")
181
168
  }, /*#__PURE__*/_react.default.createElement(_material.Grid, {
182
169
  item: true,
183
170
  xs: 4
@@ -193,10 +180,7 @@ function FeedbackInfo({
193
180
  }, feedback6.length > 0 ? feedback6[0]?.feedbackLevelName : "-"))), /*#__PURE__*/_react.default.createElement(_material.Grid, {
194
181
  container: true,
195
182
  alignItems: "flex-start",
196
- sx: {
197
- backgroundColor: "#f0f0f0",
198
- padding: 2
199
- }
183
+ sx: getModeConditionalBackground("#424242", "#f0f0f0")
200
184
  }, /*#__PURE__*/_react.default.createElement(_material.Grid, {
201
185
  item: true,
202
186
  xs: 4
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.Adornment = Adornment;
7
7
  exports.default = void 0;
8
8
  var _react = _interopRequireWildcard(require("react"));
9
+ var _styles = require("@mui/material/styles");
9
10
  var _IconButton = _interopRequireDefault(require("@mui/material/IconButton"));
10
11
  var _Input = _interopRequireDefault(require("@mui/material/Input"));
11
12
  var _OutlinedInput = _interopRequireDefault(require("@mui/material/OutlinedInput"));
@@ -19,8 +20,7 @@ var _Menu = _interopRequireDefault(require("@mui/material/Menu"));
19
20
  var _MenuItem = _interopRequireDefault(require("@mui/material/MenuItem"));
20
21
  var _FormHelperText = _interopRequireDefault(require("@mui/material/FormHelperText"));
21
22
  var _reactFeather = require("react-feather");
22
- var _react2 = _interopRequireDefault(require("@emoji-mart/react"));
23
- var _apple = _interopRequireDefault(require("@emoji-mart/data/sets/14/apple.json"));
23
+ var _emojiPickerReact = _interopRequireDefault(require("emoji-picker-react"));
24
24
  var _Dialog = _interopRequireDefault(require("@mui/material/Dialog"));
25
25
  var _index = require("../../utils/index");
26
26
  var _colors = require("@mui/material/colors");
@@ -50,6 +50,7 @@ function Adornment(props) {
50
50
  setIsDisabled,
51
51
  setIsButtonClicked
52
52
  } = props;
53
+ const theme = (0, _styles.useTheme)();
53
54
  const isEnglish = learnLang === "english";
54
55
  const isSmallScreen = (0, _useMediaQuery.default)("(max-width:420px)");
55
56
  const {
@@ -85,18 +86,17 @@ function Adornment(props) {
85
86
  }
86
87
  });
87
88
  };
88
- const addEmoji = emoji => {
89
- handleEmojiClose();
90
- const newText = [value.slice(0, selectionStart), `${emoji.native}`, value.slice(selectionStart)].join("");
89
+ const handleEmojiClose = () => {
90
+ setShowEmojiPicker(false);
91
+ };
92
+ const onEmojiClick = event => {
93
+ const newText = [value.slice(0, selectionStart), `${event.emoji}`, value.slice(selectionStart)].join("");
91
94
  onChange({
92
95
  target: {
93
96
  name: name,
94
97
  value: newText
95
98
  }
96
99
  });
97
- };
98
- const handleEmojiClose = () => {
99
- setIsDisabled(true);
100
100
  setShowEmojiPicker(false);
101
101
  };
102
102
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_InputAdornment.default, {
@@ -104,11 +104,12 @@ function Adornment(props) {
104
104
  }, emoji && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_Dialog.default, {
105
105
  open: showEmojiPicker,
106
106
  onClose: handleEmojiClose
107
- }, /*#__PURE__*/_react.default.createElement(_react2.default, {
108
- set: "apple",
109
- onEmojiSelect: addEmoji,
110
- data: _apple.default,
111
- perLine: isSmallScreen ? 6 : 9
107
+ }, /*#__PURE__*/_react.default.createElement(_emojiPickerReact.default, {
108
+ pickerStyle: {
109
+ width: "100%"
110
+ },
111
+ theme: theme.palette.mode === "dark" ? "dark" : "light",
112
+ onEmojiClick: onEmojiClick
112
113
  })), /*#__PURE__*/_react.default.createElement(_Tooltip.default, {
113
114
  title: isDisabled ? t("Please select a textfield") : t("insert_emoji")
114
115
  }, /*#__PURE__*/_react.default.createElement("span", null, /*#__PURE__*/_react.default.createElement(_IconButton.default, {
@@ -552,7 +552,8 @@ function LiveListener({
552
552
  listeningText: listeningText,
553
553
  listeningWords: listeningWords,
554
554
  setCurrentAnswer: setCurrentAnswer,
555
- exercise: exercise
555
+ exercise: exercise,
556
+ useWordBank: useWordBank
556
557
  })));
557
558
  }
558
559
  LiveListener.propTypes = {};
@@ -666,7 +666,8 @@ function LiveTranslator({
666
666
  translationText: translationText,
667
667
  translationWords: translationWords,
668
668
  setCurrentAnswer: setCurrentAnswer,
669
- exercise: exercise
669
+ exercise: exercise,
670
+ useWordBank: useWordBank
670
671
  })));
671
672
  }
672
673
  LiveTranslator.propTypes = {};