tetrons 2.3.33 → 2.3.35
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/index.cjs +47 -8
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +46 -8
- package/dist/src/index.d.ts +7 -0
- package/dist/src/index.js +61 -0
- package/package.json +1 -1
- package/dist/app/api/export/route.js +0 -4
- package/dist/app/api/register/route.js +0 -32
- package/dist/app/api/save/route.js +0 -15
- 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.jsx +0 -51
- package/dist/components/UI/Button.d.ts +0 -0
- package/dist/components/UI/Button.jsx +0 -1
- package/dist/components/UI/Dropdown.d.ts +0 -0
- package/dist/components/UI/Dropdown.jsx +0 -1
- package/dist/components/tetrons/EditorContent.jsx +0 -209
- 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/src/app/page.d.ts +0 -2
- package/dist/src/app/page.jsx +0 -51
- package/dist/src/components/tetrons/toolbar/AIGroup.d.ts +0 -5
- package/dist/src/components/tetrons/toolbar/AIGroup.jsx +0 -140
- 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
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Mark, mergeAttributes } from '@tiptap/core';
|
|
2
|
-
export const FontFamily = Mark.create({
|
|
3
|
-
name: 'fontFamily',
|
|
4
|
-
addAttributes() {
|
|
5
|
-
return {
|
|
6
|
-
font: {
|
|
7
|
-
default: null,
|
|
8
|
-
parseHTML: element => element.style.fontFamily.replace(/['"]/g, ''),
|
|
9
|
-
renderHTML: attributes => {
|
|
10
|
-
if (!attributes.font)
|
|
11
|
-
return {};
|
|
12
|
-
return { style: `font-family: ${attributes.font}` };
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
},
|
|
17
|
-
parseHTML() {
|
|
18
|
-
return [{ style: 'font-family' }];
|
|
19
|
-
},
|
|
20
|
-
renderHTML({ HTMLAttributes }) {
|
|
21
|
-
return ['span', mergeAttributes(HTMLAttributes), 0];
|
|
22
|
-
},
|
|
23
|
-
addCommands() {
|
|
24
|
-
return {
|
|
25
|
-
setFontFamily: font => ({ commands }) => commands.setMark(this.name, { font }),
|
|
26
|
-
};
|
|
27
|
-
},
|
|
28
|
-
});
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Mark, mergeAttributes } from "@tiptap/core";
|
|
2
|
-
export const FontSize = Mark.create({
|
|
3
|
-
name: "fontSize",
|
|
4
|
-
addAttributes() {
|
|
5
|
-
return {
|
|
6
|
-
size: {
|
|
7
|
-
default: null,
|
|
8
|
-
parseHTML: (element) => element.style.fontSize,
|
|
9
|
-
renderHTML: (attributes) => {
|
|
10
|
-
if (!attributes.size)
|
|
11
|
-
return {};
|
|
12
|
-
return { style: `font-size: ${attributes.size}` };
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
},
|
|
17
|
-
parseHTML() {
|
|
18
|
-
return [{ style: "font-size" }];
|
|
19
|
-
},
|
|
20
|
-
renderHTML({ HTMLAttributes }) {
|
|
21
|
-
return ["span", mergeAttributes(HTMLAttributes), 0];
|
|
22
|
-
},
|
|
23
|
-
addCommands() {
|
|
24
|
-
return {
|
|
25
|
-
setFontSize: (size) => ({ commands }) => commands.setMark(this.name, { size }),
|
|
26
|
-
};
|
|
27
|
-
},
|
|
28
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const ResizableTable: import("@tiptap/core").Node<import("@tiptap/extension-table").TableOptions, any>;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { Table } from "@tiptap/extension-table";
|
|
2
|
-
import { columnResizing, tableEditing } from "prosemirror-tables";
|
|
3
|
-
export const ResizableTable = Table.extend({
|
|
4
|
-
addOptions() {
|
|
5
|
-
var _a;
|
|
6
|
-
return Object.assign(Object.assign({}, (_a = this.parent) === null || _a === void 0 ? void 0 : _a.call(this)), { resizable: true });
|
|
7
|
-
},
|
|
8
|
-
addProseMirrorPlugins() {
|
|
9
|
-
return [columnResizing({ handleWidth: 5 }), tableEditing()];
|
|
10
|
-
},
|
|
11
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { Mark, markInputRule, markPasteRule } from "@tiptap/core";
|
|
2
|
-
export const Subscript = Mark.create({
|
|
3
|
-
name: "subscript",
|
|
4
|
-
excludes: "superscript",
|
|
5
|
-
parseHTML() {
|
|
6
|
-
return [{ tag: "sub" }, { style: "vertical-align: sub" }];
|
|
7
|
-
},
|
|
8
|
-
renderHTML() {
|
|
9
|
-
return ["sub", 0];
|
|
10
|
-
},
|
|
11
|
-
addCommands() {
|
|
12
|
-
return {
|
|
13
|
-
toggleSubscript: () => ({ chain }) => chain()
|
|
14
|
-
.unsetMark("superscript")
|
|
15
|
-
.toggleMark(this.name)
|
|
16
|
-
.run(),
|
|
17
|
-
};
|
|
18
|
-
},
|
|
19
|
-
addInputRules() {
|
|
20
|
-
return [
|
|
21
|
-
markInputRule({
|
|
22
|
-
find: /~([^~]+)~/,
|
|
23
|
-
type: this.type,
|
|
24
|
-
}),
|
|
25
|
-
];
|
|
26
|
-
},
|
|
27
|
-
addPasteRules() {
|
|
28
|
-
return [
|
|
29
|
-
markPasteRule({
|
|
30
|
-
find: /~([^~]+)~/g,
|
|
31
|
-
type: this.type,
|
|
32
|
-
}),
|
|
33
|
-
];
|
|
34
|
-
},
|
|
35
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { Mark, markInputRule, markPasteRule } from "@tiptap/core";
|
|
2
|
-
export const Superscript = Mark.create({
|
|
3
|
-
name: "superscript",
|
|
4
|
-
excludes: "subscript",
|
|
5
|
-
parseHTML() {
|
|
6
|
-
return [{ tag: "sup" }, { style: "vertical-align: super" }];
|
|
7
|
-
},
|
|
8
|
-
renderHTML() {
|
|
9
|
-
return ["sup", 0];
|
|
10
|
-
},
|
|
11
|
-
addCommands() {
|
|
12
|
-
return {
|
|
13
|
-
toggleSuperscript: () => ({ chain }) => chain()
|
|
14
|
-
.unsetMark("subscript")
|
|
15
|
-
.toggleMark(this.name)
|
|
16
|
-
.run(),
|
|
17
|
-
};
|
|
18
|
-
},
|
|
19
|
-
addInputRules() {
|
|
20
|
-
return [
|
|
21
|
-
markInputRule({
|
|
22
|
-
find: /\^([^^]+)\^/,
|
|
23
|
-
type: this.type,
|
|
24
|
-
}),
|
|
25
|
-
];
|
|
26
|
-
},
|
|
27
|
-
addPasteRules() {
|
|
28
|
-
return [
|
|
29
|
-
markPasteRule({
|
|
30
|
-
find: /\^([^^]+)\^/g,
|
|
31
|
-
type: this.type,
|
|
32
|
-
}),
|
|
33
|
-
];
|
|
34
|
-
},
|
|
35
|
-
});
|
package/dist/lib/db.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export function connectDB(): Promise<void>;
|
package/dist/lib/db.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import mongoose from "mongoose";
|
|
2
|
-
const MONGO_URL = process.env.MONGO_URL;
|
|
3
|
-
export const connectDB = async () => {
|
|
4
|
-
if (mongoose.connection.readyState >= 1) {
|
|
5
|
-
return;
|
|
6
|
-
}
|
|
7
|
-
try {
|
|
8
|
-
await mongoose.connect(MONGO_URL);
|
|
9
|
-
console.log("Connected to MongoDB 👍");
|
|
10
|
-
}
|
|
11
|
-
catch (error) {
|
|
12
|
-
console.error("MongoDB connection failed ❌", error);
|
|
13
|
-
process.exit(1);
|
|
14
|
-
}
|
|
15
|
-
};
|
package/dist/lib/export.d.ts
DELETED
|
File without changes
|
package/dist/lib/export.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";
|
package/dist/models/ApiKey.d.ts
DELETED
package/dist/models/ApiKey.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import mongoose from "mongoose";
|
|
2
|
-
const ApiKeySchema = new mongoose.Schema({
|
|
3
|
-
email: { type: String, required: true },
|
|
4
|
-
organization: { type: String, required: true },
|
|
5
|
-
version: {
|
|
6
|
-
type: String,
|
|
7
|
-
enum: ["free", "pro", "premium", "platinum"],
|
|
8
|
-
required: true,
|
|
9
|
-
},
|
|
10
|
-
apiKey: { type: String, required: true, unique: true },
|
|
11
|
-
createdAt: { type: Date, default: Date.now },
|
|
12
|
-
expiresAt: { type: Date },
|
|
13
|
-
});
|
|
14
|
-
export const ApiKey = mongoose.models.ApiKey || mongoose.model("ApiKey", ApiKeySchema);
|
package/dist/src/app/page.d.ts
DELETED
package/dist/src/app/page.jsx
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
|
-
import EditorContent from "../components/tetrons/EditorContent";
|
|
4
|
-
import "../styles/tetrons.css";
|
|
5
|
-
export default function Home() {
|
|
6
|
-
const [apiKey, setApiKey] = useState(null);
|
|
7
|
-
const [loading, setLoading] = useState(true);
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
const fetchOrGenerateApiKey = async () => {
|
|
10
|
-
let key = localStorage.getItem("tetrons-key");
|
|
11
|
-
if (!key) {
|
|
12
|
-
try {
|
|
13
|
-
const res = await fetch("/api/register", {
|
|
14
|
-
method: "POST",
|
|
15
|
-
headers: { "Content-Type": "application/json" },
|
|
16
|
-
body: JSON.stringify({
|
|
17
|
-
email: "developer@finapsys.co.in",
|
|
18
|
-
organization: "FCSPL",
|
|
19
|
-
version: "platinum",
|
|
20
|
-
}),
|
|
21
|
-
});
|
|
22
|
-
const data = await res.json();
|
|
23
|
-
if (!res.ok || !data.apiKey) {
|
|
24
|
-
throw new Error(data.error || "Failed to register for API key");
|
|
25
|
-
}
|
|
26
|
-
key = data.apiKey;
|
|
27
|
-
if (key) {
|
|
28
|
-
localStorage.setItem("tetrons-key", key);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
console.error("❌ Failed to fetch or register API key:", err);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
setApiKey(key);
|
|
36
|
-
setLoading(false);
|
|
37
|
-
};
|
|
38
|
-
fetchOrGenerateApiKey();
|
|
39
|
-
}, []);
|
|
40
|
-
if (loading) {
|
|
41
|
-
return <div className="text-center p-4">⏳ Loading Editor...</div>;
|
|
42
|
-
}
|
|
43
|
-
if (!apiKey) {
|
|
44
|
-
return <div className="text-red-600 text-center">❌ API key not found</div>;
|
|
45
|
-
}
|
|
46
|
-
return (<main className="flex flex-col h-screen overflow-hidden">
|
|
47
|
-
<div className="flex-1 overflow-auto flex flex-col">
|
|
48
|
-
<EditorContent apiKey={apiKey}/>
|
|
49
|
-
</div>
|
|
50
|
-
</main>);
|
|
51
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import React, { useState, useRef } from "react";
|
|
3
|
-
import { FaMicrophone, FaStop } from "react-icons/fa";
|
|
4
|
-
import { Waveform } from "@uiball/loaders";
|
|
5
|
-
import { motion, AnimatePresence } from "framer-motion";
|
|
6
|
-
export default function AiGroup({ editor }) {
|
|
7
|
-
const [isRecording, setIsRecording] = useState(false);
|
|
8
|
-
const [audioBlob, setAudioBlob] = useState(null);
|
|
9
|
-
const [isTranscribing, setIsTranscribing] = useState(false);
|
|
10
|
-
const [transcriptionError, setTranscriptionError] = useState("");
|
|
11
|
-
const [showPromptInput, setShowPromptInput] = useState(false);
|
|
12
|
-
const [prompt, setPrompt] = useState("");
|
|
13
|
-
const [isLoadingAI, setIsLoadingAI] = useState(false);
|
|
14
|
-
const [aiError, setAiError] = useState("");
|
|
15
|
-
const mediaRecorderRef = useRef(null);
|
|
16
|
-
const chunksRef = useRef([]);
|
|
17
|
-
const startRecording = async () => {
|
|
18
|
-
setTranscriptionError("");
|
|
19
|
-
setAudioBlob(null);
|
|
20
|
-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
21
|
-
const mediaRecorder = new MediaRecorder(stream);
|
|
22
|
-
mediaRecorderRef.current = mediaRecorder;
|
|
23
|
-
chunksRef.current = [];
|
|
24
|
-
mediaRecorder.ondataavailable = (e) => {
|
|
25
|
-
if (e.data.size > 0)
|
|
26
|
-
chunksRef.current.push(e.data);
|
|
27
|
-
};
|
|
28
|
-
mediaRecorder.onstop = () => {
|
|
29
|
-
const blob = new Blob(chunksRef.current, { type: "audio/webm" });
|
|
30
|
-
setAudioBlob(blob);
|
|
31
|
-
transcribeAudio(blob);
|
|
32
|
-
};
|
|
33
|
-
mediaRecorder.start();
|
|
34
|
-
setIsRecording(true);
|
|
35
|
-
};
|
|
36
|
-
const stopRecording = () => {
|
|
37
|
-
var _a;
|
|
38
|
-
(_a = mediaRecorderRef.current) === null || _a === void 0 ? void 0 : _a.stop();
|
|
39
|
-
setIsRecording(false);
|
|
40
|
-
};
|
|
41
|
-
const transcribeAudio = async (blob) => {
|
|
42
|
-
setIsTranscribing(true);
|
|
43
|
-
setTranscriptionError("");
|
|
44
|
-
const formData = new FormData();
|
|
45
|
-
formData.append("file", blob, "voice.webm");
|
|
46
|
-
try {
|
|
47
|
-
const res = await fetch("https://staging.tetrons.com/api/transcribe", {
|
|
48
|
-
method: "POST",
|
|
49
|
-
body: formData,
|
|
50
|
-
});
|
|
51
|
-
const data = await res.json();
|
|
52
|
-
if (!res.ok || !data.transcript) {
|
|
53
|
-
throw new Error(data.error || "Failed to transcribe");
|
|
54
|
-
}
|
|
55
|
-
editor.commands.insertContent(data.transcript);
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
console.error(e);
|
|
59
|
-
setTranscriptionError("Transcription failed. Please try again.");
|
|
60
|
-
}
|
|
61
|
-
finally {
|
|
62
|
-
setIsTranscribing(false);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
const handleAiClick = () => {
|
|
66
|
-
setShowPromptInput(true);
|
|
67
|
-
setPrompt("");
|
|
68
|
-
setAiError("");
|
|
69
|
-
};
|
|
70
|
-
const handlePromptSubmit = async () => {
|
|
71
|
-
if (!prompt.trim())
|
|
72
|
-
return;
|
|
73
|
-
setIsLoadingAI(true);
|
|
74
|
-
setAiError("");
|
|
75
|
-
try {
|
|
76
|
-
const res = await fetch("https://staging.tetrons.com/api/ai-action", {
|
|
77
|
-
method: "POST",
|
|
78
|
-
headers: { "Content-Type": "application/json" },
|
|
79
|
-
body: JSON.stringify({ content: prompt }),
|
|
80
|
-
});
|
|
81
|
-
const data = await res.json();
|
|
82
|
-
if (!res.ok || !data.response) {
|
|
83
|
-
throw new Error(data.error || "AI failed to generate content");
|
|
84
|
-
}
|
|
85
|
-
editor.commands.insertContent(data.response);
|
|
86
|
-
setShowPromptInput(false);
|
|
87
|
-
}
|
|
88
|
-
catch (e) {
|
|
89
|
-
console.error(e);
|
|
90
|
-
setAiError("Failed to generate content. Try again.");
|
|
91
|
-
}
|
|
92
|
-
finally {
|
|
93
|
-
setIsLoadingAI(false);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
return (<div className="group relative space-y-3">
|
|
97
|
-
<div className="flex gap-2 items-center">
|
|
98
|
-
{!isRecording ? (<button type="button" onClick={startRecording} className="icon-btn" title="Start Voice Input">
|
|
99
|
-
<FaMicrophone size={18}/>
|
|
100
|
-
</button>) : (<button type="button" onClick={stopRecording} className="icon-btn stop-btn" title="Stop Recording">
|
|
101
|
-
<FaStop size={18}/>
|
|
102
|
-
</button>)}
|
|
103
|
-
|
|
104
|
-
<button type="button" onClick={handleAiClick} className="ai-button" title="AI Assist">
|
|
105
|
-
AI
|
|
106
|
-
</button>
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
{isRecording && (<div className="flex flex-col items-center">
|
|
110
|
-
<Waveform size={30} lineWeight={3.5} speed={1} color="#4F46E5"/>
|
|
111
|
-
<p className="text-sm mt-1 text-gray-600">Recording...</p>
|
|
112
|
-
</div>)}
|
|
113
|
-
|
|
114
|
-
{isTranscribing && (<p className="text-sm text-gray-500">Transcribing...</p>)}
|
|
115
|
-
|
|
116
|
-
{transcriptionError && (<p className="text-sm text-red-600">{transcriptionError}</p>)}
|
|
117
|
-
|
|
118
|
-
{audioBlob && (<div className="mt-2">
|
|
119
|
-
<audio controls src={URL.createObjectURL(audioBlob)}/>
|
|
120
|
-
</div>)}
|
|
121
|
-
|
|
122
|
-
<AnimatePresence>
|
|
123
|
-
{showPromptInput && (<motion.div className="ai-modal-backdrop" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
|
|
124
|
-
<motion.div className="ai-modal-content" initial={{ scale: 0.9, opacity: 0 }} animate={{ scale: 1, opacity: 1 }} exit={{ scale: 0.9, opacity: 0 }}>
|
|
125
|
-
<h2 className="ai-modal-title">AI Prompt</h2>
|
|
126
|
-
<textarea className="ai-modal-textarea" value={prompt} onChange={(e) => setPrompt(e.target.value)} placeholder="Enter your prompt here..."/>
|
|
127
|
-
{aiError && <p className="ai-modal-error">{aiError}</p>}
|
|
128
|
-
<div className="ai-modal-actions">
|
|
129
|
-
<button onClick={() => setShowPromptInput(false)} className="ai-cancel-btn">
|
|
130
|
-
Cancel
|
|
131
|
-
</button>
|
|
132
|
-
<button onClick={handlePromptSubmit} disabled={isLoadingAI} className="ai-submit-btn">
|
|
133
|
-
{isLoadingAI ? "Generating..." : "Submit"}
|
|
134
|
-
</button>
|
|
135
|
-
</div>
|
|
136
|
-
</motion.div>
|
|
137
|
-
</motion.div>)}
|
|
138
|
-
</AnimatePresence>
|
|
139
|
-
</div>);
|
|
140
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export declare function getFreeApiKey(): string;
|
|
2
|
-
declare const VERSION_PREFIXES: {
|
|
3
|
-
readonly pro: "PRO";
|
|
4
|
-
readonly premium: "PREMIUM";
|
|
5
|
-
readonly platinum: "PLATINUM";
|
|
6
|
-
};
|
|
7
|
-
export type VersionType = keyof typeof VERSION_PREFIXES;
|
|
8
|
-
export declare function generateUserApiKey(email: string, organization: string, version: VersionType): string;
|
|
9
|
-
export declare function generateApiKey(length?: number): string;
|
|
10
|
-
export declare function generateVersionedKey(prefix?: string): string;
|
|
11
|
-
export {};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import crypto from "crypto";
|
|
2
|
-
const FREE_API_KEY = process.env.TETRONS_FREE_KEY || "TETRONS_FREE_KEY";
|
|
3
|
-
const SECRET_KEY = process.env.API_KEY_SECRET || "default-secret-key";
|
|
4
|
-
export function getFreeApiKey() {
|
|
5
|
-
return FREE_API_KEY;
|
|
6
|
-
}
|
|
7
|
-
const VERSION_PREFIXES = {
|
|
8
|
-
pro: "PRO",
|
|
9
|
-
premium: "PREMIUM",
|
|
10
|
-
platinum: "PLATINUM",
|
|
11
|
-
};
|
|
12
|
-
export function generateUserApiKey(email, organization, version) {
|
|
13
|
-
const input = `${email.trim().toLowerCase()}:${organization
|
|
14
|
-
.trim()
|
|
15
|
-
.toLowerCase()}`;
|
|
16
|
-
const hash = crypto
|
|
17
|
-
.createHmac("sha256", SECRET_KEY)
|
|
18
|
-
.update(input)
|
|
19
|
-
.digest("hex")
|
|
20
|
-
.toUpperCase();
|
|
21
|
-
const prefix = VERSION_PREFIXES[version];
|
|
22
|
-
return `${prefix}${hash.slice(0, 48 - prefix.length)}`;
|
|
23
|
-
}
|
|
24
|
-
export function generateApiKey(length = 48) {
|
|
25
|
-
return crypto
|
|
26
|
-
.randomBytes(length / 2)
|
|
27
|
-
.toString("hex")
|
|
28
|
-
.toUpperCase();
|
|
29
|
-
}
|
|
30
|
-
export function generateVersionedKey(prefix = "") {
|
|
31
|
-
const key = generateApiKey(48 - prefix.length);
|
|
32
|
-
return `${prefix}${key}`;
|
|
33
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const loadEmojiPicker: () => void;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export const loadEmojiPicker = () => {
|
|
2
|
-
if (typeof window === "undefined")
|
|
3
|
-
return;
|
|
4
|
-
if (!window.EmojiButton && !document.getElementById("emoji-picker-script")) {
|
|
5
|
-
const script = document.createElement("script");
|
|
6
|
-
script.id = "emoji-picker-script";
|
|
7
|
-
script.src =
|
|
8
|
-
"https://cdn.jsdelivr.net/npm/@joeattardi/emoji-button@latest/dist/index.min.js";
|
|
9
|
-
script.async = true;
|
|
10
|
-
document.body.appendChild(script);
|
|
11
|
-
}
|
|
12
|
-
};
|