tetrons 2.3.1 → 2.3.21
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/components/tetrons/EditorContent.tsx +282 -0
- package/dist/components/components/tetrons/ResizableImageComponent.tsx +77 -0
- package/dist/components/components/tetrons/ResizableVideoComponent.tsx +56 -0
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +12 -7
- package/dist/index.js +17254 -21
- package/dist/index.mjs +54 -11
- package/dist/tetrons-UCHWNATC.css +372 -0
- package/package.json +3 -3
- package/dist/app/api/export/route.d.ts +0 -1
- package/dist/app/api/export/route.js +0 -4
- package/dist/app/api/register/route.d.ts +0 -7
- package/dist/app/api/register/route.js +0 -32
- package/dist/app/api/save/route.d.ts +0 -6
- package/dist/app/api/save/route.js +0 -15
- package/dist/app/api/validate/route.d.ts +0 -10
- package/dist/app/api/validate/route.js +0 -58
- package/dist/app/layout.d.ts +0 -6
- package/dist/app/layout.jsx +0 -30
- package/dist/app/page.d.ts +0 -2
- package/dist/app/page.jsx +0 -51
- package/dist/components/UI/Button.jsx +0 -1
- package/dist/components/UI/Dropdown.jsx +0 -1
- package/dist/components/tetrons/EditorContent.d.ts +0 -6
- package/dist/components/tetrons/EditorContent.jsx +0 -209
- package/dist/components/tetrons/ResizableImage.d.ts +0 -1
- package/dist/components/tetrons/ResizableImage.js +0 -40
- package/dist/components/tetrons/ResizableImageComponent.d.ts +0 -11
- package/dist/components/tetrons/ResizableImageComponent.jsx +0 -37
- package/dist/components/tetrons/ResizableVideo.d.ts +0 -12
- package/dist/components/tetrons/ResizableVideo.js +0 -61
- package/dist/components/tetrons/ResizableVideoComponent.d.ts +0 -4
- package/dist/components/tetrons/ResizableVideoComponent.jsx +0 -32
- package/dist/components/tetrons/helpers.d.ts +0 -0
- package/dist/components/tetrons/helpers.js +0 -1
- package/dist/components/tetrons/toolbar/ActionGroup.d.ts +0 -7
- package/dist/components/tetrons/toolbar/ActionGroup.jsx +0 -167
- package/dist/components/tetrons/toolbar/ClipboardGroup.d.ts +0 -5
- package/dist/components/tetrons/toolbar/ClipboardGroup.jsx +0 -36
- package/dist/components/tetrons/toolbar/FileGroup.d.ts +0 -7
- package/dist/components/tetrons/toolbar/FileGroup.jsx +0 -40
- package/dist/components/tetrons/toolbar/FontStyleGroup.d.ts +0 -7
- package/dist/components/tetrons/toolbar/FontStyleGroup.jsx +0 -104
- package/dist/components/tetrons/toolbar/InsertGroup.d.ts +0 -5
- package/dist/components/tetrons/toolbar/InsertGroup.jsx +0 -163
- package/dist/components/tetrons/toolbar/ListAlignGroup.d.ts +0 -5
- package/dist/components/tetrons/toolbar/ListAlignGroup.jsx +0 -16
- package/dist/components/tetrons/toolbar/MiscGroup.d.ts +0 -7
- package/dist/components/tetrons/toolbar/MiscGroup.jsx +0 -31
- package/dist/components/tetrons/toolbar/TableContextMenu.d.ts +0 -7
- package/dist/components/tetrons/toolbar/TableContextMenu.jsx +0 -52
- package/dist/components/tetrons/toolbar/TetronsToolbar.d.ts +0 -6
- package/dist/components/tetrons/toolbar/TetronsToolbar.jsx +0 -46
- package/dist/components/tetrons/toolbar/ToolbarButton.d.ts +0 -12
- package/dist/components/tetrons/toolbar/ToolbarButton.jsx +0 -8
- package/dist/components/tetrons/toolbar/extensions/Comment.d.ts +0 -17
- package/dist/components/tetrons/toolbar/extensions/Comment.js +0 -45
- package/dist/components/tetrons/toolbar/extensions/Embed.d.ts +0 -2
- package/dist/components/tetrons/toolbar/extensions/Embed.js +0 -90
- package/dist/components/tetrons/toolbar/extensions/FontFamily.d.ts +0 -9
- package/dist/components/tetrons/toolbar/extensions/FontFamily.js +0 -28
- package/dist/components/tetrons/toolbar/extensions/FontSize.d.ts +0 -9
- package/dist/components/tetrons/toolbar/extensions/FontSize.js +0 -28
- package/dist/components/tetrons/toolbar/extensions/ResizableTable.d.ts +0 -1
- package/dist/components/tetrons/toolbar/extensions/ResizableTable.js +0 -11
- package/dist/components/tetrons/toolbar/marks/Subscript.d.ts +0 -2
- package/dist/components/tetrons/toolbar/marks/Subscript.js +0 -35
- package/dist/components/tetrons/toolbar/marks/Superscript.d.ts +0 -2
- package/dist/components/tetrons/toolbar/marks/Superscript.js +0 -35
- package/dist/lib/db.d.ts +0 -1
- package/dist/lib/db.js +0 -15
- package/dist/lib/export.d.ts +0 -0
- package/dist/lib/export.js +0 -1
- package/dist/lib/tiptap-extensions.d.ts +0 -0
- package/dist/lib/tiptap-extensions.js +0 -1
- package/dist/models/ApiKey.d.ts +0 -2
- package/dist/models/ApiKey.js +0 -14
- package/dist/utils/apiKeyUtils.d.ts +0 -11
- package/dist/utils/apiKeyUtils.js +0 -33
- package/dist/utils/loadEmojiPicker.d.ts +0 -1
- package/dist/utils/loadEmojiPicker.js +0 -12
- /package/dist/components/{UI/Button.d.ts → components/UI/Button.tsx} +0 -0
- /package/dist/components/{UI/Dropdown.d.ts → components/UI/Dropdown.tsx} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -14345,7 +14345,7 @@ var FontSize = Mark2.create({
|
|
|
14345
14345
|
});
|
|
14346
14346
|
|
|
14347
14347
|
// src/components/tetrons/toolbar/TetronsToolbar.tsx
|
|
14348
|
-
import React9, { useEffect as useEffect3 } from "react";
|
|
14348
|
+
import React9, { useEffect as useEffect3, useState as useState4 } from "react";
|
|
14349
14349
|
|
|
14350
14350
|
// src/components/tetrons/toolbar/ActionGroup.tsx
|
|
14351
14351
|
import React2, { useEffect, useRef, useState } from "react";
|
|
@@ -15233,8 +15233,11 @@ function FileGroup({ editor }) {
|
|
|
15233
15233
|
}
|
|
15234
15234
|
|
|
15235
15235
|
// src/components/tetrons/toolbar/TetronsToolbar.tsx
|
|
15236
|
-
function TetronsToolbar({
|
|
15237
|
-
|
|
15236
|
+
function TetronsToolbar({
|
|
15237
|
+
editor,
|
|
15238
|
+
version
|
|
15239
|
+
}) {
|
|
15240
|
+
const [autoSave, setAutoSave] = useState4(false);
|
|
15238
15241
|
useEffect3(() => {
|
|
15239
15242
|
if (!editor) return;
|
|
15240
15243
|
const handleUpdate = () => {
|
|
@@ -15251,7 +15254,7 @@ function TetronsToolbar({ editor }) {
|
|
|
15251
15254
|
editor.off("update", handleUpdate);
|
|
15252
15255
|
};
|
|
15253
15256
|
}, [autoSave, editor]);
|
|
15254
|
-
return /* @__PURE__ */ React9.createElement("div", { className: "tetrons-toolbar" }, /* @__PURE__ */ React9.createElement("div", { className: "group" }, /* @__PURE__ */ React9.createElement(
|
|
15257
|
+
return /* @__PURE__ */ React9.createElement("div", { className: "tetrons-toolbar" }, version !== "free" && /* @__PURE__ */ React9.createElement("div", { className: "group" }, /* @__PURE__ */ React9.createElement(
|
|
15255
15258
|
"input",
|
|
15256
15259
|
{
|
|
15257
15260
|
type: "checkbox",
|
|
@@ -15259,7 +15262,7 @@ function TetronsToolbar({ editor }) {
|
|
|
15259
15262
|
checked: autoSave,
|
|
15260
15263
|
onChange: (e) => setAutoSave(e.target.checked)
|
|
15261
15264
|
}
|
|
15262
|
-
), /* @__PURE__ */ React9.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), /* @__PURE__ */ React9.createElement(FileGroup, { editor }), /* @__PURE__ */ React9.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ React9.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ React9.createElement(ListAlignGroup, { editor }), /* @__PURE__ */ React9.createElement(InsertGroup, { editor }), /* @__PURE__ */ React9.createElement(
|
|
15265
|
+
), /* @__PURE__ */ React9.createElement("label", { htmlFor: "autoSave" }, "Auto Save")), ["pro", "premium", "platinum"].includes(version) && /* @__PURE__ */ React9.createElement(FileGroup, { editor }), /* @__PURE__ */ React9.createElement(ClipboardGroup, { editor }), /* @__PURE__ */ React9.createElement(FontStyleGroup, { editor }), /* @__PURE__ */ React9.createElement(ListAlignGroup, { editor }), ["premium", "platinum"].includes(version) && /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(InsertGroup, { editor }), /* @__PURE__ */ React9.createElement(ActionGroup, { editor })), version === "platinum" && /* @__PURE__ */ React9.createElement(MiscGroup, { editor }));
|
|
15263
15266
|
}
|
|
15264
15267
|
|
|
15265
15268
|
// src/components/tetrons/ResizableImage.ts
|
|
@@ -15460,9 +15463,9 @@ var ResizableVideo = Node2.create({
|
|
|
15460
15463
|
});
|
|
15461
15464
|
|
|
15462
15465
|
// src/components/tetrons/toolbar/TableContextMenu.tsx
|
|
15463
|
-
import React12, { useEffect as useEffect6, useState as
|
|
15466
|
+
import React12, { useEffect as useEffect6, useState as useState5 } from "react";
|
|
15464
15467
|
function TableContextMenu({ editor }) {
|
|
15465
|
-
const [menuPosition, setMenuPosition] =
|
|
15468
|
+
const [menuPosition, setMenuPosition] = useState5(null);
|
|
15466
15469
|
useEffect6(() => {
|
|
15467
15470
|
const handleContextMenu = (event) => {
|
|
15468
15471
|
const target = event.target;
|
|
@@ -17072,11 +17075,22 @@ function EditorContent({ apiKey }) {
|
|
|
17072
17075
|
const [isValid, setIsValid] = React13.useState(null);
|
|
17073
17076
|
const [error, setError] = React13.useState(null);
|
|
17074
17077
|
const [versions, setVersions] = React13.useState([]);
|
|
17078
|
+
const [userVersion, setUserVersion] = React13.useState(null);
|
|
17075
17079
|
const [currentVersionIndex, setCurrentVersionIndex] = React13.useState(null);
|
|
17080
|
+
function getApiBaseUrl() {
|
|
17081
|
+
if (typeof import.meta !== "undefined" && import.meta.env?.VITE_TETRONS_API_URL) {
|
|
17082
|
+
return import.meta.env.VITE_TETRONS_API_URL;
|
|
17083
|
+
}
|
|
17084
|
+
if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_TETRONS_API_URL) {
|
|
17085
|
+
return process.env.NEXT_PUBLIC_TETRONS_API_URL;
|
|
17086
|
+
}
|
|
17087
|
+
return "https://staging.tetrons.com";
|
|
17088
|
+
}
|
|
17089
|
+
const API_BASE_URL = getApiBaseUrl();
|
|
17076
17090
|
useEffect7(() => {
|
|
17077
17091
|
const validateKey = async () => {
|
|
17078
17092
|
try {
|
|
17079
|
-
const res = await fetch(
|
|
17093
|
+
const res = await fetch(`${API_BASE_URL}/api/validate`, {
|
|
17080
17094
|
method: "POST",
|
|
17081
17095
|
headers: {
|
|
17082
17096
|
"Content-Type": "application/json"
|
|
@@ -17086,6 +17100,7 @@ function EditorContent({ apiKey }) {
|
|
|
17086
17100
|
const data = await res.json();
|
|
17087
17101
|
if (!res.ok) throw new Error(data.error || "Invalid API Key");
|
|
17088
17102
|
setIsValid(true);
|
|
17103
|
+
setUserVersion(data.version);
|
|
17089
17104
|
} catch (err) {
|
|
17090
17105
|
if (err instanceof Error) {
|
|
17091
17106
|
setError(err.message || "Invalid API Key");
|
|
@@ -17186,7 +17201,7 @@ function EditorContent({ apiKey }) {
|
|
|
17186
17201
|
if (isValid === null) {
|
|
17187
17202
|
return /* @__PURE__ */ React13.createElement("div", { className: "editor-loading" }, "\u{1F50D} Validating license...");
|
|
17188
17203
|
}
|
|
17189
|
-
return /* @__PURE__ */ React13.createElement("div", { className: "editor-container" }, /* @__PURE__ */ React13.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ React13.createElement(
|
|
17204
|
+
return /* @__PURE__ */ React13.createElement("div", { className: "editor-container" }, userVersion !== "free" && /* @__PURE__ */ React13.createElement("div", { className: "editor-toolbar" }, /* @__PURE__ */ React13.createElement(
|
|
17190
17205
|
"button",
|
|
17191
17206
|
{
|
|
17192
17207
|
type: "button",
|
|
@@ -17205,7 +17220,7 @@ function EditorContent({ apiKey }) {
|
|
|
17205
17220
|
title: `Restore Version ${idx + 1}`
|
|
17206
17221
|
},
|
|
17207
17222
|
`V${idx + 1}`
|
|
17208
|
-
)))), editor && /* @__PURE__ */ React13.createElement(TetronsToolbar, { editor }), /* @__PURE__ */ React13.createElement(
|
|
17223
|
+
)))), editor && userVersion && /* @__PURE__ */ React13.createElement(TetronsToolbar, { editor, version: userVersion }), /* @__PURE__ */ React13.createElement(
|
|
17209
17224
|
"div",
|
|
17210
17225
|
{
|
|
17211
17226
|
ref: wrapperRef,
|
|
@@ -17217,8 +17232,36 @@ function EditorContent({ apiKey }) {
|
|
|
17217
17232
|
}
|
|
17218
17233
|
|
|
17219
17234
|
// src/index.ts
|
|
17235
|
+
import "./tetrons-UCHWNATC.css";
|
|
17236
|
+
var API_VALID = false;
|
|
17237
|
+
var API_VERSION = "";
|
|
17238
|
+
async function initializeTetrons(apiKey) {
|
|
17239
|
+
const res = await fetch("https://staging.tetrons.com/api/validate", {
|
|
17240
|
+
method: "POST",
|
|
17241
|
+
headers: {
|
|
17242
|
+
"Content-Type": "application/json"
|
|
17243
|
+
},
|
|
17244
|
+
body: JSON.stringify({ apiKey })
|
|
17245
|
+
});
|
|
17246
|
+
if (!res.ok) {
|
|
17247
|
+
const error = await res.json();
|
|
17248
|
+
throw new Error(`API Key validation failed: ${error.error}`);
|
|
17249
|
+
}
|
|
17250
|
+
const data = await res.json();
|
|
17251
|
+
API_VALID = data.valid;
|
|
17252
|
+
API_VERSION = data.version;
|
|
17253
|
+
}
|
|
17254
|
+
function getTetronsVersion() {
|
|
17255
|
+
return API_VERSION;
|
|
17256
|
+
}
|
|
17257
|
+
function isApiKeyValid() {
|
|
17258
|
+
return API_VALID;
|
|
17259
|
+
}
|
|
17220
17260
|
var index_default = EditorContent;
|
|
17221
17261
|
export {
|
|
17222
17262
|
EditorContent,
|
|
17223
|
-
index_default as default
|
|
17263
|
+
index_default as default,
|
|
17264
|
+
getTetronsVersion,
|
|
17265
|
+
initializeTetrons,
|
|
17266
|
+
isApiKeyValid
|
|
17224
17267
|
};
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
.editor-container {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
height: 100%;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.editor-toolbar {
|
|
8
|
+
padding: 0.5rem;
|
|
9
|
+
border-bottom: 1px solid #d1d5db;
|
|
10
|
+
background-color: #f9fafb;
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-wrap: wrap;
|
|
13
|
+
align-items: center;
|
|
14
|
+
gap: 0.75rem;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.editor-save-btn {
|
|
18
|
+
padding: 0.25rem 0.75rem;
|
|
19
|
+
background-color: #2563eb;
|
|
20
|
+
color: white;
|
|
21
|
+
border-radius: 0.375rem;
|
|
22
|
+
transition: background-color 0.2s;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.editor-save-btn:hover {
|
|
26
|
+
background-color: #1d4ed8;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.editor-save-btn:disabled {
|
|
30
|
+
opacity: 0.5;
|
|
31
|
+
cursor: not-allowed;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.editor-version-btn {
|
|
35
|
+
padding: 0.25rem 0.5rem;
|
|
36
|
+
border: 1px solid #d1d5db;
|
|
37
|
+
color: #374151;
|
|
38
|
+
border-radius: 0.375rem;
|
|
39
|
+
font-size: 0.875rem;
|
|
40
|
+
white-space: nowrap;
|
|
41
|
+
transition: all 0.2s;
|
|
42
|
+
background: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.editor-version-btn:hover {
|
|
46
|
+
border-color: #4b5563;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.editor-version-btn.active {
|
|
50
|
+
border-color: #2563eb;
|
|
51
|
+
color: #2563eb;
|
|
52
|
+
font-weight: 600;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.editor-content-wrapper {
|
|
56
|
+
flex-grow: 1;
|
|
57
|
+
padding: 1.5rem;
|
|
58
|
+
background-color: white;
|
|
59
|
+
border: 1px solid #d1d5db;
|
|
60
|
+
border-radius: 0.5rem;
|
|
61
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
62
|
+
overflow: auto;
|
|
63
|
+
position: relative;
|
|
64
|
+
min-height: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.editor-loading {
|
|
68
|
+
color: #6b7280;
|
|
69
|
+
font-size: 0.875rem;
|
|
70
|
+
text-align: center;
|
|
71
|
+
padding: 1rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.editor-content-wrapper .ProseMirror {
|
|
75
|
+
outline: none;
|
|
76
|
+
min-height: 300px;
|
|
77
|
+
font-size: 1rem;
|
|
78
|
+
line-height: 1.75;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.editor-content-wrapper .ProseMirror[data-placeholder]:empty::before {
|
|
82
|
+
content: attr(data-placeholder);
|
|
83
|
+
color: #9ca3af;
|
|
84
|
+
float: left;
|
|
85
|
+
height: 0;
|
|
86
|
+
pointer-events: none;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.ProseMirror pre {
|
|
90
|
+
background: #f3f4f6;
|
|
91
|
+
padding: 1rem;
|
|
92
|
+
border-radius: 0.375rem;
|
|
93
|
+
font-family: monospace;
|
|
94
|
+
font-size: 0.875rem;
|
|
95
|
+
overflow-x: auto;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.editor-versions-wrapper {
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
gap: 0.5rem;
|
|
102
|
+
overflow-x: auto;
|
|
103
|
+
max-width: 100%;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.editor-no-versions {
|
|
107
|
+
color: #6b7280;
|
|
108
|
+
font-size: 0.875rem;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.tetrons-toolbar {
|
|
112
|
+
display: flex;
|
|
113
|
+
flex-wrap: wrap;
|
|
114
|
+
align-items: center;
|
|
115
|
+
gap: 1rem;
|
|
116
|
+
padding: 0.75rem;
|
|
117
|
+
border-bottom: 1px solid #e5e7eb;
|
|
118
|
+
background-color: white;
|
|
119
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
|
120
|
+
position: relative;
|
|
121
|
+
z-index: 10;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.tetrons-toolbar .group {
|
|
125
|
+
display: flex;
|
|
126
|
+
align-items: center;
|
|
127
|
+
gap: 0.5rem;
|
|
128
|
+
border-right: 1px solid #e5e7eb;
|
|
129
|
+
padding-right: 0.75rem;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.tetrons-toolbar input[type="checkbox"] {
|
|
133
|
+
width: 1rem;
|
|
134
|
+
height: 1rem;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.tetrons-toolbar label {
|
|
138
|
+
font-size: 0.875rem;
|
|
139
|
+
-moz-user-select: none;
|
|
140
|
+
user-select: none;
|
|
141
|
+
-webkit-user-select: none;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.misc-group {
|
|
145
|
+
display: flex;
|
|
146
|
+
gap: 0.25rem;
|
|
147
|
+
align-items: center;
|
|
148
|
+
border-right: 1px solid #e5e7eb;
|
|
149
|
+
padding-right: 0.75rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.list-align-group {
|
|
153
|
+
display: flex;
|
|
154
|
+
gap: 0.25rem;
|
|
155
|
+
border-right: 1px solid #e5e7eb;
|
|
156
|
+
padding-right: 0.75rem;
|
|
157
|
+
align-items: center;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.insert-group {
|
|
161
|
+
display: flex;
|
|
162
|
+
gap: 0.25rem;
|
|
163
|
+
border-right: 1px solid #e5e7eb;
|
|
164
|
+
padding-right: 0.75rem;
|
|
165
|
+
position: relative;
|
|
166
|
+
align-items: center;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.table-grid-popup {
|
|
170
|
+
position: absolute;
|
|
171
|
+
top: 2.5rem;
|
|
172
|
+
left: 0;
|
|
173
|
+
background-color: white;
|
|
174
|
+
border: 1px solid #d1d5db;
|
|
175
|
+
border-radius: 0.25rem;
|
|
176
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
|
177
|
+
padding: 0.5rem;
|
|
178
|
+
z-index: 20;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.table-grid {
|
|
182
|
+
display: grid;
|
|
183
|
+
grid-template-columns: repeat(10, 1fr);
|
|
184
|
+
gap: 1px;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.table-grid-cell {
|
|
188
|
+
width: 1.25rem;
|
|
189
|
+
height: 1.25rem;
|
|
190
|
+
border: 1px solid #d1d5db;
|
|
191
|
+
background-color: #f3f4f6;
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.table-grid-cell.selected {
|
|
196
|
+
background-color: #3b82f6;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.table-grid-label {
|
|
200
|
+
margin-top: 0.5rem;
|
|
201
|
+
font-size: 0.75rem;
|
|
202
|
+
text-align: center;
|
|
203
|
+
color: #6b7280;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.hidden-input {
|
|
207
|
+
display: none;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.emoji-picker {
|
|
211
|
+
position: absolute;
|
|
212
|
+
top: 2.5rem;
|
|
213
|
+
left: 0;
|
|
214
|
+
z-index: 50;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.font-style-group {
|
|
218
|
+
display: flex;
|
|
219
|
+
gap: 0.25rem;
|
|
220
|
+
border-right: 1px solid #e5e7eb;
|
|
221
|
+
padding-right: 0.75rem;
|
|
222
|
+
align-items: center;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.font-style-group select {
|
|
226
|
+
font-size: 0.875rem;
|
|
227
|
+
border: 1px solid #d1d5db;
|
|
228
|
+
border-radius: 0.25rem;
|
|
229
|
+
padding: 0.125rem 0.25rem;
|
|
230
|
+
margin-right: 0.5rem;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.color-label {
|
|
234
|
+
position: relative;
|
|
235
|
+
width: 2rem;
|
|
236
|
+
height: 2rem;
|
|
237
|
+
display: flex;
|
|
238
|
+
justify-content: center;
|
|
239
|
+
align-items: center;
|
|
240
|
+
cursor: pointer;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.color-indicator {
|
|
244
|
+
content: "";
|
|
245
|
+
position: absolute;
|
|
246
|
+
bottom: 2px;
|
|
247
|
+
left: 50%;
|
|
248
|
+
transform: translateX(-50%);
|
|
249
|
+
width: 12px;
|
|
250
|
+
height: 4px;
|
|
251
|
+
background-color: var(--indicator-color, #000000);
|
|
252
|
+
border-radius: 2px;
|
|
253
|
+
pointer-events: none;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.color-label input[type="color"] {
|
|
257
|
+
position: absolute;
|
|
258
|
+
inset: 0;
|
|
259
|
+
opacity: 0;
|
|
260
|
+
cursor: pointer;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.file-group {
|
|
264
|
+
display: flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
gap: 0.25rem;
|
|
267
|
+
border-right: 1px solid #e5e7eb;
|
|
268
|
+
padding-right: 0.75rem;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.file-group input[type="file"] {
|
|
272
|
+
display: none;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.clipboard-group {
|
|
276
|
+
display: flex;
|
|
277
|
+
gap: 0.25rem;
|
|
278
|
+
border-right: 1px solid #e5e7eb;
|
|
279
|
+
padding-right: 0.75rem;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.action-group {
|
|
283
|
+
position: relative;
|
|
284
|
+
display: flex;
|
|
285
|
+
align-items: center;
|
|
286
|
+
gap: 0.25rem;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.export-button {
|
|
290
|
+
display: flex;
|
|
291
|
+
align-items: center;
|
|
292
|
+
gap: 0.25rem;
|
|
293
|
+
padding: 0.25rem 0.5rem;
|
|
294
|
+
border-radius: 0.25rem;
|
|
295
|
+
background: transparent;
|
|
296
|
+
cursor: pointer;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.export-button:hover {
|
|
300
|
+
background-color: #f3f4f6;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.export-button:focus {
|
|
304
|
+
outline: none;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.export-dropdown {
|
|
308
|
+
position: absolute;
|
|
309
|
+
z-index: 10;
|
|
310
|
+
margin-top: 0.5rem;
|
|
311
|
+
width: 10rem;
|
|
312
|
+
background-color: #fff;
|
|
313
|
+
border: 1px solid #e5e7eb;
|
|
314
|
+
border-radius: 0.25rem;
|
|
315
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.export-dropdown button {
|
|
319
|
+
width: 100%;
|
|
320
|
+
text-align: left;
|
|
321
|
+
padding: 0.5rem 1rem;
|
|
322
|
+
background: none;
|
|
323
|
+
border: none;
|
|
324
|
+
font-size: 0.875rem;
|
|
325
|
+
cursor: pointer;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.export-dropdown button:hover {
|
|
329
|
+
background-color: #f3f4f6;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.toolbar-button {
|
|
333
|
+
padding: 0.5rem;
|
|
334
|
+
border: none;
|
|
335
|
+
background-color: transparent;
|
|
336
|
+
border-radius: 0.375rem;
|
|
337
|
+
cursor: pointer;
|
|
338
|
+
display: flex;
|
|
339
|
+
align-items: center;
|
|
340
|
+
justify-content: center;
|
|
341
|
+
transition: background-color 0.2s ease;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.toolbar-button:hover {
|
|
345
|
+
background-color: #e5e7eb;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.toolbar-button.active {
|
|
349
|
+
background-color: #d1d5db;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.toolbar-button:disabled {
|
|
353
|
+
opacity: 0.5;
|
|
354
|
+
cursor: not-allowed;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.tableWrapper {
|
|
358
|
+
overflow-x: auto;
|
|
359
|
+
margin: 1rem 0;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.tableWrapper table {
|
|
363
|
+
width: 100%;
|
|
364
|
+
border-collapse: collapse;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.tableWrapper th,
|
|
368
|
+
.tableWrapper td {
|
|
369
|
+
border: 1px solid #d1d5db;
|
|
370
|
+
padding: 0.5rem;
|
|
371
|
+
text-align: left;
|
|
372
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tetrons",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.21",
|
|
4
4
|
"description": "A Next.js project written in TypeScript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@eslint/eslintrc": "^3",
|
|
42
|
-
"@tailwindcss/postcss": "^4",
|
|
42
|
+
"@tailwindcss/postcss": "^4.1.11",
|
|
43
43
|
"@types/node": "^20",
|
|
44
44
|
"@types/react": "^19",
|
|
45
45
|
"@types/react-dom": "^19",
|
|
46
|
+
"autoprefixer": "^10.4.21",
|
|
46
47
|
"copyfiles": "^2.4.1",
|
|
47
48
|
"eslint": "^9",
|
|
48
49
|
"eslint-config-next": "^15.3.2",
|
|
49
|
-
"tailwindcss": "^4",
|
|
50
50
|
"tsup": "^8.5.0",
|
|
51
51
|
"typescript": "^5"
|
|
52
52
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function GET(req: Request): Response;
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { connectDB } from "../../../lib/db";
|
|
3
|
-
import { ApiKey } from "../../../models/ApiKey";
|
|
4
|
-
import { generateUserApiKey, getFreeApiKey } from "../../../utils/apiKeyUtils";
|
|
5
|
-
export async function POST(req) {
|
|
6
|
-
const body = await req.json();
|
|
7
|
-
const { email, organization, version } = body;
|
|
8
|
-
if (!email || !organization || !version) {
|
|
9
|
-
return NextResponse.json({ error: "Missing fields" }, { status: 400 });
|
|
10
|
-
}
|
|
11
|
-
await connectDB();
|
|
12
|
-
const lowerEmail = email.trim().toLowerCase();
|
|
13
|
-
const lowerOrg = organization.trim().toLowerCase();
|
|
14
|
-
await ApiKey.deleteMany({ email: lowerEmail, version });
|
|
15
|
-
let apiKey;
|
|
16
|
-
let expiresAt = null;
|
|
17
|
-
if (version === "free") {
|
|
18
|
-
apiKey = getFreeApiKey();
|
|
19
|
-
expiresAt = new Date(Date.now() + 14 * 24 * 60 * 60 * 1000);
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
apiKey = generateUserApiKey(lowerEmail, lowerOrg, version);
|
|
23
|
-
}
|
|
24
|
-
await ApiKey.create({
|
|
25
|
-
email: lowerEmail,
|
|
26
|
-
organization: lowerOrg,
|
|
27
|
-
version,
|
|
28
|
-
apiKey,
|
|
29
|
-
expiresAt,
|
|
30
|
-
});
|
|
31
|
-
return NextResponse.json({ apiKey, expiresAt });
|
|
32
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import fs from "fs/promises";
|
|
4
|
-
export async function POST(request) {
|
|
5
|
-
try {
|
|
6
|
-
const json = await request.json();
|
|
7
|
-
const publicDir = path.join(process.cwd(), "public");
|
|
8
|
-
const filePath = path.join(publicDir, "editor-content.json");
|
|
9
|
-
await fs.writeFile(filePath, JSON.stringify(json, null, 2), "utf-8");
|
|
10
|
-
return NextResponse.json({ message: "File saved successfully" });
|
|
11
|
-
}
|
|
12
|
-
catch (_a) {
|
|
13
|
-
return NextResponse.json({ error: "Failed to save file" }, { status: 500 });
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { NextRequest, NextResponse } from "next/server";
|
|
2
|
-
export declare function OPTIONS(): Promise<Response>;
|
|
3
|
-
export declare function POST(req: NextRequest): Promise<NextResponse<{
|
|
4
|
-
error: string;
|
|
5
|
-
}> | NextResponse<{
|
|
6
|
-
valid: boolean;
|
|
7
|
-
version: any;
|
|
8
|
-
email: any;
|
|
9
|
-
organization: any;
|
|
10
|
-
}>>;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { connectDB } from "../../../lib/db";
|
|
3
|
-
import { ApiKey } from "../../../models/ApiKey";
|
|
4
|
-
const corsHeaders = {
|
|
5
|
-
"Access-Control-Allow-Origin": "*",
|
|
6
|
-
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
7
|
-
"Access-Control-Allow-Headers": "Content-Type",
|
|
8
|
-
};
|
|
9
|
-
export async function OPTIONS() {
|
|
10
|
-
return new Response(null, {
|
|
11
|
-
status: 204,
|
|
12
|
-
headers: corsHeaders,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
export async function POST(req) {
|
|
16
|
-
try {
|
|
17
|
-
const body = (await req.json());
|
|
18
|
-
const apiKey = body.apiKey;
|
|
19
|
-
if (!apiKey) {
|
|
20
|
-
return NextResponse.json({ error: "API key required" }, {
|
|
21
|
-
status: 400,
|
|
22
|
-
headers: corsHeaders,
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
await connectDB();
|
|
26
|
-
const keyEntry = await ApiKey.findOne({ apiKey });
|
|
27
|
-
if (!keyEntry) {
|
|
28
|
-
return NextResponse.json({ error: "Invalid API key" }, {
|
|
29
|
-
status: 401,
|
|
30
|
-
headers: corsHeaders,
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
if (keyEntry.version === "free" &&
|
|
34
|
-
keyEntry.expiresAt &&
|
|
35
|
-
new Date() > new Date(keyEntry.expiresAt)) {
|
|
36
|
-
return NextResponse.json({ error: "Free trial expired" }, {
|
|
37
|
-
status: 403,
|
|
38
|
-
headers: corsHeaders,
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
return NextResponse.json({
|
|
42
|
-
valid: true,
|
|
43
|
-
version: keyEntry.version,
|
|
44
|
-
email: keyEntry.email,
|
|
45
|
-
organization: keyEntry.organization,
|
|
46
|
-
}, {
|
|
47
|
-
status: 200,
|
|
48
|
-
headers: corsHeaders,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
console.error("Validation Error:", err);
|
|
53
|
-
return NextResponse.json({ error: "Server error" }, {
|
|
54
|
-
status: 500,
|
|
55
|
-
headers: corsHeaders,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|