@moontra/moonui-pro 2.8.4 → 2.8.6

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.mjs CHANGED
@@ -3,7 +3,7 @@ import { twMerge } from 'tailwind-merge';
3
3
  import * as t from 'react';
4
4
  import t__default, { useState, useRef, useCallback, forwardRef, createContext, useEffect, useContext, useMemo, useLayoutEffect, useDebugValue, Component } from 'react';
5
5
  import * as AccordionPrimitive from '@radix-ui/react-accordion';
6
- import { ChevronDown, Info, AlertCircle, AlertTriangle, Check, X, MoreHorizontal, Loader2, Minus, Search, ChevronRight, Circle, ChevronUp, Lock, Sparkles, Plus, CreditCard, Globe, CheckCircle2, XCircle, RotateCcw, Download, Clock, HelpCircle, ChevronLeft, Calendar as Calendar$1, Edit, Trash2, MapPin, User, GripVertical, MessageCircle, Paperclip, Bold as Bold$1, Italic as Italic$1, Underline as Underline$1, Strikethrough, Code as Code$1, Type, Heading1, Heading2, Heading3, AlignLeft, AlignCenter, AlignRight, AlignJustify, List, ListOrdered, CheckSquare, Quote, Palette, Highlighter, Link2, Image as Image$1, Table as Table$1, Settings, Undo, Redo, Eye, RefreshCw, Wand2, Maximize, FileText, Languages, TrendingUp, TrendingDown, ZoomOut, ZoomIn, FileSpreadsheet, FileJson, Maximize2, Move, Menu, Bell, CheckCheck, CheckCircle, Settings2, LogOut, Edit3, LayoutGrid, Upload, Share2, Save, Filter, FileDown, ArrowUp, ArrowDown, ArrowUpDown, ChevronsLeft, ChevronsRight, Pin, Sun, Moon, Monitor, Star, ExternalLink, CalendarIcon, DollarSign, Users, Github, GitFork, Activity, Server, EyeOff, RotateCw, Zap, Timer, Cpu, MemoryStick, HardDrive, Network, BarChart3, Video, Music, Archive, File, Columns, Grip, Unlock, Minimize2, Map as Map$1, Target, MoreVertical, BellOff, ArrowDownRight, ArrowUpRight } from 'lucide-react';
6
+ import { ChevronDown, Info, AlertCircle, AlertTriangle, Check, X, MoreHorizontal, Loader2, Minus, Search, ChevronRight, Circle, ChevronUp, Lock, Sparkles, Plus, CreditCard, Globe, CheckCircle2, XCircle, RotateCcw, Download, Clock, HelpCircle, ChevronLeft, Calendar as Calendar$1, Edit, Trash2, MapPin, User, GripVertical, MessageCircle, Paperclip, Bold as Bold$1, Italic as Italic$1, Underline as Underline$1, Strikethrough, Code as Code$1, Type, Heading1, Heading2, Heading3, AlignLeft, AlignCenter, AlignRight, AlignJustify, List, ListOrdered, CheckSquare, Quote, Palette, Highlighter, Link2, Image as Image$1, Table as Table$1, Settings, Undo, Redo, Eye, RefreshCw, Wand2, Maximize, FileText, Briefcase, MessageSquare, Heart, GraduationCap, Zap, Languages, Lightbulb, TrendingUp, TrendingDown, ZoomOut, ZoomIn, FileSpreadsheet, FileJson, Maximize2, Move, Menu, Bell, CheckCheck, CheckCircle, Settings2, LogOut, Edit3, LayoutGrid, Upload, Share2, Save, Filter, FileDown, ArrowUp, ArrowDown, ArrowUpDown, ChevronsLeft, ChevronsRight, Pin, Sun, Moon, Monitor, Star, ExternalLink, CalendarIcon, DollarSign, Users, Github, GitFork, Activity, Server, EyeOff, RotateCw, Timer, Cpu, MemoryStick, HardDrive, Network, BarChart3, Video, Music, Archive, File, Columns, Grip, Unlock, Minimize2, Map as Map$1, Target, MoreVertical, BellOff, ArrowDownRight, ArrowUpRight } from 'lucide-react';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
8
  import { cva } from 'class-variance-authority';
9
9
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
@@ -49910,6 +49910,328 @@ var SlashCommandsExtension = Extension.create({
49910
49910
  }
49911
49911
  });
49912
49912
 
