tetrons 2.3.100 → 2.4.1
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.
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EditorRuntimeProps } from "./types/TetronsEditorProps";
|
|
2
2
|
import "katex/dist/katex.min.css";
|
|
3
|
-
export default function Editor(props:
|
|
3
|
+
export default function Editor(props: EditorRuntimeProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import type { TetronsConfig } from "./types/TetronsEditorProps";
|
|
1
2
|
import type { ValidationResponse } from "./types/ValidationResponse";
|
|
2
3
|
interface TetronsEditorProps {
|
|
3
4
|
apiKey: string;
|
|
5
|
+
config?: TetronsConfig;
|
|
4
6
|
onError?: (msg: string) => void;
|
|
5
7
|
onSuccess?: (details: ValidationResponse) => void;
|
|
8
|
+
onChange?: (payload: {
|
|
9
|
+
html: string;
|
|
10
|
+
json: unknown;
|
|
11
|
+
}) => void;
|
|
6
12
|
}
|
|
7
|
-
export default function TetronsEditor({ apiKey, onError, onSuccess, }: TetronsEditorProps): import("react/jsx-runtime").JSX.Element | null;
|
|
13
|
+
export default function TetronsEditor({ apiKey, config, onError, onSuccess, onChange, }: TetronsEditorProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
14
|
export {};
|
|
@@ -61,6 +61,36 @@ export interface PlatinumOnlyFeatureFlags {
|
|
|
61
61
|
export type ProFeatureFlags = FreeFeatureFlags;
|
|
62
62
|
export type PremiumFeatureFlags = FreeFeatureFlags & PremiumOnlyFeatureFlags;
|
|
63
63
|
export type PlatinumFeatureFlags = FreeFeatureFlags & PremiumOnlyFeatureFlags & PlatinumOnlyFeatureFlags;
|
|
64
|
+
export interface TetronsConfig {
|
|
65
|
+
version?: ProductVersion;
|
|
66
|
+
features?: FeatureFlags;
|
|
67
|
+
addOns?: PremiumOnlyFeatureFlags & PlatinumOnlyFeatureFlags;
|
|
68
|
+
autoSave?: boolean;
|
|
69
|
+
showVersions?: boolean;
|
|
70
|
+
ui?: {
|
|
71
|
+
topMenu?: boolean;
|
|
72
|
+
paragraphDropdown?: boolean;
|
|
73
|
+
fontDropdown?: boolean;
|
|
74
|
+
fontSizeDropdown?: boolean;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export interface EditorRuntimeProps {
|
|
78
|
+
version: ProductVersion;
|
|
79
|
+
apiKey: string;
|
|
80
|
+
features?: FeatureFlags;
|
|
81
|
+
addOns?: PremiumOnlyFeatureFlags & PlatinumOnlyFeatureFlags;
|
|
82
|
+
platinumAddOns?: PlatinumOnlyFeatureFlags;
|
|
83
|
+
autoSave?: boolean;
|
|
84
|
+
showVersions?: boolean;
|
|
85
|
+
topMenu?: boolean;
|
|
86
|
+
showParagraphDropdown?: boolean;
|
|
87
|
+
showFontDropdown?: boolean;
|
|
88
|
+
showFontSizeDropdown?: boolean;
|
|
89
|
+
onChange?: (payload: {
|
|
90
|
+
html: string;
|
|
91
|
+
json: unknown;
|
|
92
|
+
}) => void;
|
|
93
|
+
}
|
|
64
94
|
interface BaseProps {
|
|
65
95
|
apiKey: string;
|
|
66
96
|
topMenu?: boolean;
|
package/dist/index.css
CHANGED
|
@@ -4886,3 +4886,69 @@ textarea#email-body {
|
|
|
4886
4886
|
z-index: 9999999999 !important;
|
|
4887
4887
|
position: relative;
|
|
4888
4888
|
}
|
|
4889
|
+
.ProseMirror table {
|
|
4890
|
+
border-collapse: collapse;
|
|
4891
|
+
table-layout: fixed;
|
|
4892
|
+
width: 100%;
|
|
4893
|
+
max-width: 100%;
|
|
4894
|
+
margin: 0.75em 0;
|
|
4895
|
+
background: #fff;
|
|
4896
|
+
}
|
|
4897
|
+
.ProseMirror th,
|
|
4898
|
+
.ProseMirror td {
|
|
4899
|
+
border: 1px solid #d0d0d0;
|
|
4900
|
+
padding: 6px 8px;
|
|
4901
|
+
vertical-align: top;
|
|
4902
|
+
word-break: break-word;
|
|
4903
|
+
overflow-wrap: anywhere;
|
|
4904
|
+
}
|
|
4905
|
+
.ProseMirror th {
|
|
4906
|
+
background-color: #f5f5f5;
|
|
4907
|
+
font-weight: 600;
|
|
4908
|
+
text-align: left;
|
|
4909
|
+
}
|
|
4910
|
+
.ProseMirror .selectedCell {
|
|
4911
|
+
background: rgba(200, 200, 255, 0.4);
|
|
4912
|
+
}
|
|
4913
|
+
.ProseMirror table p {
|
|
4914
|
+
margin: 0;
|
|
4915
|
+
}
|
|
4916
|
+
.ProseMirror {
|
|
4917
|
+
overflow-x: auto;
|
|
4918
|
+
}
|
|
4919
|
+
@media (max-width: 768px) {
|
|
4920
|
+
.ProseMirror table {
|
|
4921
|
+
display: block;
|
|
4922
|
+
width: max-content;
|
|
4923
|
+
max-width: 100%;
|
|
4924
|
+
}
|
|
4925
|
+
.ProseMirror th,
|
|
4926
|
+
.ProseMirror td {
|
|
4927
|
+
min-width: 120px;
|
|
4928
|
+
}
|
|
4929
|
+
}
|
|
4930
|
+
@media (max-width: 480px) {
|
|
4931
|
+
.ProseMirror th,
|
|
4932
|
+
.ProseMirror td {
|
|
4933
|
+
min-width: 100px;
|
|
4934
|
+
padding: 6px;
|
|
4935
|
+
font-size: 13px;
|
|
4936
|
+
}
|
|
4937
|
+
}
|
|
4938
|
+
.ProseMirror .column-resize-handle {
|
|
4939
|
+
position: absolute;
|
|
4940
|
+
right: -2px;
|
|
4941
|
+
top: 0;
|
|
4942
|
+
bottom: 0;
|
|
4943
|
+
width: 4px;
|
|
4944
|
+
background-color: rgba(0, 0, 0, 0.15);
|
|
4945
|
+
pointer-events: none;
|
|
4946
|
+
}
|
|
4947
|
+
.ProseMirror th:hover .column-resize-handle,
|
|
4948
|
+
.ProseMirror td:hover .column-resize-handle {
|
|
4949
|
+
pointer-events: auto;
|
|
4950
|
+
}
|
|
4951
|
+
.ProseMirror table:focus-within {
|
|
4952
|
+
outline: 2px solid rgba(100, 150, 255, 0.35);
|
|
4953
|
+
outline-offset: 2px;
|
|
4954
|
+
}
|
package/dist/index.mjs
CHANGED
|
@@ -10940,85 +10940,6 @@ function InsertGroup({
|
|
|
10940
10940
|
};
|
|
10941
10941
|
const handleTableInsert = (rows, cols) => {
|
|
10942
10942
|
editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
|
|
10943
|
-
setTimeout(() => {
|
|
10944
|
-
var _a, _b;
|
|
10945
|
-
const table = editor.view.dom.querySelector("table");
|
|
10946
|
-
if (table && !((_a = table.parentElement) == null ? void 0 : _a.classList.contains("resizable-table-wrapper"))) {
|
|
10947
|
-
const wrapper = document.createElement("div");
|
|
10948
|
-
wrapper.className = "resizable-table-wrapper";
|
|
10949
|
-
wrapper.style.position = "relative";
|
|
10950
|
-
wrapper.style.display = "inline-block";
|
|
10951
|
-
wrapper.style.width = "600px";
|
|
10952
|
-
wrapper.style.maxWidth = "100%";
|
|
10953
|
-
(_b = table.parentNode) == null ? void 0 : _b.insertBefore(wrapper, table);
|
|
10954
|
-
wrapper.appendChild(table);
|
|
10955
|
-
const resizeHandle = document.createElement("div");
|
|
10956
|
-
resizeHandle.className = "resize-handle";
|
|
10957
|
-
resizeHandle.style.position = "absolute";
|
|
10958
|
-
resizeHandle.style.right = "0";
|
|
10959
|
-
resizeHandle.style.bottom = "0";
|
|
10960
|
-
resizeHandle.style.width = "12px";
|
|
10961
|
-
resizeHandle.style.height = "12px";
|
|
10962
|
-
resizeHandle.style.cursor = "se-resize";
|
|
10963
|
-
resizeHandle.style.background = "transparent";
|
|
10964
|
-
wrapper.appendChild(resizeHandle);
|
|
10965
|
-
const dragHandle = document.createElement("div");
|
|
10966
|
-
dragHandle.className = "drag-handle";
|
|
10967
|
-
dragHandle.style.position = "absolute";
|
|
10968
|
-
dragHandle.style.left = "0";
|
|
10969
|
-
dragHandle.style.top = "0";
|
|
10970
|
-
dragHandle.style.width = "16px";
|
|
10971
|
-
dragHandle.style.height = "16px";
|
|
10972
|
-
dragHandle.style.cursor = "move";
|
|
10973
|
-
dragHandle.style.background = "transparent";
|
|
10974
|
-
dragHandle.style.display = "flex";
|
|
10975
|
-
dragHandle.style.justifyContent = "center";
|
|
10976
|
-
dragHandle.style.alignItems = "center";
|
|
10977
|
-
dragHandle.innerHTML = "\u2630";
|
|
10978
|
-
dragHandle.style.color = "#fff";
|
|
10979
|
-
dragHandle.style.fontSize = "12px";
|
|
10980
|
-
wrapper.appendChild(dragHandle);
|
|
10981
|
-
let startWidth = 0;
|
|
10982
|
-
let startHeight = 0;
|
|
10983
|
-
let startX = 0;
|
|
10984
|
-
let startY = 0;
|
|
10985
|
-
resizeHandle.addEventListener("mousedown", (e) => {
|
|
10986
|
-
e.preventDefault();
|
|
10987
|
-
startX = e.clientX;
|
|
10988
|
-
startY = e.clientY;
|
|
10989
|
-
startWidth = wrapper.offsetWidth;
|
|
10990
|
-
startHeight = wrapper.offsetHeight;
|
|
10991
|
-
const onMouseMove = (e2) => {
|
|
10992
|
-
const dx = e2.clientX - startX;
|
|
10993
|
-
const dy = e2.clientY - startY;
|
|
10994
|
-
wrapper.style.width = Math.max(100, startWidth + dx) + "px";
|
|
10995
|
-
wrapper.style.height = Math.max(50, startHeight + dy) + "px";
|
|
10996
|
-
};
|
|
10997
|
-
const onMouseUp = () => {
|
|
10998
|
-
document.removeEventListener("mousemove", onMouseMove);
|
|
10999
|
-
document.removeEventListener("mouseup", onMouseUp);
|
|
11000
|
-
};
|
|
11001
|
-
document.addEventListener("mousemove", onMouseMove);
|
|
11002
|
-
document.addEventListener("mouseup", onMouseUp);
|
|
11003
|
-
});
|
|
11004
|
-
dragHandle.addEventListener("mousedown", (e) => {
|
|
11005
|
-
e.preventDefault();
|
|
11006
|
-
startX = e.clientX;
|
|
11007
|
-
startY = e.clientY;
|
|
11008
|
-
const onMouseMove = (e2) => {
|
|
11009
|
-
const dx = e2.clientX - startX;
|
|
11010
|
-
const dy = e2.clientY - startY;
|
|
11011
|
-
wrapper.style.transform = `translate(${dx}px, ${dy}px)`;
|
|
11012
|
-
};
|
|
11013
|
-
const onMouseUp = () => {
|
|
11014
|
-
document.removeEventListener("mousemove", onMouseMove);
|
|
11015
|
-
document.removeEventListener("mouseup", onMouseUp);
|
|
11016
|
-
};
|
|
11017
|
-
document.addEventListener("mousemove", onMouseMove);
|
|
11018
|
-
document.addEventListener("mouseup", onMouseUp);
|
|
11019
|
-
});
|
|
11020
|
-
}
|
|
11021
|
-
}, 0);
|
|
11022
10943
|
setShowTableGrid(false);
|
|
11023
10944
|
setSelectedRows(1);
|
|
11024
10945
|
setSelectedCols(1);
|
|
@@ -12142,6 +12063,7 @@ var SpellCheck = Extension.create({
|
|
|
12142
12063
|
let spell = null;
|
|
12143
12064
|
let activePopup = null;
|
|
12144
12065
|
let lastHoveredWord = null;
|
|
12066
|
+
const key = new PluginKey("spellcheck");
|
|
12145
12067
|
function closePopup() {
|
|
12146
12068
|
if (activePopup) {
|
|
12147
12069
|
activePopup.remove();
|
|
@@ -12150,25 +12072,22 @@ var SpellCheck = Extension.create({
|
|
|
12150
12072
|
}
|
|
12151
12073
|
return [
|
|
12152
12074
|
new Plugin({
|
|
12153
|
-
key
|
|
12154
|
-
view
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
if (!spell) return;
|
|
12160
|
-
if (activePopup) {
|
|
12161
|
-
const rect = activePopup.getBoundingClientRect();
|
|
12162
|
-
if (event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom) {
|
|
12163
|
-
return;
|
|
12164
|
-
}
|
|
12075
|
+
key,
|
|
12076
|
+
view(view) {
|
|
12077
|
+
let destroyed = false;
|
|
12078
|
+
fetch("https://tetrons.com/api/dictionary").then((r) => r.json()).then((dict) => {
|
|
12079
|
+
if (!destroyed) {
|
|
12080
|
+
spell = nspell(dict);
|
|
12165
12081
|
}
|
|
12166
|
-
|
|
12167
|
-
|
|
12168
|
-
|
|
12082
|
+
}).catch(console.error);
|
|
12083
|
+
const onMouseMove = (e) => {
|
|
12084
|
+
if (!spell) return;
|
|
12085
|
+
const coords = view.posAtCoords({
|
|
12086
|
+
left: e.clientX,
|
|
12087
|
+
top: e.clientY
|
|
12169
12088
|
});
|
|
12170
|
-
if (!
|
|
12171
|
-
const word = getWordAtPosition(
|
|
12089
|
+
if (!coords) return;
|
|
12090
|
+
const word = getWordAtPosition(view, coords.pos);
|
|
12172
12091
|
if (!word) return;
|
|
12173
12092
|
if (!spell.correct(word.text)) {
|
|
12174
12093
|
if (lastHoveredWord && lastHoveredWord.start === word.start && lastHoveredWord.end === word.end) {
|
|
@@ -12176,57 +12095,54 @@ var SpellCheck = Extension.create({
|
|
|
12176
12095
|
}
|
|
12177
12096
|
lastHoveredWord = word;
|
|
12178
12097
|
closePopup();
|
|
12179
|
-
const suggestions = spell.suggest(word.text);
|
|
12180
12098
|
activePopup = showSuggestionsPopup(
|
|
12181
|
-
|
|
12182
|
-
|
|
12099
|
+
view,
|
|
12100
|
+
coords.pos,
|
|
12183
12101
|
word,
|
|
12184
|
-
|
|
12102
|
+
spell.suggest(word.text),
|
|
12185
12103
|
closePopup
|
|
12186
12104
|
);
|
|
12187
|
-
}
|
|
12188
|
-
};
|
|
12189
|
-
const handleOutsideClick = (event) => {
|
|
12190
|
-
if (activePopup && !activePopup.contains(event.target)) {
|
|
12105
|
+
} else {
|
|
12191
12106
|
closePopup();
|
|
12192
12107
|
}
|
|
12193
12108
|
};
|
|
12194
|
-
document.addEventListener("mousemove",
|
|
12195
|
-
document.addEventListener("mousedown",
|
|
12109
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
12110
|
+
document.addEventListener("mousedown", closePopup);
|
|
12196
12111
|
return {
|
|
12197
12112
|
destroy() {
|
|
12198
|
-
|
|
12199
|
-
|
|
12113
|
+
destroyed = true;
|
|
12114
|
+
closePopup();
|
|
12115
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
12116
|
+
document.removeEventListener("mousedown", closePopup);
|
|
12200
12117
|
}
|
|
12201
12118
|
};
|
|
12202
12119
|
},
|
|
12203
|
-
state: {
|
|
12204
|
-
init() {
|
|
12205
|
-
return DecorationSet.empty;
|
|
12206
|
-
},
|
|
12207
|
-
apply(tr, old) {
|
|
12208
|
-
if (!spell) return old;
|
|
12209
|
-
const text = tr.doc.textBetween(0, tr.doc.content.size, " ");
|
|
12210
|
-
const words = text.split(/\s+/);
|
|
12211
|
-
const decorations = [];
|
|
12212
|
-
let pos = 0;
|
|
12213
|
-
for (const word of words) {
|
|
12214
|
-
const clean = word.replace(/[.,!?;:()"\']/g, "");
|
|
12215
|
-
if (clean.length > 0 && !spell.correct(clean)) {
|
|
12216
|
-
decorations.push(
|
|
12217
|
-
Decoration.inline(pos, pos + word.length, {
|
|
12218
|
-
class: "spell-wrong"
|
|
12219
|
-
})
|
|
12220
|
-
);
|
|
12221
|
-
}
|
|
12222
|
-
pos += word.length + 1;
|
|
12223
|
-
}
|
|
12224
|
-
return DecorationSet.create(tr.doc, decorations);
|
|
12225
|
-
}
|
|
12226
|
-
},
|
|
12227
12120
|
props: {
|
|
12228
12121
|
decorations(state) {
|
|
12229
|
-
|
|
12122
|
+
const sp = spell;
|
|
12123
|
+
if (!sp) return DecorationSet.empty;
|
|
12124
|
+
const decorations = [];
|
|
12125
|
+
state.doc.descendants((node, pos) => {
|
|
12126
|
+
if (!node.isText || !node.text) return;
|
|
12127
|
+
const text = node.text;
|
|
12128
|
+
const wordRegex = /\b[^\s.,!?;:()"'`]+\b/g;
|
|
12129
|
+
let match;
|
|
12130
|
+
while (match = wordRegex.exec(text)) {
|
|
12131
|
+
const word = match[0];
|
|
12132
|
+
const from = pos + match.index;
|
|
12133
|
+
const to = from + word.length;
|
|
12134
|
+
if (from < 0) continue;
|
|
12135
|
+
if (to > state.doc.content.size) continue;
|
|
12136
|
+
if (!sp.correct(word)) {
|
|
12137
|
+
decorations.push(
|
|
12138
|
+
Decoration.inline(from, to, {
|
|
12139
|
+
class: "spell-wrong"
|
|
12140
|
+
})
|
|
12141
|
+
);
|
|
12142
|
+
}
|
|
12143
|
+
}
|
|
12144
|
+
});
|
|
12145
|
+
return DecorationSet.create(state.doc, decorations);
|
|
12230
12146
|
}
|
|
12231
12147
|
}
|
|
12232
12148
|
})
|
|
@@ -12235,41 +12151,39 @@ var SpellCheck = Extension.create({
|
|
|
12235
12151
|
});
|
|
12236
12152
|
function getWordAtPosition(view, pos) {
|
|
12237
12153
|
const $pos = view.state.doc.resolve(pos);
|
|
12238
|
-
|
|
12239
|
-
const
|
|
12240
|
-
|
|
12241
|
-
let
|
|
12242
|
-
|
|
12243
|
-
while (
|
|
12244
|
-
start--;
|
|
12245
|
-
}
|
|
12246
|
-
while (end < text.length && !/\s/.test(text[end])) {
|
|
12247
|
-
end++;
|
|
12248
|
-
}
|
|
12154
|
+
if (!$pos.parent.isTextblock) return null;
|
|
12155
|
+
const text = $pos.parent.textContent;
|
|
12156
|
+
let start = $pos.parentOffset;
|
|
12157
|
+
let end = start;
|
|
12158
|
+
while (start > 0 && !/\s/.test(text[start - 1])) start--;
|
|
12159
|
+
while (end < text.length && !/\s/.test(text[end])) end++;
|
|
12249
12160
|
const word = text.slice(start, end);
|
|
12250
12161
|
if (!word.trim()) return null;
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12162
|
+
return {
|
|
12163
|
+
text: word,
|
|
12164
|
+
start: $pos.start() + start,
|
|
12165
|
+
end: $pos.start() + end
|
|
12166
|
+
};
|
|
12254
12167
|
}
|
|
12255
|
-
function showSuggestionsPopup(view, pos, word, suggestions,
|
|
12256
|
-
const
|
|
12257
|
-
|
|
12168
|
+
function showSuggestionsPopup(view, pos, word, suggestions, close2) {
|
|
12169
|
+
const el = document.createElement("div");
|
|
12170
|
+
el.className = "spell-suggestions-popup";
|
|
12171
|
+
el.style.position = "absolute";
|
|
12258
12172
|
suggestions.forEach((s) => {
|
|
12259
12173
|
const item = document.createElement("div");
|
|
12260
12174
|
item.className = "suggestion-item";
|
|
12261
12175
|
item.textContent = s;
|
|
12262
12176
|
item.onclick = () => {
|
|
12263
12177
|
view.dispatch(view.state.tr.insertText(s, word.start, word.end));
|
|
12264
|
-
|
|
12178
|
+
close2();
|
|
12265
12179
|
};
|
|
12266
|
-
|
|
12180
|
+
el.appendChild(item);
|
|
12267
12181
|
});
|
|
12268
|
-
document.body.appendChild(
|
|
12182
|
+
document.body.appendChild(el);
|
|
12269
12183
|
const coords = view.coordsAtPos(pos);
|
|
12270
|
-
|
|
12271
|
-
|
|
12272
|
-
return
|
|
12184
|
+
el.style.left = `${coords.left}px`;
|
|
12185
|
+
el.style.top = `${coords.bottom}px`;
|
|
12186
|
+
return el;
|
|
12273
12187
|
}
|
|
12274
12188
|
function AIModal({
|
|
12275
12189
|
open,
|
|
@@ -16588,9 +16502,8 @@ function Editor2(props) {
|
|
|
16588
16502
|
}, [versions]);
|
|
16589
16503
|
useEffect(() => {
|
|
16590
16504
|
if (!editor) return;
|
|
16591
|
-
|
|
16592
|
-
|
|
16593
|
-
}, [editor, spellCheckEnabled]);
|
|
16505
|
+
editor.view.dispatch(editor.state.tr);
|
|
16506
|
+
}, [spellCheckEnabled]);
|
|
16594
16507
|
const showThirdRow = props.showParagraphDropdown || props.showFontDropdown || props.showFontSizeDropdown;
|
|
16595
16508
|
const handleAISubmit = async (prompt) => {
|
|
16596
16509
|
try {
|
|
@@ -16820,16 +16733,6 @@ function Editor2(props) {
|
|
|
16820
16733
|
if (!editor || !editorRight) return;
|
|
16821
16734
|
editorRight.commands.setContent(editor.getJSON());
|
|
16822
16735
|
}, [editor, editorRight]);
|
|
16823
|
-
useEffect(() => {
|
|
16824
|
-
if (!editor || !editorRight) return;
|
|
16825
|
-
const handler = () => {
|
|
16826
|
-
editorRight.commands.setContent(editor.getJSON());
|
|
16827
|
-
};
|
|
16828
|
-
editor.on("update", handler);
|
|
16829
|
-
return () => {
|
|
16830
|
-
editor.off("update", handler);
|
|
16831
|
-
};
|
|
16832
|
-
}, [editor, editorRight]);
|
|
16833
16736
|
function dispatchTetronsEvent2(name, detail) {
|
|
16834
16737
|
if (typeof window !== "undefined") {
|
|
16835
16738
|
window.dispatchEvent(new CustomEvent(name, { detail }));
|
|
@@ -16979,6 +16882,20 @@ function Editor2(props) {
|
|
|
16979
16882
|
onHelpOpen
|
|
16980
16883
|
);
|
|
16981
16884
|
}, []);
|
|
16885
|
+
useEffect(() => {
|
|
16886
|
+
if (!editor || !props.onChange) return;
|
|
16887
|
+
const handler = () => {
|
|
16888
|
+
var _a2;
|
|
16889
|
+
(_a2 = props.onChange) == null ? void 0 : _a2.call(props, {
|
|
16890
|
+
html: editor.getHTML(),
|
|
16891
|
+
json: editor.getJSON()
|
|
16892
|
+
});
|
|
16893
|
+
};
|
|
16894
|
+
editor.on("update", handler);
|
|
16895
|
+
return () => {
|
|
16896
|
+
editor.off("update", handler);
|
|
16897
|
+
};
|
|
16898
|
+
}, [editor, props.onChange]);
|
|
16982
16899
|
if (!editor) return null;
|
|
16983
16900
|
return /* @__PURE__ */ jsxs("div", { className: "tetrons-editor__container", children: [
|
|
16984
16901
|
props.topMenu && /* @__PURE__ */ jsx(
|
|
@@ -17320,9 +17237,12 @@ Output: ${output}
|
|
|
17320
17237
|
}
|
|
17321
17238
|
function TetronsEditor({
|
|
17322
17239
|
apiKey,
|
|
17240
|
+
config,
|
|
17323
17241
|
onError,
|
|
17324
|
-
onSuccess
|
|
17242
|
+
onSuccess,
|
|
17243
|
+
onChange
|
|
17325
17244
|
}) {
|
|
17245
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
17326
17246
|
const [loading, setLoading] = useState(true);
|
|
17327
17247
|
const [error, setError] = useState(null);
|
|
17328
17248
|
const [details, setDetails] = useState(null);
|
|
@@ -17335,31 +17255,25 @@ function TetronsEditor({
|
|
|
17335
17255
|
body: JSON.stringify({ apiKey })
|
|
17336
17256
|
});
|
|
17337
17257
|
if (!res.ok) {
|
|
17338
|
-
|
|
17339
|
-
console.error("Server response:", errData);
|
|
17340
|
-
setError("Invalid or expired API key.");
|
|
17341
|
-
if (onError) onError("Invalid or expired API key.");
|
|
17342
|
-
setLoading(false);
|
|
17343
|
-
return;
|
|
17258
|
+
throw new Error("Invalid or expired API key.");
|
|
17344
17259
|
}
|
|
17345
17260
|
const data = await res.json();
|
|
17346
17261
|
setDetails(data);
|
|
17347
|
-
|
|
17262
|
+
onSuccess == null ? void 0 : onSuccess(data);
|
|
17348
17263
|
} catch (err) {
|
|
17349
|
-
console.error("Fetch error:", err);
|
|
17350
17264
|
const msg = err instanceof Error ? err.message : "Failed to validate API key.";
|
|
17351
17265
|
setError(msg);
|
|
17352
|
-
|
|
17266
|
+
onError == null ? void 0 : onError(msg);
|
|
17353
17267
|
} finally {
|
|
17354
17268
|
setLoading(false);
|
|
17355
17269
|
}
|
|
17356
17270
|
}
|
|
17357
17271
|
validateApiKey();
|
|
17358
|
-
}, [apiKey]);
|
|
17272
|
+
}, [apiKey, onError, onSuccess]);
|
|
17359
17273
|
if (loading) return /* @__PURE__ */ jsx("p", { children: "Validating API key..." });
|
|
17360
17274
|
if (error) return /* @__PURE__ */ jsx("p", { className: "error-message", children: error });
|
|
17361
17275
|
if (!details) return null;
|
|
17362
|
-
const
|
|
17276
|
+
const backendVersion = details.version.charAt(0).toUpperCase() + details.version.slice(1).toLowerCase();
|
|
17363
17277
|
const freeFeatures = {
|
|
17364
17278
|
newFile: true,
|
|
17365
17279
|
openFile: true,
|
|
@@ -17367,157 +17281,57 @@ function TetronsEditor({
|
|
|
17367
17281
|
cut: true,
|
|
17368
17282
|
copy: true,
|
|
17369
17283
|
paste: true,
|
|
17370
|
-
formatPainter: true,
|
|
17371
17284
|
undo: true,
|
|
17372
17285
|
redo: true,
|
|
17373
17286
|
bold: true,
|
|
17374
17287
|
italic: true,
|
|
17375
17288
|
underline: true,
|
|
17376
|
-
strikeout: true,
|
|
17377
|
-
subscript: true,
|
|
17378
|
-
superscript: true,
|
|
17379
|
-
fontColor: true,
|
|
17380
|
-
highlightColor: true,
|
|
17381
|
-
clearFormatting: true,
|
|
17382
17289
|
bulletedList: true,
|
|
17383
|
-
numberedList: true
|
|
17384
|
-
lineHeight: true,
|
|
17385
|
-
lineSpacing: true,
|
|
17386
|
-
indentIncrease: true,
|
|
17387
|
-
indentDecrease: true,
|
|
17388
|
-
alignLeft: true,
|
|
17389
|
-
alignCenter: true,
|
|
17390
|
-
alignRight: true,
|
|
17391
|
-
alignJustify: true
|
|
17290
|
+
numberedList: true
|
|
17392
17291
|
};
|
|
17393
|
-
const
|
|
17292
|
+
const premiumFeatures = {
|
|
17394
17293
|
insertTable: true,
|
|
17395
17294
|
insertImage: true,
|
|
17396
17295
|
insertVideo: true,
|
|
17397
17296
|
insertAudio: true,
|
|
17398
|
-
insertCheckboxList: true,
|
|
17399
17297
|
insertLink: true,
|
|
17400
|
-
insertComments: true,
|
|
17401
|
-
insertEmoji: true,
|
|
17402
|
-
insertHorizontalRule: true,
|
|
17403
|
-
insertEmbedVideo: true,
|
|
17404
|
-
zoomIn: true,
|
|
17405
|
-
zoomOut: true,
|
|
17406
17298
|
print: true,
|
|
17407
17299
|
exportFile: true
|
|
17408
17300
|
};
|
|
17409
|
-
const
|
|
17410
|
-
resetFormatting: true,
|
|
17411
|
-
preview: true,
|
|
17412
|
-
codeBlock: true,
|
|
17413
|
-
spellCheck: true,
|
|
17414
|
-
voice: true,
|
|
17301
|
+
const platinumFeatures = {
|
|
17415
17302
|
ai: true,
|
|
17416
|
-
|
|
17417
|
-
|
|
17303
|
+
voice: true,
|
|
17304
|
+
spellCheck: true,
|
|
17418
17305
|
mathEquation: true,
|
|
17419
|
-
|
|
17420
|
-
getContentFromImage: true
|
|
17306
|
+
codeEditor: true
|
|
17421
17307
|
};
|
|
17422
|
-
|
|
17423
|
-
|
|
17424
|
-
|
|
17425
|
-
"insertVideo",
|
|
17426
|
-
"insertAudio",
|
|
17427
|
-
"insertCheckboxList",
|
|
17428
|
-
"insertLink",
|
|
17429
|
-
"insertComments",
|
|
17430
|
-
"insertEmoji",
|
|
17431
|
-
"insertHorizontalRule",
|
|
17432
|
-
"insertEmbedVideo",
|
|
17433
|
-
"zoomIn",
|
|
17434
|
-
"zoomOut",
|
|
17435
|
-
"print",
|
|
17436
|
-
"exportFile"
|
|
17437
|
-
];
|
|
17438
|
-
const platinumAddOnKeys = [
|
|
17439
|
-
"resetFormatting",
|
|
17440
|
-
"preview",
|
|
17441
|
-
"codeBlock",
|
|
17442
|
-
"spellCheck",
|
|
17443
|
-
"voice",
|
|
17444
|
-
"ai",
|
|
17445
|
-
"languageConverter",
|
|
17446
|
-
"codeEditor",
|
|
17447
|
-
"mathEquation",
|
|
17448
|
-
"virtualKeyboard"
|
|
17449
|
-
];
|
|
17450
|
-
const activePremiumAddOns = {};
|
|
17451
|
-
const activePlatinumAddOns = {};
|
|
17452
|
-
const isPremiumAddOn = (add) => premiumAddOnKeys.includes(add);
|
|
17453
|
-
const isPlatinumAddOn = (add) => platinumAddOnKeys.includes(add);
|
|
17454
|
-
details.addOn.forEach((add) => {
|
|
17455
|
-
if (isPremiumAddOn(add)) activePremiumAddOns[add] = true;
|
|
17456
|
-
if (isPlatinumAddOn(add)) activePlatinumAddOns[add] = true;
|
|
17457
|
-
});
|
|
17458
|
-
switch (normalizedVersion) {
|
|
17459
|
-
case "Free":
|
|
17460
|
-
return /* @__PURE__ */ jsx(
|
|
17461
|
-
Editor2,
|
|
17462
|
-
{
|
|
17463
|
-
version: "Free",
|
|
17464
|
-
apiKey,
|
|
17465
|
-
topMenu: true,
|
|
17466
|
-
showParagraphDropdown: true,
|
|
17467
|
-
showFontDropdown: true,
|
|
17468
|
-
showFontSizeDropdown: true,
|
|
17469
|
-
features: freeFeatures
|
|
17470
|
-
}
|
|
17471
|
-
);
|
|
17472
|
-
case "Pro":
|
|
17473
|
-
return /* @__PURE__ */ jsx(
|
|
17474
|
-
Editor2,
|
|
17475
|
-
{
|
|
17476
|
-
version: "Pro",
|
|
17477
|
-
apiKey,
|
|
17478
|
-
topMenu: true,
|
|
17479
|
-
showParagraphDropdown: true,
|
|
17480
|
-
showFontDropdown: true,
|
|
17481
|
-
showFontSizeDropdown: true,
|
|
17482
|
-
autoSave: true,
|
|
17483
|
-
showVersions: true,
|
|
17484
|
-
features: freeFeatures,
|
|
17485
|
-
addOns: __spreadValues(__spreadValues({}, activePremiumAddOns), activePlatinumAddOns)
|
|
17486
|
-
}
|
|
17487
|
-
);
|
|
17488
|
-
case "Premium":
|
|
17489
|
-
return /* @__PURE__ */ jsx(
|
|
17490
|
-
Editor2,
|
|
17491
|
-
{
|
|
17492
|
-
version: "Premium",
|
|
17493
|
-
apiKey,
|
|
17494
|
-
topMenu: true,
|
|
17495
|
-
showParagraphDropdown: true,
|
|
17496
|
-
showFontDropdown: true,
|
|
17497
|
-
showFontSizeDropdown: true,
|
|
17498
|
-
autoSave: true,
|
|
17499
|
-
showVersions: true,
|
|
17500
|
-
features: __spreadValues(__spreadValues({}, freeFeatures), allPremiumFeatures),
|
|
17501
|
-
platinumAddOns: activePlatinumAddOns
|
|
17502
|
-
}
|
|
17503
|
-
);
|
|
17504
|
-
case "Platinum":
|
|
17505
|
-
return /* @__PURE__ */ jsx(
|
|
17506
|
-
Editor2,
|
|
17507
|
-
{
|
|
17508
|
-
version: "Platinum",
|
|
17509
|
-
apiKey,
|
|
17510
|
-
topMenu: true,
|
|
17511
|
-
showParagraphDropdown: true,
|
|
17512
|
-
showFontDropdown: true,
|
|
17513
|
-
showFontSizeDropdown: true,
|
|
17514
|
-
autoSave: true,
|
|
17515
|
-
showVersions: true,
|
|
17516
|
-
features: __spreadValues(__spreadValues(__spreadValues({}, freeFeatures), allPremiumFeatures), allPlatinumFeatures),
|
|
17517
|
-
platinumAddOns: activePlatinumAddOns
|
|
17518
|
-
}
|
|
17519
|
-
);
|
|
17308
|
+
let entitledFeatures = __spreadValues({}, freeFeatures);
|
|
17309
|
+
if (backendVersion === "Premium" || backendVersion === "Platinum") {
|
|
17310
|
+
entitledFeatures = __spreadValues(__spreadValues({}, entitledFeatures), premiumFeatures);
|
|
17520
17311
|
}
|
|
17312
|
+
if (backendVersion === "Platinum") {
|
|
17313
|
+
entitledFeatures = __spreadValues(__spreadValues({}, entitledFeatures), platinumFeatures);
|
|
17314
|
+
}
|
|
17315
|
+
const effectiveVersion = (_a = config == null ? void 0 : config.version) != null ? _a : backendVersion;
|
|
17316
|
+
const effectiveFeatures = (_b = config == null ? void 0 : config.features) != null ? _b : entitledFeatures;
|
|
17317
|
+
const effectiveAddOns = config == null ? void 0 : config.addOns;
|
|
17318
|
+
return /* @__PURE__ */ jsx(
|
|
17319
|
+
Editor2,
|
|
17320
|
+
{
|
|
17321
|
+
version: effectiveVersion,
|
|
17322
|
+
apiKey,
|
|
17323
|
+
features: effectiveFeatures,
|
|
17324
|
+
addOns: effectiveAddOns,
|
|
17325
|
+
platinumAddOns: effectiveAddOns,
|
|
17326
|
+
autoSave: config == null ? void 0 : config.autoSave,
|
|
17327
|
+
showVersions: config == null ? void 0 : config.showVersions,
|
|
17328
|
+
topMenu: (_d = (_c = config == null ? void 0 : config.ui) == null ? void 0 : _c.topMenu) != null ? _d : true,
|
|
17329
|
+
showParagraphDropdown: (_f = (_e = config == null ? void 0 : config.ui) == null ? void 0 : _e.paragraphDropdown) != null ? _f : true,
|
|
17330
|
+
showFontDropdown: (_h = (_g = config == null ? void 0 : config.ui) == null ? void 0 : _g.fontDropdown) != null ? _h : true,
|
|
17331
|
+
showFontSizeDropdown: (_j = (_i = config == null ? void 0 : config.ui) == null ? void 0 : _i.fontSizeDropdown) != null ? _j : true,
|
|
17332
|
+
onChange
|
|
17333
|
+
}
|
|
17334
|
+
);
|
|
17521
17335
|
}
|
|
17522
17336
|
|
|
17523
17337
|
// src/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tetrons",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "Tetrons is a fully-featured, modern WYSIWYG rich text editor built on TipTap.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"nspell": "^2.1.5",
|
|
69
69
|
"re-resizable": "^6.11.2",
|
|
70
70
|
"react-icons": "^5.5.0",
|
|
71
|
-
"tesseract.js": "^
|
|
71
|
+
"tesseract.js": "^7.0.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"react": ">=18",
|
|
@@ -93,7 +93,7 @@
|
|
|
93
93
|
"optionalDependencies": {
|
|
94
94
|
"mongoose": "^9.0.1",
|
|
95
95
|
"nodemailer": "^7.0.11",
|
|
96
|
-
"openai": "^6.
|
|
96
|
+
"openai": "^6.13.0"
|
|
97
97
|
},
|
|
98
98
|
"exports": {
|
|
99
99
|
".": {
|