@collabchron/notiq 0.2.0

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 (188) hide show
  1. package/README.md +71 -0
  2. package/components.json +21 -0
  3. package/eslint.config.mjs +16 -0
  4. package/next.config.ts +12 -0
  5. package/package.json +108 -0
  6. package/postcss.config.mjs +5 -0
  7. package/public/file.svg +1 -0
  8. package/public/globe.svg +1 -0
  9. package/public/images/icons/plus.svg +10 -0
  10. package/public/next.svg +1 -0
  11. package/public/vercel.svg +1 -0
  12. package/public/window.svg +1 -0
  13. package/src/app/actions.ts +2 -0
  14. package/src/app/api/ai/route.ts +175 -0
  15. package/src/app/api/edgestore/[...edgestore]/route.ts +28 -0
  16. package/src/app/favicon.ico +0 -0
  17. package/src/app/globals.css +205 -0
  18. package/src/app/layout.tsx +38 -0
  19. package/src/app/page.tsx +12 -0
  20. package/src/components/editor/Core.tsx +220 -0
  21. package/src/components/editor/hooks/instructions-messages.ts +300 -0
  22. package/src/components/editor/hooks/use-mobile.ts +19 -0
  23. package/src/components/editor/hooks/useReport.ts +67 -0
  24. package/src/components/editor/hooks/useResizeObservert.ts +22 -0
  25. package/src/components/editor/index.tsx +39 -0
  26. package/src/components/editor/lexical-on-change.tsx +28 -0
  27. package/src/components/editor/nodes/CollapsibleNode/CollapsibleContainerNode.ts +92 -0
  28. package/src/components/editor/nodes/CollapsibleNode/CollapsibleContentNode.ts +65 -0
  29. package/src/components/editor/nodes/CollapsibleNode/CollapsibleTitleNode.ts +105 -0
  30. package/src/components/editor/nodes/EquationNode/EquationComponent.tsx +143 -0
  31. package/src/components/editor/nodes/EquationNode/EquationNode.tsx +170 -0
  32. package/src/components/editor/nodes/ExcalidrawNode/ExcalidrawComponent.tsx +228 -0
  33. package/src/components/editor/nodes/ExcalidrawNode/ExcalidrawImage.tsx +137 -0
  34. package/src/components/editor/nodes/ExcalidrawNode/ImageResizer.tsx +317 -0
  35. package/src/components/editor/nodes/ExcalidrawNode/index.tsx +204 -0
  36. package/src/components/editor/nodes/FigmaNode/FigmaNode.tsx +134 -0
  37. package/src/components/editor/nodes/Hint/HintComponet.tsx +221 -0
  38. package/src/components/editor/nodes/Hint/index.tsx +190 -0
  39. package/src/components/editor/nodes/ImageNode/index.tsx +328 -0
  40. package/src/components/editor/nodes/InlineImageNode/InlineImageComponent.tsx +383 -0
  41. package/src/components/editor/nodes/InlineImageNode/InlineImageNode.css +94 -0
  42. package/src/components/editor/nodes/InlineImageNode/InlineImageNode.tsx +309 -0
  43. package/src/components/editor/nodes/LayoutNode/LayoutContainerNode.ts +146 -0
  44. package/src/components/editor/nodes/LayoutNode/LayoutItemNode.ts +79 -0
  45. package/src/components/editor/nodes/PollNode/index.tsx +204 -0
  46. package/src/components/editor/nodes/Stepper/index.tsx +260 -0
  47. package/src/components/editor/nodes/TweetNode/index.tsx +214 -0
  48. package/src/components/editor/nodes/index.ts +81 -0
  49. package/src/components/editor/plugins/AutoEmbedPlugin/index.tsx +350 -0
  50. package/src/components/editor/plugins/AutoLinkPlugin/index.tsx +56 -0
  51. package/src/components/editor/plugins/CodeActionMenuPlugin/components/CopyButton.tsx +70 -0
  52. package/src/components/editor/plugins/CodeActionMenuPlugin/components/PrettierButton.tsx +192 -0
  53. package/src/components/editor/plugins/CodeActionMenuPlugin/index.tsx +217 -0
  54. package/src/components/editor/plugins/CodeActionMenuPlugin/utils.ts +26 -0
  55. package/src/components/editor/plugins/CodeHighlightPlugin/index.ts +21 -0
  56. package/src/components/editor/plugins/CollapsiblePlugin/Collapsible.css +76 -0
  57. package/src/components/editor/plugins/CollapsiblePlugin/index.ts +228 -0
  58. package/src/components/editor/plugins/DragDropPastePlugin/index.tsx +44 -0
  59. package/src/components/editor/plugins/DraggableBlockPlugin/index.tsx +52 -0
  60. package/src/components/editor/plugins/EquationsPlugin/index.tsx +85 -0
  61. package/src/components/editor/plugins/ExcalidrawPlugin/index.tsx +98 -0
  62. package/src/components/editor/plugins/FigmaPlugin/index.tsx +42 -0
  63. package/src/components/editor/plugins/FloatingLinkEditorPlugin/index.tsx +445 -0
  64. package/src/components/editor/plugins/FloatingTextFormatToolbarPlugin/index.tsx +275 -0
  65. package/src/components/editor/plugins/ImagesPlugin/index.tsx +222 -0
  66. package/src/components/editor/plugins/InlineImagePlugin/index.tsx +351 -0
  67. package/src/components/editor/plugins/LayoutPlugin/index.tsx +238 -0
  68. package/src/components/editor/plugins/LinkPlugin/index.tsx +36 -0
  69. package/src/components/editor/plugins/LinkWithMetaData/index.tsx +271 -0
  70. package/src/components/editor/plugins/MarkdownShortcutPlugin/index.tsx +11 -0
  71. package/src/components/editor/plugins/MarkdownTransformers/index.tsx +304 -0
  72. package/src/components/editor/plugins/PollPlugin/index.tsx +49 -0
  73. package/src/components/editor/plugins/ShortcutsPlugin/index.tsx +180 -0
  74. package/src/components/editor/plugins/ShortcutsPlugin/shortcuts.ts +253 -0
  75. package/src/components/editor/plugins/SlashCommand/index.tsx +621 -0
  76. package/src/components/editor/plugins/SpeechToTextPlugin/index.ts +127 -0
  77. package/src/components/editor/plugins/TabFocusPlugin/index.ts +58 -0
  78. package/src/components/editor/plugins/TableCellActionMenuPlugin/index.tsx +759 -0
  79. package/src/components/editor/plugins/TableCellResizer/index.tsx +438 -0
  80. package/src/components/editor/plugins/TableHoverActionsPlugin/index.tsx +314 -0
  81. package/src/components/editor/plugins/TablePlugin/index.tsx +99 -0
  82. package/src/components/editor/plugins/ToolbarPlugin/index.tsx +522 -0
  83. package/src/components/editor/plugins/TwitterPlugin/index.ts +35 -0
  84. package/src/components/editor/plugins/YouTubeNode/index.tsx +179 -0
  85. package/src/components/editor/plugins/YouTubePlugin/index.ts +41 -0
  86. package/src/components/editor/themes/editor-theme.ts +113 -0
  87. package/src/components/editor/themes/theme.css +377 -0
  88. package/src/components/editor/utils/ai.ts +291 -0
  89. package/src/components/editor/utils/canUseDOM.ts +12 -0
  90. package/src/components/editor/utils/editorFormatting.ts +282 -0
  91. package/src/components/editor/utils/environment.ts +50 -0
  92. package/src/components/editor/utils/extract-data.ts +166 -0
  93. package/src/components/editor/utils/getAllLexicalChildren.ts +13 -0
  94. package/src/components/editor/utils/getDOMRangeRect.ts +27 -0
  95. package/src/components/editor/utils/getSelectedNode.ts +27 -0
  96. package/src/components/editor/utils/gif.ts +29 -0
  97. package/src/components/editor/utils/invariant.ts +15 -0
  98. package/src/components/editor/utils/setFloatingElemPosition.ts +51 -0
  99. package/src/components/editor/utils/setFloatingElemPositionForLinkEditor.ts +40 -0
  100. package/src/components/editor/utils/setNodePlaceholderFromSelection/getNodePlaceholder.ts +51 -0
  101. package/src/components/editor/utils/setNodePlaceholderFromSelection/setNodePlaceholderFromSelection.ts +15 -0
  102. package/src/components/editor/utils/setNodePlaceholderFromSelection/setPlaceholderOnSelection.ts +114 -0
  103. package/src/components/editor/utils/setNodePlaceholderFromSelection/styles.css +6 -0
  104. package/src/components/editor/utils/url.ts +109 -0
  105. package/src/components/editor/utils/useLayoutEffect.ts +13 -0
  106. package/src/components/providers/QueryProvider.tsx +15 -0
  107. package/src/components/providers/SharedHistoryContext.tsx +28 -0
  108. package/src/components/providers/ToolbarContext.tsx +123 -0
  109. package/src/components/providers/theme-provider.tsx +11 -0
  110. package/src/components/theme/ModeToggle.tsx +40 -0
  111. package/src/components/ui/FileInput.tsx +40 -0
  112. package/src/components/ui/Input.css +32 -0
  113. package/src/components/ui/Select.css +42 -0
  114. package/src/components/ui/Select.tsx +36 -0
  115. package/src/components/ui/TextInput.tsx +48 -0
  116. package/src/components/ui/ai/ai-button.tsx +574 -0
  117. package/src/components/ui/ai/border.tsx +99 -0
  118. package/src/components/ui/ai/placeholder-input-vanish.tsx +282 -0
  119. package/src/components/ui/button.tsx +89 -0
  120. package/src/components/ui/card.tsx +76 -0
  121. package/src/components/ui/checkbox.tsx +30 -0
  122. package/src/components/ui/command.tsx +153 -0
  123. package/src/components/ui/dialog/Dialog.css +25 -0
  124. package/src/components/ui/dialog/Dialog.tsx +34 -0
  125. package/src/components/ui/dialog.tsx +122 -0
  126. package/src/components/ui/drop-downs/background-color.tsx +183 -0
  127. package/src/components/ui/drop-downs/block-format.tsx +159 -0
  128. package/src/components/ui/drop-downs/code.tsx +42 -0
  129. package/src/components/ui/drop-downs/color.tsx +177 -0
  130. package/src/components/ui/drop-downs/font-size.tsx +138 -0
  131. package/src/components/ui/drop-downs/font.tsx +155 -0
  132. package/src/components/ui/drop-downs/index.tsx +122 -0
  133. package/src/components/ui/drop-downs/insert-node.tsx +213 -0
  134. package/src/components/ui/drop-downs/text-align.tsx +123 -0
  135. package/src/components/ui/drop-downs/text-format.tsx +104 -0
  136. package/src/components/ui/dropdown-menu.tsx +201 -0
  137. package/src/components/ui/equation/EquationEditor.css +38 -0
  138. package/src/components/ui/equation/EquationEditor.tsx +56 -0
  139. package/src/components/ui/equation/KatexEquationAlterer.css +41 -0
  140. package/src/components/ui/equation/KatexEquationAlterer.tsx +83 -0
  141. package/src/components/ui/equation/KatexRenderer.tsx +66 -0
  142. package/src/components/ui/excalidraw/ExcalidrawModal.css +64 -0
  143. package/src/components/ui/excalidraw/ExcalidrawModal.tsx +234 -0
  144. package/src/components/ui/excalidraw/Modal.css +62 -0
  145. package/src/components/ui/excalidraw/Modal.tsx +110 -0
  146. package/src/components/ui/hover-card.tsx +29 -0
  147. package/src/components/ui/image/error-image.tsx +17 -0
  148. package/src/components/ui/image/file-upload.tsx +240 -0
  149. package/src/components/ui/image/image-resizer.tsx +297 -0
  150. package/src/components/ui/image/image-toolbar.tsx +264 -0
  151. package/src/components/ui/image/index.tsx +408 -0
  152. package/src/components/ui/image/lazy-image.tsx +68 -0
  153. package/src/components/ui/image/lazy-video.tsx +71 -0
  154. package/src/components/ui/input.tsx +22 -0
  155. package/src/components/ui/models/custom-dialog.tsx +320 -0
  156. package/src/components/ui/models/insert-gif.tsx +90 -0
  157. package/src/components/ui/models/insert-image.tsx +52 -0
  158. package/src/components/ui/models/insert-poll.tsx +29 -0
  159. package/src/components/ui/models/insert-table.tsx +62 -0
  160. package/src/components/ui/models/use-model.tsx +91 -0
  161. package/src/components/ui/poll/poll-component.tsx +304 -0
  162. package/src/components/ui/popover.tsx +33 -0
  163. package/src/components/ui/progress.tsx +28 -0
  164. package/src/components/ui/scroll-area.tsx +48 -0
  165. package/src/components/ui/separator.tsx +31 -0
  166. package/src/components/ui/skeleton.tsx +15 -0
  167. package/src/components/ui/sonner.tsx +31 -0
  168. package/src/components/ui/stepper/step.tsx +179 -0
  169. package/src/components/ui/stepper/stepper.tsx +89 -0
  170. package/src/components/ui/textarea.tsx +22 -0
  171. package/src/components/ui/toggle.tsx +71 -0
  172. package/src/components/ui/tooltip.tsx +32 -0
  173. package/src/components/ui/write/text-format-floting-toolbar.tsx +346 -0
  174. package/src/lib/edgestore.ts +9 -0
  175. package/src/lib/pinecone-client.ts +0 -0
  176. package/src/lib/utils.ts +6 -0
  177. package/src/utils/docSerialization.ts +77 -0
  178. package/src/utils/emoji-list.ts +16615 -0
  179. package/src/utils/getDOMRangeRect.ts +27 -0
  180. package/src/utils/getSelectedNode.ts +27 -0
  181. package/src/utils/getThemeSelector.ts +25 -0
  182. package/src/utils/isMobileWidth.ts +7 -0
  183. package/src/utils/joinClasses.ts +13 -0
  184. package/src/utils/setFloatingElemPosition.ts +74 -0
  185. package/src/utils/setFloatingElemPositionForLinkEditor.ts +46 -0
  186. package/src/utils/swipe.ts +127 -0
  187. package/src/utils/url.ts +38 -0
  188. package/tsconfig.json +27 -0