49913
+ // src/lib/ai-providers.ts
49914
+ var GeminiProvider = class {
49915
+ constructor(config) {
49916
+ this.apiUrl = "https://generativelanguage.googleapis.com/v1beta/models";
49917
+ this.apiKey = config.apiKey;
49918
+ this.model = config.model || "gemini-2.0-flash";
49919
+ }
49920
+ async callGeminiAPI(prompt) {
49921
+ try {
49922
+ const response = await fetch(`${this.apiUrl}/${this.model}:generateContent`, {
49923
+ method: "POST",
49924
+ headers: {
49925
+ "Content-Type": "application/json",
49926
+ "X-goog-api-key": this.apiKey
49927
+ },
49928
+ body: JSON.stringify({
49929
+ contents: [{
49930
+ parts: [{
49931
+ text: prompt
49932
+ }]
49933
+ }]
49934
+ })
49935
+ });
49936
+ if (!response.ok) {
49937
+ const errorData = await response.text();
49938
+ console.error("Gemini API error response:", errorData);
49939
+ throw new Error(`Gemini API error: ${response.status} ${response.statusText} - ${errorData}`);
49940
+ }
49941
+ const data = await response.json();
49942
+ if (data.error) {
49943
+ throw new Error(`Gemini API error: ${data.error.message || JSON.stringify(data.error)}`);
49944
+ }
49945
+ if (data.candidates?.[0]?.finishReason === "SAFETY") {
49946
+ throw new Error("Content was blocked by safety filters");
49947
+ }
49948
+ const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
49949
+ if (!text) {
49950
+ console.error("Gemini API response:", JSON.stringify(data, null, 2));
49951
+ throw new Error("No text content in Gemini API response");
49952
+ }
49953
+ return text.trim();
49954
+ } catch (error) {
49955
+ console.error("Gemini API error details:", error);
49956
+ if (error instanceof Error) {
49957
+ throw error;
49958
+ }
49959
+ throw new Error("Unknown error occurred while calling Gemini API");
49960
+ }
49961
+ }
49962
+ async generateText(prompt) {
49963
+ return this.callGeminiAPI(prompt);
49964
+ }
49965
+ async rewrite(text) {
49966
+ const prompt = `Rewrite the following text to make it clearer and more engaging while maintaining the same meaning. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Only return the rewritten text, nothing else:
49967
+
49968
+ ${text}`;
49969
+ return this.callGeminiAPI(prompt);
49970
+ }
49971
+ async expand(text) {
49972
+ const prompt = `Expand the following text with more details, examples, and explanations. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Only return the expanded text, nothing else:
49973
+
49974
+ ${text}`;
49975
+ return this.callGeminiAPI(prompt);
49976
+ }
49977
+ async summarize(text) {
49978
+ const prompt = `Summarize the following text concisely while keeping the main points. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Only return the summary, nothing else:
49979
+
49980
+ ${text}`;
49981
+ return this.callGeminiAPI(prompt);
49982
+ }
49983
+ async fixGrammar(text) {
49984
+ const prompt = `Fix any grammar and spelling errors in the following text. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Only return the corrected text, nothing else:
49985
+
49986
+ ${text}`;
49987
+ return this.callGeminiAPI(prompt);
49988
+ }
49989
+ async translate(text, targetLang) {
49990
+ const prompt = `Translate the following text to ${targetLang}. Only return the translation, nothing else:
49991
+
49992
+ ${text}`;
49993
+ return this.callGeminiAPI(prompt);
49994
+ }
49995
+ async changeTone(text, tone) {
49996
+ const toneDescriptions = {
49997
+ professional: "professional and business-appropriate",
49998
+ casual: "casual and conversational",
49999
+ friendly: "warm and friendly",
50000
+ formal: "formal and academic"
50001
+ };
50002
+ const toneDesc = toneDescriptions[tone] || tone;
50003
+ const prompt = `Rewrite the following text in a ${toneDesc} tone. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Only return the rewritten text, nothing else:
50004
+
50005
+ ${text}`;
50006
+ return this.callGeminiAPI(prompt);
50007
+ }
50008
+ async continueWriting(text) {
50009
+ const prompt = `Continue writing from where this text ends. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Only return the continuation, nothing else:
50010
+
50011
+ ${text}`;
50012
+ return this.callGeminiAPI(prompt);
50013
+ }
50014
+ async improveWriting(text) {
50015
+ const prompt = `Improve the following text by making it more compelling, clear, and well-structured. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Only return the improved text, nothing else:
50016
+
50017
+ ${text}`;
50018
+ return this.callGeminiAPI(prompt);
50019
+ }
50020
+ async generateIdeas(text) {
50021
+ const prompt = `Generate creative ideas and suggestions based on this topic. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Format as a bullet list:
50022
+
50023
+ ${text}`;
50024
+ return this.callGeminiAPI(prompt);
50025
+ }
50026
+ async complete(text) {
50027
+ const prompt = `Complete this text naturally. IMPORTANT: Respond in the SAME LANGUAGE as the input text. Only return the completion, nothing else:
50028
+
50029
+ ${text}`;
50030
+ return this.callGeminiAPI(prompt);
50031
+ }
50032
+ };
50033
+ var OpenAIProvider = class {
50034
+ constructor(config) {
50035
+ this.apiUrl = "https://api.openai.com/v1/chat/completions";
50036
+ this.apiKey = config.apiKey;
50037
+ this.model = config.model || "gpt-3.5-turbo";
50038
+ this.temperature = config.temperature || 0.7;
50039
+ this.maxTokens = config.maxTokens || 1e3;
50040
+ }
50041
+ async callOpenAI(systemPrompt, userPrompt) {
50042
+ try {
50043
+ const response = await fetch(this.apiUrl, {
50044
+ method: "POST",
50045
+ headers: {
50046
+ "Content-Type": "application/json",
50047
+ "Authorization": `Bearer ${this.apiKey}`
50048
+ },
50049
+ body: JSON.stringify({
50050
+ model: this.model,
50051
+ messages: [
50052
+ { role: "system", content: systemPrompt },
50053
+ { role: "user", content: userPrompt }
50054
+ ],
50055
+ temperature: this.temperature,
50056
+ max_tokens: this.maxTokens
50057
+ })
50058
+ });
50059
+ if (!response.ok) {
50060
+ throw new Error(`OpenAI API error: ${response.statusText}`);
50061
+ }
50062
+ const data = await response.json();
50063
+ return data.choices?.[0]?.message?.content || "";
50064
+ } catch (error) {
50065
+ console.error("OpenAI API error:", error);
50066
+ throw error;
50067
+ }
50068
+ }
50069
+ async generateText(prompt) {
50070
+ return this.callOpenAI("You are a helpful writing assistant. Always respond in the same language as the input text.", prompt);
50071
+ }
50072
+ async rewrite(text) {
50073
+ return this.callOpenAI(
50074
+ "You are a professional editor. Rewrite text to be clearer and more engaging. Always respond in the same language as the input text.",
50075
+ text
50076
+ );
50077
+ }
50078
+ async expand(text) {
50079
+ return this.callOpenAI(
50080
+ "You are a content writer. Expand the given text with more details and examples. Always respond in the same language as the input text.",
50081
+ text
50082
+ );
50083
+ }
50084
+ async summarize(text) {
50085
+ return this.callOpenAI(
50086
+ "You are a summarization expert. Create concise summaries. Always respond in the same language as the input text.",
50087
+ text
50088
+ );
50089
+ }
50090
+ async fixGrammar(text) {
50091
+ return this.callOpenAI(
50092
+ "You are a grammar expert. Fix all grammar and spelling errors. Always respond in the same language as the input text.",
50093
+ text
50094
+ );
50095
+ }
50096
+ async translate(text, targetLang) {
50097
+ return this.callOpenAI(
50098
+ `You are a professional translator. Translate to ${targetLang}.`,
50099
+ text
50100
+ );
50101
+ }
50102
+ async changeTone(text, tone) {
50103
+ return this.callOpenAI(
50104
+ `You are a writing expert. Rewrite the text in a ${tone} tone. Always respond in the same language as the input text.`,
50105
+ text
50106
+ );
50107
+ }
50108
+ async continueWriting(text) {
50109
+ return this.callOpenAI(
50110
+ "You are a creative writer. Continue writing from where the text ends. Always respond in the same language as the input text.",
50111
+ text
50112
+ );
50113
+ }
50114
+ async improveWriting(text) {
50115
+ return this.callOpenAI(
50116
+ "You are a professional editor. Improve the text quality. Always respond in the same language as the input text.",
50117
+ text
50118
+ );
50119
+ }
50120
+ async generateIdeas(text) {
50121
+ return this.callOpenAI(
50122
+ "You are a creative consultant. Generate ideas based on the topic. Always respond in the same language as the input text.",
50123
+ text
50124
+ );
50125
+ }
50126
+ async complete(text) {
50127
+ return this.callOpenAI(
50128
+ "You are a writing assistant. Complete the text naturally. Always respond in the same language as the input text.",
50129
+ text
50130
+ );
50131
+ }
50132
+ };
50133
+ var ClaudeProvider = class {
50134
+ constructor(config) {
50135
+ this.apiUrl = "https://api.anthropic.com/v1/messages";
50136
+ this.apiKey = config.apiKey;
50137
+ this.model = config.model || "claude-3-sonnet-20240229";
50138
+ }
50139
+ async callClaude(prompt) {
50140
+ try {
50141
+ const response = await fetch(this.apiUrl, {
50142
+ method: "POST",
50143
+ headers: {
50144
+ "Content-Type": "application/json",
50145
+ "x-api-key": this.apiKey,
50146
+ "anthropic-version": "2023-06-01"
50147
+ },
50148
+ body: JSON.stringify({
50149
+ model: this.model,
50150
+ max_tokens: 1e3,
50151
+ messages: [
50152
+ { role: "user", content: prompt }
50153
+ ]
50154
+ })
50155
+ });
50156
+ if (!response.ok) {
50157
+ throw new Error(`Claude API error: ${response.statusText}`);
50158
+ }
50159
+ const data = await response.json();
50160
+ return data.content?.[0]?.text || "";
50161
+ } catch (error) {
50162
+ console.error("Claude API error:", error);
50163
+ throw error;
50164
+ }
50165
+ }
50166
+ async generateText(prompt) {
50167
+ return this.callClaude(`${prompt}
50168
+
50169
+ IMPORTANT: Respond in the SAME LANGUAGE as the input text.`);
50170
+ }
50171
+ async rewrite(text) {
50172
+ return this.callClaude(`Rewrite this text to be clearer and more engaging. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50173
+
50174
+ ${text}`);
50175
+ }
50176
+ async expand(text) {
50177
+ return this.callClaude(`Expand this text with more details. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50178
+
50179
+ ${text}`);
50180
+ }
50181
+ async summarize(text) {
50182
+ return this.callClaude(`Summarize this text concisely. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50183
+
50184
+ ${text}`);
50185
+ }
50186
+ async fixGrammar(text) {
50187
+ return this.callClaude(`Fix grammar and spelling errors. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50188
+
50189
+ ${text}`);
50190
+ }
50191
+ async translate(text, targetLang) {
50192
+ return this.callClaude(`Translate to ${targetLang}:
50193
+
50194
+ ${text}`);
50195
+ }
50196
+ async changeTone(text, tone) {
50197
+ return this.callClaude(`Rewrite in a ${tone} tone. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50198
+
50199
+ ${text}`);
50200
+ }
50201
+ async continueWriting(text) {
50202
+ return this.callClaude(`Continue writing from where this text ends. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50203
+
50204
+ ${text}`);
50205
+ }
50206
+ async improveWriting(text) {
50207
+ return this.callClaude(`Improve this text. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50208
+
50209
+ ${text}`);
50210
+ }
50211
+ async generateIdeas(text) {
50212
+ return this.callClaude(`Generate ideas for this topic. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50213
+
50214
+ ${text}`);
50215
+ }
50216
+ async complete(text) {
50217
+ return this.callClaude(`Complete this text naturally. IMPORTANT: Respond in the SAME LANGUAGE as the input text:
50218
+
50219
+ ${text}`);
50220
+ }
50221
+ };
50222
+ function createAIProvider(provider, config) {
50223
+ switch (provider) {
50224
+ case "gemini":
50225
+ return new GeminiProvider(config);
50226
+ case "openai":
50227
+ return new OpenAIProvider(config);
50228
+ case "claude":
50229
+ return new ClaudeProvider(config);
50230
+ default:
50231
+ throw new Error(`Unsupported AI provider: ${provider}`);
50232
+ }
50233
+ }
50234
+
49913
50235
  // src/components/rich-text-editor/slash-commands.css
