tetrons 2.3.97 → 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.cjs +338 -79
- package/dist/index.mjs +326 -67
- package/dist/styles/tetrons.css +281 -7
- package/package.json +1 -1
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
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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] =
|
|
89
|
-
const [code, setCode] =
|
|
90
|
-
const [output, setOutput] =
|
|
91
|
-
const [loading, setLoading] =
|
|
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__ */
|
|
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__ */
|
|
135
|
-
/* @__PURE__ */
|
|
136
|
-
/* @__PURE__ */
|
|
137
|
-
/* @__PURE__ */
|
|
138
|
-
/* @__PURE__ */
|
|
139
|
-
), /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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
|
|
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,18 +16884,251 @@ function FileGroup({ editor }) {
|
|
|
16884
16884
|
}
|
|
16885
16885
|
|
|
16886
16886
|
// src/components/tetrons/toolbar/AIGroup.tsx
|
|
16887
|
-
import
|
|
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
|
+
|
|
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
|
|
16890
17122
|
function AiGroup({ editor, enabledFeatures }) {
|
|
16891
|
-
const [isRecording, setIsRecording] =
|
|
16892
|
-
const [audioBlob, setAudioBlob] =
|
|
16893
|
-
const [isTranscribing, setIsTranscribing] =
|
|
16894
|
-
const [transcriptionError, setTranscriptionError] =
|
|
16895
|
-
const [showPromptInput, setShowPromptInput] =
|
|
16896
|
-
const [prompt2, setPrompt] =
|
|
16897
|
-
const [isLoadingAI, setIsLoadingAI] =
|
|
16898
|
-
const [aiError, setAiError] =
|
|
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);
|
|
16899
17132
|
const mediaRecorderRef = useRef6(null);
|
|
16900
17133
|
const chunksRef = useRef6([]);
|
|
16901
17134
|
const startRecording = async () => {
|
|
@@ -16970,7 +17203,16 @@ function AiGroup({ editor, enabledFeatures }) {
|
|
|
16970
17203
|
setIsLoadingAI(false);
|
|
16971
17204
|
}
|
|
16972
17205
|
};
|
|
16973
|
-
|
|
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(
|
|
16974
17216
|
"button",
|
|
16975
17217
|
{
|
|
16976
17218
|
type: "button",
|
|
@@ -16978,8 +17220,8 @@ function AiGroup({ editor, enabledFeatures }) {
|
|
|
16978
17220
|
className: "icon-btn",
|
|
16979
17221
|
title: "Start Voice Input"
|
|
16980
17222
|
},
|
|
16981
|
-
/* @__PURE__ */
|
|
16982
|
-
) : /* @__PURE__ */
|
|
17223
|
+
/* @__PURE__ */ React15.createElement(FaMicrophone3, { size: 18 })
|
|
17224
|
+
) : /* @__PURE__ */ React15.createElement(
|
|
16983
17225
|
"button",
|
|
16984
17226
|
{
|
|
16985
17227
|
type: "button",
|
|
@@ -16987,8 +17229,8 @@ function AiGroup({ editor, enabledFeatures }) {
|
|
|
16987
17229
|
className: "icon-btn stop-btn",
|
|
16988
17230
|
title: "Stop Recording"
|
|
16989
17231
|
},
|
|
16990
|
-
/* @__PURE__ */
|
|
16991
|
-
)), enabledFeatures.includes("ai") && /* @__PURE__ */
|
|
17232
|
+
/* @__PURE__ */ React15.createElement(FaStop, { size: 18 })
|
|
17233
|
+
)), enabledFeatures.includes("ai") && /* @__PURE__ */ React15.createElement(
|
|
16992
17234
|
"button",
|
|
16993
17235
|
{
|
|
16994
17236
|
type: "button",
|
|
@@ -16997,7 +17239,16 @@ function AiGroup({ editor, enabledFeatures }) {
|
|
|
16997
17239
|
title: "AI Assist"
|
|
16998
17240
|
},
|
|
16999
17241
|
"AI"
|
|
17000
|
-
)
|
|
17242
|
+
), enabledFeatures.includes("language") && /* @__PURE__ */ React15.createElement(
|
|
17243
|
+
"button",
|
|
17244
|
+
{
|
|
17245
|
+
type: "button",
|
|
17246
|
+
onClick: handleLangClick,
|
|
17247
|
+
className: "lang-button ml-2",
|
|
17248
|
+
title: "Convert/Translate"
|
|
17249
|
+
},
|
|
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(
|
|
17001
17252
|
"textarea",
|
|
17002
17253
|
{
|
|
17003
17254
|
className: "ai-modal-textarea",
|
|
@@ -17005,7 +17256,7 @@ function AiGroup({ editor, enabledFeatures }) {
|
|
|
17005
17256
|
onChange: (e) => setPrompt(e.target.value),
|
|
17006
17257
|
placeholder: "Enter your prompt here..."
|
|
17007
17258
|
}
|
|
17008
|
-
), aiError && /* @__PURE__ */
|
|
17259
|
+
), aiError && /* @__PURE__ */ React15.createElement("p", { className: "ai-modal-error" }, aiError), /* @__PURE__ */ React15.createElement("div", { className: "ai-modal-actions" }, /* @__PURE__ */ React15.createElement(
|
|
17009
17260
|
"button",
|
|
17010
17261
|
{
|
|
17011
17262
|
type: "button",
|
|
@@ -17013,7 +17264,7 @@ function AiGroup({ editor, enabledFeatures }) {
|
|
|
17013
17264
|
className: "ai-cancel-btn"
|
|
17014
17265
|
},
|
|
17015
17266
|
"Cancel"
|
|
17016
|
-
), /* @__PURE__ */
|
|
17267
|
+
), /* @__PURE__ */ React15.createElement(
|
|
17017
17268
|
"button",
|
|
17018
17269
|
{
|
|
17019
17270
|
type: "button",
|
|
@@ -17022,11 +17273,19 @@ function AiGroup({ editor, enabledFeatures }) {
|
|
|
17022
17273
|
className: "ai-submit-btn"
|
|
17023
17274
|
},
|
|
17024
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"
|
|
17025
17284
|
)))));
|
|
17026
17285
|
}
|
|
17027
17286
|
|
|
17028
17287
|
// src/components/tetrons/toolbar/AddOnGroup.tsx
|
|
17029
|
-
import
|
|
17288
|
+
import React18, { useState as useState12 } from "react";
|
|
17030
17289
|
import { SquareRadical, MessageSquareCode } from "lucide-react";
|
|
17031
17290
|
import dynamic from "next/dynamic";
|
|
17032
17291
|
import "katex/dist/katex.min.css";
|
|
@@ -17035,9 +17294,9 @@ var CodeEditorModal2 = dynamic(() => Promise.resolve().then(() => (init_CodeEdit
|
|
|
17035
17294
|
ssr: false
|
|
17036
17295
|
});
|
|
17037
17296
|
var AddOnGroup = ({ editor, addOns }) => {
|
|
17038
|
-
const [isMathModalOpen, setMathModalOpen] =
|
|
17039
|
-
const [latexValue, setLatexValue] =
|
|
17040
|
-
const [isCodeModalOpen, setCodeModalOpen] =
|
|
17297
|
+
const [isMathModalOpen, setMathModalOpen] = useState12(false);
|
|
17298
|
+
const [latexValue, setLatexValue] = useState12("");
|
|
17299
|
+
const [isCodeModalOpen, setCodeModalOpen] = useState12(false);
|
|
17041
17300
|
if (!editor) return null;
|
|
17042
17301
|
const insertCodeBlock = () => setCodeModalOpen(true);
|
|
17043
17302
|
const handleMathInsert = (latex) => {
|
|
@@ -17068,7 +17327,7 @@ var AddOnGroup = ({ editor, addOns }) => {
|
|
|
17068
17327
|
}).run();
|
|
17069
17328
|
setCodeModalOpen(false);
|
|
17070
17329
|
};
|
|
17071
|
-
return /* @__PURE__ */
|
|
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(
|
|
17072
17331
|
"button",
|
|
17073
17332
|
{
|
|
17074
17333
|
type: "button",
|
|
@@ -17076,8 +17335,8 @@ var AddOnGroup = ({ editor, addOns }) => {
|
|
|
17076
17335
|
className: "addon-btn",
|
|
17077
17336
|
title: "Open Code Editor"
|
|
17078
17337
|
},
|
|
17079
|
-
/* @__PURE__ */
|
|
17080
|
-
), addOns.includes("math") && /* @__PURE__ */
|
|
17338
|
+
/* @__PURE__ */ React18.createElement(MessageSquareCode, { size: 18 })
|
|
17339
|
+
), addOns.includes("math") && /* @__PURE__ */ React18.createElement(
|
|
17081
17340
|
"button",
|
|
17082
17341
|
{
|
|
17083
17342
|
type: "button",
|
|
@@ -17085,8 +17344,8 @@ var AddOnGroup = ({ editor, addOns }) => {
|
|
|
17085
17344
|
className: "addon-btn",
|
|
17086
17345
|
title: "Insert Math Equation"
|
|
17087
17346
|
},
|
|
17088
|
-
/* @__PURE__ */
|
|
17089
|
-
)), addOns.includes("math") && /* @__PURE__ */
|
|
17347
|
+
/* @__PURE__ */ React18.createElement(SquareRadical, { size: 18 })
|
|
17348
|
+
)), addOns.includes("math") && /* @__PURE__ */ React18.createElement(
|
|
17090
17349
|
MathModal2,
|
|
17091
17350
|
{
|
|
17092
17351
|
isOpen: isMathModalOpen,
|
|
@@ -17095,7 +17354,7 @@ var AddOnGroup = ({ editor, addOns }) => {
|
|
|
17095
17354
|
value: latexValue,
|
|
17096
17355
|
setValue: setLatexValue
|
|
17097
17356
|
}
|
|
17098
|
-
), addOns.includes("code") && /* @__PURE__ */
|
|
17357
|
+
), addOns.includes("code") && /* @__PURE__ */ React18.createElement(
|
|
17099
17358
|
CodeEditorModal2,
|
|
17100
17359
|
{
|
|
17101
17360
|
isOpen: isCodeModalOpen,
|
|
@@ -17113,7 +17372,7 @@ function TetronsToolbar({
|
|
|
17113
17372
|
version,
|
|
17114
17373
|
addOns = []
|
|
17115
17374
|
}) {
|
|
17116
|
-
const [autoSave, setAutoSave] =
|
|
17375
|
+
const [autoSave, setAutoSave] = useState13(false);
|
|
17117
17376
|
useEffect8(() => {
|
|
17118
17377
|
if (!editor || !autoSave) return;
|
|
17119
17378
|
const handleUpdate = () => {
|
|
@@ -17151,7 +17410,7 @@ function TetronsToolbar({
|
|
|
17151
17410
|
return [];
|
|
17152
17411
|
}
|
|
17153
17412
|
})();
|
|
17154
|
-
return /* @__PURE__ */
|
|
17413
|
+
return /* @__PURE__ */ React19.createElement("div", { className: "tetrons-toolbar" }, version !== "free" && /* @__PURE__ */ React19.createElement("div", { className: "group" }, /* @__PURE__ */ React19.createElement(
|
|
17155
17414
|
"input",
|
|
17156
17415
|
{
|
|
17157
17416
|
type: "checkbox",
|
|
@@ -17159,7 +17418,7 @@ function TetronsToolbar({
|
|
|
17159
17418
|
checked: autoSave,
|
|
17160
17419
|
onChange: (e) => setAutoSave(e.target.checked)
|
|
17161
17420
|
}
|
|
17162
|
-
), /* @__PURE__ */
|
|
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(
|
|
17163
17422
|
MiscGroup,
|
|
17164
17423
|
{
|
|
17165
17424
|
editor,
|
|
@@ -17174,18 +17433,18 @@ function TetronsToolbar({
|
|
|
17174
17433
|
].includes(a)
|
|
17175
17434
|
)
|
|
17176
17435
|
}
|
|
17177
|
-
), (version === "platinum" || effectiveAddOns.includes("ai") || effectiveAddOns.includes("voice to text")) && /* @__PURE__ */
|
|
17436
|
+
), (version === "platinum" || effectiveAddOns.includes("ai") || effectiveAddOns.includes("voice to text")) && /* @__PURE__ */ React19.createElement(
|
|
17178
17437
|
AiGroup,
|
|
17179
17438
|
{
|
|
17180
17439
|
editor,
|
|
17181
17440
|
enabledFeatures: [
|
|
17182
|
-
...version === "platinum" ? ["ai"] : [],
|
|
17441
|
+
...version === "platinum" ? ["ai", "language"] : [],
|
|
17183
17442
|
...effectiveAddOns.filter(
|
|
17184
|
-
(a) => ["ai", "voice to text"].includes(a)
|
|
17443
|
+
(a) => ["ai", "voice to text", "language"].includes(a)
|
|
17185
17444
|
)
|
|
17186
17445
|
]
|
|
17187
17446
|
}
|
|
17188
|
-
), effectiveAddOns.some((a) => a === "math" || a === "code") && /* @__PURE__ */
|
|
17447
|
+
), effectiveAddOns.some((a) => a === "math" || a === "code") && /* @__PURE__ */ React19.createElement(
|
|
17189
17448
|
AddOnGroup_default,
|
|
17190
17449
|
{
|
|
17191
17450
|
editor,
|
|
@@ -17200,14 +17459,14 @@ lowlight.register("js", javascript);
|
|
|
17200
17459
|
lowlight.register("ts", typescript);
|
|
17201
17460
|
function EditorContent({ apiKey }) {
|
|
17202
17461
|
const typo = useTypo();
|
|
17203
|
-
const [isValid, setIsValid] =
|
|
17204
|
-
const [error, setError] =
|
|
17205
|
-
const [versions, setVersions] =
|
|
17206
|
-
const [userVersion, setUserVersion] =
|
|
17207
|
-
const [currentVersionIndex, setCurrentVersionIndex] =
|
|
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(
|
|
17208
17467
|
null
|
|
17209
17468
|
);
|
|
17210
|
-
const [addOns, setAddOns] =
|
|
17469
|
+
const [addOns, setAddOns] = useState14([]);
|
|
17211
17470
|
const wrapperRef = useRef7(null);
|
|
17212
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";
|
|
17213
17472
|
useEffect9(() => {
|
|
@@ -17318,15 +17577,15 @@ function EditorContent({ apiKey }) {
|
|
|
17318
17577
|
}
|
|
17319
17578
|
};
|
|
17320
17579
|
if (isValid === false) {
|
|
17321
|
-
return /* @__PURE__ */
|
|
17580
|
+
return /* @__PURE__ */ React20.createElement("div", { className: "editor-error" }, "\u26A0\uFE0F ", error);
|
|
17322
17581
|
}
|
|
17323
17582
|
if (isValid === null) {
|
|
17324
|
-
return /* @__PURE__ */
|
|
17583
|
+
return /* @__PURE__ */ React20.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
|
|
17325
17584
|
}
|
|
17326
17585
|
if (!typo) {
|
|
17327
|
-
return /* @__PURE__ */
|
|
17586
|
+
return /* @__PURE__ */ React20.createElement("div", { className: "editor-loading" }, "\u{1F4D6} Loading dictionary...");
|
|
17328
17587
|
}
|
|
17329
|
-
return /* @__PURE__ */
|
|
17588
|
+
return /* @__PURE__ */ React20.createElement("div", { className: "editor-container" }, userVersion !== "free" && /* @__PURE__ */ React20.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ React20.createElement(
|
|
17330
17589
|
"button",
|
|
17331
17590
|
{
|
|
17332
17591
|
type: "button",
|
|
@@ -17335,7 +17594,7 @@ function EditorContent({ apiKey }) {
|
|
|
17335
17594
|
className: "editor-save-btn"
|
|
17336
17595
|
},
|
|
17337
17596
|
"Save Version"
|
|
17338
|
-
), /* @__PURE__ */
|
|
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(
|
|
17339
17598
|
"button",
|
|
17340
17599
|
{
|
|
17341
17600
|
key: idx,
|
|
@@ -17345,14 +17604,14 @@ function EditorContent({ apiKey }) {
|
|
|
17345
17604
|
title: `Restore Version ${idx + 1}`
|
|
17346
17605
|
},
|
|
17347
17606
|
`V${idx + 1}`
|
|
17348
|
-
)))), editor && userVersion && /* @__PURE__ */
|
|
17607
|
+
)))), editor && userVersion && /* @__PURE__ */ React20.createElement(TetronsToolbar, { editor, version: userVersion, addOns }), /* @__PURE__ */ React20.createElement(
|
|
17349
17608
|
"div",
|
|
17350
17609
|
{
|
|
17351
17610
|
ref: wrapperRef,
|
|
17352
17611
|
className: "editor-content-wrapper",
|
|
17353
17612
|
onClick: handleEditorClick
|
|
17354
17613
|
},
|
|
17355
|
-
editor ? /* @__PURE__ */
|
|
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...")
|
|
17356
17615
|
));
|
|
17357
17616
|
}
|
|
17358
17617
|
|