tetrons 2.3.77 → 2.3.78

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.
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/app/api/execute/route.ts
21
+ var route_exports = {};
22
+ __export(route_exports, {
23
+ POST: () => POST
24
+ });
25
+ module.exports = __toCommonJS(route_exports);
26
+ var import_server = require("next/server");
27
+ async function POST(req) {
28
+ const { language, code } = await req.json();
29
+ console.log(language, code);
30
+ const res = await fetch("https://emkc.org/api/v2/piston/execute", {
31
+ method: "POST",
32
+ headers: { "Content-Type": "application/json" },
33
+ body: JSON.stringify({
34
+ language,
35
+ version: "*",
36
+ files: [
37
+ {
38
+ name: `main.${language === "cpp" ? "cpp" : language}`,
39
+ content: code
40
+ }
41
+ ],
42
+ args: [],
43
+ stdin: ""
44
+ })
45
+ });
46
+ const data = await res.json();
47
+ return import_server.NextResponse.json({
48
+ stdout: data.run?.stdout ?? "",
49
+ stderr: data.run?.stderr ?? ""
50
+ });
51
+ }
52
+ // Annotate the CommonJS export names for ESM import in node:
53
+ 0 && (module.exports = {
54
+ POST
55
+ });
@@ -0,0 +1,8 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ declare function POST(req: NextRequest): Promise<NextResponse<{
4
+ stdout: any;
5
+ stderr: any;
6
+ }>>;
7
+
8
+ export { POST };
@@ -0,0 +1,8 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ declare function POST(req: NextRequest): Promise<NextResponse<{
4
+ stdout: any;
5
+ stderr: any;
6
+ }>>;
7
+
8
+ export { POST };
@@ -0,0 +1,30 @@
1
+ // src/app/api/execute/route.ts
2
+ import { NextResponse } from "next/server";
3
+ async function POST(req) {
4
+ const { language, code } = await req.json();
5
+ console.log(language, code);
6
+ const res = await fetch("https://emkc.org/api/v2/piston/execute", {
7
+ method: "POST",
8
+ headers: { "Content-Type": "application/json" },
9
+ body: JSON.stringify({
10
+ language,
11
+ version: "*",
12
+ files: [
13
+ {
14
+ name: `main.${language === "cpp" ? "cpp" : language}`,
15
+ content: code
16
+ }
17
+ ],
18
+ args: [],
19
+ stdin: ""
20
+ })
21
+ });
22
+ const data = await res.json();
23
+ return NextResponse.json({
24
+ stdout: data.run?.stdout ?? "",
25
+ stderr: data.run?.stderr ?? ""
26
+ });
27
+ }
28
+ export {
29
+ POST
30
+ };
package/dist/index.cjs CHANGED
@@ -90,6 +90,73 @@ var init_MathModal = __esm({
90
90
  }
91
91
  });
92
92
 
93
+ // src/components/tetrons/toolbar/CodeEditorModal.js
94
+ var CodeEditorModal_exports = {};
95
+ __export(CodeEditorModal_exports, {
96
+ default: () => CodeEditorModal_default
97
+ });
98
+ var import_react20, import_react21, CodeEditorModal, CodeEditorModal_default;
99
+ var init_CodeEditorModal = __esm({
100
+ "src/components/tetrons/toolbar/CodeEditorModal.js"() {
101
+ "use strict";
102
+ "use client";
103
+ import_react20 = __toESM(require("react"));
104
+ import_react21 = __toESM(require("@monaco-editor/react"));
105
+ CodeEditorModal = ({ isOpen, onClose }) => {
106
+ const [language, setLanguage] = (0, import_react20.useState)("javascript");
107
+ const [code, setCode] = (0, import_react20.useState)("// Write your code here");
108
+ const [output, setOutput] = (0, import_react20.useState)("");
109
+ const [loading, setLoading] = (0, import_react20.useState)(false);
110
+ const runCode = async () => {
111
+ setLoading(true);
112
+ try {
113
+ const res = await fetch("/api/execute", {
114
+ method: "POST",
115
+ headers: { "Content-Type": "application/json" },
116
+ body: JSON.stringify({ language, code })
117
+ });
118
+ const data = await res.json();
119
+ let result = "";
120
+ if (data.stderr) result += `Error:
121
+ ${data.stderr}
122
+ `;
123
+ if (data.stdout) result += data.stdout;
124
+ if (!data.stdout && !data.stderr) result = "No output";
125
+ setOutput(result);
126
+ } catch (err) {
127
+ console.log(err.message);
128
+ setOutput("Error running code");
129
+ }
130
+ setLoading(false);
131
+ };
132
+ if (!isOpen) return null;
133
+ return /* @__PURE__ */ import_react20.default.createElement("div", { className: "code-modal-overlay" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "code-modal-content" }, /* @__PURE__ */ import_react20.default.createElement("div", { className: "code-modal-header" }, /* @__PURE__ */ import_react20.default.createElement("h2", null, "Run Code"), /* @__PURE__ */ import_react20.default.createElement("button", { onClick: onClose, className: "code-close-btn" }, "\xD7")), /* @__PURE__ */ import_react20.default.createElement("div", { className: "code-modal-controls" }, /* @__PURE__ */ import_react20.default.createElement("label", { htmlFor: "language" }, "Language:"), /* @__PURE__ */ import_react20.default.createElement(
134
+ "select",
135
+ {
136
+ id: "language",
137
+ value: language,
138
+ onChange: (e) => setLanguage(e.target.value)
139
+ },
140
+ /* @__PURE__ */ import_react20.default.createElement("option", { value: "javascript" }, "JavaScript"),
141
+ /* @__PURE__ */ import_react20.default.createElement("option", { value: "python" }, "Python"),
142
+ /* @__PURE__ */ import_react20.default.createElement("option", { value: "cpp" }, "C++"),
143
+ /* @__PURE__ */ import_react20.default.createElement("option", { value: "java" }, "Java"),
144
+ /* @__PURE__ */ import_react20.default.createElement("option", { value: "typescript" }, "TypeScript")
145
+ ), /* @__PURE__ */ import_react20.default.createElement("button", { className: "run-code", onClick: runCode, disabled: loading }, loading ? "Running..." : "Run")), /* @__PURE__ */ import_react20.default.createElement(
146
+ import_react21.default,
147
+ {
148
+ height: "50vh",
149
+ theme: "vs-dark",
150
+ language,
151
+ value: code,
152
+ onChange: (v) => setCode(v ?? "")
153
+ }
154
+ ), /* @__PURE__ */ import_react20.default.createElement("div", { className: "code-output" }, /* @__PURE__ */ import_react20.default.createElement("strong", null, "Output:"), /* @__PURE__ */ import_react20.default.createElement("pre", null, output.trim() === "" ? "\u2190 Click Run to see output here" : output))));
155
+ };
156
+ CodeEditorModal_default = CodeEditorModal;
157
+ }
158
+ });
159
+
93
160
  // src/index.ts