49914
50236
  styleInject(".slash-commands-menu {\n border-radius: var(--radius);\n border-width: 1px;\n --tw-border-opacity: 1;\n border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow:\n var(--tw-ring-offset-shadow, 0 0 #0000),\n var(--tw-ring-shadow, 0 0 #0000),\n var(--tw-shadow);\n}\n.slash-commands-menu:is(.dark *) {\n --tw-border-opacity: 1;\n border-color: rgb(55 65 81 / var(--tw-border-opacity, 1));\n --tw-bg-opacity: 1;\n background-color: rgb(17 24 39 / var(--tw-bg-opacity, 1));\n}\n.slash-commands-menu {\n max-height: 20rem;\n min-width: 280px;\n overflow-y: auto;\n padding: 0.5rem;\n}\n.slash-command-item {\n display: flex;\n cursor: pointer;\n align-items: center;\n gap: 0.75rem;\n border-radius: calc(var(--radius) - 2px);\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n transition-property:\n color,\n background-color,\n border-color,\n text-decoration-color,\n fill,\n stroke;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.slash-command-item:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.slash-command-item:hover:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\n}\n.slash-command-item.selected {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.slash-command-item.selected:is(.dark *) {\n --tw-bg-opacity: 1;\n background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));\n}\n.slash-command-item svg {\n height: 1rem;\n width: 1rem;\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.slash-command-item svg:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.slash-command-item > div {\n flex: 1 1 0%;\n}\n.slash-command-item .command-name {\n font-size: 0.875rem;\n line-height: 1.25rem;\n font-weight: 500;\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.slash-command-item .command-name:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(243 244 246 / var(--tw-text-opacity, 1));\n}\n.slash-command-item .command-description {\n margin-top: 0.125rem;\n font-size: 0.75rem;\n line-height: 1rem;\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.slash-command-item .command-description:is(.dark *) {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.dark .slash-commands-menu {\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3), 0 4px 6px -2px rgba(0, 0, 0, 0.2);\n}\n");
