tetrons 2.3.90 → 2.3.92
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/components/tetrons/EditorContent.tsx +1 -1
- package/dist/index.cjs +169 -132
- package/dist/index.mjs +169 -132
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { MathInline } from "./extensions/MathExtension";
|
|
3
3
|
import React, { useEffect, useRef, useState } from "react";
|
|
4
4
|
import { useEditor, EditorContent as TiptapEditorContent } from "@tiptap/react";
|
|
5
|
-
import type { AddOn } from "
|
|
5
|
+
import type { AddOn } from "../../types/types";
|
|
6
6
|
import { getActivePlan, Plan } from "../../utils/licenseTracker";
|
|
7
7
|
|
|
8
8
|
import Document from "@tiptap/extension-document";
|
package/dist/index.cjs
CHANGED
|
@@ -16016,14 +16016,10 @@ function ActionGroup({ editor }) {
|
|
|
16016
16016
|
setDropdownOpen(false);
|
|
16017
16017
|
}
|
|
16018
16018
|
};
|
|
16019
|
-
if (dropdownOpen)
|
|
16019
|
+
if (dropdownOpen)
|
|
16020
16020
|
document.addEventListener("mousedown", handleClickOutside);
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
}
|
|
16024
|
-
return () => {
|
|
16025
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
16026
|
-
};
|
|
16021
|
+
else document.removeEventListener("mousedown", handleClickOutside);
|
|
16022
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
16027
16023
|
}, [dropdownOpen]);
|
|
16028
16024
|
const zoomIn = () => {
|
|
16029
16025
|
const element = document.querySelector(
|
|
@@ -16032,8 +16028,7 @@ function ActionGroup({ editor }) {
|
|
|
16032
16028
|
if (element) {
|
|
16033
16029
|
const style = element.style;
|
|
16034
16030
|
const currentZoom = parseFloat(style.zoom || "1");
|
|
16035
|
-
|
|
16036
|
-
style.zoom = next.toString();
|
|
16031
|
+
style.zoom = Math.min(currentZoom + 0.1, 2).toString();
|
|
16037
16032
|
}
|
|
16038
16033
|
};
|
|
16039
16034
|
const zoomOut = () => {
|
|
@@ -16043,28 +16038,24 @@ function ActionGroup({ editor }) {
|
|
|
16043
16038
|
if (element) {
|
|
16044
16039
|
const style = element.style;
|
|
16045
16040
|
const currentZoom = parseFloat(style.zoom || "1");
|
|
16046
|
-
|
|
16047
|
-
style.zoom = next.toString();
|
|
16041
|
+
style.zoom = Math.max(currentZoom - 0.1, 0.5).toString();
|
|
16048
16042
|
}
|
|
16049
16043
|
};
|
|
16050
16044
|
const handlePrint = () => {
|
|
16045
|
+
if (!editor) return;
|
|
16051
16046
|
const html = editor.getHTML();
|
|
16052
16047
|
const printWindow = window.open("", "_blank");
|
|
16053
16048
|
if (printWindow) {
|
|
16054
|
-
printWindow.document.write(
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
<title>Print</title>
|
|
16058
|
-
</head>
|
|
16059
|
-
<body>${html}</body>
|
|
16060
|
-
</html>
|
|
16061
|
-
`);
|
|
16049
|
+
printWindow.document.write(
|
|
16050
|
+
`<html><head><title>Print</title></head><body>${html}</body></html>`
|
|
16051
|
+
);
|
|
16062
16052
|
printWindow.document.close();
|
|
16063
16053
|
printWindow.focus();
|
|
16064
16054
|
printWindow.print();
|
|
16065
16055
|
}
|
|
16066
16056
|
};
|
|
16067
16057
|
const handleSave = async () => {
|
|
16058
|
+
if (!editor) return;
|
|
16068
16059
|
const content = editor.getJSON();
|
|
16069
16060
|
try {
|
|
16070
16061
|
const response = await fetch("/api/save", {
|
|
@@ -16074,14 +16065,14 @@ function ActionGroup({ editor }) {
|
|
|
16074
16065
|
});
|
|
16075
16066
|
if (!response.ok) throw new Error("Failed to save file");
|
|
16076
16067
|
const result = await response.json();
|
|
16077
|
-
|
|
16078
|
-
alert("Content saved successfully!");
|
|
16068
|
+
alert(result.message || "Content saved successfully!");
|
|
16079
16069
|
} catch (error) {
|
|
16080
|
-
console.error(
|
|
16070
|
+
console.error(error);
|
|
16081
16071
|
alert("Failed to save content.");
|
|
16082
16072
|
}
|
|
16083
16073
|
};
|
|
16084
16074
|
const handleDownloadPDF = async () => {
|
|
16075
|
+
if (!editor) return;
|
|
16085
16076
|
const html = editor.getHTML();
|
|
16086
16077
|
const container = document.createElement("div");
|
|
16087
16078
|
container.innerHTML = html;
|
|
@@ -16089,22 +16080,22 @@ function ActionGroup({ editor }) {
|
|
|
16089
16080
|
document.body.appendChild(container);
|
|
16090
16081
|
try {
|
|
16091
16082
|
const domToPdf = (await import("dom-to-pdf")).default;
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
overrideWidth: 800,
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
16098
|
-
|
|
16099
|
-
});
|
|
16083
|
+
domToPdf(
|
|
16084
|
+
container,
|
|
16085
|
+
{ filename: "document.pdf", overrideWidth: 800, overrideHeight: 1120 },
|
|
16086
|
+
() => {
|
|
16087
|
+
console.log("PDF downloaded!");
|
|
16088
|
+
}
|
|
16089
|
+
);
|
|
16100
16090
|
} catch (error) {
|
|
16101
|
-
console.error(
|
|
16091
|
+
console.error(error);
|
|
16102
16092
|
alert("Failed to download PDF.");
|
|
16103
16093
|
} finally {
|
|
16104
16094
|
document.body.removeChild(container);
|
|
16105
16095
|
}
|
|
16106
16096
|
};
|
|
16107
16097
|
const handleDownloadHTML = () => {
|
|
16098
|
+
if (!editor) return;
|
|
16108
16099
|
const html = editor.getHTML();
|
|
16109
16100
|
const blob = new Blob([html], { type: "text/html" });
|
|
16110
16101
|
const link = document.createElement("a");
|
|
@@ -16115,15 +16106,11 @@ function ActionGroup({ editor }) {
|
|
|
16115
16106
|
document.body.removeChild(link);
|
|
16116
16107
|
};
|
|
16117
16108
|
const handleDownloadDOCX = async () => {
|
|
16109
|
+
if (!editor) return;
|
|
16118
16110
|
const { Document: Document2, Packer, Paragraph: Paragraph2 } = await import("docx");
|
|
16119
16111
|
const text = editor.getText();
|
|
16120
16112
|
const doc3 = new Document2({
|
|
16121
|
-
sections: [
|
|
16122
|
-
{
|
|
16123
|
-
properties: {},
|
|
16124
|
-
children: [new Paragraph2(text)]
|
|
16125
|
-
}
|
|
16126
|
-
]
|
|
16113
|
+
sections: [{ properties: {}, children: [new Paragraph2(text)] }]
|
|
16127
16114
|
});
|
|
16128
16115
|
const blob = await Packer.toBlob(doc3);
|
|
16129
16116
|
const link = document.createElement("a");
|
|
@@ -16133,49 +16120,59 @@ function ActionGroup({ editor }) {
|
|
|
16133
16120
|
link.click();
|
|
16134
16121
|
document.body.removeChild(link);
|
|
16135
16122
|
};
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
type: "button",
|
|
16140
|
-
onClick: () => setDropdownOpen((open) => !open),
|
|
16141
|
-
"aria-haspopup": "menu",
|
|
16142
|
-
"aria-expanded": dropdownOpen ? "true" : "false",
|
|
16143
|
-
className: "export-button",
|
|
16144
|
-
title: "Export"
|
|
16145
|
-
},
|
|
16146
|
-
/* @__PURE__ */ import_react10.default.createElement(import_md.MdDownload, null),
|
|
16147
|
-
/* @__PURE__ */ import_react10.default.createElement("span", { className: "text-sm" })
|
|
16148
|
-
), dropdownOpen && /* @__PURE__ */ import_react10.default.createElement("div", { className: "export-dropdown" }, /* @__PURE__ */ import_react10.default.createElement(
|
|
16149
|
-
"button",
|
|
16150
|
-
{
|
|
16151
|
-
type: "button",
|
|
16152
|
-
onClick: () => {
|
|
16153
|
-
setDropdownOpen(false);
|
|
16154
|
-
handleDownloadPDF();
|
|
16155
|
-
}
|
|
16156
|
-
},
|
|
16157
|
-
"Export as PDF"
|
|
16158
|
-
), /* @__PURE__ */ import_react10.default.createElement(
|
|
16159
|
-
"button",
|
|
16160
|
-
{
|
|
16161
|
-
type: "button",
|
|
16162
|
-
onClick: () => {
|
|
16163
|
-
setDropdownOpen(false);
|
|
16164
|
-
handleDownloadHTML();
|
|
16165
|
-
}
|
|
16166
|
-
},
|
|
16167
|
-
"Export as HTML"
|
|
16168
|
-
), /* @__PURE__ */ import_react10.default.createElement(
|
|
16169
|
-
"button",
|
|
16123
|
+
if (!editor) return null;
|
|
16124
|
+
return /* @__PURE__ */ import_react10.default.createElement(
|
|
16125
|
+
"div",
|
|
16170
16126
|
{
|
|
16171
|
-
|
|
16172
|
-
|
|
16173
|
-
|
|
16174
|
-
handleDownloadDOCX();
|
|
16175
|
-
}
|
|
16127
|
+
className: "action-group bg-white text-black dark:bg-gray-800 dark:text-white",
|
|
16128
|
+
role: "group",
|
|
16129
|
+
"aria-label": "Editor actions"
|
|
16176
16130
|
},
|
|
16177
|
-
"
|
|
16178
|
-
|
|
16131
|
+
/* @__PURE__ */ import_react10.default.createElement(ToolbarButton_default, { icon: import_md.MdZoomIn, onClick: zoomIn, title: "Zoom In" }),
|
|
16132
|
+
/* @__PURE__ */ import_react10.default.createElement(ToolbarButton_default, { icon: import_md.MdZoomOut, onClick: zoomOut, title: "Zoom Out" }),
|
|
16133
|
+
/* @__PURE__ */ import_react10.default.createElement(ToolbarButton_default, { icon: import_md.MdPrint, onClick: handlePrint, title: "Print" }),
|
|
16134
|
+
/* @__PURE__ */ import_react10.default.createElement(ToolbarButton_default, { icon: import_md.MdSave, onClick: handleSave, title: "Save" }),
|
|
16135
|
+
/* @__PURE__ */ import_react10.default.createElement("div", { className: "relative", ref: dropdownRef }, /* @__PURE__ */ import_react10.default.createElement(
|
|
16136
|
+
"button",
|
|
16137
|
+
{
|
|
16138
|
+
type: "button",
|
|
16139
|
+
onClick: () => setDropdownOpen((o) => !o),
|
|
16140
|
+
className: "export-button",
|
|
16141
|
+
title: "Export"
|
|
16142
|
+
},
|
|
16143
|
+
/* @__PURE__ */ import_react10.default.createElement(import_md.MdDownload, null)
|
|
16144
|
+
), dropdownOpen && /* @__PURE__ */ import_react10.default.createElement("div", { className: "export-dropdown" }, /* @__PURE__ */ import_react10.default.createElement(
|
|
16145
|
+
"button",
|
|
16146
|
+
{
|
|
16147
|
+
type: "button",
|
|
16148
|
+
onClick: () => {
|
|
16149
|
+
setDropdownOpen(false);
|
|
16150
|
+
handleDownloadPDF();
|
|
16151
|
+
}
|
|
16152
|
+
},
|
|
16153
|
+
"Export as PDF"
|
|
16154
|
+
), /* @__PURE__ */ import_react10.default.createElement(
|
|
16155
|
+
"button",
|
|
16156
|
+
{
|
|
16157
|
+
type: "button",
|
|
16158
|
+
onClick: () => {
|
|
16159
|
+
setDropdownOpen(false);
|
|
16160
|
+
handleDownloadHTML();
|
|
16161
|
+
}
|
|
16162
|
+
},
|
|
16163
|
+
"Export as HTML"
|
|
16164
|
+
), /* @__PURE__ */ import_react10.default.createElement(
|
|
16165
|
+
"button",
|
|
16166
|
+
{
|
|
16167
|
+
type: "button",
|
|
16168
|
+
onClick: () => {
|
|
16169
|
+
setDropdownOpen(false);
|
|
16170
|
+
handleDownloadDOCX();
|
|
16171
|
+
}
|
|
16172
|
+
},
|
|
16173
|
+
"Export as DOCX"
|
|
16174
|
+
)))
|
|
16175
|
+
);
|
|
16179
16176
|
}
|
|
16180
16177
|
|
|
16181
16178
|
// src/components/tetrons/toolbar/ClipboardGroup.tsx
|
|
@@ -16638,13 +16635,18 @@ function InsertGroup({ editor }) {
|
|
|
16638
16635
|
var import_react15 = __toESM(require("react"));
|
|
16639
16636
|
var import_md5 = require("react-icons/md");
|
|
16640
16637
|
function ListAlignGroup({ editor }) {
|
|
16641
|
-
|
|
16638
|
+
if (!editor) return null;
|
|
16639
|
+
const canToggleBullet = editor.can().toggleBulletList() || editor.isEmpty;
|
|
16640
|
+
const canToggleOrdered = editor.can().toggleOrderedList() || editor.isEmpty;
|
|
16641
|
+
const canSink = editor.can().sinkListItem("listItem");
|
|
16642
|
+
const canLift = editor.can().liftListItem("listItem");
|
|
16643
|
+
return /* @__PURE__ */ import_react15.default.createElement("div", { className: "list-align-group bg-white text-black dark:bg-gray-800 dark:text-white" }, /* @__PURE__ */ import_react15.default.createElement(
|
|
16642
16644
|
ToolbarButton_default,
|
|
16643
16645
|
{
|
|
16644
16646
|
icon: import_md5.MdFormatListBulleted,
|
|
16645
16647
|
title: "Bulleted List",
|
|
16646
16648
|
onClick: () => editor.chain().focus().toggleBulletList().run(),
|
|
16647
|
-
disabled: !
|
|
16649
|
+
disabled: !canToggleBullet
|
|
16648
16650
|
}
|
|
16649
16651
|
), /* @__PURE__ */ import_react15.default.createElement(
|
|
16650
16652
|
ToolbarButton_default,
|
|
@@ -16652,7 +16654,7 @@ function ListAlignGroup({ editor }) {
|
|
|
16652
16654
|
icon: import_md5.MdFormatListNumbered,
|
|
16653
16655
|
title: "Numbered List",
|
|
16654
16656
|
onClick: () => editor.chain().focus().toggleOrderedList().run(),
|
|
16655
|
-
disabled: !
|
|
16657
|
+
disabled: !canToggleOrdered
|
|
16656
16658
|
}
|
|
16657
16659
|
), /* @__PURE__ */ import_react15.default.createElement(
|
|
16658
16660
|
ToolbarButton_default,
|
|
@@ -16660,7 +16662,7 @@ function ListAlignGroup({ editor }) {
|
|
|
16660
16662
|
icon: import_md5.MdFormatIndentIncrease,
|
|
16661
16663
|
title: "Increase Indent",
|
|
16662
16664
|
onClick: () => editor.chain().focus().sinkListItem("listItem").run(),
|
|
16663
|
-
disabled: !
|
|
16665
|
+
disabled: !canSink
|
|
16664
16666
|
}
|
|
16665
16667
|
), /* @__PURE__ */ import_react15.default.createElement(
|
|
16666
16668
|
ToolbarButton_default,
|
|
@@ -16668,7 +16670,7 @@ function ListAlignGroup({ editor }) {
|
|
|
16668
16670
|
icon: import_md5.MdFormatIndentDecrease,
|
|
16669
16671
|
title: "Decrease Indent",
|
|
16670
16672
|
onClick: () => editor.chain().focus().liftListItem("listItem").run(),
|
|
16671
|
-
disabled: !
|
|
16673
|
+
disabled: !canLift
|
|
16672
16674
|
}
|
|
16673
16675
|
), /* @__PURE__ */ import_react15.default.createElement(
|
|
16674
16676
|
ToolbarButton_default,
|
|
@@ -16729,26 +16731,7 @@ async function checkGrammar(text) {
|
|
|
16729
16731
|
}
|
|
16730
16732
|
|
|
16731
16733
|
// src/components/tetrons/toolbar/MiscGroup.tsx
|
|
16732
|
-
function MiscGroup({ editor }) {
|
|
16733
|
-
const handlePreview = () => {
|
|
16734
|
-
const html = editor.getHTML();
|
|
16735
|
-
const previewWindow = window.open("", "_blank");
|
|
16736
|
-
if (previewWindow) {
|
|
16737
|
-
previewWindow.document.open();
|
|
16738
|
-
previewWindow.document.write(`
|
|
16739
|
-
<html>
|
|
16740
|
-
<head>
|
|
16741
|
-
<title>Preview</title>
|
|
16742
|
-
<style>
|
|
16743
|
-
body { font-family: sans-serif; padding: 2rem; line-height: 1.6; }
|
|
16744
|
-
</style>
|
|
16745
|
-
</head>
|
|
16746
|
-
<body>${html}</body>
|
|
16747
|
-
</html>
|
|
16748
|
-
`);
|
|
16749
|
-
previewWindow.document.close();
|
|
16750
|
-
}
|
|
16751
|
-
};
|
|
16734
|
+
function MiscGroup({ editor, enabledFeatures }) {
|
|
16752
16735
|
const handleGrammarCheck = async () => {
|
|
16753
16736
|
const text = editor.getText();
|
|
16754
16737
|
try {
|
|
@@ -16772,7 +16755,26 @@ Reason: ${issue.message}
|
|
|
16772
16755
|
alert("\u274C Failed to check grammar. Please try again later.");
|
|
16773
16756
|
}
|
|
16774
16757
|
};
|
|
16775
|
-
|
|
16758
|
+
const handlePreview = () => {
|
|
16759
|
+
const html = editor.getHTML();
|
|
16760
|
+
const previewWindow = window.open("", "_blank");
|
|
16761
|
+
if (previewWindow) {
|
|
16762
|
+
previewWindow.document.open();
|
|
16763
|
+
previewWindow.document.write(`
|
|
16764
|
+
<html>
|
|
16765
|
+
<head>
|
|
16766
|
+
<title>Preview</title>
|
|
16767
|
+
<style>
|
|
16768
|
+
body { font-family: sans-serif; padding: 2rem; line-height: 1.6; }
|
|
16769
|
+
</style>
|
|
16770
|
+
</head>
|
|
16771
|
+
<body>${html}</body>
|
|
16772
|
+
</html>
|
|
16773
|
+
`);
|
|
16774
|
+
previewWindow.document.close();
|
|
16775
|
+
}
|
|
16776
|
+
};
|
|
16777
|
+
return /* @__PURE__ */ import_react16.default.createElement("div", { className: "misc-group" }, enabledFeatures.includes("undo") && /* @__PURE__ */ import_react16.default.createElement(
|
|
16776
16778
|
ToolbarButton_default,
|
|
16777
16779
|
{
|
|
16778
16780
|
icon: import_md6.MdUndo,
|
|
@@ -16780,7 +16782,7 @@ Reason: ${issue.message}
|
|
|
16780
16782
|
onClick: () => editor.chain().focus().undo().run(),
|
|
16781
16783
|
disabled: !editor.can().undo()
|
|
16782
16784
|
}
|
|
16783
|
-
), /* @__PURE__ */ import_react16.default.createElement(
|
|
16785
|
+
), enabledFeatures.includes("redo") && /* @__PURE__ */ import_react16.default.createElement(
|
|
16784
16786
|
ToolbarButton_default,
|
|
16785
16787
|
{
|
|
16786
16788
|
icon: import_md6.MdRedo,
|
|
@@ -16788,14 +16790,14 @@ Reason: ${issue.message}
|
|
|
16788
16790
|
onClick: () => editor.chain().focus().redo().run(),
|
|
16789
16791
|
disabled: !editor.can().redo()
|
|
16790
16792
|
}
|
|
16791
|
-
), /* @__PURE__ */ import_react16.default.createElement(
|
|
16793
|
+
), enabledFeatures.includes("resetFormatting") && /* @__PURE__ */ import_react16.default.createElement(
|
|
16792
16794
|
ToolbarButton_default,
|
|
16793
16795
|
{
|
|
16794
16796
|
icon: import_md6.MdRefresh,
|
|
16795
16797
|
label: "Reset Formatting",
|
|
16796
16798
|
onClick: () => editor.chain().focus().unsetAllMarks().clearNodes().run()
|
|
16797
16799
|
}
|
|
16798
|
-
), /* @__PURE__ */ import_react16.default.createElement(
|
|
16800
|
+
), enabledFeatures.includes("codeBlock") && /* @__PURE__ */ import_react16.default.createElement(
|
|
16799
16801
|
ToolbarButton_default,
|
|
16800
16802
|
{
|
|
16801
16803
|
icon: import_md6.MdCode,
|
|
@@ -16803,14 +16805,14 @@ Reason: ${issue.message}
|
|
|
16803
16805
|
onClick: () => editor.chain().focus().toggleCodeBlock().run(),
|
|
16804
16806
|
isActive: editor.isActive("codeBlock")
|
|
16805
16807
|
}
|
|
16806
|
-
), /* @__PURE__ */ import_react16.default.createElement(
|
|
16808
|
+
), enabledFeatures.includes("preview") && /* @__PURE__ */ import_react16.default.createElement(
|
|
16807
16809
|
ToolbarButton_default,
|
|
16808
16810
|
{
|
|
16809
16811
|
icon: import_md6.MdVisibility,
|
|
16810
16812
|
label: "Preview",
|
|
16811
16813
|
onClick: handlePreview
|
|
16812
16814
|
}
|
|
16813
|
-
), /* @__PURE__ */ import_react16.default.createElement(
|
|
16815
|
+
), enabledFeatures.includes("spell check") && /* @__PURE__ */ import_react16.default.createElement(
|
|
16814
16816
|
ToolbarButton_default,
|
|
16815
16817
|
{
|
|
16816
16818
|
icon: import_md6.MdSpellcheck,
|
|
@@ -16877,7 +16879,7 @@ var import_react18 = __toESM(require("react"));
|
|
|
16877
16879
|
var import_fa2 = require("react-icons/fa");
|
|
16878
16880
|
var import_loaders = require("@uiball/loaders");
|
|
16879
16881
|
var import_framer_motion = require("framer-motion");
|
|
16880
|
-
function AiGroup({ editor }) {
|
|
16882
|
+
function AiGroup({ editor, enabledFeatures }) {
|
|
16881
16883
|
const [isRecording, setIsRecording] = (0, import_react18.useState)(false);
|
|
16882
16884
|
const [audioBlob, setAudioBlob] = (0, import_react18.useState)(null);
|
|
16883
16885
|
const [isTranscribing, setIsTranscribing] = (0, import_react18.useState)(false);
|
|
@@ -16960,7 +16962,8 @@ function AiGroup({ editor }) {
|
|
|
16960
16962
|
setIsLoadingAI(false);
|
|
16961
16963
|
}
|
|
16962
16964
|
};
|
|
16963
|
-
|
|
16965
|
+
if (!enabledFeatures.includes("voice to text")) return null;
|
|
16966
|
+
return /* @__PURE__ */ import_react18.default.createElement("div", { className: "group flex flex-col gap-2 items-start" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "flex gap-2 items-center" }, !isRecording ? /* @__PURE__ */ import_react18.default.createElement(
|
|
16964
16967
|
"button",
|
|
16965
16968
|
{
|
|
16966
16969
|
type: "button",
|
|
@@ -17043,20 +17046,15 @@ var MathModal2 = (0, import_dynamic.default)(() => Promise.resolve().then(() =>
|
|
|
17043
17046
|
var CodeEditorModal2 = (0, import_dynamic.default)(() => Promise.resolve().then(() => (init_CodeEditorModal(), CodeEditorModal_exports)), {
|
|
17044
17047
|
ssr: false
|
|
17045
17048
|
});
|
|
17046
|
-
var AddOnGroup = ({ editor }) => {
|
|
17047
|
-
const [
|
|
17049
|
+
var AddOnGroup = ({ editor, addOns }) => {
|
|
17050
|
+
const [isMathModalOpen, setMathModalOpen] = (0, import_react22.useState)(false);
|
|
17048
17051
|
const [latexValue, setLatexValue] = (0, import_react22.useState)("");
|
|
17049
17052
|
const [isCodeModalOpen, setCodeModalOpen] = (0, import_react22.useState)(false);
|
|
17050
17053
|
if (!editor) return null;
|
|
17051
|
-
const insertCodeBlock = () =>
|
|
17052
|
-
setCodeModalOpen(true);
|
|
17053
|
-
};
|
|
17054
|
+
const insertCodeBlock = () => setCodeModalOpen(true);
|
|
17054
17055
|
const handleMathInsert = (latex) => {
|
|
17055
|
-
editor.chain().focus().insertContent({
|
|
17056
|
-
|
|
17057
|
-
attrs: { formula: latex }
|
|
17058
|
-
}).run();
|
|
17059
|
-
setModalOpen(false);
|
|
17056
|
+
editor.chain().focus().insertContent({ type: "mathInline", attrs: { formula: latex } }).run();
|
|
17057
|
+
setMathModalOpen(false);
|
|
17060
17058
|
setLatexValue("");
|
|
17061
17059
|
};
|
|
17062
17060
|
const handleSubmitCode = (code) => {
|
|
@@ -17082,7 +17080,7 @@ var AddOnGroup = ({ editor }) => {
|
|
|
17082
17080
|
}).run();
|
|
17083
17081
|
setCodeModalOpen(false);
|
|
17084
17082
|
};
|
|
17085
|
-
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(
|
|
17083
|
+
return /* @__PURE__ */ import_react22.default.createElement(import_react22.default.Fragment, null, /* @__PURE__ */ import_react22.default.createElement("div", { className: "group flex gap-2 items-center" }, addOns.includes("code") && /* @__PURE__ */ import_react22.default.createElement(
|
|
17086
17084
|
"button",
|
|
17087
17085
|
{
|
|
17088
17086
|
type: "button",
|
|
@@ -17091,25 +17089,25 @@ var AddOnGroup = ({ editor }) => {
|
|
|
17091
17089
|
title: "Open Code Editor"
|
|
17092
17090
|
},
|
|
17093
17091
|
/* @__PURE__ */ import_react22.default.createElement(import_lucide_react.MessageSquareCode, { size: 18 })
|
|
17094
|
-
), /* @__PURE__ */ import_react22.default.createElement(
|
|
17092
|
+
), addOns.includes("math") && /* @__PURE__ */ import_react22.default.createElement(
|
|
17095
17093
|
"button",
|
|
17096
17094
|
{
|
|
17097
17095
|
type: "button",
|
|
17098
|
-
onClick: () =>
|
|
17096
|
+
onClick: () => setMathModalOpen(true),
|
|
17099
17097
|
className: "addon-btn",
|
|
17100
17098
|
title: "Insert Math Equation"
|
|
17101
17099
|
},
|
|
17102
17100
|
/* @__PURE__ */ import_react22.default.createElement(import_lucide_react.SquareRadical, { size: 18 })
|
|
17103
|
-
)), /* @__PURE__ */ import_react22.default.createElement(
|
|
17101
|
+
)), addOns.includes("math") && /* @__PURE__ */ import_react22.default.createElement(
|
|
17104
17102
|
MathModal2,
|
|
17105
17103
|
{
|
|
17106
|
-
isOpen:
|
|
17107
|
-
onClose: () =>
|
|
17104
|
+
isOpen: isMathModalOpen,
|
|
17105
|
+
onClose: () => setMathModalOpen(false),
|
|
17108
17106
|
onSubmit: handleMathInsert,
|
|
17109
17107
|
value: latexValue,
|
|
17110
17108
|
setValue: setLatexValue
|
|
17111
17109
|
}
|
|
17112
|
-
), /* @__PURE__ */ import_react22.default.createElement(
|
|
17110
|
+
), addOns.includes("code") && /* @__PURE__ */ import_react22.default.createElement(
|
|
17113
17111
|
CodeEditorModal2,
|
|
17114
17112
|
{
|
|
17115
17113
|
isOpen: isCodeModalOpen,
|
|
@@ -17129,9 +17127,8 @@ function TetronsToolbar({
|
|
|
17129
17127
|
}) {
|
|
17130
17128
|
const [autoSave, setAutoSave] = (0, import_react23.useState)(false);
|
|
17131
17129
|
(0, import_react23.useEffect)(() => {
|
|
17132
|
-
if (!editor) return;
|
|
17130
|
+
if (!editor || !autoSave) return;
|
|
17133
17131
|
const handleUpdate = () => {
|
|
17134
|
-
if (!autoSave) return;
|
|
17135
17132
|
const content = editor.getJSON();
|
|
17136
17133
|
fetch("/api/save", {
|
|
17137
17134
|
method: "POST",
|
|
@@ -17150,7 +17147,18 @@ function TetronsToolbar({
|
|
|
17150
17147
|
case "premium":
|
|
17151
17148
|
return addOns;
|
|
17152
17149
|
case "platinum":
|
|
17153
|
-
return [
|
|
17150
|
+
return [
|
|
17151
|
+
"math",
|
|
17152
|
+
"code",
|
|
17153
|
+
"ai",
|
|
17154
|
+
"voice to text",
|
|
17155
|
+
"undo",
|
|
17156
|
+
"redo",
|
|
17157
|
+
"resetFormatting",
|
|
17158
|
+
"preview",
|
|
17159
|
+
"codeBlock",
|
|
17160
|
+
"spell check"
|
|
17161
|
+
];
|
|
17154
17162
|
default:
|
|
17155
17163
|
return [];
|
|
17156
17164
|
}
|
|
@@ -17163,7 +17171,36 @@ function TetronsToolbar({
|
|
|
17163
17171
|
checked: autoSave,
|
|
17164
17172
|
onChange: (e) => setAutoSave(e.target.checked)
|
|
17165
17173
|
}
|
|
17166
|
-
), /* @__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 })),
|
|
17174
|
+
), /* @__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 })), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ import_react23.default.createElement(
|
|
17175
|
+
MiscGroup,
|
|
17176
|
+
{
|
|
17177
|
+
editor,
|
|
17178
|
+
enabledFeatures: effectiveAddOns.filter(
|
|
17179
|
+
(a) => [
|
|
17180
|
+
"undo",
|
|
17181
|
+
"redo",
|
|
17182
|
+
"resetFormatting",
|
|
17183
|
+
"preview",
|
|
17184
|
+
"codeBlock",
|
|
17185
|
+
"spell check"
|
|
17186
|
+
].includes(a)
|
|
17187
|
+
)
|
|
17188
|
+
}
|
|
17189
|
+
), effectiveAddOns.some((a) => ["ai", "voice to text"].includes(a)) && /* @__PURE__ */ import_react23.default.createElement(
|
|
17190
|
+
AiGroup,
|
|
17191
|
+
{
|
|
17192
|
+
editor,
|
|
17193
|
+
enabledFeatures: effectiveAddOns.filter(
|
|
17194
|
+
(a) => ["ai", "voice to text"].includes(a)
|
|
17195
|
+
)
|
|
17196
|
+
}
|
|
17197
|
+
), effectiveAddOns.some((a) => a === "math" || a === "code") && /* @__PURE__ */ import_react23.default.createElement(
|
|
17198
|
+
AddOnGroup_default,
|
|
17199
|
+
{
|
|
17200
|
+
editor,
|
|
17201
|
+
addOns: effectiveAddOns.filter((a) => a === "math" || a === "code")
|
|
17202
|
+
}
|
|
17203
|
+
));
|
|
17167
17204
|
}
|
|
17168
17205
|
|
|
17169
17206
|
// src/components/tetrons/EditorContent.tsx
|
package/dist/index.mjs
CHANGED
|
@@ -15986,14 +15986,10 @@ function ActionGroup({ editor }) {
|
|
|
15986
15986
|
setDropdownOpen(false);
|
|
15987
15987
|
}
|
|
15988
15988
|
};
|
|
15989
|
-
if (dropdownOpen)
|
|
15989
|
+
if (dropdownOpen)
|
|
15990
15990
|
document.addEventListener("mousedown", handleClickOutside);
|
|
15991
|
-
|
|
15992
|
-
|
|
15993
|
-
}
|
|
15994
|
-
return () => {
|
|
15995
|
-
document.removeEventListener("mousedown", handleClickOutside);
|
|
15996
|
-
};
|
|
15991
|
+
else document.removeEventListener("mousedown", handleClickOutside);
|
|
15992
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
15997
15993
|
}, [dropdownOpen]);
|
|
15998
15994
|
const zoomIn = () => {
|
|
15999
15995
|
const element = document.querySelector(
|
|
@@ -16002,8 +15998,7 @@ function ActionGroup({ editor }) {
|
|
|
16002
15998
|
if (element) {
|
|
16003
15999
|
const style = element.style;
|
|
16004
16000
|
const currentZoom = parseFloat(style.zoom || "1");
|
|
16005
|
-
|
|
16006
|
-
style.zoom = next.toString();
|
|
16001
|
+
style.zoom = Math.min(currentZoom + 0.1, 2).toString();
|
|
16007
16002
|
}
|
|
16008
16003
|
};
|
|
16009
16004
|
const zoomOut = () => {
|
|
@@ -16013,28 +16008,24 @@ function ActionGroup({ editor }) {
|
|
|
16013
16008
|
if (element) {
|
|
16014
16009
|
const style = element.style;
|
|
16015
16010
|
const currentZoom = parseFloat(style.zoom || "1");
|
|
16016
|
-
|
|
16017
|
-
style.zoom = next.toString();
|
|
16011
|
+
style.zoom = Math.max(currentZoom - 0.1, 0.5).toString();
|
|
16018
16012
|
}
|
|
16019
16013
|
};
|
|
16020
16014
|
const handlePrint = () => {
|
|
16015
|
+
if (!editor) return;
|
|
16021
16016
|
const html = editor.getHTML();
|
|
16022
16017
|
const printWindow = window.open("", "_blank");
|
|
16023
16018
|
if (printWindow) {
|
|
16024
|
-
printWindow.document.write(
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
<title>Print</title>
|
|
16028
|
-
</head>
|
|
16029
|
-
<body>${html}</body>
|
|
16030
|
-
</html>
|
|
16031
|
-
`);
|
|
16019
|
+
printWindow.document.write(
|
|
16020
|
+
`<html><head><title>Print</title></head><body>${html}</body></html>`
|
|
16021
|
+
);
|
|
16032
16022
|
printWindow.document.close();
|
|
16033
16023
|
printWindow.focus();
|
|
16034
16024
|
printWindow.print();
|
|
16035
16025
|
}
|
|
16036
16026
|
};
|
|
16037
16027
|
const handleSave = async () => {
|
|
16028
|
+
if (!editor) return;
|
|
16038
16029
|
const content = editor.getJSON();
|
|
16039
16030
|
try {
|
|
16040
16031
|
const response = await fetch("/api/save", {
|
|
@@ -16044,14 +16035,14 @@ function ActionGroup({ editor }) {
|
|
|
16044
16035
|
});
|
|
16045
16036
|
if (!response.ok) throw new Error("Failed to save file");
|
|
16046
16037
|
const result = await response.json();
|
|
16047
|
-
|
|
16048
|
-
alert("Content saved successfully!");
|
|
16038
|
+
alert(result.message || "Content saved successfully!");
|
|
16049
16039
|
} catch (error) {
|
|
16050
|
-
console.error(
|
|
16040
|
+
console.error(error);
|
|
16051
16041
|
alert("Failed to save content.");
|
|
16052
16042
|
}
|
|
16053
16043
|
};
|
|
16054
16044
|
const handleDownloadPDF = async () => {
|
|
16045
|
+
if (!editor) return;
|
|
16055
16046
|
const html = editor.getHTML();
|
|
16056
16047
|
const container = document.createElement("div");
|
|
16057
16048
|
container.innerHTML = html;
|
|
@@ -16059,22 +16050,22 @@ function ActionGroup({ editor }) {
|
|
|
16059
16050
|
document.body.appendChild(container);
|
|
16060
16051
|
try {
|
|
16061
16052
|
const domToPdf = (await import("dom-to-pdf")).default;
|
|
16062
|
-
|
|
16063
|
-
|
|
16064
|
-
overrideWidth: 800,
|
|
16065
|
-
|
|
16066
|
-
|
|
16067
|
-
|
|
16068
|
-
|
|
16069
|
-
});
|
|
16053
|
+
domToPdf(
|
|
16054
|
+
container,
|
|
16055
|
+
{ filename: "document.pdf", overrideWidth: 800, overrideHeight: 1120 },
|
|
16056
|
+
() => {
|
|
16057
|
+
console.log("PDF downloaded!");
|
|
16058
|
+
}
|
|
16059
|
+
);
|
|
16070
16060
|
} catch (error) {
|
|
16071
|
-
console.error(
|
|
16061
|
+
console.error(error);
|
|
16072
16062
|
alert("Failed to download PDF.");
|
|
16073
16063
|
} finally {
|
|
16074
16064
|
document.body.removeChild(container);
|
|
16075
16065
|
}
|
|
16076
16066
|
};
|
|
16077
16067
|
const handleDownloadHTML = () => {
|
|
16068
|
+
if (!editor) return;
|
|
16078
16069
|
const html = editor.getHTML();
|
|
16079
16070
|
const blob = new Blob([html], { type: "text/html" });
|
|
16080
16071
|
const link = document.createElement("a");
|
|
@@ -16085,15 +16076,11 @@ function ActionGroup({ editor }) {
|
|
|
16085
16076
|
document.body.removeChild(link);
|
|
16086
16077
|
};
|
|
16087
16078
|
const handleDownloadDOCX = async () => {
|
|
16079
|
+
if (!editor) return;
|
|
16088
16080
|
const { Document: Document2, Packer, Paragraph: Paragraph2 } = await import("docx");
|
|
16089
16081
|
const text = editor.getText();
|
|
16090
16082
|
const doc3 = new Document2({
|
|
16091
|
-
sections: [
|
|
16092
|
-
{
|
|
16093
|
-
properties: {},
|
|
16094
|
-
children: [new Paragraph2(text)]
|
|
16095
|
-
}
|
|
16096
|
-
]
|
|
16083
|
+
sections: [{ properties: {}, children: [new Paragraph2(text)] }]
|
|
16097
16084
|
});
|
|
16098
16085
|
const blob = await Packer.toBlob(doc3);
|
|
16099
16086
|
const link = document.createElement("a");
|
|
@@ -16103,49 +16090,59 @@ function ActionGroup({ editor }) {
|
|
|
16103
16090
|
link.click();
|
|
16104
16091
|
document.body.removeChild(link);
|
|
16105
16092
|
};
|
|
16106
|
-
|
|
16107
|
-
|
|
16108
|
-
|
|
16109
|
-
type: "button",
|
|
16110
|
-
onClick: () => setDropdownOpen((open) => !open),
|
|
16111
|
-
"aria-haspopup": "menu",
|
|
16112
|
-
"aria-expanded": dropdownOpen ? "true" : "false",
|
|
16113
|
-
className: "export-button",
|
|
16114
|
-
title: "Export"
|
|
16115
|
-
},
|
|
16116
|
-
/* @__PURE__ */ React5.createElement(MdDownload, null),
|
|
16117
|
-
/* @__PURE__ */ React5.createElement("span", { className: "text-sm" })
|
|
16118
|
-
), dropdownOpen && /* @__PURE__ */ React5.createElement("div", { className: "export-dropdown" }, /* @__PURE__ */ React5.createElement(
|
|
16119
|
-
"button",
|
|
16120
|
-
{
|
|
16121
|
-
type: "button",
|
|
16122
|
-
onClick: () => {
|
|
16123
|
-
setDropdownOpen(false);
|
|
16124
|
-
handleDownloadPDF();
|
|
16125
|
-
}
|
|
16126
|
-
},
|
|
16127
|
-
"Export as PDF"
|
|
16128
|
-
), /* @__PURE__ */ React5.createElement(
|
|
16129
|
-
"button",
|
|
16130
|
-
{
|
|
16131
|
-
type: "button",
|
|
16132
|
-
onClick: () => {
|
|
16133
|
-
setDropdownOpen(false);
|
|
16134
|
-
handleDownloadHTML();
|
|
16135
|
-
}
|
|
16136
|
-
},
|
|
16137
|
-
"Export as HTML"
|
|
16138
|
-
), /* @__PURE__ */ React5.createElement(
|
|
16139
|
-
"button",
|
|
16093
|
+
if (!editor) return null;
|
|
16094
|
+
return /* @__PURE__ */ React5.createElement(
|
|
16095
|
+
"div",
|
|
16140
16096
|
{
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
handleDownloadDOCX();
|
|
16145
|
-
}
|
|
16097
|
+
className: "action-group bg-white text-black dark:bg-gray-800 dark:text-white",
|
|
16098
|
+
role: "group",
|
|
16099
|
+
"aria-label": "Editor actions"
|
|
16146
16100
|
},
|
|
16147
|
-
"
|
|
16148
|
-
|
|
16101
|
+
/* @__PURE__ */ React5.createElement(ToolbarButton_default, { icon: MdZoomIn, onClick: zoomIn, title: "Zoom In" }),
|
|
16102
|
+
/* @__PURE__ */ React5.createElement(ToolbarButton_default, { icon: MdZoomOut, onClick: zoomOut, title: "Zoom Out" }),
|
|
16103
|
+
/* @__PURE__ */ React5.createElement(ToolbarButton_default, { icon: MdPrint, onClick: handlePrint, title: "Print" }),
|
|
16104
|
+
/* @__PURE__ */ React5.createElement(ToolbarButton_default, { icon: MdSave, onClick: handleSave, title: "Save" }),
|
|
16105
|
+
/* @__PURE__ */ React5.createElement("div", { className: "relative", ref: dropdownRef }, /* @__PURE__ */ React5.createElement(
|
|
16106
|
+
"button",
|
|
16107
|
+
{
|
|
16108
|
+
type: "button",
|
|
16109
|
+
onClick: () => setDropdownOpen((o) => !o),
|
|
16110
|
+
className: "export-button",
|
|
16111
|
+
title: "Export"
|
|
16112
|
+
},
|
|
16113
|
+
/* @__PURE__ */ React5.createElement(MdDownload, null)
|
|
16114
|
+
), dropdownOpen && /* @__PURE__ */ React5.createElement("div", { className: "export-dropdown" }, /* @__PURE__ */ React5.createElement(
|
|
16115
|
+
"button",
|
|
16116
|
+
{
|
|
16117
|
+
type: "button",
|
|
16118
|
+
onClick: () => {
|
|
16119
|
+
setDropdownOpen(false);
|
|
16120
|
+
handleDownloadPDF();
|
|
16121
|
+
}
|
|
16122
|
+
},
|
|
16123
|
+
"Export as PDF"
|
|
16124
|
+
), /* @__PURE__ */ React5.createElement(
|
|
16125
|
+
"button",
|
|
16126
|
+
{
|
|
16127
|
+
type: "button",
|
|
16128
|
+
onClick: () => {
|
|
16129
|
+
setDropdownOpen(false);
|
|
16130
|
+
handleDownloadHTML();
|
|
16131
|
+
}
|
|
16132
|
+
},
|
|
16133
|
+
"Export as HTML"
|
|
16134
|
+
), /* @__PURE__ */ React5.createElement(
|
|
16135
|
+
"button",
|
|
16136
|
+
{
|
|
16137
|
+
type: "button",
|
|
16138
|
+
onClick: () => {
|
|
16139
|
+
setDropdownOpen(false);
|
|
16140
|
+
handleDownloadDOCX();
|
|
16141
|
+
}
|
|
16142
|
+
},
|
|
16143
|
+
"Export as DOCX"
|
|
16144
|
+
)))
|
|
16145
|
+
);
|
|
16149
16146
|
}
|
|
16150
16147
|
|
|
16151
16148
|
// src/components/tetrons/toolbar/ClipboardGroup.tsx
|
|
@@ -16640,13 +16637,18 @@ import {
|
|
|
16640
16637
|
MdFormatAlignJustify
|
|
16641
16638
|
} from "react-icons/md";
|
|
16642
16639
|
function ListAlignGroup({ editor }) {
|
|
16643
|
-
|
|
16640
|
+
if (!editor) return null;
|
|
16641
|
+
const canToggleBullet = editor.can().toggleBulletList() || editor.isEmpty;
|
|
16642
|
+
const canToggleOrdered = editor.can().toggleOrderedList() || editor.isEmpty;
|
|
16643
|
+
const canSink = editor.can().sinkListItem("listItem");
|
|
16644
|
+
const canLift = editor.can().liftListItem("listItem");
|
|
16645
|
+
return /* @__PURE__ */ React9.createElement("div", { className: "list-align-group bg-white text-black dark:bg-gray-800 dark:text-white" }, /* @__PURE__ */ React9.createElement(
|
|
16644
16646
|
ToolbarButton_default,
|
|
16645
16647
|
{
|
|
16646
16648
|
icon: MdFormatListBulleted,
|
|
16647
16649
|
title: "Bulleted List",
|
|
16648
16650
|
onClick: () => editor.chain().focus().toggleBulletList().run(),
|
|
16649
|
-
disabled: !
|
|
16651
|
+
disabled: !canToggleBullet
|
|
16650
16652
|
}
|
|
16651
16653
|
), /* @__PURE__ */ React9.createElement(
|
|
16652
16654
|
ToolbarButton_default,
|
|
@@ -16654,7 +16656,7 @@ function ListAlignGroup({ editor }) {
|
|
|
16654
16656
|
icon: MdFormatListNumbered,
|
|
16655
16657
|
title: "Numbered List",
|
|
16656
16658
|
onClick: () => editor.chain().focus().toggleOrderedList().run(),
|
|
16657
|
-
disabled: !
|
|
16659
|
+
disabled: !canToggleOrdered
|
|
16658
16660
|
}
|
|
16659
16661
|
), /* @__PURE__ */ React9.createElement(
|
|
16660
16662
|
ToolbarButton_default,
|
|
@@ -16662,7 +16664,7 @@ function ListAlignGroup({ editor }) {
|
|
|
16662
16664
|
icon: MdFormatIndentIncrease,
|
|
16663
16665
|
title: "Increase Indent",
|
|
16664
16666
|
onClick: () => editor.chain().focus().sinkListItem("listItem").run(),
|
|
16665
|
-
disabled: !
|
|
16667
|
+
disabled: !canSink
|
|
16666
16668
|
}
|
|
16667
16669
|
), /* @__PURE__ */ React9.createElement(
|
|
16668
16670
|
ToolbarButton_default,
|
|
@@ -16670,7 +16672,7 @@ function ListAlignGroup({ editor }) {
|
|
|
16670
16672
|
icon: MdFormatIndentDecrease,
|
|
16671
16673
|
title: "Decrease Indent",
|
|
16672
16674
|
onClick: () => editor.chain().focus().liftListItem("listItem").run(),
|
|
16673
|
-
disabled: !
|
|
16675
|
+
disabled: !canLift
|
|
16674
16676
|
}
|
|
16675
16677
|
), /* @__PURE__ */ React9.createElement(
|
|
16676
16678
|
ToolbarButton_default,
|
|
@@ -16738,26 +16740,7 @@ async function checkGrammar(text) {
|
|
|
16738
16740
|
}
|
|
16739
16741
|
|
|
16740
16742
|
// src/components/tetrons/toolbar/MiscGroup.tsx
|
|
16741
|
-
function MiscGroup({ editor }) {
|
|
16742
|
-
const handlePreview = () => {
|
|
16743
|
-
const html = editor.getHTML();
|
|
16744
|
-
const previewWindow = window.open("", "_blank");
|
|
16745
|
-
if (previewWindow) {
|
|
16746
|
-
previewWindow.document.open();
|
|
16747
|
-
previewWindow.document.write(`
|
|
16748
|
-
<html>
|
|
16749
|
-
<head>
|
|
16750
|
-
<title>Preview</title>
|
|
16751
|
-
<style>
|
|
16752
|
-
body { font-family: sans-serif; padding: 2rem; line-height: 1.6; }
|
|
16753
|
-
</style>
|
|
16754
|
-
</head>
|
|
16755
|
-
<body>${html}</body>
|
|
16756
|
-
</html>
|
|
16757
|
-
`);
|
|
16758
|
-
previewWindow.document.close();
|
|
16759
|
-
}
|
|
16760
|
-
};
|
|
16743
|
+
function MiscGroup({ editor, enabledFeatures }) {
|
|
16761
16744
|
const handleGrammarCheck = async () => {
|
|
16762
16745
|
const text = editor.getText();
|
|
16763
16746
|
try {
|
|
@@ -16781,7 +16764,26 @@ Reason: ${issue.message}
|
|
|
16781
16764
|
alert("\u274C Failed to check grammar. Please try again later.");
|
|
16782
16765
|
}
|
|
16783
16766
|
};
|
|
16784
|
-
|
|
16767
|
+
const handlePreview = () => {
|
|
16768
|
+
const html = editor.getHTML();
|
|
16769
|
+
const previewWindow = window.open("", "_blank");
|
|
16770
|
+
if (previewWindow) {
|
|
16771
|
+
previewWindow.document.open();
|
|
16772
|
+
previewWindow.document.write(`
|
|
16773
|
+
<html>
|
|
16774
|
+
<head>
|
|
16775
|
+
<title>Preview</title>
|
|
16776
|
+
<style>
|
|
16777
|
+
body { font-family: sans-serif; padding: 2rem; line-height: 1.6; }
|
|
16778
|
+
</style>
|
|
16779
|
+
</head>
|
|
16780
|
+
<body>${html}</body>
|
|
16781
|
+
</html>
|
|
16782
|
+
`);
|
|
16783
|
+
previewWindow.document.close();
|
|
16784
|
+
}
|
|
16785
|
+
};
|
|
16786
|
+
return /* @__PURE__ */ React10.createElement("div", { className: "misc-group" }, enabledFeatures.includes("undo") && /* @__PURE__ */ React10.createElement(
|
|
16785
16787
|
ToolbarButton_default,
|
|
16786
16788
|
{
|
|
16787
16789
|
icon: MdUndo,
|
|
@@ -16789,7 +16791,7 @@ Reason: ${issue.message}
|
|
|
16789
16791
|
onClick: () => editor.chain().focus().undo().run(),
|
|
16790
16792
|
disabled: !editor.can().undo()
|
|
16791
16793
|
}
|
|
16792
|
-
), /* @__PURE__ */ React10.createElement(
|
|
16794
|
+
), enabledFeatures.includes("redo") && /* @__PURE__ */ React10.createElement(
|
|
16793
16795
|
ToolbarButton_default,
|
|
16794
16796
|
{
|
|
16795
16797
|
icon: MdRedo,
|
|
@@ -16797,14 +16799,14 @@ Reason: ${issue.message}
|
|
|
16797
16799
|
onClick: () => editor.chain().focus().redo().run(),
|
|
16798
16800
|
disabled: !editor.can().redo()
|
|
16799
16801
|
}
|
|
16800
|
-
), /* @__PURE__ */ React10.createElement(
|
|
16802
|
+
), enabledFeatures.includes("resetFormatting") && /* @__PURE__ */ React10.createElement(
|
|
16801
16803
|
ToolbarButton_default,
|
|
16802
16804
|
{
|
|
16803
16805
|
icon: MdRefresh,
|
|
16804
16806
|
label: "Reset Formatting",
|
|
16805
16807
|
onClick: () => editor.chain().focus().unsetAllMarks().clearNodes().run()
|
|
16806
16808
|
}
|
|
16807
|
-
), /* @__PURE__ */ React10.createElement(
|
|
16809
|
+
), enabledFeatures.includes("codeBlock") && /* @__PURE__ */ React10.createElement(
|
|
16808
16810
|
ToolbarButton_default,
|
|
16809
16811
|
{
|
|
16810
16812
|
icon: MdCode,
|
|
@@ -16812,14 +16814,14 @@ Reason: ${issue.message}
|
|
|
16812
16814
|
onClick: () => editor.chain().focus().toggleCodeBlock().run(),
|
|
16813
16815
|
isActive: editor.isActive("codeBlock")
|
|
16814
16816
|
}
|
|
16815
|
-
), /* @__PURE__ */ React10.createElement(
|
|
16817
|
+
), enabledFeatures.includes("preview") && /* @__PURE__ */ React10.createElement(
|
|
16816
16818
|
ToolbarButton_default,
|
|
16817
16819
|
{
|
|
16818
16820
|
icon: MdVisibility,
|
|
16819
16821
|
label: "Preview",
|
|
16820
16822
|
onClick: handlePreview
|
|
16821
16823
|
}
|
|
16822
|
-
), /* @__PURE__ */ React10.createElement(
|
|
16824
|
+
), enabledFeatures.includes("spell check") && /* @__PURE__ */ React10.createElement(
|
|
16823
16825
|
ToolbarButton_default,
|
|
16824
16826
|
{
|
|
16825
16827
|
icon: MdSpellcheck,
|
|
@@ -16886,7 +16888,7 @@ import React12, { useState as useState7, useRef as useRef6 } from "react";
|
|
|
16886
16888
|
import { FaMicrophone, FaStop } from "react-icons/fa";
|
|
16887
16889
|
import { Waveform } from "@uiball/loaders";
|
|
16888
16890
|
import { motion, AnimatePresence } from "framer-motion";
|
|
16889
|
-
function AiGroup({ editor }) {
|
|
16891
|
+
function AiGroup({ editor, enabledFeatures }) {
|
|
16890
16892
|
const [isRecording, setIsRecording] = useState7(false);
|
|
16891
16893
|
const [audioBlob, setAudioBlob] = useState7(null);
|
|
16892
16894
|
const [isTranscribing, setIsTranscribing] = useState7(false);
|
|
@@ -16969,7 +16971,8 @@ function AiGroup({ editor }) {
|
|
|
16969
16971
|
setIsLoadingAI(false);
|
|
16970
16972
|
}
|
|
16971
16973
|
};
|
|
16972
|
-
|
|
16974
|
+
if (!enabledFeatures.includes("voice to text")) return null;
|
|
16975
|
+
return /* @__PURE__ */ React12.createElement("div", { className: "group flex flex-col gap-2 items-start" }, /* @__PURE__ */ React12.createElement("div", { className: "flex gap-2 items-center" }, !isRecording ? /* @__PURE__ */ React12.createElement(
|
|
16973
16976
|
"button",
|
|
16974
16977
|
{
|
|
16975
16978
|
type: "button",
|
|
@@ -17052,20 +17055,15 @@ var MathModal2 = dynamic(() => Promise.resolve().then(() => (init_MathModal(), M
|
|
|
17052
17055
|
var CodeEditorModal2 = dynamic(() => Promise.resolve().then(() => (init_CodeEditorModal(), CodeEditorModal_exports)), {
|
|
17053
17056
|
ssr: false
|
|
17054
17057
|
});
|
|
17055
|
-
var AddOnGroup = ({ editor }) => {
|
|
17056
|
-
const [
|
|
17058
|
+
var AddOnGroup = ({ editor, addOns }) => {
|
|
17059
|
+
const [isMathModalOpen, setMathModalOpen] = useState9(false);
|
|
17057
17060
|
const [latexValue, setLatexValue] = useState9("");
|
|
17058
17061
|
const [isCodeModalOpen, setCodeModalOpen] = useState9(false);
|
|
17059
17062
|
if (!editor) return null;
|
|
17060
|
-
const insertCodeBlock = () =>
|
|
17061
|
-
setCodeModalOpen(true);
|
|
17062
|
-
};
|
|
17063
|
+
const insertCodeBlock = () => setCodeModalOpen(true);
|
|
17063
17064
|
const handleMathInsert = (latex) => {
|
|
17064
|
-
editor.chain().focus().insertContent({
|
|
17065
|
-
|
|
17066
|
-
attrs: { formula: latex }
|
|
17067
|
-
}).run();
|
|
17068
|
-
setModalOpen(false);
|
|
17065
|
+
editor.chain().focus().insertContent({ type: "mathInline", attrs: { formula: latex } }).run();
|
|
17066
|
+
setMathModalOpen(false);
|
|
17069
17067
|
setLatexValue("");
|
|
17070
17068
|
};
|
|
17071
17069
|
const handleSubmitCode = (code) => {
|
|
@@ -17091,7 +17089,7 @@ var AddOnGroup = ({ editor }) => {
|
|
|
17091
17089
|
}).run();
|
|
17092
17090
|
setCodeModalOpen(false);
|
|
17093
17091
|
};
|
|
17094
|
-
return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "group flex gap-2 items-center" }, /* @__PURE__ */ React15.createElement(
|
|
17092
|
+
return /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement("div", { className: "group flex gap-2 items-center" }, addOns.includes("code") && /* @__PURE__ */ React15.createElement(
|
|
17095
17093
|
"button",
|
|
17096
17094
|
{
|
|
17097
17095
|
type: "button",
|
|
@@ -17100,25 +17098,25 @@ var AddOnGroup = ({ editor }) => {
|
|
|
17100
17098
|
title: "Open Code Editor"
|
|
17101
17099
|
},
|
|
17102
17100
|
/* @__PURE__ */ React15.createElement(MessageSquareCode, { size: 18 })
|
|
17103
|
-
), /* @__PURE__ */ React15.createElement(
|
|
17101
|
+
), addOns.includes("math") && /* @__PURE__ */ React15.createElement(
|
|
17104
17102
|
"button",
|
|
17105
17103
|
{
|
|
17106
17104
|
type: "button",
|
|
17107
|
-
onClick: () =>
|
|
17105
|
+
onClick: () => setMathModalOpen(true),
|
|
17108
17106
|
className: "addon-btn",
|
|
17109
17107
|
title: "Insert Math Equation"
|
|
17110
17108
|
},
|
|
17111
17109
|
/* @__PURE__ */ React15.createElement(SquareRadical, { size: 18 })
|
|
17112
|
-
)), /* @__PURE__ */ React15.createElement(
|
|
17110
|
+
)), addOns.includes("math") && /* @__PURE__ */ React15.createElement(
|
|
17113
17111
|
MathModal2,
|
|
17114
17112
|
{
|
|
17115
|
-
isOpen:
|
|
17116
|
-
onClose: () =>
|
|
17113
|
+
isOpen: isMathModalOpen,
|
|
17114
|
+
onClose: () => setMathModalOpen(false),
|
|
17117
17115
|
onSubmit: handleMathInsert,
|
|
17118
17116
|
value: latexValue,
|
|
17119
17117
|
setValue: setLatexValue
|
|
17120
17118
|
}
|
|
17121
|
-
), /* @__PURE__ */ React15.createElement(
|
|
17119
|
+
), addOns.includes("code") && /* @__PURE__ */ React15.createElement(
|
|
17122
17120
|
CodeEditorModal2,
|
|
17123
17121
|
{
|
|
17124
17122
|
isOpen: isCodeModalOpen,
|
|
@@ -17138,9 +17136,8 @@ function TetronsToolbar({
|
|
|
17138
17136
|
}) {
|
|
17139
17137
|
const [autoSave, setAutoSave] = useState10(false);
|
|
17140
17138
|
useEffect8(() => {
|
|
17141
|
-
if (!editor) return;
|
|
17139
|
+
if (!editor || !autoSave) return;
|
|
17142
17140
|
const handleUpdate = () => {
|
|
17143
|
-
if (!autoSave) return;
|
|
17144
17141
|
const content = editor.getJSON();
|
|
17145
17142
|
fetch("/api/save", {
|
|
17146
17143
|
method: "POST",
|
|
@@ -17159,7 +17156,18 @@ function TetronsToolbar({
|
|
|
17159
17156
|
case "premium":
|
|
17160
17157
|
return addOns;
|
|
17161
17158
|
case "platinum":
|
|
17162
|
-
return [
|
|
17159
|
+
return [
|
|
17160
|
+
"math",
|
|
17161
|
+
"code",
|
|
17162
|
+
"ai",
|
|
17163
|
+
"voice to text",
|
|
17164
|
+
"undo",
|
|
17165
|
+
"redo",
|
|
17166
|
+
"resetFormatting",
|
|
17167
|
+
"preview",
|
|
17168
|
+
"codeBlock",
|
|
17169
|
+
"spell check"
|
|
17170
|
+
];
|
|
17163
17171
|
default:
|
|
17164
17172
|
return [];
|
|
17165
17173
|
}
|
|
@@ -17172,7 +17180,36 @@ function TetronsToolbar({
|
|
|
17172
17180
|
checked: autoSave,
|
|
17173
17181
|
onChange: (e) => setAutoSave(e.target.checked)
|
|
17174
17182
|
}
|
|
17175
|
-
), /* @__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 })),
|
|
17183
|
+
), /* @__PURE__ */ React16.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ React16.createElement(FileGroup, { editor }), /* @__PURE__ */ React16.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ React16.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ React16.createElement(ListAlignGroup, { editor }), ["premium", "platinum"].includes(version) && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(InsertGroup, { editor }), /* @__PURE__ */ React16.createElement(ActionGroup, { editor })), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ React16.createElement(
|
|
17184
|
+
MiscGroup,
|
|
17185
|
+
{
|
|
17186
|
+
editor,
|
|
17187
|
+
enabledFeatures: effectiveAddOns.filter(
|
|
17188
|
+
(a) => [
|
|
17189
|
+
"undo",
|
|
17190
|
+
"redo",
|
|
17191
|
+
"resetFormatting",
|
|
17192
|
+
"preview",
|
|
17193
|
+
"codeBlock",
|
|
17194
|
+
"spell check"
|
|
17195
|
+
].includes(a)
|
|
17196
|
+
)
|
|
17197
|
+
}
|
|
17198
|
+
), effectiveAddOns.some((a) => ["ai", "voice to text"].includes(a)) && /* @__PURE__ */ React16.createElement(
|
|
17199
|
+
AiGroup,
|
|
17200
|
+
{
|
|
17201
|
+
editor,
|
|
17202
|
+
enabledFeatures: effectiveAddOns.filter(
|
|
17203
|
+
(a) => ["ai", "voice to text"].includes(a)
|
|
17204
|
+
)
|
|
17205
|
+
}
|
|
17206
|
+
), effectiveAddOns.some((a) => a === "math" || a === "code") && /* @__PURE__ */ React16.createElement(
|
|
17207
|
+
AddOnGroup_default,
|
|
17208
|
+
{
|
|
17209
|
+
editor,
|
|
17210
|
+
addOns: effectiveAddOns.filter((a) => a === "math" || a === "code")
|
|
17211
|
+
}
|
|
17212
|
+
));
|
|
17176
17213
|
}
|
|
17177
17214
|
|
|
17178
17215
|
// src/components/tetrons/EditorContent.tsx
|