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.cjs +359 -121
- package/dist/index.mjs +347 -109
- 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,19 +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
|
-
|
|
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] =
|
|
16893
|
-
const [audioBlob, setAudioBlob] =
|
|
16894
|
-
const [isTranscribing, setIsTranscribing] =
|
|
16895
|
-
const [transcriptionError, setTranscriptionError] =
|
|
16896
|
-
const [showPromptInput, setShowPromptInput] =
|
|
16897
|
-
const [prompt2, setPrompt] =
|
|
16898
|
-
const [isLoadingAI, setIsLoadingAI] =
|
|
16899
|
-
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);
|
|
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
|
-
|
|
16975
|
-
|
|
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__ */
|
|
16984
|
-
)
|
|
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__ */
|
|
16993
|
-
), enabledFeatures.includes("ai") && /* @__PURE__ */
|
|
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
|
-
)
|
|
17003
|
-
|
|
17242
|
+
), enabledFeatures.includes("language") && /* @__PURE__ */ React15.createElement(
|
|
17243
|
+
"button",
|
|
17004
17244
|
{
|
|
17005
|
-
|
|
17006
|
-
|
|
17007
|
-
|
|
17008
|
-
|
|
17245
|
+
type: "button",
|
|
17246
|
+
onClick: handleLangClick,
|
|
17247
|
+
className: "lang-button ml-2",
|
|
17248
|
+
title: "Convert/Translate"
|
|
17009
17249
|
},
|
|
17010
|
-
/* @__PURE__ */
|
|
17011
|
-
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
|
|
17022
|
-
|
|
17023
|
-
|
|
17024
|
-
|
|
17025
|
-
|
|
17026
|
-
|
|
17027
|
-
|
|
17028
|
-
|
|
17029
|
-
|
|
17030
|
-
|
|
17031
|
-
|
|
17032
|
-
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
17043
|
-
|
|
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
|
|
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] =
|
|
17060
|
-
const [latexValue, setLatexValue] =
|
|
17061
|
-
const [isCodeModalOpen, setCodeModalOpen] =
|
|
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__ */
|
|
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__ */
|
|
17101
|
-
), addOns.includes("math") && /* @__PURE__ */
|
|
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__ */
|
|
17110
|
-
)), addOns.includes("math") && /* @__PURE__ */
|
|
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__ */
|
|
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] =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
17225
|
-
const [error, setError] =
|
|
17226
|
-
const [versions, setVersions] =
|
|
17227
|
-
const [userVersion, setUserVersion] =
|
|
17228
|
-
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(
|
|
17229
17467
|
null
|
|
17230
17468
|
);
|
|
17231
|
-
const [addOns, setAddOns] =
|
|
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__ */
|
|
17580
|
+
return /* @__PURE__ */ React20.createElement("div", { className: "editor-error" }, "\u26A0\uFE0F ", error);
|
|
17343
17581
|
}
|
|
17344
17582
|
if (isValid === null) {
|
|
17345
|
-
return /* @__PURE__ */
|
|
17583
|
+
return /* @__PURE__ */ React20.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
|
|
17346
17584
|
}
|
|
17347
17585
|
if (!typo) {
|
|
17348
|
-
return /* @__PURE__ */
|
|
17586
|
+
return /* @__PURE__ */ React20.createElement("div", { className: "editor-loading" }, "\u{1F4D6} Loading dictionary...");
|
|
17349
17587
|
}
|
|
17350
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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
|
|