49915
50237
 
@@ -49917,56 +50239,29 @@ styleInject(".slash-commands-menu {\n border-radius: var(--radius);\n border-w
49917
50239
  styleInject('.ProseMirror table {\n border-collapse: collapse;\n margin: 0;\n overflow: hidden;\n table-layout: fixed;\n width: 100%;\n border: 1px solid #d1d5db;\n}\n.ProseMirror table td,\n.ProseMirror table th {\n border: 1px solid #d1d5db;\n box-sizing: border-box;\n min-width: 1em;\n padding: 6px 8px;\n position: relative;\n vertical-align: top;\n}\n.ProseMirror table th {\n background-color: #f9fafb;\n font-weight: 600;\n text-align: left;\n}\n.ProseMirror table .selectedCell:after {\n background-color: rgba(59, 130, 246, 0.1);\n content: "";\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n pointer-events: none;\n position: absolute;\n z-index: 2;\n}\n.ProseMirror table .column-resize-handle {\n background-color: #3b82f6;\n bottom: -2px;\n position: absolute;\n right: -2px;\n top: 0;\n width: 4px;\n pointer-events: none;\n}\n.dark .ProseMirror table {\n border: 1px solid #374151;\n}\n.dark .ProseMirror table td,\n.dark .ProseMirror table th {\n border: 1px solid #374151;\n}\n.dark .ProseMirror table th {\n background-color: #111827;\n}\n.dark .ProseMirror table .selectedCell:after {\n background-color: rgba(59, 130, 246, 0.2);\n}\n');
49918
50240
  var lowlight = createLowlight(grammars);
49919
50241
  var getAIProvider = (settings) => {
49920
- const generateWithPrompt = async (systemPrompt, userText) => {
49921
- const result = `[${systemPrompt}] ${userText}`;
49922
- return { text: result, error: void 0 };
49923
- };
49924
- return {
49925
- generateText: async (prompt) => {
49926
- const result = await generateWithPrompt("Generate text", prompt);
49927
- return result.text;
49928
- },
49929
- rewrite: async (text) => {
49930
- const result = await generateWithPrompt("Rewrite this text", text);
49931
- return result;
49932
- },
49933
- expand: async (text) => {
49934
- const result = await generateWithPrompt("Expand this text", text);
49935
- return result;
49936
- },
49937
- summarize: async (text) => {
49938
- const result = await generateWithPrompt("Summarize this text", text);
49939
- return result;
49940
- },
49941
- fixGrammar: async (text) => {
49942
- const result = await generateWithPrompt("Fix grammar and spelling", text);
49943
- return result;
49944
- },
49945
- translate: async (text, targetLang) => {
49946
- const result = await generateWithPrompt(`Translate to ${targetLang}`, text);
49947
- return result;
49948
- },
49949
- changeTone: async (text, tone) => {
49950
- const result = await generateWithPrompt(`Change tone to ${tone}`, text);
49951
- return result;
49952
- },
49953
- continueWriting: async (text) => {
49954
- const result = await generateWithPrompt("Continue writing", text);
49955
- return result;
49956
- },
49957
- improveWriting: async (text) => {
49958
- const result = await generateWithPrompt("Improve writing quality", text);
49959
- return result;
49960
- },
49961
- generateIdeas: async (text) => {
49962
- const result = await generateWithPrompt("Generate writing ideas", text);
49963
- return result;
49964
- },
49965
- complete: async (text) => {
49966
- const result = await generateWithPrompt("Complete this text", text);
49967
- return result;
49968
- }
49969
- };
50242
+ if (!settings.apiKey)
50243
+ return null;
50244
+ try {
50245
+ const providerMap = {
50246
+ "openai": "openai",
50247
+ "gemini": "gemini",
50248
+ "claude": "claude",
50249
+ "anthropic": "claude",
50250
+ // Map anthropic to claude
50251
+ "cohere": "openai"
50252
+ // Use OpenAI as fallback for unsupported providers
50253
+ };
50254
+ const mappedProvider = providerMap[settings.provider] || "openai";
50255
+ return createAIProvider(mappedProvider, {
50256
+ apiKey: settings.apiKey,
50257
+ model: settings.model,
50258
+ temperature: settings.temperature,
50259
+ maxTokens: settings.maxTokens
50260
+ });
50261
+ } catch (error) {
50262
+ console.error("Failed to create AI provider:", error);
50263
+ return null;
50264
+ }
49970
50265
  };
49971
50266
  var EditorColorPicker = ({
49972
50267
  onColorSelect,
@@ -50071,10 +50366,11 @@ function RichTextEditor({
50071
50366
  aiConfig = {
50072
50367
  provider: "openai",
50073
50368
  apiKey: "",
50074
- model: "gpt-4",
50369
+ model: "gpt-3.5-turbo",
50075
50370
  temperature: 0.7,
50076
50371
  maxTokens: 1e3
50077
- }
50372
+ },
50373
+ persistAISettings = true
50078
50374
  }) {
50079
50375
  const { hasProAccess, isLoading } = useSubscription();
50080
50376
  if (!isLoading && !hasProAccess) {
@@ -50090,12 +50386,31 @@ function RichTextEditor({
50090
50386
  ] })
50091
50387
  ] }) }) });
