tetrons 2.3.96 → 2.3.98

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/index.mjs CHANGED
@@ -13,7 +13,7 @@ var MathModal_exports = {};
13
13
  __export(MathModal_exports, {
14
14
  default: () => MathModal
15
15
  });
16
- import React13, { useEffect as useEffect7 } from "react";
16
+ import React16, { useEffect as useEffect7 } from "react";
17
17
  import katex2 from "katex";
18
18
  import "katex/dist/katex.min.css";
19
19
  function MathModal({
@@ -33,7 +33,7 @@ function MathModal({
33
33
  return () => window.removeEventListener("keydown", onEsc);
34
34
  }, [isOpen, onClose]);
35
35
  if (!isOpen) return null;
36
- return /* @__PURE__ */ React13.createElement("div", { className: "ai-modal-backdrop" }, /* @__PURE__ */ React13.createElement("div", { className: "ai-modal-content" }, /* @__PURE__ */ React13.createElement("div", { className: "ai-modal-title" }, "Insert LaTeX Equation"), /* @__PURE__ */ React13.createElement(
36
+ return /* @__PURE__ */ React16.createElement("div", { className: "ai-modal-backdrop" }, /* @__PURE__ */ React16.createElement("div", { className: "ai-modal-content" }, /* @__PURE__ */ React16.createElement("div", { className: "ai-modal-title" }, "Insert LaTeX Equation"), /* @__PURE__ */ React16.createElement(
37
37
  "textarea",
38
38
  {
39
39
  className: "ai-modal-textarea",
@@ -41,7 +41,7 @@ function MathModal({
41
41
  value,
42
42
  onChange: (e) => setValue(e.target.value)
43
43
  }
44
- ), /* @__PURE__ */ React13.createElement("div", { className: "ai-modal-preview" }, /* @__PURE__ */ React13.createElement("strong", null, "Preview:"), /* @__PURE__ */ React13.createElement("div", { className: "ai-modal-preview-output" }, /* @__PURE__ */ React13.createElement("span", { dangerouslySetInnerHTML: { __html: renderLatex(value) } }))), /* @__PURE__ */ React13.createElement("div", { className: "ai-modal-actions" }, /* @__PURE__ */ React13.createElement("button", { type: "button", className: "ai-cancel-btn", onClick: onClose }, "Cancel"), /* @__PURE__ */ React13.createElement(
44
+ ), /* @__PURE__ */ React16.createElement("div", { className: "ai-modal-preview" }, /* @__PURE__ */ React16.createElement("strong", null, "Preview:"), /* @__PURE__ */ React16.createElement("div", { className: "ai-modal-preview-output" }, /* @__PURE__ */ React16.createElement("span", { dangerouslySetInnerHTML: { __html: renderLatex(value) } }))), /* @__PURE__ */ React16.createElement("div", { className: "ai-modal-actions" }, /* @__PURE__ */ React16.createElement("button", { type: "button", className: "ai-cancel-btn", onClick: onClose }, "Cancel"), /* @__PURE__ */ React16.createElement(
45
45
  "button",
46
46
  {
47
47
  className: "ai-submit-btn",
@@ -72,7 +72,7 @@ var CodeEditorModal_exports = {};
72
72
  __export(CodeEditorModal_exports, {
73
73
  default: () => CodeEditorModal_default
74
74
  });
75
- import React14, { useState as useState8 } from "react";
75
+ import React17, { useState as useState11 } from "react";
76
76
  import Editor from "@monaco-editor/react";
77
77
  var CodeEditorModal, CodeEditorModal_default;
78
78
  var init_CodeEditorModal = __esm({
@@ -85,10 +85,10 @@ var init_CodeEditorModal = __esm({
85
85
  onSubmitCode,
86
86
  onSubmitCodeWithOutput
87
87
  }) => {
88
- const [language, setLanguage] = useState8("javascript");
89
- const [code, setCode] = useState8("// Write your code here");
90
- const [output, setOutput] = useState8("");
91
- const [loading, setLoading] = useState8(false);
88
+ const [language, setLanguage] = useState11("javascript");
89
+ const [code, setCode] = useState11("// Write your code here");
90
+ const [output, setOutput] = useState11("");
91
+ const [loading, setLoading] = useState11(false);
92
92
  const runCode = async () => {
93
93
  setLoading(true);
94
94
  try {
@@ -124,19 +124,19 @@ ${data.stderr}
124
124
  onClose();
125
125
  };
126
126
  if (!isOpen) return null;
127
- return /* @__PURE__ */ React14.createElement("div", { className: "code-modal-overlay" }, /* @__PURE__ */ React14.createElement("div", { className: "code-modal-content" }, /* @__PURE__ */ React14.createElement("div", { className: "code-modal-header" }, /* @__PURE__ */ React14.createElement("h2", null, "Run Code"), /* @__PURE__ */ React14.createElement("button", { onClick: onClose, className: "code-close-btn" }, "\xD7")), /* @__PURE__ */ React14.createElement("div", { className: "code-modal-controls" }, /* @__PURE__ */ React14.createElement("label", { htmlFor: "language" }, "Language:"), /* @__PURE__ */ React14.createElement(
127
+ return /* @__PURE__ */ React17.createElement("div", { className: "code-modal-overlay" }, /* @__PURE__ */ React17.createElement("div", { className: "code-modal-content" }, /* @__PURE__ */ React17.createElement("div", { className: "code-modal-header" }, /* @__PURE__ */ React17.createElement("h2", null, "Run Code"), /* @__PURE__ */ React17.createElement("button", { onClick: onClose, className: "code-close-btn" }, "\xD7")), /* @__PURE__ */ React17.createElement("div", { className: "code-modal-controls" }, /* @__PURE__ */ React17.createElement("label", { htmlFor: "language" }, "Language:"), /* @__PURE__ */ React17.createElement(
128
128
  "select",
129
129
  {
130
130
  id: "language",
131
131
  value: language,
132
132
  onChange: (e) => setLanguage(e.target.value)
133
133
  },
134
- /* @__PURE__ */ React14.createElement("option", { value: "javascript" }, "JavaScript"),
135
- /* @__PURE__ */ React14.createElement("option", { value: "python" }, "Python"),
136
- /* @__PURE__ */ React14.createElement("option", { value: "cpp" }, "C++"),
137
- /* @__PURE__ */ React14.createElement("option", { value: "java" }, "Java"),
138
- /* @__PURE__ */ React14.createElement("option", { value: "typescript" }, "TypeScript")
139
- ), /* @__PURE__ */ React14.createElement("button", { className: "run-code", onClick: runCode, disabled: loading }, loading ? "Running..." : "Run")), /* @__PURE__ */ React14.createElement(
134
+ /* @__PURE__ */ React17.createElement("option", { value: "javascript" }, "JavaScript"),
135
+ /* @__PURE__ */ React17.createElement("option", { value: "python" }, "Python"),
136
+ /* @__PURE__ */ React17.createElement("option", { value: "cpp" }, "C++"),
137
+ /* @__PURE__ */ React17.createElement("option", { value: "java" }, "Java"),
138
+ /* @__PURE__ */ React17.createElement("option", { value: "typescript" }, "TypeScript")
139
+ ), /* @__PURE__ */ React17.createElement("button", { className: "run-code", onClick: runCode, disabled: loading }, loading ? "Running..." : "Run")), /* @__PURE__ */ React17.createElement(
140
140
  Editor,
141
141
  {
142
142
  height: "50vh",
@@ -145,7 +145,7 @@ ${data.stderr}
145
145
  value: code,
146
146
  onChange: (v) => setCode(v ?? "")
147
147
  }
148
- ), /* @__PURE__ */ React14.createElement("div", { className: "code-output" }, /* @__PURE__ */ React14.createElement("strong", null, "Output:"), /* @__PURE__ */ React14.createElement("pre", null, output.trim() === "" ? "\u2190 Click Run to see output here" : output)), /* @__PURE__ */ React14.createElement("div", { className: "code-submit-buttons-container" }, /* @__PURE__ */ React14.createElement(
148
+ ), /* @__PURE__ */ React17.createElement("div", { className: "code-output" }, /* @__PURE__ */ React17.createElement("strong", null, "Output:"), /* @__PURE__ */ React17.createElement("pre", null, output.trim() === "" ? "\u2190 Click Run to see output here" : output)), /* @__PURE__ */ React17.createElement("div", { className: "code-submit-buttons-container" }, /* @__PURE__ */ React17.createElement(
149
149
  "button",
150
150
  {
151
151
  className: "code-submit-buttons",
@@ -153,7 +153,7 @@ ${data.stderr}
153
153
  disabled: loading || !code
154
154
  },
155
155
  "Submit Code Snippet Only"
156
- ), /* @__PURE__ */ React14.createElement(
156
+ ), /* @__PURE__ */ React17.createElement(
157
157
  "button",
158
158
  {
159
159
  className: "code-submit-buttons",
@@ -224,7 +224,7 @@ var MathInline = Node.create({
224
224
  });
225
225
 
226
226
  // src/components/tetrons/EditorContent.tsx
227
- import React17, { useEffect as useEffect9, useRef as useRef7, useState as useState11 } from "react";
227
+ import React20, { useEffect as useEffect9, useRef as useRef7, useState as useState14 } from "react";
228
228
  import { useEditor, EditorContent as TiptapEditorContent } from "@tiptap/react";
229
229
 
230
230
  // src/utils/licenseTracker.ts
@@ -15942,7 +15942,7 @@ function TableContextMenu({ editor }) {
15942
15942
  }
15943
15943
 
15944
15944
  // src/components/tetrons/toolbar/TetronsToolbar.tsx
15945
- import React16, { useEffect as useEffect8, useState as useState10 } from "react";
15945
+ import React19, { useEffect as useEffect8, useState as useState13 } from "react";
15946
15946
 
15947
15947
  // src/components/tetrons/toolbar/ActionGroup.tsx
15948
15948
  import React5, { useEffect as useEffect5, useRef as useRef3, useState as useState4 } from "react";
@@ -16884,19 +16884,251 @@ function FileGroup({ editor }) {
16884
16884
  }
16885
16885
 
16886
16886
  // src/components/tetrons/toolbar/AIGroup.tsx
16887
- import React12, { useState as useState7, useRef as useRef6 } from "react";
16888
- import { FaMicrophone, FaStop } from "react-icons/fa";
16887
+ import React15, { useState as useState10, useRef as useRef6 } from "react";
16888
+ import { FaMicrophone as FaMicrophone3, FaStop, FaLanguage } from "react-icons/fa";
16889
16889
  import { Waveform } from "@uiball/loaders";
16890
- import { motion, AnimatePresence } from "framer-motion";
16890
+
16891
+ // src/components/tetrons/toolbar/Tabs.tsx
16892
+ import { useState as useState9 } from "react";
16893
+
16894
+ // src/components/tetrons/toolbar/Converter.tsx
16895
+ import React12, { useState as useState7 } from "react";
16896
+
16897
+ // src/utils/languages.ts
16898
+ var indianLanguages = [
16899
+ "Assamese",
16900
+ "Bengali",
16901
+ "Bodo",
16902
+ "Dogri",
16903
+ "Gujarati",
16904
+ "Hindi",
16905
+ "Kannada",
16906
+ "Kashmiri",
16907
+ "Konkani",
16908
+ "Maithili",
16909
+ "Malayalam",
16910
+ "Manipuri",
16911
+ "Marathi",
16912
+ "Nepali",
16913
+ "Odia",
16914
+ "Punjabi",
16915
+ "Sanskrit",
16916
+ "Santali",
16917
+ "Sindhi",
16918
+ "Tamil",
16919
+ "Telugu",
16920
+ "Urdu",
16921
+ "English"
16922
+ ];
16923
+
16924
+ // src/components/tetrons/toolbar/Converter.tsx
16925
+ import { FaMicrophone } from "react-icons/fa";
16926
+ function Converter({
16927
+ onResult
16928
+ }) {
16929
+ const [sourceLang, setSourceLang] = useState7("Hindi");
16930
+ const [targetLang, setTargetLang] = useState7("Bengali");
16931
+ const [text, setText] = useState7("");
16932
+ const [result, setResult] = useState7("");
16933
+ const handleConvert = async () => {
16934
+ const res = await fetch("https://tetrons.com/api/translate", {
16935
+ method: "POST",
16936
+ headers: { "Content-Type": "application/json" },
16937
+ body: JSON.stringify({ text, sourceLang, targetLang, mode: "convert" })
16938
+ });
16939
+ const data = await res.json();
16940
+ setResult(data.result);
16941
+ if (data.result && onResult) {
16942
+ onResult(data.result);
16943
+ }
16944
+ };
16945
+ const handleSpeakOutput = async () => {
16946
+ if (!result) return;
16947
+ const res = await fetch("https://tetrons.com/api/speak", {
16948
+ method: "POST",
16949
+ headers: { "Content-Type": "application/json" },
16950
+ body: JSON.stringify({ text: result, lang: targetLang })
16951
+ });
16952
+ const blob = await res.blob();
16953
+ const url = URL.createObjectURL(blob);
16954
+ const audio = new Audio(url);
16955
+ audio.play();
16956
+ };
16957
+ return /* @__PURE__ */ React12.createElement("div", { className: "container" }, /* @__PURE__ */ React12.createElement("div", { className: "field" }, /* @__PURE__ */ React12.createElement("label", { htmlFor: "sourceLang", className: "label" }, "Source Language:"), /* @__PURE__ */ React12.createElement(
16958
+ "select",
16959
+ {
16960
+ id: "sourceLang",
16961
+ value: sourceLang,
16962
+ onChange: (e) => setSourceLang(e.target.value),
16963
+ className: "select"
16964
+ },
16965
+ indianLanguages.map((lang) => /* @__PURE__ */ React12.createElement("option", { key: lang }, lang))
16966
+ )), /* @__PURE__ */ React12.createElement("div", { className: "field" }, /* @__PURE__ */ React12.createElement("label", { htmlFor: "targetLang", className: "label" }, "Target Language:"), /* @__PURE__ */ React12.createElement(
16967
+ "select",
16968
+ {
16969
+ id: "targetLang",
16970
+ value: targetLang,
16971
+ onChange: (e) => setTargetLang(e.target.value),
16972
+ className: "select"
16973
+ },
16974
+ indianLanguages.map((lang) => /* @__PURE__ */ React12.createElement("option", { key: lang }, lang))
16975
+ )), /* @__PURE__ */ React12.createElement("div", { className: "field" }, /* @__PURE__ */ React12.createElement("label", { htmlFor: "inputText", className: "label" }, "Enter Text:"), /* @__PURE__ */ React12.createElement(
16976
+ "textarea",
16977
+ {
16978
+ id: "inputText",
16979
+ placeholder: "Enter text...",
16980
+ value: text,
16981
+ onChange: (e) => setText(e.target.value),
16982
+ className: "textarea"
16983
+ }
16984
+ )), /* @__PURE__ */ React12.createElement("button", { type: "button", onClick: handleConvert, className: "button" }, "Convert"), /* @__PURE__ */ React12.createElement("div", { className: "outputWrapper" }, /* @__PURE__ */ React12.createElement("div", { className: "output" }, result), result && /* @__PURE__ */ React12.createElement(
16985
+ "button",
16986
+ {
16987
+ type: "button",
16988
+ onClick: handleSpeakOutput,
16989
+ className: "iconButton",
16990
+ "aria-label": "Play conversion",
16991
+ title: "Play conversion"
16992
+ },
16993
+ /* @__PURE__ */ React12.createElement(FaMicrophone, null)
16994
+ )));
16995
+ }
16996
+
16997
+ // src/components/tetrons/toolbar/Translator.tsx
16998
+ import React13, { useState as useState8 } from "react";
16999
+ import { FaMicrophone as FaMicrophone2, FaVolumeUp } from "react-icons/fa";
17000
+ function Translator({
17001
+ onResult
17002
+ }) {
17003
+ const [sourceLang, setSourceLang] = useState8("Hindi");
17004
+ const [targetLang, setTargetLang] = useState8("English");
17005
+ const [text, setText] = useState8("");
17006
+ const [result, setResult] = useState8("");
17007
+ const [listening, setListening] = useState8(false);
17008
+ const handleTranslate = async () => {
17009
+ const res = await fetch("https://tetrons.com/api/translate", {
17010
+ method: "POST",
17011
+ headers: { "Content-Type": "application/json" },
17012
+ body: JSON.stringify({ text, sourceLang, targetLang, mode: "translate" })
17013
+ });
17014
+ const data = await res.json();
17015
+ setResult(data.result);
17016
+ if (data.result && onResult) {
17017
+ onResult(data.result);
17018
+ }
17019
+ };
17020
+ const handleMicInput = () => {
17021
+ const SpeechRecognitionClass = window.SpeechRecognition || window.webkitSpeechRecognition;
17022
+ if (!SpeechRecognitionClass) {
17023
+ alert("Speech recognition is not supported in this browser.");
17024
+ return;
17025
+ }
17026
+ const recognition = new SpeechRecognitionClass();
17027
+ recognition.lang = sourceLang === "English" ? "en-IN" : "hi-IN";
17028
+ recognition.interimResults = false;
17029
+ recognition.onstart = () => setListening(true);
17030
+ recognition.onend = () => setListening(false);
17031
+ recognition.onresult = (event) => {
17032
+ const transcript = event.results[0][0].transcript;
17033
+ setText((prev) => prev ? prev + " " + transcript : transcript);
17034
+ };
17035
+ recognition.start();
17036
+ };
17037
+ const handleSpeakOutput = async () => {
17038
+ if (!result) return;
17039
+ const res = await fetch("/api/speak", {
17040
+ method: "POST",
17041
+ headers: { "Content-Type": "application/json" },
17042
+ body: JSON.stringify({ text: result, lang: targetLang })
17043
+ });
17044
+ const blob = await res.blob();
17045
+ const url = URL.createObjectURL(blob);
17046
+ const audio = new Audio(url);
17047
+ audio.play();
17048
+ };
17049
+ return /* @__PURE__ */ React13.createElement("div", { className: "container" }, /* @__PURE__ */ React13.createElement("div", { className: "field" }, /* @__PURE__ */ React13.createElement("label", { htmlFor: "sourceLang", className: "label" }, "Source Language:"), /* @__PURE__ */ React13.createElement(
17050
+ "select",
17051
+ {
17052
+ id: "sourceLang",
17053
+ value: sourceLang,
17054
+ onChange: (e) => setSourceLang(e.target.value),
17055
+ className: "select"
17056
+ },
17057
+ indianLanguages.map((lang) => /* @__PURE__ */ React13.createElement("option", { key: lang }, lang))
17058
+ )), /* @__PURE__ */ React13.createElement("div", { className: "field" }, /* @__PURE__ */ React13.createElement("label", { htmlFor: "targetLang", className: "label" }, "Target Language:"), /* @__PURE__ */ React13.createElement(
17059
+ "select",
17060
+ {
17061
+ id: "targetLang",
17062
+ value: targetLang,
17063
+ onChange: (e) => setTargetLang(e.target.value),
17064
+ className: "select"
17065
+ },
17066
+ indianLanguages.map((lang) => /* @__PURE__ */ React13.createElement("option", { key: lang }, lang))
17067
+ )), /* @__PURE__ */ React13.createElement("div", { className: "field" }, /* @__PURE__ */ React13.createElement("label", { htmlFor: "inputText", className: "label" }, "Enter Text:"), /* @__PURE__ */ React13.createElement("div", { className: "textareaWrapper" }, /* @__PURE__ */ React13.createElement(
17068
+ "textarea",
17069
+ {
17070
+ id: "inputText",
17071
+ placeholder: "Enter text...",
17072
+ value: text,
17073
+ onChange: (e) => setText(e.target.value),
17074
+ className: "textarea"
17075
+ }
17076
+ ), /* @__PURE__ */ React13.createElement(
17077
+ "button",
17078
+ {
17079
+ type: "button",
17080
+ onClick: handleMicInput,
17081
+ className: "iconButton",
17082
+ title: listening ? "Listening..." : "Start voice input"
17083
+ },
17084
+ /* @__PURE__ */ React13.createElement(FaMicrophone2, { color: listening ? "red" : "black" })
17085
+ ))), /* @__PURE__ */ React13.createElement("button", { type: "button", onClick: handleTranslate, className: "button" }, "Translate"), /* @__PURE__ */ React13.createElement("div", { className: "outputWrapper" }, /* @__PURE__ */ React13.createElement("div", { className: "output" }, result), result && /* @__PURE__ */ React13.createElement(
17086
+ "button",
17087
+ {
17088
+ type: "button",
17089
+ onClick: handleSpeakOutput,
17090
+ className: "iconButton",
17091
+ "aria-label": "Play translation",
17092
+ title: "Play translation"
17093
+ },
17094
+ /* @__PURE__ */ React13.createElement(FaVolumeUp, null)
17095
+ )));
17096
+ }
17097
+
17098
+ // src/components/tetrons/toolbar/Tabs.tsx
17099
+ import * as React14 from "react";
17100
+ function Tabs({ onResult }) {
17101
+ const [activeTab, setActiveTab] = useState9("convert");
17102
+ return /* @__PURE__ */ React14.createElement("div", null, /* @__PURE__ */ React14.createElement("div", { className: "tabHeader" }, /* @__PURE__ */ React14.createElement(
17103
+ "button",
17104
+ {
17105
+ type: "button",
17106
+ className: `$"tabButton" ${activeTab === "convert" ? "active" : ""}`,
17107
+ onClick: () => setActiveTab("convert")
17108
+ },
17109
+ "Convert"
17110
+ ), /* @__PURE__ */ React14.createElement(
17111
+ "button",
17112
+ {
17113
+ type: "button",
17114
+ className: `$"tabButton" ${activeTab === "translate" ? "active" : ""}`,
17115
+ onClick: () => setActiveTab("translate")
17116
+ },
17117
+ "Translate"
17118
+ )), /* @__PURE__ */ React14.createElement("div", { className: "tabContent" }, activeTab === "convert" ? /* @__PURE__ */ React14.createElement(Converter, { onResult }) : /* @__PURE__ */ React14.createElement(Translator, { onResult })));
17119
+ }
17120
+
17121
+ // src/components/tetrons/toolbar/AIGroup.tsx
16891
17122
  function AiGroup({ editor, enabledFeatures }) {
16892
- const [isRecording, setIsRecording] = useState7(false);
16893
- const [audioBlob, setAudioBlob] = useState7(null);
16894
- const [isTranscribing, setIsTranscribing] = useState7(false);
16895
- const [transcriptionError, setTranscriptionError] = useState7("");
16896
- const [showPromptInput, setShowPromptInput] = useState7(false);
16897
- const [prompt2, setPrompt] = useState7("");
16898
- const [isLoadingAI, setIsLoadingAI] = useState7(false);
16899
- const [aiError, setAiError] = useState7("");
17123
+ const [isRecording, setIsRecording] = useState10(false);
17124
+ const [audioBlob, setAudioBlob] = useState10(null);
17125
+ const [isTranscribing, setIsTranscribing] = useState10(false);
17126
+ const [transcriptionError, setTranscriptionError] = useState10("");
17127
+ const [showPromptInput, setShowPromptInput] = useState10(false);
17128
+ const [prompt2, setPrompt] = useState10("");
17129
+ const [isLoadingAI, setIsLoadingAI] = useState10(false);
17130
+ const [aiError, setAiError] = useState10("");
17131
+ const [showLangModal, setShowLangModal] = useState10(false);
16900
17132
  const mediaRecorderRef = useRef6(null);
16901
17133
  const chunksRef = useRef6([]);
16902
17134
  const startRecording = async () => {
@@ -16971,8 +17203,16 @@ function AiGroup({ editor, enabledFeatures }) {
16971
17203
  setIsLoadingAI(false);
16972
17204
  }
16973
17205
  };
16974
- if (!enabledFeatures.includes("voice to text")) return null;
16975
- return /* @__PURE__ */ React12.createElement("div", { className: "group flex flex-col gap-2 items-start" }, /* @__PURE__ */ React12.createElement("div", { className: "flex gap-2 items-center" }, enabledFeatures.includes("voice to text") && !isRecording && /* @__PURE__ */ React12.createElement(
17206
+ const handleLangClick = () => {
17207
+ setShowLangModal(true);
17208
+ };
17209
+ const handleLangResult = (output) => {
17210
+ if (output) {
17211
+ editor.commands.insertContent(output);
17212
+ setShowLangModal(false);
17213
+ }
17214
+ };
17215
+ return /* @__PURE__ */ React15.createElement("div", { className: "group flex flex-col gap-2 items-start" }, /* @__PURE__ */ React15.createElement("div", { className: "flex gap-2 items-center" }, enabledFeatures.includes("voice to text") && /* @__PURE__ */ React15.createElement(React15.Fragment, null, !isRecording ? /* @__PURE__ */ React15.createElement(
16976
17216
  "button",
16977
17217
  {
16978
17218
  type: "button",
@@ -16980,8 +17220,8 @@ function AiGroup({ editor, enabledFeatures }) {
16980
17220
  className: "icon-btn",
16981
17221
  title: "Start Voice Input"
16982
17222
  },
16983
- /* @__PURE__ */ React12.createElement(FaMicrophone, { size: 18 })
16984
- ), enabledFeatures.includes("voice to text") && isRecording && /* @__PURE__ */ React12.createElement(
17223
+ /* @__PURE__ */ React15.createElement(FaMicrophone3, { size: 18 })
17224
+ ) : /* @__PURE__ */ React15.createElement(
16985
17225
  "button",
16986
17226
  {
16987
17227
  type: "button",
@@ -16989,8 +17229,8 @@ function AiGroup({ editor, enabledFeatures }) {
16989
17229
  className: "icon-btn stop-btn",
16990
17230
  title: "Stop Recording"
16991
17231
  },
16992
- /* @__PURE__ */ React12.createElement(FaStop, { size: 18 })
16993
- ), enabledFeatures.includes("ai") && /* @__PURE__ */ React12.createElement(
17232
+ /* @__PURE__ */ React15.createElement(FaStop, { size: 18 })
17233
+ )), enabledFeatures.includes("ai") && /* @__PURE__ */ React15.createElement(
16994
17234
  "button",
16995
17235
  {
16996
17236
  type: "button",
@@ -16999,55 +17239,53 @@ function AiGroup({ editor, enabledFeatures }) {
16999
17239
  title: "AI Assist"
17000
17240
  },
17001
17241
  "AI"
17002
- )), isRecording && /* @__PURE__ */ React12.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React12.createElement(Waveform, { size: 30, lineWeight: 3.5, speed: 1, color: "#4F46E5" }), /* @__PURE__ */ React12.createElement("p", { className: "text-sm mt-1 text-gray-600" }, "Recording...")), isTranscribing && /* @__PURE__ */ React12.createElement("p", { className: "text-sm text-gray-500" }, "Transcribing..."), transcriptionError && /* @__PURE__ */ React12.createElement("p", { className: "text-sm text-red-600" }, transcriptionError), audioBlob && /* @__PURE__ */ React12.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React12.createElement("audio", { controls: true, src: URL.createObjectURL(audioBlob) })), /* @__PURE__ */ React12.createElement(AnimatePresence, null, showPromptInput && /* @__PURE__ */ React12.createElement(
17003
- motion.div,
17242
+ ), enabledFeatures.includes("language") && /* @__PURE__ */ React15.createElement(
17243
+ "button",
17004
17244
  {
17005
- className: "ai-modal-backdrop",
17006
- initial: { opacity: 0 },
17007
- animate: { opacity: 1 },
17008
- exit: { opacity: 0 }
17245
+ type: "button",
17246
+ onClick: handleLangClick,
17247
+ className: "lang-button ml-2",
17248
+ title: "Convert/Translate"
17009
17249
  },
17010
- /* @__PURE__ */ React12.createElement(
17011
- motion.div,
17012
- {
17013
- className: "ai-modal-content",
17014
- initial: { scale: 0.9, opacity: 0 },
17015
- animate: { scale: 1, opacity: 1 },
17016
- exit: { scale: 0.9, opacity: 0 }
17017
- },
17018
- /* @__PURE__ */ React12.createElement("h2", { className: "ai-modal-title" }, "AI Prompt"),
17019
- /* @__PURE__ */ React12.createElement(
17020
- "textarea",
17021
- {
17022
- className: "ai-modal-textarea",
17023
- value: prompt2,
17024
- onChange: (e) => setPrompt(e.target.value),
17025
- placeholder: "Enter your prompt here..."
17026
- }
17027
- ),
17028
- aiError && /* @__PURE__ */ React12.createElement("p", { className: "ai-modal-error" }, aiError),
17029
- /* @__PURE__ */ React12.createElement("div", { className: "ai-modal-actions" }, /* @__PURE__ */ React12.createElement(
17030
- "button",
17031
- {
17032
- onClick: () => setShowPromptInput(false),
17033
- className: "ai-cancel-btn"
17034
- },
17035
- "Cancel"
17036
- ), /* @__PURE__ */ React12.createElement(
17037
- "button",
17038
- {
17039
- onClick: handlePromptSubmit,
17040
- disabled: isLoadingAI,
17041
- className: "ai-submit-btn"
17042
- },
17043
- isLoadingAI ? "Generating..." : "Submit"
17044
- ))
17045
- )
17046
- )));
17250
+ /* @__PURE__ */ React15.createElement(FaLanguage, { size: 18 })
17251
+ )), isRecording && /* @__PURE__ */ React15.createElement("div", { className: "flex flex-col items-center" }, /* @__PURE__ */ React15.createElement(Waveform, { size: 30, lineWeight: 3.5, speed: 1, color: "#4F46E5" }), /* @__PURE__ */ React15.createElement("p", { className: "text-sm mt-1 text-gray-600" }, "Recording...")), isTranscribing && /* @__PURE__ */ React15.createElement("p", { className: "text-sm text-gray-500" }, "Transcribing..."), transcriptionError && /* @__PURE__ */ React15.createElement("p", { className: "text-sm text-red-600" }, transcriptionError), audioBlob && /* @__PURE__ */ React15.createElement("div", { className: "mt-2" }, /* @__PURE__ */ React15.createElement("audio", { controls: true, src: URL.createObjectURL(audioBlob) })), showPromptInput && /* @__PURE__ */ React15.createElement("div", { className: "ai-modal-backdrop" }, /* @__PURE__ */ React15.createElement("div", { className: "ai-modal-content" }, /* @__PURE__ */ React15.createElement("h2", { className: "ai-modal-title" }, "AI Prompt"), /* @__PURE__ */ React15.createElement(
17252
+ "textarea",
17253
+ {
17254
+ className: "ai-modal-textarea",
17255
+ value: prompt2,
17256
+ onChange: (e) => setPrompt(e.target.value),
17257
+ placeholder: "Enter your prompt here..."
17258
+ }
17259
+ ), aiError && /* @__PURE__ */ React15.createElement("p", { className: "ai-modal-error" }, aiError), /* @__PURE__ */ React15.createElement("div", { className: "ai-modal-actions" }, /* @__PURE__ */ React15.createElement(
17260
+ "button",
17261
+ {
17262
+ type: "button",
17263
+ onClick: () => setShowPromptInput(false),
17264
+ className: "ai-cancel-btn"
17265
+ },
17266
+ "Cancel"
17267
+ ), /* @__PURE__ */ React15.createElement(
17268
+ "button",
17269
+ {
17270
+ type: "button",
17271
+ onClick: handlePromptSubmit,
17272
+ disabled: isLoadingAI,
17273
+ className: "ai-submit-btn"
17274
+ },
17275
+ isLoadingAI ? "Generating..." : "Submit"
17276
+ )))), showLangModal && /* @__PURE__ */ React15.createElement("div", { className: "ai-modal-backdrop" }, /* @__PURE__ */ React15.createElement("div", { className: "ai-modal-content" }, /* @__PURE__ */ React15.createElement("h2", { className: "ai-modal-title" }, "Convert / Translate"), /* @__PURE__ */ React15.createElement(Tabs, { onResult: handleLangResult }), /* @__PURE__ */ React15.createElement("div", { className: "ai-modal-actions mt-2" }, /* @__PURE__ */ React15.createElement(
17277
+ "button",
17278
+ {
17279
+ type: "button",
17280
+ onClick: () => setShowLangModal(false),
17281
+ className: "ai-cancel-btn"
17282
+ },
17283
+ "Close"
17284
+ )))));
17047
17285
  }
17048
17286
 
17049
17287
  // src/components/tetrons/toolbar/AddOnGroup.tsx
17050
- import React15, { useState as useState9 } from "react";
17288
+ import React18, { useState as useState12 } from "react";
17051
17289
  import { SquareRadical, MessageSquareCode } from "lucide-react";
17052
17290
  import dynamic from "next/dynamic";
17053
17291
  import "katex/dist/katex.min.css";
@@ -17056,9 +17294,9 @@ var CodeEditorModal2 = dynamic(() => Promise.resolve().then(() => (init_CodeEdit
17056
17294
  ssr: false
17057
17295
  });
17058
17296
  var AddOnGroup = ({ editor, addOns }) => {
17059
- const [isMathModalOpen, setMathModalOpen] = useState9(false);
17060
- const [latexValue, setLatexValue] = useState9("");
17061
- const [isCodeModalOpen, setCodeModalOpen] = useState9(false);
17297
+ const [isMathModalOpen, setMathModalOpen] = useState12(false);
17298
+ const [latexValue, setLatexValue] = useState12("");
17299
+ const [isCodeModalOpen, setCodeModalOpen] = useState12(false);
17062
17300
  if (!editor) return null;
17063
17301
  const insertCodeBlock = () => setCodeModalOpen(true);
17064
17302
  const handleMathInsert = (latex) => {
@@ -17089,7 +17327,7 @@ var AddOnGroup = ({ editor, addOns }) => {
17089
17327
  }).run();
17090
17328
  setCodeModalOpen(false);
17091
17329
  };
17092
- return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "group flex gap-2 items-center" }, addOns.includes("code") && /* @__PURE__ */ React15.createElement(
17330
+ return /* @__PURE__ */ React18.createElement(React18.Fragment, null, /* @__PURE__ */ React18.createElement("div", { className: "group flex gap-2 items-center" }, addOns.includes("code") && /* @__PURE__ */ React18.createElement(
17093
17331
  "button",
17094
17332
  {
17095
17333
  type: "button",
@@ -17097,8 +17335,8 @@ var AddOnGroup = ({ editor, addOns }) => {
17097
17335
  className: "addon-btn",
17098
17336
  title: "Open Code Editor"
17099
17337
  },
17100
- /* @__PURE__ */ React15.createElement(MessageSquareCode, { size: 18 })
17101
- ), addOns.includes("math") && /* @__PURE__ */ React15.createElement(
17338
+ /* @__PURE__ */ React18.createElement(MessageSquareCode, { size: 18 })
17339
+ ), addOns.includes("math") && /* @__PURE__ */ React18.createElement(
17102
17340
  "button",
17103
17341
  {
17104
17342
  type: "button",
@@ -17106,8 +17344,8 @@ var AddOnGroup = ({ editor, addOns }) => {
17106
17344
  className: "addon-btn",
17107
17345
  title: "Insert Math Equation"
17108
17346
  },
17109
- /* @__PURE__ */ React15.createElement(SquareRadical, { size: 18 })
17110
- )), addOns.includes("math") && /* @__PURE__ */ React15.createElement(
17347
+ /* @__PURE__ */ React18.createElement(SquareRadical, { size: 18 })
17348
+ )), addOns.includes("math") && /* @__PURE__ */ React18.createElement(
17111
17349
  MathModal2,
17112
17350
  {
17113
17351
  isOpen: isMathModalOpen,
@@ -17116,7 +17354,7 @@ var AddOnGroup = ({ editor, addOns }) => {
17116
17354
  value: latexValue,
17117
17355
  setValue: setLatexValue
17118
17356
  }
17119
- ), addOns.includes("code") && /* @__PURE__ */ React15.createElement(
17357
+ ), addOns.includes("code") && /* @__PURE__ */ React18.createElement(
17120
17358
  CodeEditorModal2,
17121
17359
  {
17122
17360
  isOpen: isCodeModalOpen,
@@ -17134,7 +17372,7 @@ function TetronsToolbar({
17134
17372
  version,
17135
17373
  addOns = []
17136
17374
  }) {
17137
- const [autoSave, setAutoSave] = useState10(false);
17375
+ const [autoSave, setAutoSave] = useState13(false);
17138
17376
  useEffect8(() => {
17139
17377
  if (!editor || !autoSave) return;
17140
17378
  const handleUpdate = () => {
@@ -17172,7 +17410,7 @@ function TetronsToolbar({
17172
17410
  return [];
17173
17411
  }
17174
17412
  })();
17175
- return /* @__PURE__ */ React16.createElement("div", { className: "tetrons-toolbar" }, version !== "free" && /* @__PURE__ */ React16.createElement("div", { className: "group" }, /* @__PURE__ */ React16.createElement(
17413
+ return /* @__PURE__ */ React19.createElement("div", { className: "tetrons-toolbar" }, version !== "free" && /* @__PURE__ */ React19.createElement("div", { className: "group" }, /* @__PURE__ */ React19.createElement(
17176
17414
  "input",
17177
17415
  {
17178
17416
  type: "checkbox",
@@ -17180,7 +17418,7 @@ function TetronsToolbar({
17180
17418
  checked: autoSave,
17181
17419
  onChange: (e) => setAutoSave(e.target.checked)
17182
17420
  }
17183
- ), /* @__PURE__ */ React16.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ React16.createElement(FileGroup, { editor }), /* @__PURE__ */ React16.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ React16.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ React16.createElement(ListAlignGroup, { editor }), ["premium", "platinum"].includes(version) && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(InsertGroup, { editor }), /* @__PURE__ */ React16.createElement(ActionGroup, { editor })), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ React16.createElement(
17421
+ ), /* @__PURE__ */ React19.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ React19.createElement(FileGroup, { editor }), /* @__PURE__ */ React19.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ React19.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ React19.createElement(ListAlignGroup, { editor }), ["premium", "platinum"].includes(version) && /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(InsertGroup, { editor }), /* @__PURE__ */ React19.createElement(ActionGroup, { editor })), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ React19.createElement(
17184
17422
  MiscGroup,
17185
17423
  {
17186
17424
  editor,
@@ -17195,18 +17433,18 @@ function TetronsToolbar({
17195
17433
  ].includes(a)
17196
17434
  )
17197
17435
  }
17198
- ), (version === "platinum" || effectiveAddOns.includes("ai") || effectiveAddOns.includes("voice to text")) && /* @__PURE__ */ React16.createElement(
17436
+ ), (version === "platinum" || effectiveAddOns.includes("ai") || effectiveAddOns.includes("voice to text")) && /* @__PURE__ */ React19.createElement(
17199
17437
  AiGroup,
17200
17438
  {
17201
17439
  editor,
17202
17440
  enabledFeatures: [
17203
- ...version === "platinum" ? ["ai"] : [],
17441
+ ...version === "platinum" ? ["ai", "language"] : [],
17204
17442
  ...effectiveAddOns.filter(
17205
- (a) => ["ai", "voice to text"].includes(a)
17443
+ (a) => ["ai", "voice to text", "language"].includes(a)
17206
17444
  )
17207
17445
  ]
17208
17446
  }
17209
- ), effectiveAddOns.some((a) => a === "math" || a === "code") && /* @__PURE__ */ React16.createElement(
17447
+ ), effectiveAddOns.some((a) => a === "math" || a === "code") && /* @__PURE__ */ React19.createElement(
17210
17448
  AddOnGroup_default,
17211
17449
  {
17212
17450
  editor,
@@ -17221,14 +17459,14 @@ lowlight.register("js", javascript);
17221
17459
  lowlight.register("ts", typescript);
17222
17460
  function EditorContent({ apiKey }) {
17223
17461
  const typo = useTypo();
17224
- const [isValid, setIsValid] = useState11(null);
17225
- const [error, setError] = useState11(null);
17226
- const [versions, setVersions] = useState11([]);
17227
- const [userVersion, setUserVersion] = useState11(null);
17228
- const [currentVersionIndex, setCurrentVersionIndex] = useState11(
17462
+ const [isValid, setIsValid] = useState14(null);
17463
+ const [error, setError] = useState14(null);
17464
+ const [versions, setVersions] = useState14([]);
17465
+ const [userVersion, setUserVersion] = useState14(null);
17466
+ const [currentVersionIndex, setCurrentVersionIndex] = useState14(
17229
17467
  null
17230
17468
  );
17231
- const [addOns, setAddOns] = useState11([]);
17469
+ const [addOns, setAddOns] = useState14([]);
17232
17470
  const wrapperRef = useRef7(null);
17233
17471
  const API_BASE_URL = typeof process !== "undefined" && process.env?.NEXT_PUBLIC_TETRONS_API_URL ? process.env.NEXT_PUBLIC_TETRONS_API_URL : "https://staging.tetrons.com";
17234
17472
  useEffect9(() => {
@@ -17339,15 +17577,15 @@ function EditorContent({ apiKey }) {
17339
17577
  }
17340
17578
  };
17341
17579
  if (isValid === false) {
17342
- return /* @__PURE__ */ React17.createElement("div", { className: "editor-error" }, "\u26A0\uFE0F ", error);
17580
+ return /* @__PURE__ */ React20.createElement("div", { className: "editor-error" }, "\u26A0\uFE0F ", error);
17343
17581
  }
17344
17582
  if (isValid === null) {
17345
- return /* @__PURE__ */ React17.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
17583
+ return /* @__PURE__ */ React20.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
17346
17584
  }
17347
17585
  if (!typo) {
17348
- return /* @__PURE__ */ React17.createElement("div", { className: "editor-loading" }, "\u{1F4D6} Loading dictionary...");
17586
+ return /* @__PURE__ */ React20.createElement("div", { className: "editor-loading" }, "\u{1F4D6} Loading dictionary...");
17349
17587
  }
17350
- return /* @__PURE__ */ React17.createElement("div", { className: "editor-container" }, userVersion !== "free" && /* @__PURE__ */ React17.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ React17.createElement(
17588
+ return /* @__PURE__ */ React20.createElement("div", { className: "editor-container" }, userVersion !== "free" && /* @__PURE__ */ React20.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ React20.createElement(
17351
17589
  "button",
17352
17590
  {
17353
17591
  type: "button",
@@ -17356,7 +17594,7 @@ function EditorContent({ apiKey }) {
17356
17594
  className: "editor-save-btn"
17357
17595
  },
17358
17596
  "Save Version"
17359
- ), /* @__PURE__ */ React17.createElement("div", { className: "editor-versions-wrapper" }, versions.length === 0 ? /* @__PURE__ */ React17.createElement("span", { className: "editor-no-versions" }, "No saved versions") : versions.map((_, idx) => /* @__PURE__ */ React17.createElement(
17597
+ ), /* @__PURE__ */ React20.createElement("div", { className: "editor-versions-wrapper" }, versions.length === 0 ? /* @__PURE__ */ React20.createElement("span", { className: "editor-no-versions" }, "No saved versions") : versions.map((_, idx) => /* @__PURE__ */ React20.createElement(
17360
17598
  "button",
17361
17599
  {
17362
17600
  key: idx,
@@ -17366,14 +17604,14 @@ function EditorContent({ apiKey }) {
17366
17604
  title: `Restore Version ${idx + 1}`
17367
17605
  },
17368
17606
  `V${idx + 1}`
17369
- )))), editor && userVersion && /* @__PURE__ */ React17.createElement(TetronsToolbar, { editor, version: userVersion, addOns }), /* @__PURE__ */ React17.createElement(
17607
+ )))), editor && userVersion && /* @__PURE__ */ React20.createElement(TetronsToolbar, { editor, version: userVersion, addOns }), /* @__PURE__ */ React20.createElement(
17370
17608
  "div",
17371
17609
  {
17372
17610
  ref: wrapperRef,
17373
17611
  className: "editor-content-wrapper",
17374
17612
  onClick: handleEditorClick
17375
17613
  },
17376
- editor ? /* @__PURE__ */ React17.createElement(React17.Fragment, null, /* @__PURE__ */ React17.createElement(TiptapEditorContent, { editor }), /* @__PURE__ */ React17.createElement(TableContextMenu, { editor })) : /* @__PURE__ */ React17.createElement("div", { className: "editor-loading" }, "Loading editor...")
17614
+ editor ? /* @__PURE__ */ React20.createElement(React20.Fragment, null, /* @__PURE__ */ React20.createElement(TiptapEditorContent, { editor }), /* @__PURE__ */ React20.createElement(TableContextMenu, { editor })) : /* @__PURE__ */ React20.createElement("div", { className: "editor-loading" }, "Loading editor...")
17377
17615
  ));
17378
17616
  }
17379
17617