94
161
  var index_exports = {};
95
162
  __export(index_exports, {
@@ -159,8 +226,8 @@ var MathInline = import_core.Node.create({
159
226
  });
160
227
 
161
228
  // src/components/tetrons/EditorContent.tsx
162
- var import_react22 = __toESM(require("react"));
163
- var import_react23 = require("@tiptap/react");
229
+ var import_react24 = __toESM(require("react"));
230
+ var import_react25 = require("@tiptap/react");
164
231
 
165
232
  // node_modules/@tiptap/extension-document/dist/index.js
166
233
  var import_core2 = require("@tiptap/core");
@@ -15840,7 +15907,7 @@ function TableContextMenu({ editor }) {
15840
15907
  }
15841
15908
 
15842
15909
  // src/components/tetrons/toolbar/TetronsToolbar.tsx
15843
- var import_react21 = __toESM(require("react"));
15910
+ var import_react23 = __toESM(require("react"));
15844
15911
 
15845
15912
  // src/components/tetrons/toolbar/ActionGroup.tsx
15846
15913
  var import_react10 = __toESM(require("react"));
@@ -16897,17 +16964,21 @@ function AiGroup({ editor }) {
16897
16964
  }
16898
16965
 
16899
16966
  // src/components/tetrons/toolbar/AddOnGroup.tsx
16900
- var import_react20 = __toESM(require("react"));
16901
- var import_fa3 = require("react-icons/fa");
16967
+ var import_react22 = __toESM(require("react"));
16968
+ var import_lucide_react = require("lucide-react");
16902
16969
  var import_dynamic = __toESM(require("next/dynamic"));
16903
16970
  var import_katex_min2 = require("katex/dist/katex.min.css");
16904
16971
  var MathModal2 = (0, import_dynamic.default)(() => Promise.resolve().then(() => (init_MathModal(), MathModal_exports)), { ssr: false });
16972
+ var CodeEditorModal2 = (0, import_dynamic.default)(() => Promise.resolve().then(() => (init_CodeEditorModal(), CodeEditorModal_exports)), {
16973
+ ssr: false
16974
+ });
16905
16975
  var AddOnGroup = ({ editor }) => {
16906
- const [isModalOpen, setModalOpen] = (0, import_react20.useState)(false);
16907
- const [latexValue, setLatexValue] = (0, import_react20.useState)("");
16976
+ const [isModalOpen, setModalOpen] = (0, import_react22.useState)(false);
16977
+ const [latexValue, setLatexValue] = (0, import_react22.useState)("");
16978
+ const [isCodeModalOpen, setCodeModalOpen] = (0, import_react22.useState)(false);
16908
16979
  if (!editor) return null;
16909
16980
  const insertCodeBlock = () => {
16910
- editor.chain().focus().toggleCodeBlock().run();
16981
+ setCodeModalOpen(true);
16911
16982
  };
16912
16983
  const handleMathInsert = (latex) => {
16913
16984
  editor.chain().focus().insertContent({
@@ -16917,25 +16988,25 @@ var AddOnGroup = ({ editor }) => {
16917
16988
  setModalOpen(false);
16918
16989
  setLatexValue("");
16919
16990
  };
16920
- return /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement("div", { className: "group flex gap-2 items-center" }, /* @__PURE__ */ import_react20.default.createElement(
16991
+ return /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "group flex gap-2 items-center" }, /* @__PURE__ */ import_react22.default.createElement(
16921
16992
  "button",
16922
16993
  {
16923
16994
  type: "button",
16924
16995
  onClick: insertCodeBlock,
16925
- className: "icon-btn",
16926
- title: "Insert Code Block"
16996
+ className: "addon-btn",
16997
+ title: "Open Code Editor"
16927
16998
  },
16928
- /* @__PURE__ */ import_react20.default.createElement(import_fa3.FaCode, { size: 18 })
16929
- ), /* @__PURE__ */ import_react20.default.createElement(
16999
+ /* @__PURE__ */ import_react22.default.createElement(import_lucide_react.MessageSquareCode, { size: 18 })
17000
+ ), /* @__PURE__ */ import_react22.default.createElement(
16930
17001
  "button",
16931
17002
  {
16932
17003
  type: "button",
16933
17004
  onClick: () => setModalOpen(true),
16934
- className: "icon-btn",
17005
+ className: "addon-btn",
16935
17006
  title: "Insert Math Equation"
16936
17007
  },
16937
- /* @__PURE__ */ import_react20.default.createElement(import_fa3.FaSuperscript, { size: 18 })
16938
- )), /* @__PURE__ */ import_react20.default.createElement(
17008
+ /* @__PURE__ */ import_react22.default.createElement(import_lucide_react.SquareRadical, { size: 18 })
17009
+ )), /* @__PURE__ */ import_react22.default.createElement(
16939
17010
  MathModal2,
16940
17011
  {
16941
17012
  isOpen: isModalOpen,
@@ -16944,6 +17015,12 @@ var AddOnGroup = ({ editor }) => {
16944
17015
  value: latexValue,
16945
17016
  setValue: setLatexValue
16946
17017
  }
17018
+ ), /* @__PURE__ */ import_react22.default.createElement(
17019
+ CodeEditorModal2,
17020
+ {
17021
+ isOpen: isCodeModalOpen,
17022
+ onClose: () => setCodeModalOpen(false)
17023
+ }
16947
17024
  ));
16948
17025
  };
16949
17026
  var AddOnGroup_default = AddOnGroup;
@@ -16954,8 +17031,8 @@ function TetronsToolbar({
16954
17031
  version,
16955
17032
  addOns = []
16956
17033
  }) {
16957
- const [autoSave, setAutoSave] = (0, import_react21.useState)(false);
16958
- (0, import_react21.useEffect)(() => {
17034
+ const [autoSave, setAutoSave] = (0, import_react23.useState)(false);
17035
+ (0, import_react23.useEffect)(() => {
16959
17036
  if (!editor) return;
16960
17037
  const handleUpdate = () => {
16961
17038
  if (!autoSave) return;
@@ -16971,7 +17048,7 @@ function TetronsToolbar({
16971
17048
  editor.off("update", handleUpdate);
16972
17049
  };
16973
17050
  }, [autoSave, editor]);
16974
- return /* @__PURE__ */ import_react21.default.createElement("div", { className: "tetrons-toolbar" }, version !== "free" && /* @__PURE__ */ import_react21.default.createElement("div", { className: "group" }, /* @__PURE__ */ import_react21.default.createElement(
17051
+ return /* @__PURE__ */ import_react23.default.createElement("div", { className: "tetrons-toolbar" }, version !== "free" && /* @__PURE__ */ import_react23.default.createElement("div", { className: "group" }, /* @__PURE__ */ import_react23.default.createElement(
16975
17052
  "input",
16976
17053
  {
16977
17054
  type: "checkbox",
@@ -16979,7 +17056,7 @@ function TetronsToolbar({
16979
17056
  checked: autoSave,
16980
17057
  onChange: (e) => setAutoSave(e.target.checked)
16981
17058
  }
16982
- ), /* @__PURE__ */ import_react21.default.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ import_react21.default.createElement(FileGroup, { editor }), /* @__PURE__ */ import_react21.default.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ import_react21.default.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ import_react21.default.createElement(ListAlignGroup, { editor }), ["premium", "platinum"].includes(version) && /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement(InsertGroup, { editor }), /* @__PURE__ */ import_react21.default.createElement(ActionGroup, { editor })), version === "platinum" && /* @__PURE__ */ import_react21.default.createElement(import_react21.default.Fragment, null, /* @__PURE__ */ import_react21.default.createElement(MiscGroup, { editor }), /* @__PURE__ */ import_react21.default.createElement(AiGroup, { editor })), addOns.length > 0 && /* @__PURE__ */ import_react21.default.createElement(AddOnGroup_default, { editor }));
17059
+ ), /* @__PURE__ */ import_react23.default.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ import_react23.default.createElement(FileGroup, { editor }), /* @__PURE__ */ import_react23.default.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ import_react23.default.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ import_react23.default.createElement(ListAlignGroup, { editor }), ["premium", "platinum"].includes(version) && /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement(InsertGroup, { editor }), /* @__PURE__ */ import_react23.default.createElement(ActionGroup, { editor })), version === "platinum" && /* @__PURE__ */ import_react23.default.createElement(import_react23.default.Fragment, null, /* @__PURE__ */ import_react23.default.createElement(MiscGroup, { editor }), /* @__PURE__ */ import_react23.default.createElement(AiGroup, { editor })), addOns.length > 0 && /* @__PURE__ */ import_react23.default.createElement(AddOnGroup_default, { editor }));
16983
17060
  }
16984
17061
 
16985
17062
  // src/components/tetrons/EditorContent.tsx
@@ -16988,16 +17065,16 @@ lowlight.register("js", javascript);
16988
17065
  lowlight.register("ts", typescript);
16989
17066
  function EditorContent({ apiKey }) {
16990
17067
  const typo = useTypo();
16991
- const [isValid, setIsValid] = (0, import_react22.useState)(null);
16992
- const [error, setError] = (0, import_react22.useState)(null);
16993
- const [versions, setVersions] = (0, import_react22.useState)([]);
16994
- const [userVersion, setUserVersion] = (0, import_react22.useState)(null);
16995
- const [currentVersionIndex, setCurrentVersionIndex] = (0, import_react22.useState)(
17068
+ const [isValid, setIsValid] = (0, import_react24.useState)(null);
17069
+ const [error, setError] = (0, import_react24.useState)(null);
17070
+ const [versions, setVersions] = (0, import_react24.useState)([]);
17071
+ const [userVersion, setUserVersion] = (0, import_react24.useState)(null);
17072
+ const [currentVersionIndex, setCurrentVersionIndex] = (0, import_react24.useState)(
16996
17073
  null
16997
17074
  );
16998
- const wrapperRef = (0, import_react22.useRef)(null);
17075
+ const wrapperRef = (0, import_react24.useRef)(null);
16999
17076
  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";
17000
- (0, import_react22.useEffect)(() => {
17077
+ (0, import_react24.useEffect)(() => {
17001
17078
  const validateKey = async () => {
17002
17079
  try {
17003
17080
  const res = await fetch(`${API_BASE_URL}/api/validate`, {
@@ -17018,7 +17095,7 @@ function EditorContent({ apiKey }) {
17018
17095
  };
17019
17096
  validateKey();
17020
17097
  }, [apiKey, API_BASE_URL]);
17021
- const editor = (0, import_react23.useEditor)({
17098
+ const editor = (0, import_react25.useEditor)({
17022
17099
  extensions: [
17023
17100
  Document,
17024
17101
  Paragraph,
@@ -17080,7 +17157,7 @@ function EditorContent({ apiKey }) {
17080
17157
  },
17081
17158
  immediatelyRender: false
17082
17159
  });
17083
- (0, import_react22.useEffect)(() => {
17160
+ (0, import_react24.useEffect)(() => {
17084
17161
  return () => {
17085
17162
  editor?.destroy();
17086
17163
  };
@@ -17105,13 +17182,13 @@ function EditorContent({ apiKey }) {
17105
17182
  }
17106
17183
  };
17107
17184
  if (isValid === false) {
17108
- return /* @__PURE__ */ import_react22.default.createElement("div", { className: "editor-error" }, "\u26A0\uFE0F ", error);
17185
+ return /* @__PURE__ */ import_react24.default.createElement("div", { className: "editor-error" }, "\u26A0\uFE0F ", error);
17109
17186
  }
17110
17187
  if (isValid === null) {
17111
- return /* @__PURE__ */ import_react22.default.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
17188
+ return /* @__PURE__ */ import_react24.default.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
17112
17189
  }
17113
17190
  if (!typo) {
17114
- return /* @__PURE__ */ import_react22.default.createElement("div", { className: "editor-loading" }, "\u{1F4D6} Loading dictionary...");
17191
+ return /* @__PURE__ */ import_react24.default.createElement("div", { className: "editor-loading" }, "\u{1F4D6} Loading dictionary...");
17115
17192
  }
17116
17193
  const versionAddOnsMap = {
17117
17194
  free: [],
@@ -17120,7 +17197,7 @@ function EditorContent({ apiKey }) {
17120
17197
  platinum: ["code", "math"]
17121
17198
  };
17122
17199
  const enabledAddOns = userVersion ? versionAddOnsMap[userVersion] || [] : [];
17123
- return /* @__PURE__ */ import_react22.default.createElement("div", { className: "editor-container" }, userVersion !== "free" && /* @__PURE__ */ import_react22.default.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ import_react22.default.createElement(
17200
+ return /* @__PURE__ */ import_react24.default.createElement("div", { className: "editor-container" }, userVersion !== "free" && /* @__PURE__ */ import_react24.default.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ import_react24.default.createElement(
17124
17201
  "button",
17125
17202
  {
17126
17203
  type: "button",
@@ -17129,7 +17206,7 @@ function EditorContent({ apiKey }) {
17129
17206
  className: "editor-save-btn"
17130
17207
  },
17131
17208
  "Save Version"
17132
- ), /* @__PURE__ */ import_react22.default.createElement("div", { className: "editor-versions-wrapper" }, versions.length === 0 ? /* @__PURE__ */ import_react22.default.createElement("span", { className: "editor-no-versions" }, "No saved versions") : versions.map((_, idx) => /* @__PURE__ */ import_react22.default.createElement(
17209
+ ), /* @__PURE__ */ import_react24.default.createElement("div", { className: "editor-versions-wrapper" }, versions.length === 0 ? /* @__PURE__ */ import_react24.default.createElement("span", { className: "editor-no-versions" }, "No saved versions") : versions.map((_, idx) => /* @__PURE__ */ import_react24.default.createElement(
17133
17210
  "button",
17134
17211
  {
17135
17212
  key: idx,
@@ -17139,21 +17216,21 @@ function EditorContent({ apiKey }) {
17139
17216
  title: `Restore Version ${idx + 1}`
17140
17217
  },
17141
17218
  `V${idx + 1}`
17142
- )))), editor && userVersion && /* @__PURE__ */ import_react22.default.createElement(
17219
+ )))), editor && userVersion && /* @__PURE__ */ import_react24.default.createElement(
17143
17220
  TetronsToolbar,
17144
17221
  {
17145
17222
  editor,
17146
17223
  version: userVersion,
17147
17224
  addOns: enabledAddOns
17148
17225
  }
17149
- ), /* @__PURE__ */ import_react22.default.createElement(
17226
+ ), /* @__PURE__ */ import_react24.default.createElement(
17150
17227
  "div",
17151
17228
  {
17152
17229
  ref: wrapperRef,
17153
17230
  className: "editor-content-wrapper",
17154
17231
  onClick: handleEditorClick
17155
17232
  },
17156
- editor ? /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement(import_react23.EditorContent, { editor }), /* @__PURE__ */ import_react22.default.createElement(TableContextMenu, { editor })) : /* @__PURE__ */ import_react22.default.createElement("div", { className: "editor-loading" }, "Loading editor...")
17233
+ editor ? /* @__PURE__ */ import_react24.default.createElement(import_react24.default.Fragment, null, /* @__PURE__ */ import_react24.default.createElement(import_react25.EditorContent, { editor }), /* @__PURE__ */ import_react24.default.createElement(TableContextMenu, { editor })) : /* @__PURE__ */ import_react24.default.createElement("div", { className: "editor-loading" }, "Loading editor...")
17157
17234
  ));
17158
17235
  }
17159
17236
 
package/dist/index.mjs CHANGED
@@ -67,6 +67,73 @@ var init_MathModal = __esm({
67
67
  }
68
68
  });
69
69
 
70
+ // src/components/tetrons/toolbar/CodeEditorModal.js
71
+ var CodeEditorModal_exports = {};
72
+ __export(CodeEditorModal_exports, {
73
+ default: () => CodeEditorModal_default
74
+ });
75
+ import React14, { useState as useState8 } from "react";
76
+ import Editor from "@monaco-editor/react";
77
+ var CodeEditorModal, CodeEditorModal_default;
78
+ var init_CodeEditorModal = __esm({
79
+ "src/components/tetrons/toolbar/CodeEditorModal.js"() {
80
+ "use strict";
81
+ "use client";
82
+ CodeEditorModal = ({ isOpen, onClose }) => {
83
+ const [language, setLanguage] = useState8("javascript");
84
+ const [code, setCode] = useState8("// Write your code here");
85
+ const [output, setOutput] = useState8("");
86
+ const [loading, setLoading] = useState8(false);
87
+ const runCode = async () => {
88
+ setLoading(true);
89
+ try {
90
+ const res = await fetch("/api/execute", {
91
+ method: "POST",
92
+ headers: { "Content-Type": "application/json" },
93
+ body: JSON.stringify({ language, code })
94
+ });
95
+ const data = await res.json();
96
+ let result = "";
97
+ if (data.stderr) result += `Error:
98
+ ${data.stderr}
99
+ `;
100
+ if (data.stdout) result += data.stdout;
101
+ if (!data.stdout && !data.stderr) result = "No output";
102
+ setOutput(result);
103
+ } catch (err) {
104
+ console.log(err.message);
105
+ setOutput("Error running code");
106
+ }
107
+ setLoading(false);
108
+ };
109
+ if (!isOpen) return null;
110
+ 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(
111
+ "select",
112
+ {
113
+ id: "language",
114
+ value: language,
115
+ onChange: (e) => setLanguage(e.target.value)
116
+ },
117
+ /* @__PURE__ */ React14.createElement("option", { value: "javascript" }, "JavaScript"),
118
+ /* @__PURE__ */ React14.createElement("option", { value: "python" }, "Python"),
119
+ /* @__PURE__ */ React14.createElement("option", { value: "cpp" }, "C++"),
120
+ /* @__PURE__ */ React14.createElement("option", { value: "java" }, "Java"),
121
+ /* @__PURE__ */ React14.createElement("option", { value: "typescript" }, "TypeScript")
122
+ ), /* @__PURE__ */ React14.createElement("button", { className: "run-code", onClick: runCode, disabled: loading }, loading ? "Running..." : "Run")), /* @__PURE__ */ React14.createElement(
123
+ Editor,
124
+ {
125
+ height: "50vh",
126
+ theme: "vs-dark",
127
+ language,
128
+ value: code,
129
+ onChange: (v) => setCode(v ?? "")
130
+ }
131
+ ), /* @__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))));
132
+ };
133
+ CodeEditorModal_default = CodeEditorModal;
134
+ }
135
+ });
136
+
70
137
  // src/components/tetrons/extensions/MathExtension.ts
71
138
  import { Node, mergeAttributes } from "@tiptap/core";
72
139
  import katex from "katex";
@@ -124,7 +191,7 @@ var MathInline = Node.create({
124
191
  });
125
192
 
126
193
  // src/components/tetrons/EditorContent.tsx
127
- import React16, { useEffect as useEffect9, useRef as useRef7, useState as useState10 } from "react";
194
+ import React17, { useEffect as useEffect9, useRef as useRef7, useState as useState11 } from "react";
128
195
  import { useEditor, EditorContent as TiptapEditorContent } from "@tiptap/react";
129
196
 
130
197
  // node_modules/@tiptap/extension-document/dist/index.js
@@ -15805,7 +15872,7 @@ function TableContextMenu({ editor }) {
15805
15872
  }
15806
15873
 
15807
15874
  // src/components/tetrons/toolbar/TetronsToolbar.tsx
15808
- import React15, { useEffect as useEffect8, useState as useState9 } from "react";
15875
+ import React16, { useEffect as useEffect8, useState as useState10 } from "react";
15809
15876
 
15810
15877
  // src/components/tetrons/toolbar/ActionGroup.tsx
15811
15878
  import React6, { useEffect as useEffect5, useRef as useRef3, useState as useState4 } from "react";
@@ -16907,17 +16974,21 @@ function AiGroup({ editor }) {
16907
16974
  }
16908
16975
 
16909
16976
  // src/components/tetrons/toolbar/AddOnGroup.tsx
16910
- import React14, { useState as useState8 } from "react";
16911
- import { FaCode, FaSuperscript } from "react-icons/fa";
16977
+ import React15, { useState as useState9 } from "react";
16978
+ import { SquareRadical, MessageSquareCode } from "lucide-react";
16912
16979
  import dynamic from "next/dynamic";
16913
16980
  import "katex/dist/katex.min.css";
16914
16981
  var MathModal2 = dynamic(() => Promise.resolve().then(() => (init_MathModal(), MathModal_exports)), { ssr: false });
16982
+ var CodeEditorModal2 = dynamic(() => Promise.resolve().then(() => (init_CodeEditorModal(), CodeEditorModal_exports)), {
16983
+ ssr: false
16984
+ });
16915
16985
  var AddOnGroup = ({ editor }) => {
16916
- const [isModalOpen, setModalOpen] = useState8(false);
16917
- const [latexValue, setLatexValue] = useState8("");
16986
+ const [isModalOpen, setModalOpen] = useState9(false);
16987
+ const [latexValue, setLatexValue] = useState9("");
16988
+ const [isCodeModalOpen, setCodeModalOpen] = useState9(false);
16918
16989
  if (!editor) return null;
16919
16990
  const insertCodeBlock = () => {
16920
- editor.chain().focus().toggleCodeBlock().run();
16991
+ setCodeModalOpen(true);
16921
16992
  };
16922
16993
  const handleMathInsert = (latex) => {
16923
16994
  editor.chain().focus().insertContent({
@@ -16927,25 +16998,25 @@ var AddOnGroup = ({ editor }) => {
16927
16998
  setModalOpen(false);
16928
16999
  setLatexValue("");
16929
17000
  };
16930
- return /* @__PURE__ */ React14.createElement(React14.Fragment, null, /* @__PURE__ */ React14.createElement("div", { className: "group flex gap-2 items-center" }, /* @__PURE__ */ React14.createElement(
17001
+ return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "group flex gap-2 items-center" }, /* @__PURE__ */ React15.createElement(
16931
17002
  "button",
16932
17003
  {
16933
17004
  type: "button",
16934
17005
  onClick: insertCodeBlock,
16935
- className: "icon-btn",
16936
- title: "Insert Code Block"
17006
+ className: "addon-btn",
17007
+ title: "Open Code Editor"
16937
17008
  },
16938
- /* @__PURE__ */ React14.createElement(FaCode, { size: 18 })
16939
- ), /* @__PURE__ */ React14.createElement(
17009
+ /* @__PURE__ */ React15.createElement(MessageSquareCode, { size: 18 })
17010
+ ), /* @__PURE__ */ React15.createElement(
16940
17011
  "button",
16941
17012
  {
16942
17013
  type: "button",
16943
17014
  onClick: () => setModalOpen(true),
16944
- className: "icon-btn",
17015
+ className: "addon-btn",
16945
17016
  title: "Insert Math Equation"
16946
17017
  },
16947
- /* @__PURE__ */ React14.createElement(FaSuperscript, { size: 18 })
16948
- )), /* @__PURE__ */ React14.createElement(
17018
+ /* @__PURE__ */ React15.createElement(SquareRadical, { size: 18 })
17019
+ )), /* @__PURE__ */ React15.createElement(
16949
17020
  MathModal2,
16950
17021
  {
16951
17022
  isOpen: isModalOpen,
@@ -16954,6 +17025,12 @@ var AddOnGroup = ({ editor }) => {
16954
17025
  value: latexValue,
16955
17026
  setValue: setLatexValue
16956
17027
  }
17028
+ ), /* @__PURE__ */ React15.createElement(
17029
+ CodeEditorModal2,
17030
+ {
17031
+ isOpen: isCodeModalOpen,
17032
+ onClose: () => setCodeModalOpen(false)
17033
+ }
16957
17034
  ));
16958
17035
  };
16959
17036
  var AddOnGroup_default = AddOnGroup;
@@ -16964,7 +17041,7 @@ function TetronsToolbar({
16964
17041
  version,
16965
17042
  addOns = []
16966
17043
  }) {
16967
- const [autoSave, setAutoSave] = useState9(false);
17044
+ const [autoSave, setAutoSave] = useState10(false);
16968
17045
  useEffect8(() => {
16969
17046
  if (!editor) return;
16970
17047
  const handleUpdate = () => {
@@ -16981,7 +17058,7 @@ function TetronsToolbar({
16981
17058
  editor.off("update", handleUpdate);
16982
17059
  };
16983
17060
  }, [autoSave, editor]);
16984
- return /* @__PURE__ */ React15.createElement("div", { className: "tetrons-toolbar" }, version !== "free" && /* @__PURE__ */ React15.createElement("div", { className: "group" }, /* @__PURE__ */ React15.createElement(
17061
+ return /* @__PURE__ */ React16.createElement("div", { className: "tetrons-toolbar" }, version !== "free" && /* @__PURE__ */ React16.createElement("div", { className: "group" }, /* @__PURE__ */ React16.createElement(
16985
17062
  "input",
16986
17063
  {
16987
17064
  type: "checkbox",
@@ -16989,7 +17066,7 @@ function TetronsToolbar({
16989
17066
  checked: autoSave,
16990
17067
  onChange: (e) => setAutoSave(e.target.checked)
16991
17068
  }
16992
- ), /* @__PURE__ */ React15.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ React15.createElement(FileGroup, { editor }), /* @__PURE__ */ React15.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ React15.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ React15.createElement(ListAlignGroup, { editor }), ["premium", "platinum"].includes(version) && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(InsertGroup, { editor }), /* @__PURE__ */ React15.createElement(ActionGroup, { editor })), version === "platinum" && /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(MiscGroup, { editor }), /* @__PURE__ */ React15.createElement(AiGroup, { editor })), addOns.length > 0 && /* @__PURE__ */ React15.createElement(AddOnGroup_default, { editor }));
17069
+ ), /* @__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 })), version === "platinum" && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(MiscGroup, { editor }), /* @__PURE__ */ React16.createElement(AiGroup, { editor })), addOns.length > 0 && /* @__PURE__ */ React16.createElement(AddOnGroup_default, { editor }));
16993
17070
  }
16994
17071
 
16995
17072
  // src/components/tetrons/EditorContent.tsx
@@ -16998,11 +17075,11 @@ lowlight.register("js", javascript);
16998
17075
  lowlight.register("ts", typescript);
16999
17076
  function EditorContent({ apiKey }) {
17000
17077
  const typo = useTypo();
17001
- const [isValid, setIsValid] = useState10(null);
17002
- const [error, setError] = useState10(null);
17003
- const [versions, setVersions] = useState10([]);
17004
- const [userVersion, setUserVersion] = useState10(null);
17005
- const [currentVersionIndex, setCurrentVersionIndex] = useState10(
17078
+ const [isValid, setIsValid] = useState11(null);
17079
+ const [error, setError] = useState11(null);
17080
+ const [versions, setVersions] = useState11([]);
17081
+ const [userVersion, setUserVersion] = useState11(null);
17082
+ const [currentVersionIndex, setCurrentVersionIndex] = useState11(
17006
17083
  null
17007
17084
  );
17008
17085
  const wrapperRef = useRef7(null);
@@ -17115,13 +17192,13 @@ function EditorContent({ apiKey }) {
17115
17192
  }
17116
17193
  };
17117
17194
  if (isValid === false) {
17118
- return /* @__PURE__ */ React16.createElement("div", { className: "editor-error" }, "\u26A0\uFE0F ", error);
17195
+ return /* @__PURE__ */ React17.createElement("div", { className: "editor-error" }, "\u26A0\uFE0F ", error);
17119
17196
  }
17120
17197
  if (isValid === null) {
17121
- return /* @__PURE__ */ React16.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
17198
+ return /* @__PURE__ */ React17.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
17122
17199
  }
17123
17200
  if (!typo) {
17124
- return /* @__PURE__ */ React16.createElement("div", { className: "editor-loading" }, "\u{1F4D6} Loading dictionary...");
17201
+ return /* @__PURE__ */ React17.createElement("div", { className: "editor-loading" }, "\u{1F4D6} Loading dictionary...");
17125
17202
  }
17126
17203
  const versionAddOnsMap = {
17127
17204
  free: [],
@@ -17130,7 +17207,7 @@ function EditorContent({ apiKey }) {
17130
17207
  platinum: ["code", "math"]
17131
17208
  };
17132
17209
  const enabledAddOns = userVersion ? versionAddOnsMap[userVersion] || [] : [];
17133
- return /* @__PURE__ */ React16.createElement("div", { className: "editor-container" }, userVersion !== "free" && /* @__PURE__ */ React16.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ React16.createElement(
17210
+ return /* @__PURE__ */ React17.createElement("div", { className: "editor-container" }, userVersion !== "free" && /* @__PURE__ */ React17.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ React17.createElement(
17134
17211
  "button",
17135
17212
  {
17136
17213
  type: "button",
@@ -17139,7 +17216,7 @@ function EditorContent({ apiKey }) {
17139
17216
  className: "editor-save-btn"
17140
17217
  },
17141
17218
  "Save Version"
17142
- ), /* @__PURE__ */ React16.createElement("div", { className: "editor-versions-wrapper" }, versions.length === 0 ? /* @__PURE__ */ React16.createElement("span", { className: "editor-no-versions" }, "No saved versions") : versions.map((_, idx) => /* @__PURE__ */ React16.createElement(
17219
+ ), /* @__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(
17143
17220
  "button",
17144
17221
  {
17145
17222
  key: idx,
@@ -17149,21 +17226,21 @@ function EditorContent({ apiKey }) {
17149
17226
  title: `Restore Version ${idx + 1}`
17150
17227
  },
17151
17228
  `V${idx + 1}`
17152
- )))), editor && userVersion && /* @__PURE__ */ React16.createElement(
17229
+ )))), editor && userVersion && /* @__PURE__ */ React17.createElement(
17153
17230
  TetronsToolbar,
17154
17231
  {
17155
17232
  editor,
17156
17233
  version: userVersion,
17157
17234
  addOns: enabledAddOns
17158
17235
  }
17159
- ), /* @__PURE__ */ React16.createElement(
17236
+ ), /* @__PURE__ */ React17.createElement(
17160
17237
  "div",
17161
17238
  {
17162
17239
  ref: wrapperRef,
17163
17240
  className: "editor-content-wrapper",
17164
17241
  onClick: handleEditorClick
17165
17242
  },
17166
- editor ? /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(TiptapEditorContent, { editor }), /* @__PURE__ */ React16.createElement(TableContextMenu, { editor })) : /* @__PURE__ */ React16.createElement("div", { className: "editor-loading" }, "Loading editor...")
17243
+ 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...")
17167
17244
  ));
17168
17245
  }
17169
17246
 
@@ -570,3 +570,101 @@
570
570
  opacity: 0.5;
571
571
  cursor: not-allowed;
572
572
  }
573
+
574
+ .code-modal-overlay {
575
+ position: fixed;
576
+ top: 0;
577
+ left: 0;
578
+ width: 100%;
579
+ height: 100%;
580
+ background: rgba(0, 0, 0, 0.6);
581
+ display: flex;
582
+ justify-content: center;
583
+ align-items: center;
584
+ z-index: 9999;
585
+ }
586
+
587
+ .code-modal-content {
588
+ background: white;
589
+ width: 90%;
590
+ max-width: 800px;
591
+ border-radius: 8px;
592
+ padding: 20px;
593
+ box-shadow: 0 0 10px #00000033;
594
+ display: flex;
595
+ flex-direction: column;
596
+ }
597
+
598
+ .code-modal-header {
599
+ display: flex;
600
+ justify-content: space-between;
601
+ align-items: center;
602
+ margin-bottom: 1rem;
603
+ }
604
+
605
+ .code-close-btn {
606
+ font-size: 24px;
607
+ border: none;
608
+ background: transparent;
609
+ cursor: pointer;
610
+ }
611
+
612
+ .code-modal-controls {
613
+ display: flex;
614
+ align-items: center;
615
+ gap: 10px;
616
+ margin-bottom: 10px;
617
+ }
618
+
619
+ .code-modal-controls select,
620
+ .code-modal-controls button {
621
+ padding: 6px 12px;
622
+ font-size: 14px;
623
+ }
624
+
625
+ .code-output {
626
+ background: #f2f2f2;
627
+ padding: 12px;
628
+ border-radius: 4px;
629
+ margin-top: 15px;
630
+ height: 150px;
631
+ overflow-y: auto;
632
+ white-space: pre-wrap;
633
+ }
634
+
635
+ .addon-btn {
636
+ padding: 8px 16px;
637
+ background: linear-gradient(to right, #7f00ff, #4f46e5);
638
+ color: white;
639
+ font-weight: bold;
640
+ border: none;
641
+ border-radius: 6px;
642
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
643
+ cursor: pointer;
644
+ transition: background 0.3s ease, transform 0.2s ease;
645
+ }
646
+
647
+ .addon-btn:hover {
648
+ background: linear-gradient(to right, #6b00d6, #4338ca);
649
+ transform: translateY(-1px);
650
+ }
651
+
652
+ .addon-btn:active {
653
+ transform: scale(0.97);
654
+ }
655
+
656
+ .run-code{
657
+ margin-left: auto;
658
+ background-color: black;
659
+ color: white;
660
+ padding: 6px 16px;
661
+ border: none;
662
+ border-radius: 4px;
663
+ cursor: pointer;
664
+ font-size: 14px;
665
+ }
666
+
667
+ .run-code:disabled {
668
+ opacity: 0.6;
669
+ cursor: not-allowed;
670
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tetrons",
3
- "version": "2.3.77",
3
+ "version": "2.3.78",
4
4
  "description": "A Next.js project written in TypeScript",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -13,6 +13,7 @@
13
13
  },
14
14
  "dependencies": {
15
15
  "@emoji-mart/react": "1.1.1",
16
+ "@monaco-editor/react": "^4.7.0",
16
17
  "@tiptap/core": "2.24.1",
17
18
  "@tiptap/extension-code-block-lowlight": "2.24.1",
18
19
  "@tiptap/extension-color": "2.24.1",
@@ -37,11 +38,15 @@
37
38
  "html2pdf.js": "0.10.3",
38
39
  "katex": "^0.16.22",
39
40
  "lowlight": "3.3.0",
41
+ "lucide-react": "^0.537.0",
40
42
  "mime": "4.0.7",
41
- "mongoose": "8.16.0",
43
+ "mongoose": "^8.17.1",
42
44
  "openai": "^4.40.0",
45
+ "prettier": "^3.6.2",
46
+ "prettier-plugin-jsdoc": "^1.3.3",
43
47
  "react-icons": "5.5.0",
44
- "typo-js": "1.2.5"
48
+ "typo-js": "1.2.5",
49
+ "uuid": "^11.1.0"
45
50
  },
46
51
  "peerDependencies": {
47
52
  "next": "15.3.2",
@@ -56,7 +61,7 @@
56
61
  "@types/react-dom": "^18.2.7",
57
62
  "autoprefixer": "10.4.21",
58
63
  "copyfiles": "2.4.1",
59
- "eslint": "9.0.0",
64
+ "eslint": "^8.57.0",
60
65
  "eslint-config-next": "15.3.2",
61
66
  "tsup": "8.5.0",
62
67
  "typescript": "5.4.5"
@@ -102,6 +107,10 @@
102
107
  "./app/api/validate/route": {
103
108
  "import": "./dist/app/api/validate/route.mjs",
104
109
  "require": "./dist/app/api/validate/route.cjs"
110
+ },
111
+ "./app/api/execute/route": {
112
+ "import": "./dist/app/api/execute/route.mjs",
113
+ "require": "./dist/app/api/execute/route.cjs"
105
114
  }
106
115
  },
107
116
  "files": [
@@ -114,4 +123,4 @@
114
123
  "url": "https://github.com/Finapsys/Tetrons/issues"
115
124
  },
116
125
  "homepage": "https://github.com/Finapsys/Tetrons#readme"
117
- }
126
+ }