50092
50388
  }
50093
- const [aiSettings, setAiSettings] = useState({
50094
- provider: aiConfig.provider || "openai",
50095
- apiKey: aiConfig.apiKey || "",
50096
- model: aiConfig.model || "gpt-4",
50097
- temperature: aiConfig.temperature || 0.7,
50098
- maxTokens: aiConfig.maxTokens || 1e3
50389
+ const [aiSettings, setAiSettings] = useState(() => {
50390
+ if (persistAISettings) {
50391
+ try {
50392
+ const stored = localStorage.getItem("moonui-ai-settings");
50393
+ if (stored) {
50394
+ const parsed = JSON.parse(stored);
50395
+ return {
50396
+ provider: aiConfig.provider || parsed.provider || "openai",
50397
+ apiKey: aiConfig.apiKey || parsed.apiKey || "",
50398
+ model: aiConfig.model || parsed.model || "gpt-3.5-turbo",
50399
+ temperature: aiConfig.temperature ?? parsed.temperature ?? 0.7,
50400
+ maxTokens: aiConfig.maxTokens ?? parsed.maxTokens ?? 1e3
50401
+ };
50402
+ }
50403
+ } catch (e) {
50404
+ console.error("Failed to load AI settings from localStorage:", e);
50405
+ }
50406
+ }
50407
+ return {
50408
+ provider: aiConfig.provider || "openai",
50409
+ apiKey: aiConfig.apiKey || "",
50410
+ model: aiConfig.model || "gpt-3.5-turbo",
50411
+ temperature: aiConfig.temperature ?? 0.7,
50412
+ maxTokens: aiConfig.maxTokens ?? 1e3
50413
+ };
50099
50414
  });
50100
50415
  const [isAiSettingsOpen, setIsAiSettingsOpen] = useState(false);
50101
50416
  const [isProcessing, setIsProcessing] = useState(false);
@@ -50304,6 +50619,9 @@ function RichTextEditor({
50304
50619
  setIsProcessing(true);
50305
50620
  try {
50306
50621
  const provider = getAIProvider(aiSettings);
50622
+ if (!provider) {
50623
+ throw new Error("Failed to initialize AI provider");
50624
+ }
50307
50625
  let response;
50308
50626
  switch (action) {
50309
50627
  case "rewrite":
@@ -50345,19 +50663,11 @@ function RichTextEditor({
50345
50663
  default:
50346
50664
  response = await provider.complete(text);
50347
50665
  }
50348
- if (response.error) {
50349
- toast({
50350
- title: "AI Error",
50351
- description: response.error,
50352
- variant: "destructive"
50353
- });
50354
- return null;
50355
- }
50356
- return response.text;
50357
- } catch {
50666
+ return response;
50667
+ } catch (error) {
50358
50668
  toast({
50359
50669
  title: "AI Error",
50360
- description: "Failed to process with AI. Please check your settings.",
50670
+ description: error instanceof Error ? error.message : "Failed to process with AI",
50361
50671
  variant: "destructive"
50362
50672
  });
50363
50673
  return null;
@@ -50378,15 +50688,44 @@ function RichTextEditor({
50378
50688
  });
50379
50689
  return;
50380
50690
  }
50691
+ const processingToast = toast({
50692
+ title: "Processing with AI...",
50693
+ description: getActionDescription(action),
50694
+ duration: 6e4
50695
+ // Long duration
50696
+ });
50381
50697
  const result = await callAI(action, selectedText || editor.getText());
50698
+ processingToast.dismiss();
50382
50699
  if (result) {
50383
50700
  if (selectedText) {
50384
50701
  editor.chain().focus().deleteSelection().insertContent(result).run();
50385
50702
  } else {
50386
50703
  editor.chain().focus().insertContent(result).run();
50387
50704
  }
50705
+ toast({
50706
+ title: "AI action completed",
50707
+ description: "Your text has been updated successfully."
50708
+ });
50388
50709
  }
50389
50710
  };
50711
+ const getActionDescription = (action) => {
50712
+ const descriptions = {
50713
+ rewrite: "Rewriting your text...",
50714
+ improve: "Improving your writing...",
50715
+ expand: "Expanding your text...",
50716
+ summarize: "Creating a summary...",
50717
+ fix: "Fixing grammar and spelling...",
50718
+ translate: "Translating to Turkish...",
50719
+ tone_professional: "Making text professional...",
50720
+ tone_casual: "Making text casual...",
50721
+ tone_friendly: "Making text friendly...",
50722
+ tone_formal: "Making text formal...",
50723
+ continue: "Continuing your writing...",
50724
+ ideas: "Generating ideas...",
50725
+ complete: "Completing your text..."
50726
+ };
50727
+ return descriptions[action] || "Processing...";
50728
+ };
50390
50729
  const [linkUrl, setLinkUrl] = useState("");
50391
50730
  const [imageUrl, setImageUrl] = useState("");
50392
50731
  const [isLinkDialogOpen, setIsLinkDialogOpen] = useState(false);
@@ -50905,7 +51244,7 @@ function RichTextEditor({
50905
51244
  {
50906
51245
  variant: "ghost",
50907
51246
  size: "sm",
50908
- className: "h-8 px-3 bg-purple-100 hover:bg-purple-200 dark:bg-purple-900 dark:hover:bg-purple-800",
51247
+ className: "h-8 px-3 bg-purple-100 hover:bg-purple-200 dark:bg-purple-900 dark:hover:bg-purple-800 transition-colors",
50909
51248
  disabled: isProcessing,
50910
51249
  children: [
50911
51250
  isProcessing ? /* @__PURE__ */ jsx(RefreshCw, { className: "w-4 h-4 mr-1 animate-spin" }) : /* @__PURE__ */ jsx(Wand2, { className: "w-4 h-4 mr-1" }),
@@ -50913,57 +51252,172 @@ function RichTextEditor({
50913
51252
  ]
50914
51253
  }
50915
51254
  ) }),
50916
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuContentPro, { className: "w-56", children: [
50917
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("rewrite"), children: [
50918
- /* @__PURE__ */ jsx(RefreshCw, { className: "w-4 h-4 mr-2" }),
50919
- "Rewrite Selection"
50920
- ] }),
50921
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("improve"), children: [
50922
- /* @__PURE__ */ jsx(Wand2, { className: "w-4 h-4 mr-2" }),
50923
- "Improve Writing"
50924
- ] }),
50925
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("expand"), children: [
50926
- /* @__PURE__ */ jsx(Maximize, { className: "w-4 h-4 mr-2" }),
50927
- "Expand Text"
50928
- ] }),
50929
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("summarize"), children: [
50930
- /* @__PURE__ */ jsx(FileText, { className: "w-4 h-4 mr-2" }),
50931
- "Summarize"
50932
- ] }),
50933
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("continue"), children: [
50934
- /* @__PURE__ */ jsx(Plus, { className: "w-4 h-4 mr-2" }),
50935
- "Continue Writing"
50936
- ] }),
50937
- /* @__PURE__ */ jsx(MoonUIDropdownMenuSeparatorPro, {}),
50938
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("fix"), children: [
50939
- /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 mr-2" }),
50940
- "Fix Grammar & Spelling"
51255
+ /* @__PURE__ */ jsxs(MoonUIDropdownMenuContentPro, { className: "w-64", children: [
51256
+ /* @__PURE__ */ jsxs("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground flex items-center gap-2", children: [
51257
+ /* @__PURE__ */ jsx(Wand2, { className: "w-3 h-3" }),
51258
+ "Writing Improvements"
50941
51259
  ] }),
51260
+ /* @__PURE__ */ jsxs(
51261
+ MoonUIDropdownMenuItemPro,
51262
+ {
51263
+ onClick: () => handleAIAction("rewrite"),
51264
+ disabled: isProcessing,
51265
+ children: [
51266
+ /* @__PURE__ */ jsx(RefreshCw, { className: "w-4 h-4 mr-2" }),
51267
+ "Rewrite Selection",
51268
+ /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs text-muted-foreground", children: "Alt+R" })
51269
+ ]
51270
+ }
51271
+ ),
51272
+ /* @__PURE__ */ jsxs(
51273
+ MoonUIDropdownMenuItemPro,
51274
+ {
51275
+ onClick: () => handleAIAction("improve"),
51276
+ disabled: isProcessing,
51277
+ children: [
51278
+ /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 mr-2" }),
51279
+ "Improve Writing"
51280
+ ]
51281
+ }
51282
+ ),
51283
+ /* @__PURE__ */ jsxs(
51284
+ MoonUIDropdownMenuItemPro,
51285
+ {
51286
+ onClick: () => handleAIAction("expand"),
51287
+ disabled: isProcessing,
51288
+ children: [
51289
+ /* @__PURE__ */ jsx(Maximize, { className: "w-4 h-4 mr-2" }),
51290
+ "Expand Text"
51291
+ ]
51292
+ }
51293
+ ),
51294
+ /* @__PURE__ */ jsxs(
51295
+ MoonUIDropdownMenuItemPro,
51296
+ {
51297
+ onClick: () => handleAIAction("summarize"),
51298
+ disabled: isProcessing,
51299
+ children: [
51300
+ /* @__PURE__ */ jsx(FileText, { className: "w-4 h-4 mr-2" }),
51301
+ "Summarize"
51302
+ ]
51303
+ }
51304
+ ),
51305
+ /* @__PURE__ */ jsxs(
51306
+ MoonUIDropdownMenuItemPro,
51307
+ {
51308
+ onClick: () => handleAIAction("continue"),
51309
+ disabled: isProcessing,
51310
+ children: [
51311
+ /* @__PURE__ */ jsx(Plus, { className: "w-4 h-4 mr-2" }),
51312
+ "Continue Writing"
51313
+ ]
51314
+ }
51315
+ ),
50942
51316
  /* @__PURE__ */ jsx(MoonUIDropdownMenuSeparatorPro, {}),
50943
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("tone_professional"), children: [
50944
- /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 mr-2" }),
50945
- "Make Professional"
50946
- ] }),
50947
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("tone_casual"), children: [
50948
- /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 mr-2" }),
50949
- "Make Casual"
50950
- ] }),
50951
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("tone_friendly"), children: [
50952
- /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 mr-2" }),
50953
- "Make Friendly"
50954
- ] }),
50955
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("tone_formal"), children: [
50956
- /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 mr-2" }),
50957
- "Make Formal"
51317
+ /* @__PURE__ */ jsxs("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground flex items-center gap-2", children: [
51318
+ /* @__PURE__ */ jsx(Palette, { className: "w-3 h-3" }),
51319
+ "Tone Adjustments"
50958
51320
  ] }),