@@ -0,0 +1,574 @@
1
+ import { Loader2, RotateCcw, StarsIcon, WandSparkles } from "lucide-react";
2
+ import React, { useMemo, useState } from "react";
3
+ import {
4
+ Popover,
5
+ PopoverContent,
6
+ PopoverTrigger,
7
+ } from "@/components/ui/popover";
8
+ import {
9
+ Command,
10
+ CommandEmpty,
11
+ CommandGroup,
12
+ CommandInput,
13
+ CommandItem,
14
+ CommandList,
15
+ CommandSeparator,
16
+ } from "@/components/ui/command";
17
+ import {
18
+ HoverCard,
19
+ HoverCardContent,
20
+ HoverCardTrigger,
21
+ } from "@/components/ui/hover-card";
22
+ import { HoverBorderGradient } from "./border";
23
+ import { PlaceholdersAndVanishInput } from "./placeholder-input-vanish";
24
+ import { motion } from "framer-motion";
25
+ import {
26
+ getSelectedText,
27
+ insertText,
28
+ insertTextUnderSelected,
29
+ replaceSelectedText,
30
+ } from "../../editor/utils/ai";
31
+ import { LexicalEditor } from "lexical";
32
+ import { useCompletion } from "@ai-sdk/react";
33
+ import { toast } from "sonner";
34
+ import ReactMarkdown from "react-markdown";
35
+ import { ExtractData } from "../../editor/utils/extract-data";
36
+ import { AIAction } from "../../editor/hooks/instructions-messages";
37
+ const placeholders = [
38
+ "Chat with what you are writing.",
39
+ "Click on the stepper to generate tasks step by step.",
40
+ "Click on autocomplete to complete sentences.",
41
+ "Is your text too long? Do you want to make it shorter?"
42
+ ];
43
+ export default function AiButton({ editor }: { editor: LexicalEditor }) {
44
+ const [actionType, setActionType] = useState<AIAction | null>(null); // track the user action
45
+ const [streamedResponse, setStreamedResponse] = useState<string>("");
46
+
47
+ const { completion, isLoading, complete, handleInputChange, input } =useCompletion({
48
+ api: "/api/ai",
49
+ onError: (err) => {
50
+ toast.error(err.message);
51
+ },
52
+ onResponse: (response) => {
53
+ setStreamedResponse("");
54
+ },
55
+ onFinish: (prompt,compeletion) => {
56
+ if (actionType === "Steps") {
57
+ setStreamedResponse(compeletion)
58
+ }
59
+ },
60
+ });
61
+ const handleAction = async (
62
+ action: AIAction,
63
+ payload: {
64
+ prompt?: string;
65
+ question?: string;
66
+ context?: string;
67
+ }
68
+ ) => {
69
+ try {
70
+ await complete("", {
71
+ body: {
72
+ action,
73
+ ...payload,
74
+ },
75
+ });
76
+ setActionType(action);
77
+ } catch (err) {
78
+ toast.error("Failed to process AI action. Please try again.");
79
+ }
80
+ };
81
+ const handleRegeneration = async () => {
82
+ if (!completion) {
83
+ toast.error("No content to regenerate");
84
+ return;
85
+ }
86
+ await handleAction("GenerateAgain", { prompt: completion });
87
+ };
88
+
89
+ const handleAutoComplete = async () => {
90
+ const selectedText = getSelectedText(editor, 30);
91
+ await handleAction("autoComplete", { prompt: selectedText });
92
+ };
93
+ const handleImproveWriting = async () => {
94
+ const selectedText = getSelectedText(editor);
95
+ await handleAction("ImproveWriting", { prompt: selectedText });
96
+ };
97
+ const handleSimplifyLanguage = async () => {
98
+ const selectedText = getSelectedText(editor);
99
+ await handleAction("SimplifyLanguage", { prompt: selectedText });
100
+ };
101
+ const handleMakeLong = async () => {
102
+ const selectedText = getSelectedText(editor);
103
+ await handleAction("MakeLong", { prompt: selectedText });
104
+ };
105
+ const handleMakeShort = async () => {
106
+ const selectedText = getSelectedText(editor);
107
+ await handleAction("MakeShort", { prompt: selectedText });
108
+ };
109
+ const handleFixSpellingGrammar = async () => {
110
+ const selectedText = getSelectedText(editor);
111
+ await handleAction("FixSpellingGrammar", { prompt: selectedText });
112
+ };
113
+ const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
114
+ e.preventDefault();
115
+ if (!input) {
116
+ toast.error("Please enter a question or instruction");
117
+ return;
118
+ }
119
+ if (actionType === "Steps") {
120
+ await handleAction("Steps", { prompt: input });
121
+ } else {
122
+ const data = ExtractData(editor);
123
+ const selectedText = getSelectedText(editor, 30);
124
+ if (!selectedText) {
125
+ toast.error("Please select some text first");
126
+ return;
127
+ }
128
+ await handleAction("ChatWithSelectedString", {
129
+ prompt: input,
130
+ context: data,
131
+ });
132
+ setActionType(null);
133
+ }
134
+ };
135
+
136
+ const renderSteps = () => {
137
+ if (!streamedResponse ) return null;
138
+
139
+ try {
140
+ const steps = JSON.parse(streamedResponse);
141
+ return (
142
+ <ul className="list-none space-y-2">
143
+ {steps.map((step: { id: number; title: string; content: string }) => (
144
+ <li key={step.id} className="rounded-md shadow-md p-1">
145
+ <h3 className="font-semibold text-lg">
146
+ {step.id+1}. {step.title}
147
+ </h3>
148
+ <p className="text-gray-600 dark:text-gray-300 mtx-2">
149
+ {step.content}
150
+ </p>
151
+ </li>
152
+ ))}
153
+ </ul>
154
+ );
155
+ } catch (error) {
156
+ return
157
+
158
+ }
159
+ };
160
+ const Actions = useMemo(
161
+ () => ({
162
+ suggestion: [
163
+ {
164
+ icon: (
165
+ <svg
166
+ xmlns="http://www.w3.org/2000/svg"
167
+ className="size-5 text-purple-500"
168
+ viewBox="0 0 24 24"
169
+ >
170
+ <path
171
+ fill="currentColor"
172
+ d="m19 9l-1.25-2.75L15 5l2.75-1.25L19 1l1.25 2.75L23 5l-2.75 1.25Zm0 14l-1.25-2.75L15 19l2.75-1.25L19 15l1.25 2.75L23 19l-2.75 1.25ZM4.8 16L8 7h2l3.2 9h-1.9l-.7-2H7.4l-.7 2Zm3.05-3.35h2.3L9 9ZM9 18q2.5 0 4.25-1.75T15 12q0-2.5-1.75-4.25T9 6Q6.5 6 4.75 7.75T3 12q0 2.5 1.75 4.25T9 18Zm0 2q-3.35 0-5.675-2.325Q1 15.35 1 12q0-3.35 2.325-5.675Q5.65 4 9 4q3.35 0 5.675 2.325Q17 8.65 17 12q0 3.35-2.325 5.675Q12.35 20 9 20Z"
173
+ ></path>
174
+ </svg>
175
+ ),
176
+ label: "auto compeletion",
177
+ HoverCard: {
178
+ desc: "Improve your sentences effortlessly—just select the text you want to refine, and let AI work its magic! ✨",
179
+ },
180
+ onClick: handleAutoComplete,
181
+ },
182
+ {
183
+ icon: (
184
+ <svg
185
+ xmlns="http://www.w3.org/2000/svg"
186
+ className="size-5 text-purple-500"
187
+ viewBox="0 0 24 24"
188
+ >
189
+ <path
190
+ fill="currentColor"
191
+ d="M7.5 5.6L10 7L8.6 4.5L10 2L7.5 3.4L5 2l1.4 2.5L5 7zm12 9.8L17 14l1.4 2.5L17 19l2.5-1.4L22 19l-1.4-2.5L22 14zM22 2l-2.5 1.4L17 2l1.4 2.5L17 7l2.5-1.4L22 7l-1.4-2.5zm-7.63 5.29a.996.996 0 0 0-1.41 0L1.29 18.96a.996.996 0 0 0 0 1.41l2.34 2.34c.39.39 1.02.39 1.41 0L16.7 11.05a.996.996 0 0 0 0-1.41zm-1.03 5.49l-2.12-2.12l2.44-2.44l2.12 2.12z"
192
+ ></path>
193
+ </svg>
194
+ ),
195
+ label: "Improve Writing",
196
+ HoverCard: {
197
+ desc: " Simply select the text you want, and let our AI refine your writing effortlessly! 📝🚀",
198
+ },
199
+ onClick: handleImproveWriting,
200
+ },
201
+
202
+ {
203
+ icon: (
204
+ <svg
205
+ xmlns="http://www.w3.org/2000/svg"
206
+ className="size-5 text-purple-500"
207
+ viewBox="0 0 24 24"
208
+ >
209
+ <path
210
+ fill="currentColor"
211
+ d="m9 16.2l-3.5-3.5a.984.984 0 0 0-1.4 0a.984.984 0 0 0 0 1.4l4.19 4.19c.39.39 1.02.39 1.41 0L20.3 7.7a.984.984 0 0 0 0-1.4a.984.984 0 0 0-1.4 0z"
212
+ ></path>
213
+ </svg>
214
+ ),
215
+ label: "Fix spelling & grammar",
216
+ HoverCard: {
217
+ desc: "📝 Select your messy text, and let AI transform it into perfection! 🚀",
218
+ },
219
+ onClick: handleFixSpellingGrammar,
220
+ },
221
+ ],
222
+ Edit: [
223
+ {
224
+ icon: (
225
+ <svg
226
+ xmlns="http://www.w3.org/2000/svg"
227
+ className="h-4 flex-shrink-0 w-4 block text-green-400"
228
+ viewBox="0 0 20 20"
229
+ >
230
+ <path
231
+ fill="currentColor"
232
+ d="M3.5 5a.5.5 0 0 0 0 1h13a.5.5 0 0 0 0-1zm0 3a.5.5 0 0 0 0 1h13a.5.5 0 0 0 0-1zm0 7h7.002l.416-1H3.5a.5.5 0 0 0 0 1m8.668-4l-.416 1H3.5a.5.5 0 0 1 0-1zm-.667 6.012h1.75l-.59 2.363c-.121.485.462.828.826.488l4.873-4.556c.497-.466.169-1.301-.512-1.301H16.75l.781-2.347a.5.5 0 0 0-.474-.659h-3.473a.5.5 0 0 0-.462.308l-2.083 5.01a.5.5 0 0 0 .462.694"
233
+ ></path>
234
+ </svg>
235
+ ),
236
+ label: "Make longer",
237
+ HoverCard: {
238
+ desc: "Enhance your text by adding more detail and context. Let AI expand your ideas! 🚀",
239
+ },
240
+ onClick:handleMakeLong,
241
+ },
242
+ {
243
+ icon: (
244
+ <svg
245
+ xmlns="http://www.w3.org/2000/svg"
246
+ className="h-4 flex-shrink-0 w-4 block text-green-400"
247
+ viewBox="0 0 32 32"
248
+ >
249
+ <path fill="currentColor" d="M6 18h14v2H6zm0-6h20v2H6z"></path>
250
+ </svg>
251
+ ),
252
+ label: "Make shorter",
253
+ HoverCard: {
254
+ desc: "Select your dummy short paragraph and let our AI expand it while preserving its original content! 🚀✨",
255
+ },
256
+ onClick: handleMakeShort,
257
+ },
258
+ {
259
+ icon: (
260
+ <svg
261
+ xmlns="http://www.w3.org/2000/svg"
262
+ className="h-4 flex-shrink-0 w-4 block text-green-400"
263
+ viewBox="0 0 24 24"
264
+ >
265
+ <path
266
+ fill="currentColor"
267
+ fillRule="evenodd"
268
+ d="M12.75 18.96V22h-1.5v-3.04A7 7 0 0 1 5 12v-2h1.5v2a5.5 5.5 0 0 0 11 0v-2H19v2a7 7 0 0 1-6.25 6.96M8 6a4 4 0 1 1 8 0v6a4 4 0 1 1-8 0z"
269
+ ></path>
270
+ </svg>
271
+ ),
272
+ label: "Simplify Language",
273
+ HoverCard: {
274
+ desc: "If you're using overly complex language and want to simplify it for easier understanding, let our AI transform your text into clear, concise, and engaging content! 😊✨",
275
+ },
276
+ onClick: handleSimplifyLanguage,
277
+ },
278
+ ],
279
+ format_block: [
280
+ {
281
+ icon: (
282
+ <svg
283
+ xmlns="http://www.w3.org/2000/svg"
284
+ className="size-5 text-yellow-400"
285
+ viewBox="0 0 24 24"
286
+ >
287
+ <g fill="none">
288
+ <path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path>
289
+ <path
290
+ fill="currentColor"
291
+ d="M5.436 16.72a1.466 1.466 0 0 1 1.22 2.275a1.466 1.466 0 0 1-1.22 2.275c-.587 0-1.134-.21-1.38-.79c-.153-.361-.112-.79.297-.963a.65.65 0 0 1 .852.344a.18.18 0 0 0 .165.11c.114-.003.23-.026.23-.168c0-.1-.073-.143-.156-.155l-.051-.003a.65.65 0 0 1-.112-1.29l.112-.01c.102 0 .207-.037.207-.158c0-.141-.116-.165-.23-.168a.18.18 0 0 0-.164.11a.65.65 0 0 1-.853.345c-.409-.174-.45-.603-.297-.963c.246-.58.793-.79 1.38-.79ZM20 17.5a1.5 1.5 0 0 1 0 3H9a1.5 1.5 0 0 1 0-3zM6.08 9.945a1.552 1.552 0 0 1 .43 2.442l-.554.593h.47a.65.65 0 1 1 0 1.3H4.573a.655.655 0 0 1-.655-.654c0-.207.029-.399.177-.557L5.559 11.5c.142-.152.03-.473-.203-.415c-.087.022-.123.089-.134.165l-.004.059a.65.65 0 1 1-1.3 0c0-.692.439-1.314 1.123-1.485c.35-.088.718-.04 1.04.121ZM20 10.5a1.5 1.5 0 0 1 .144 2.993L20 13.5H9a1.5 1.5 0 0 1-.144-2.993L9 10.5zM6.15 3.39v3.24a.65.65 0 0 1-1.3 0V4.523a.65.65 0 0 1-.46-1.184l.742-.494a.655.655 0 0 1 1.018.544ZM20 3.5a1.5 1.5 0 0 1 .144 2.993L20 6.5H9a1.5 1.5 0 0 1-.144-2.993L9 3.5z"
292
+ ></path>
293
+ </g>
294
+ </svg>
295
+ ),
296
+ label: "Step-by-Step Guide",
297
+ HoverCard: {
298
+ desc: "Need a clear roadmap to programming mastery? step-by-step guide that breaks down complex topics into simple, actionable steps. Let it light your path to coding success! 🚀💻",
299
+ },
300
+ onClick: () => setActionType("Steps"),
301
+ },
302
+ ],
303
+ }),
304
+ []
305
+ );
306
+
307
+ const response = useMemo(
308
+ () => [
309
+ {
310
+ icon: (
311
+ <svg
312
+ xmlns="http://www.w3.org/2000/svg"
313
+ className="text-[#8d5bc1] size-5"
314
+ viewBox="0 0 16 16"
315
+ >
316
+ <path
317
+ fill="currentColor"
318
+ fillRule="evenodd"
319
+ d="M0 3.2c0-1.12 0-1.68.218-2.11C.41.714.716.408 1.092.216c.428-.218.988-.218 2.11-.218h.6c1.12 0 1.68 0 2.11.218c.376.192.682.498.874.874c.218.428.218.988.218 2.11v.6c0 1.12 0 1.68-.218 2.11a2 2 0 0 1-.874.874c-.428.218-.988.218-2.11.218h-.6c-1.12 0-1.68 0-2.11-.218a2 2 0 0 1-.874-.874C0 5.482 0 4.922 0 3.8zM3.2 1h.6c.577 0 .949 0 1.23.024c.272.022.372.06.422.085c.188.096.341.249.437.437c.025.05.063.15.085.422c.023.283.024.656.024 1.23v.6c0 .577 0 .949-.024 1.23c-.022.272-.06.372-.085.422a1 1 0 0 1-.437.437c-.05.025-.15.063-.422.085c-.283.023-.656.024-1.23.024h-.6c-.577 0-.949 0-1.23-.024c-.272-.022-.372-.06-.422-.085a1 1 0 0 1-.437-.437c-.025-.05-.063-.15-.085-.422a17 17 0 0 1-.024-1.23v-.6c0-.577 0-.949.024-1.23c.022-.272.06-.372.085-.422c.096-.188.249-.341.437-.437c.05-.025.15-.063.422-.085C2.253 1 2.626 1 3.2 1M9 12.2c0-1.12 0-1.68.218-2.11c.192-.376.498-.682.874-.874c.428-.218.988-.218 2.11-.218h.6c1.12 0 1.68 0 2.11.218c.376.192.682.498.874.874c.218.428.218.988.218 2.11v.6c0 1.12 0 1.68-.218 2.11a2 2 0 0 1-.874.874c-.428.218-.988.218-2.11.218h-.6c-1.12 0-1.68 0-2.11-.218a2 2 0 0 1-.874-.874C9 14.482 9 13.922 9 12.8zm3.8-2.2c.577 0 .949 0 1.23.024c.272.022.372.06.422.085c.188.096.341.249.437.437c.025.05.063.15.085.422c.023.283.024.656.024 1.23v.6c0 .577 0 .949-.024 1.23c-.022.272-.06.372-.085.422a1 1 0 0 1-.437.437c-.05.025-.15.063-.422.085c-.283.023-.656.024-1.23.024h-.6c-.577 0-.949 0-1.23-.024c-.272-.022-.372-.06-.422-.085a1 1 0 0 1-.437-.437c-.025-.05-.063-.15-.085-.422a17 17 0 0 1-.024-1.23v-.6c0-.577 0-.949.024-1.23c.022-.272.06-.372.085-.422c.096-.188.249-.341.437-.437c.05-.025.15-.063.422-.085c.283-.023.656-.024 1.23-.024z"
320
+ clipRule="evenodd"
321
+ ></path>
322
+ <path
323
+ fill="currentColor"
324
+ d="M8 2.5a.5.5 0 0 1 .5-.5h2A2.5 2.5 0 0 1 13 4.5v1.79l1.15-1.15a.5.5 0 0 1 .707.707l-2 2a.5.5 0 0 1-.707 0l-2-2a.5.5 0 0 1 .707-.707l1.15 1.15V4.5a1.5 1.5 0 0 0-1.5-1.5h-2a.5.5 0 0 1-.5-.5zM3.31 8.04a.5.5 0 0 1 .188-.038h.006a.5.5 0 0 1 .351.146l2 2a.5.5 0 0 1-.707.707l-1.15-1.15v1.79a1.5 1.5 0 0 0 1.5 1.5h2a.5.5 0 0 1 0 1h-2a2.5 2.5 0 0 1-2.5-2.5v-1.79l-1.15 1.15a.5.5 0 0 1-.707-.707l2-2a.5.5 0 0 1 .162-.109z"
325
+ ></path>
326
+ </svg>
327
+ ),
328
+ label: "rplace text",
329
+ HoverCard: {
330
+ desc: "Select your text and let our AI replace it with a polished, enhanced version! 🚀✨",
331
+ },
332
+ func: () => replaceSelectedText(completion, editor),
333
+ },
334
+ {
335
+ icon: (
336
+ <svg
337
+ xmlns="http://www.w3.org/2000/svg"
338
+ className="text-[#8d5bc1] size-5"
339
+ viewBox="0 0 56 56"
340
+ >
341
+ <path
342
+ fill="currentColor"
343
+ d="M33.8 11.36h16.01c1.008 0 1.804-.774 1.804-1.782c0-.984-.797-1.758-1.804-1.758H33.8c-1.008 0-1.782.774-1.782 1.758c0 1.008.774 1.781 1.782 1.781M7.083 26.944c1.71 0 2.695-1.195 2.695-3.093v-4.477c0-.516.235-.82.797-.82h6.375v2.343c0 1.852 1.875 2.555 3.281 1.43l6.352-5.062c.96-.774.96-2.11 0-2.86L20.23 9.32c-1.453-1.195-3.28-.469-3.28 1.43v2.438h-6.891c-3.305 0-5.672 2.039-5.672 5.367v5.297c0 1.898.984 3.093 2.695 3.093m26.719-3.304h16.008c1.008 0 1.804-.774 1.804-1.782c0-.984-.797-1.758-1.804-1.758H33.8c-1.008 0-1.782.774-1.782 1.758c0 1.008.774 1.782 1.782 1.782M6.168 35.92h43.64a1.786 1.786 0 0 0 1.805-1.78c0-.985-.797-1.758-1.804-1.758H6.168c-1.008 0-1.781.773-1.781 1.758c0 .984.773 1.78 1.78 1.78m0 12.259h43.64c1.008 0 1.805-.774 1.805-1.758s-.797-1.781-1.804-1.781H6.168a1.766 1.766 0 0 0-1.781 1.78c0 .985.773 1.759 1.78 1.759"
344
+ ></path>
345
+ </svg>
346
+ ),
347
+ label: "insert text",
348
+ HoverCard: {
349
+ desc: "text will inserted immediately following your selection.",
350
+ },
351
+ func: () => insertText(completion, editor),
352
+ },
353
+ {
354
+ icon: (
355
+ <svg
356
+ xmlns="http://www.w3.org/2000/svg"
357
+ className="text-[#8d5bc1] size-5"
358
+ viewBox="0 0 14 14"
359
+ >
360
+ <g
361
+ fill="none"
362
+ stroke="currentColor"
363
+ strokeLinecap="round"
364
+ strokeLinejoin="round"
365
+ >
366
+ <path d="M9.5 6.5h-9m13-3H.5m13-3H.5"></path>
367
+ <rect
368
+ width="4"
369
+ height="13"
370
+ x="5"
371
+ y="5"
372
+ rx=".5"
373
+ transform="rotate(-90 7 11.5)"
374
+ ></rect>
375
+ </g>
376
+ </svg>
377
+ ),
378
+ label: "insert below",
379
+ HoverCard: {
380
+ desc: "text will inserted under your selection.",
381
+ },
382
+ func: () => insertTextUnderSelected(completion, editor),
383
+ },
384
+
385
+ {
386
+ icon: <RotateCcw className="text-[#8d5bc1] size-4" />,
387
+ label: "try again",
388
+ HoverCard: {
389
+ desc: "you did not like the ai response? try it again with what do you want",
390
+ },
391
+ func: handleRegeneration,
392
+ },
393
+ ],
394
+ [completion]
395
+ );
396
+
397
+ return (
398
+ <Popover >
399
+ <PopoverTrigger asChild>
400
+ <button className="inline-flex px-6 max-sm:py-2 max-sm:px-[5px] h-6 animate-background-shine items-center justify-center rounded-md border border-gray-800 bg-[linear-gradient(110deg,#000103,45%,#1e2631,55%,#000103)] bg-[length:200%_100%] font-medium text-gray-400 transition-colors focus:outline-none focus:ring-2 focus:ring-gray-400 focus:ring-offset-2 focus:ring-offset-gray-50">
401
+ <WandSparkles className=" size-4 text-purple-400" />
402
+ </button>
403
+ </PopoverTrigger>
404
+ <PopoverContent className="absolute max-h-[300px] h-fit shadow-sm shadow-black dark:shadow-gray-500 p-0 w-[420px] max-sm:w-[200px] min-w-[200px] max-w-[420px] top-[10px] max-sm:left-6 -left-7 AI-format">
405
+ <div className="w-full relative">
406
+ <div className="flex flex-col items-start justify-between">
407
+ {(completion || actionType === "Steps") && (
408
+ <motion.div
409
+ initial={{ opacity: 0, y: 20 }}
410
+ animate={{ opacity: 1, y: 0 }}
411
+ transition={{ duration: 0.5, ease: "easeOut" }}
412
+ className="cursor-text w-full p-2 z-20 break-words max-h-64 h-fit overflow-y-auto"
413
+ >
414
+ {streamedResponse!=="" ? (
415
+ renderSteps()
416
+ ) : (
417
+ <ReactMarkdown>
418
+ {completion ||
419
+ "Ask for a step-by-step guide on any programming topic. Example: 'How can I become a backend developer?'"}
420
+ </ReactMarkdown>
421
+ )}
422
+ </motion.div>
423
+ )}
424
+ <div className="relative w-full">
425
+ <div className=" absolute top-1/2 -translate-y-1/2 left-2">
426
+ <HoverBorderGradient
427
+ duration={2}
428
+ clockwise={false}
429
+ containerClassName="rounded-full border-0"
430
+ as="button"
431
+ className="dark:bg-white size-5 bg-black dark:text-white flex justify-center items-center"
432
+ >
433
+ {isLoading ? (
434
+ <Loader2 className="size-3 dark:text-black text-white animate-spin" />
435
+ ) : (
436
+ <StarsIcon className="dark:text-purple-600 text-purple-300 size-3" />
437
+ )}
438
+ </HoverBorderGradient>
439
+ </div>
440
+ <PlaceholdersAndVanishInput
441
+ placeholders={placeholders}
442
+ onChange={handleInputChange}
443
+ onSubmit={handleSubmit}
444
+ disabled={isLoading}
445
+ />
446
+ </div>
447
+ </div>
448
+ <div className="w-[200px] h-[180px] z-50 rounded border mt-2 fixed">
449
+ {!completion ? (
450
+ <Command id="toolbar" className="w-full ">
451
+ <CommandInput placeholder="Type a command" />
452
+ <CommandList>
453
+ <CommandEmpty>No results found.</CommandEmpty>
454
+ <CommandGroup heading="Suggested">
455
+ {Actions.suggestion.map((sug) => (
456
+ <HoverCard key={sug.label}>
457
+ <HoverCardTrigger
458
+ onClick={sug.onClick}
459
+ className="w-full p-0"
460
+ >
461
+ <CommandItem className="w-full">
462
+ <div>{sug.icon}</div>
463
+ <span>{sug.label}</span>
464
+ </CommandItem>
465
+ </HoverCardTrigger>
466
+ <HoverCardContent
467
+ className=" p-2"
468
+ side="right"
469
+ alignOffset={60}
470
+ sideOffset={30}
471
+ >
472
+ <span className="text-sm break-words text-muted-foreground">
473
+ {sug.HoverCard.desc}
474
+ </span>
475
+ </HoverCardContent>
476
+ </HoverCard>
477
+ ))}
478
+ </CommandGroup>
479
+
480
+ <CommandSeparator />
481
+ <CommandGroup heading="format block">
482
+ {Actions.format_block.map((sug) => (
483
+ <HoverCard key={sug.label}>
484
+ <HoverCardTrigger
485
+ onClick={sug.onClick}
486
+ className="w-full p-0"
487
+ >
488
+ <CommandItem className="w-full">
489
+ <div>{sug.icon}</div>
490
+ <span>{sug.label}</span>
491
+ </CommandItem>
492
+ </HoverCardTrigger>
493
+ <HoverCardContent
494
+ className=" p-2"
495
+ side="right"
496
+ alignOffset={60}
497
+ sideOffset={30}
498
+ >
499
+ <span className="text-sm break-words text-muted-foreground">
500
+ {sug.HoverCard.desc}
501
+ </span>
502
+ </HoverCardContent>
503
+ </HoverCard>
504
+ ))}
505
+ </CommandGroup>
506
+ <CommandSeparator />
507
+
508
+ <CommandGroup heading="Edit">
509
+ {Actions.Edit.map((sug) => (
510
+ <HoverCard key={sug.label}>
511
+ <HoverCardTrigger
512
+ onClick={sug.onClick}
513
+ className="w-full p-0"
514
+ >
515
+ <CommandItem className="w-full">
516
+ <div>{sug.icon}</div>
517
+ <span>{sug.label}</span>
518
+ </CommandItem>
519
+ </HoverCardTrigger>
520
+ <HoverCardContent
521
+ className="p-2"
522
+ side="right"
523
+ alignOffset={60}
524
+ sideOffset={30}
525
+ >
526
+ <span className="text-sm text-muted-foreground">
527
+ {sug.HoverCard.desc}
528
+ </span>
529
+ </HoverCardContent>
530
+ </HoverCard>
531
+ ))}
532
+ </CommandGroup>
533
+ </CommandList>
534
+ </Command>
535
+ ) : (
536
+ <Command id="toolbar" className="w-full">
537
+ <CommandInput placeholder="Type a command" />
538
+ <CommandList>
539
+ <CommandEmpty>No results found.</CommandEmpty>
540
+ <CommandGroup>
541
+ {response.map((sug) => (
542
+ <HoverCard key={sug.label}>
543
+ <HoverCardTrigger
544
+ onClick={sug.func}
545
+
546
+ className="w-full p-0"
547
+ >
548
+ <CommandItem disabled={isLoading} className="w-full">
549
+ <div>{sug.icon}</div>
550
+ <span>{sug.label}</span>
551
+ </CommandItem>
552
+ </HoverCardTrigger>
553
+ <HoverCardContent
554
+ className=" p-2"
555
+ side="right"
556
+ alignOffset={60}
557
+ sideOffset={30}
558
+ >
559
+ <span className="text-sm break-words text-muted-foreground">
560
+ {sug.HoverCard.desc}
561
+ </span>
562
+ </HoverCardContent>
563
+ </HoverCard>
564
+ ))}
565
+ </CommandGroup>
566
+ </CommandList>
567
+ </Command>
568
+ )}
569
+ </div>
570
+ </div>
571
+ </PopoverContent>
572
+ </Popover>
573
+ );
574
+ }
@@ -0,0 +1,99 @@
1
+ "use client";
2
+ import React, { useState, useEffect, useRef } from "react";
3
+
4
+ import { motion } from "framer-motion";
5
+ import { cn } from "@/lib/utils";
6
+
7
+ type Direction = "TOP" | "LEFT" | "BOTTOM" | "RIGHT";
8
+
9
+ export function HoverBorderGradient({
10
+ children,
11
+ containerClassName,
12
+ className,
13
+ as: Tag = "button",
14
+ duration = 1,
15
+ clockwise = true,
16
+ ...props
17
+ }: React.PropsWithChildren<
18
+ {
19
+ as?: React.ElementType;
20
+ containerClassName?: string;
21
+ className?: string;
22
+ duration?: number;
23
+ clockwise?: boolean;
24
+ } & React.HTMLAttributes<HTMLElement>
25
+ >) {
26
+ const [hovered, setHovered] = useState<boolean>(false);
27
+ const [direction, setDirection] = useState<Direction>("TOP");
28
+
29
+ const rotateDirection = (currentDirection: Direction): Direction => {
30
+ const directions: Direction[] = ["TOP", "LEFT", "BOTTOM", "RIGHT"];
31
+ const currentIndex = directions.indexOf(currentDirection);
32
+ const nextIndex = clockwise
33
+ ? (currentIndex - 1 + directions.length) % directions.length
34
+ : (currentIndex + 1) % directions.length;
35
+ return directions[nextIndex];
36
+ };
37
+
38
+ const movingMap: Record<Direction, string> = {
39
+ TOP: "radial-gradient(20.7% 50% at 50% 0%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
40
+ LEFT: "radial-gradient(16.6% 43.1% at 0% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
41
+ BOTTOM:
42
+ "radial-gradient(20.7% 50% at 50% 100%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
43
+ RIGHT:
44
+ "radial-gradient(16.2% 41.199999999999996% at 100% 50%, hsl(0, 0%, 100%) 0%, rgba(255, 255, 255, 0) 100%)",
45
+ };
46
+
47
+ const highlight =
48
+ "radial-gradient(75% 181.15942028985506% at 50% 50%, #3275F8 0%, rgba(255, 255, 255, 0) 100%)";
49
+
50
+ useEffect(() => {
51
+ if (!hovered) {
52
+ const interval = setInterval(() => {
53
+ setDirection((prevState) => rotateDirection(prevState));
54
+ }, duration * 1000);
55
+ return () => clearInterval(interval);
56
+ }
57
+ }, [hovered]);
58
+ return (
59
+ <Tag
60
+ onMouseEnter={(event: React.MouseEvent<HTMLDivElement>) => {
61
+ setHovered(true);
62
+ }}
63
+ onMouseLeave={() => setHovered(false)}
64
+ className={cn(
65
+ "relative flex rounded-full border content-center bg-black/20 hover:bg-black/10 transition duration-500 dark:bg-white/20 items-center flex-col flex-nowrap justify-center overflow-visible p-px decoration-clone w-fit",
66
+ containerClassName
67
+ )}
68
+ {...props}
69
+ >
70
+ <div
71
+ className={cn(
72
+ "w-auto text-white z-10 bg-black rounded-[inherit]",
73
+ className
74
+ )}
75
+ >
76
+ {children}
77
+ </div>
78
+ <motion.div
79
+ className={cn(
80
+ "flex-none inset-0 overflow-hidden absolute z-0 rounded-[inherit]"
81
+ )}
82
+ style={{
83
+ filter: "blur(2px)",
84
+ position: "absolute",
85
+ width: "100%",
86
+ height: "100%",
87
+ }}
88
+ initial={{ background: movingMap[direction] }}
89
+ animate={{
90
+ background: hovered
91
+ ? [movingMap[direction], highlight]
92
+ : movingMap[direction],
93
+ }}
94
+ transition={{ ease: "linear", duration: duration ?? 1 }}
95
+ />
96
+ <div className="bg-black absolute z-1 flex-none inset-[2px] rounded-[100px]" />
97
+ </Tag>
98
+ );
99
+ }