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.
Files changed (83) hide show
  1. package/dist/components/components/tetrons/EditorContent.tsx +282 -0
  2. package/dist/components/components/tetrons/ResizableImageComponent.tsx +77 -0
  3. package/dist/components/components/tetrons/ResizableVideoComponent.tsx +56 -0
  4. package/dist/index.d.mts +5 -1
  5. package/dist/index.d.ts +12 -7
  6. package/dist/index.js +17254 -21
  7. package/dist/index.mjs +54 -11
  8. package/dist/tetrons-UCHWNATC.css +372 -0
  9. package/package.json +3 -3
  10. package/dist/app/api/export/route.d.ts +0 -1
  11. package/dist/app/api/export/route.js +0 -4
  12. package/dist/app/api/register/route.d.ts +0 -7
  13. package/dist/app/api/register/route.js +0 -32
  14. package/dist/app/api/save/route.d.ts +0 -6
  15. package/dist/app/api/save/route.js +0 -15
  16. package/dist/app/api/validate/route.d.ts +0 -10
  17. package/dist/app/api/validate/route.js +0 -58
  18. package/dist/app/layout.d.ts +0 -6
  19. package/dist/app/layout.jsx +0 -30
  20. package/dist/app/page.d.ts +0 -2
  21. package/dist/app/page.jsx +0 -51
  22. package/dist/components/UI/Button.jsx +0 -1
  23. package/dist/components/UI/Dropdown.jsx +0 -1
  24. package/dist/components/tetrons/EditorContent.d.ts +0 -6
  25. package/dist/components/tetrons/EditorContent.jsx +0 -209
  26. package/dist/components/tetrons/ResizableImage.d.ts +0 -1
  27. package/dist/components/tetrons/ResizableImage.js +0 -40
  28. package/dist/components/tetrons/ResizableImageComponent.d.ts +0 -11
  29. package/dist/components/tetrons/ResizableImageComponent.jsx +0 -37
  30. package/dist/components/tetrons/ResizableVideo.d.ts +0 -12
  31. package/dist/components/tetrons/ResizableVideo.js +0 -61
  32. package/dist/components/tetrons/ResizableVideoComponent.d.ts +0 -4
  33. package/dist/components/tetrons/ResizableVideoComponent.jsx +0 -32
  34. package/dist/components/tetrons/helpers.d.ts +0 -0
  35. package/dist/components/tetrons/helpers.js +0 -1
  36. package/dist/components/tetrons/toolbar/ActionGroup.d.ts +0 -7
  37. package/dist/components/tetrons/toolbar/ActionGroup.jsx +0 -167
  38. package/dist/components/tetrons/toolbar/ClipboardGroup.d.ts +0 -5
  39. package/dist/components/tetrons/toolbar/ClipboardGroup.jsx +0 -36
  40. package/dist/components/tetrons/toolbar/FileGroup.d.ts +0 -7
  41. package/dist/components/tetrons/toolbar/FileGroup.jsx +0 -40
  42. package/dist/components/tetrons/toolbar/FontStyleGroup.d.ts +0 -7
  43. package/dist/components/tetrons/toolbar/FontStyleGroup.jsx +0 -104
  44. package/dist/components/tetrons/toolbar/InsertGroup.d.ts +0 -5
  45. package/dist/components/tetrons/toolbar/InsertGroup.jsx +0 -163
  46. package/dist/components/tetrons/toolbar/ListAlignGroup.d.ts +0 -5
  47. package/dist/components/tetrons/toolbar/ListAlignGroup.jsx +0 -16
  48. package/dist/components/tetrons/toolbar/MiscGroup.d.ts +0 -7
  49. package/dist/components/tetrons/toolbar/MiscGroup.jsx +0 -31
  50. package/dist/components/tetrons/toolbar/TableContextMenu.d.ts +0 -7
  51. package/dist/components/tetrons/toolbar/TableContextMenu.jsx +0 -52
  52. package/dist/components/tetrons/toolbar/TetronsToolbar.d.ts +0 -6
  53. package/dist/components/tetrons/toolbar/TetronsToolbar.jsx +0 -46
  54. package/dist/components/tetrons/toolbar/ToolbarButton.d.ts +0 -12
  55. package/dist/components/tetrons/toolbar/ToolbarButton.jsx +0 -8
  56. package/dist/components/tetrons/toolbar/extensions/Comment.d.ts +0 -17
  57. package/dist/components/tetrons/toolbar/extensions/Comment.js +0 -45
  58. package/dist/components/tetrons/toolbar/extensions/Embed.d.ts +0 -2
  59. package/dist/components/tetrons/toolbar/extensions/Embed.js +0 -90
  60. package/dist/components/tetrons/toolbar/extensions/FontFamily.d.ts +0 -9
  61. package/dist/components/tetrons/toolbar/extensions/FontFamily.js +0 -28
  62. package/dist/components/tetrons/toolbar/extensions/FontSize.d.ts +0 -9
  63. package/dist/components/tetrons/toolbar/extensions/FontSize.js +0 -28
  64. package/dist/components/tetrons/toolbar/extensions/ResizableTable.d.ts +0 -1
  65. package/dist/components/tetrons/toolbar/extensions/ResizableTable.js +0 -11
  66. package/dist/components/tetrons/toolbar/marks/Subscript.d.ts +0 -2
  67. package/dist/components/tetrons/toolbar/marks/Subscript.js +0 -35
  68. package/dist/components/tetrons/toolbar/marks/Superscript.d.ts +0 -2
  69. package/dist/components/tetrons/toolbar/marks/Superscript.js +0 -35
  70. package/dist/lib/db.d.ts +0 -1
  71. package/dist/lib/db.js +0 -15
  72. package/dist/lib/export.d.ts +0 -0
  73. package/dist/lib/export.js +0 -1
  74. package/dist/lib/tiptap-extensions.d.ts +0 -0
  75. package/dist/lib/tiptap-extensions.js +0 -1
  76. package/dist/models/ApiKey.d.ts +0 -2
  77. package/dist/models/ApiKey.js +0 -14
  78. package/dist/utils/apiKeyUtils.d.ts +0 -11
  79. package/dist/utils/apiKeyUtils.js +0 -33
  80. package/dist/utils/loadEmojiPicker.d.ts +0 -1
  81. package/dist/utils/loadEmojiPicker.js +0 -12
  82. /package/dist/components/{UI/Button.d.ts → components/UI/Button.tsx} +0 -0
  83. /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({ editor }) {
15237
- const [autoSave, setAutoSave] = React9.useState(false);
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(MiscGroup, { editor }), /* @__PURE__ */ React9.createElement(ActionGroup, { editor }));
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 useState4 } from "react";
15466
+ import React12, { useEffect as useEffect6, useState as useState5 } from "react";
15464
15467
  function TableContextMenu({ editor }) {
15465
- const [menuPosition, setMenuPosition] = useState4(null);
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("/api/validate", {
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.1",
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,4 +0,0 @@
1
- export function GET(req) {
2
- console.log(req.method); // Example usage
3
- return new Response("Hello, world!", { status: 200 });
4
- }
@@ -1,7 +0,0 @@
1
- import { NextRequest, NextResponse } from "next/server";
2
- export declare function POST(req: NextRequest): Promise<NextResponse<{
3
- error: string;
4
- }> | NextResponse<{
5
- apiKey: string;
6
- expiresAt: Date | null;
7
- }>>;
@@ -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,6 +0,0 @@
1
- import { NextRequest, NextResponse } from "next/server";
2
- export declare function POST(request: NextRequest): Promise<NextResponse<{
3
- message: string;
4
- }> | NextResponse<{
5
- error: string;
6
- }>>;
@@ -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
- }
@@ -1,6 +0,0 @@
1
- import type { Metadata } from "next";
2
- import "./globals.css";
3
- export declare const metadata: Metadata;
4
- export default function RootLayout({ children, }: {
5
- children: React.ReactNode;
6
- }): import("react").JSX.Element;