51321
+ /* @__PURE__ */ jsxs(
51322
+ MoonUIDropdownMenuItemPro,
51323
+ {
51324
+ onClick: () => handleAIAction("tone_professional"),
51325
+ disabled: isProcessing,
51326
+ children: [
51327
+ /* @__PURE__ */ jsx(Briefcase, { className: "w-4 h-4 mr-2" }),
51328
+ "Make Professional"
51329
+ ]
51330
+ }
51331
+ ),
51332
+ /* @__PURE__ */ jsxs(
51333
+ MoonUIDropdownMenuItemPro,
51334
+ {
51335
+ onClick: () => handleAIAction("tone_casual"),
51336
+ disabled: isProcessing,
51337
+ children: [
51338
+ /* @__PURE__ */ jsx(MessageSquare, { className: "w-4 h-4 mr-2" }),
51339
+ "Make Casual"
51340
+ ]
51341
+ }
51342
+ ),
51343
+ /* @__PURE__ */ jsxs(
51344
+ MoonUIDropdownMenuItemPro,
51345
+ {
51346
+ onClick: () => handleAIAction("tone_friendly"),
51347
+ disabled: isProcessing,
51348
+ children: [
51349
+ /* @__PURE__ */ jsx(Heart, { className: "w-4 h-4 mr-2" }),
51350
+ "Make Friendly"
51351
+ ]
51352
+ }
51353
+ ),
51354
+ /* @__PURE__ */ jsxs(
51355
+ MoonUIDropdownMenuItemPro,
51356
+ {
51357
+ onClick: () => handleAIAction("tone_formal"),
51358
+ disabled: isProcessing,
51359
+ children: [
51360
+ /* @__PURE__ */ jsx(GraduationCap, { className: "w-4 h-4 mr-2" }),
51361
+ "Make Formal"
51362
+ ]
51363
+ }
51364
+ ),
50959
51365
  /* @__PURE__ */ jsx(MoonUIDropdownMenuSeparatorPro, {}),
50960
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("translate"), children: [
50961
- /* @__PURE__ */ jsx(Languages, { className: "w-4 h-4 mr-2" }),
50962
- "Translate to Turkish"
51366
+ /* @__PURE__ */ jsxs("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground flex items-center gap-2", children: [
51367
+ /* @__PURE__ */ jsx(Zap, { className: "w-3 h-3" }),
51368
+ "Other Actions"
50963
51369
  ] }),
50964
- /* @__PURE__ */ jsxs(MoonUIDropdownMenuItemPro, { onClick: () => handleAIAction("ideas"), children: [
50965
- /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 mr-2" }),
50966
- "Generate Ideas"
51370
+ /* @__PURE__ */ jsxs(
51371
+ MoonUIDropdownMenuItemPro,
51372
+ {
51373
+ onClick: () => handleAIAction("fix"),
51374
+ disabled: isProcessing,
51375
+ children: [
51376
+ /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 mr-2" }),
51377
+ "Fix Grammar & Spelling",
51378
+ /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs text-muted-foreground", children: "F7" })
51379
+ ]
51380
+ }
51381
+ ),
51382
+ /* @__PURE__ */ jsxs(
51383
+ MoonUIDropdownMenuItemPro,
51384
+ {
51385
+ onClick: () => handleAIAction("translate"),
51386
+ disabled: isProcessing,
51387
+ children: [
51388
+ /* @__PURE__ */ jsx(Languages, { className: "w-4 h-4 mr-2" }),
51389
+ "Translate to Turkish"
51390
+ ]
51391
+ }
51392
+ ),
51393
+ /* @__PURE__ */ jsxs(
51394
+ MoonUIDropdownMenuItemPro,
51395
+ {
51396
+ onClick: () => handleAIAction("ideas"),
51397
+ disabled: isProcessing,
51398
+ children: [
51399
+ /* @__PURE__ */ jsx(Lightbulb, { className: "w-4 h-4 mr-2" }),
51400
+ "Generate Ideas"
51401
+ ]
51402
+ }
51403
+ ),
51404
+ !aiSettings.apiKey && /* @__PURE__ */ jsxs(Fragment, { children: [
51405
+ /* @__PURE__ */ jsx(MoonUIDropdownMenuSeparatorPro, {}),
51406
+ /* @__PURE__ */ jsx("div", { className: "px-2 py-2", children: /* @__PURE__ */ jsx(
51407
+ motion.div,
51408
+ {
51409
+ initial: { opacity: 0, y: -10 },
51410
+ animate: { opacity: 1, y: 0 },
51411
+ className: "text-xs text-muted-foreground bg-yellow-100 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-md p-3",
51412
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
51413
+ /* @__PURE__ */ jsx(Settings, { className: "w-3 h-3 mt-0.5 text-yellow-600 dark:text-yellow-400" }),
51414
+ /* @__PURE__ */ jsxs("div", { children: [
51415
+ /* @__PURE__ */ jsx("div", { className: "font-medium text-yellow-900 dark:text-yellow-200 mb-1", children: "API Key Required" }),
51416
+ /* @__PURE__ */ jsx("div", { className: "text-yellow-800 dark:text-yellow-300", children: "Click the settings icon to configure your AI provider and API key." })
51417
+ ] })
51418
+ ] })
51419
+ }
51420
+ ) })
50967
51421
  ] })
50968
51422
  ] })
50969
51423
  ] }),
@@ -50989,7 +51443,19 @@ function RichTextEditor({
50989
51443
  MoonUISelectPro,
50990
51444
  {
50991
51445
  value: aiSettings.provider,
50992
- onValueChange: (value) => setAiSettings({ ...aiSettings, provider: value }),
51446
+ onValueChange: (value) => {
51447
+ const defaultModels = {
51448
+ openai: "gpt-3.5-turbo",
51449
+ claude: "claude-3-sonnet-20240229",
51450
+ gemini: "gemini-2.0-flash",
51451
+ cohere: "command"
51452
+ };
51453
+ setAiSettings({
51454
+ ...aiSettings,
51455
+ provider: value,
51456
+ model: defaultModels[value] || "gpt-3.5-turbo"
51457
+ });
51458
+ },
50993
51459
  children: [
50994
51460
  /* @__PURE__ */ jsx(MoonUISelectTriggerPro, { children: /* @__PURE__ */ jsx(MoonUISelectValuePro, {}) }),
50995
51461
  /* @__PURE__ */ jsxs(MoonUISelectContentPro, { children: [
@@ -51035,8 +51501,9 @@ function RichTextEditor({
51035
51501
  /* @__PURE__ */ jsx(MoonUISelectItemPro, { value: "claude-3-haiku", children: "Claude 3 Haiku" })
51036
51502
  ] }),
51037
51503
  aiSettings.provider === "gemini" && /* @__PURE__ */ jsxs(Fragment, { children: [
51038
- /* @__PURE__ */ jsx(MoonUISelectItemPro, { value: "gemini-pro", children: "Gemini Pro" }),
51039
- /* @__PURE__ */ jsx(MoonUISelectItemPro, { value: "gemini-pro-vision", children: "Gemini Pro Vision" })
51504
+ /* @__PURE__ */ jsx(MoonUISelectItemPro, { value: "gemini-2.0-flash", children: "Gemini 2.0 Flash" }),
51505
+ /* @__PURE__ */ jsx(MoonUISelectItemPro, { value: "gemini-1.5-flash", children: "Gemini 1.5 Flash" }),
51506
+ /* @__PURE__ */ jsx(MoonUISelectItemPro, { value: "gemini-1.5-pro", children: "Gemini 1.5 Pro" })
51040
51507
  ] }),
51041
51508
  aiSettings.provider === "cohere" && /* @__PURE__ */ jsxs(Fragment, { children: [
51042
51509
  /* @__PURE__ */ jsx(MoonUISelectItemPro, { value: "command", children: "Command" }),
@@ -51079,13 +51546,61 @@ function RichTextEditor({
51079
51546
  ] })
51080
51547
  ] })
51081
51548
  ] }),
51082
- /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(MoonUIButtonPro, { onClick: () => {
51083
- setIsAiSettingsOpen(false);
51084
- toast({
51085
- title: "Settings saved",
51086
- description: "Your AI settings have been updated."
51087
- });
51088
- }, children: "Save Settings" }) })
51549
+ persistAISettings && /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
51550
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-2", children: [
51551
+ /* @__PURE__ */ jsx(
51552
+ MoonUICheckboxPro,
51553
+ {
51554
+ id: "rememberSettings",
51555
+ defaultChecked: true,
51556
+ onCheckedChange: (checked) => {
51557
+ if (!checked) {
51558
+ localStorage.removeItem("moonui-ai-settings");
51559
+ }
51560
+ }
51561
+ }
51562
+ ),
51563
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-1.5 leading-none", children: [
51564
+ /* @__PURE__ */ jsx(
51565
+ MoonUILabelPro,
51566
+ {
51567
+ htmlFor: "rememberSettings",
51568
+ className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
51569
+ children: "Remember my settings"
51570
+ }
51571
+ ),
51572
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Save settings locally for future sessions" })
51573
+ ] })
51574
+ ] }),
51575
+ aiSettings.apiKey && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-yellow-50 dark:bg-yellow-900/10 p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex", children: [
51576
+ /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4 text-yellow-400" }) }),
51577
+ /* @__PURE__ */ jsx("div", { className: "ml-3", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-yellow-800 dark:text-yellow-200", children: [
51578
+ /* @__PURE__ */ jsx("strong", { children: "Security Notice:" }),
51579
+ " API keys will be stored in your browser's local storage. For production use, consider using a server-side proxy."
51580
+ ] }) })
51581
+ ] }) })
51582
+ ] }),
51583
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
51584
+ /* @__PURE__ */ jsx(
51585
+ MoonUIButtonPro,
51586
+ {
51587
+ variant: "outline",
51588
+ onClick: () => setIsAiSettingsOpen(false),
51589
+ children: "Cancel"
51590
+ }
51591
+ ),
51592
+ /* @__PURE__ */ jsx(MoonUIButtonPro, { onClick: () => {
51593
+ if (persistAISettings) {
51594
+ const toStore = { ...aiSettings };
51595
+ localStorage.setItem("moonui-ai-settings", JSON.stringify(toStore));
51596
+ }
51597
+ setIsAiSettingsOpen(false);
51598
+ toast({
51599
+ title: "Settings saved",
51600
+ description: "Your AI settings have been updated."
51601
+ });
51602
+ }, children: "Save Settings" })
51603
+ ] })
51089
51604
  ] })
51090
51605
  ] })
51091
51606
  ] })
@@ -61148,7 +61663,7 @@ var MoonUIPhoneNumberInputPro = t__default.forwardRef(({
61148
61663
  onPaste: handlePaste2,
61149
61664
  onFocus: () => setIsFocused(true),
61150
61665
  onBlur: () => setIsFocused(false),
61151
- placeholder: selectedCountry.format.replace(/x/g, "\u2022"),
61666
+ placeholder: selectedCountry?.format?.replace(/x/g, "\u2022") || "Enter phone number",
61152
61667
  className: cn(
61153
61668
  "pr-10",
61154
61669
  error && "border-destructive",