@lastbrain/ai-ui-react 1.0.9 → 1.0.11

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.
@@ -1 +1 @@
1
- {"version":3,"file":"AiImageButton.d.ts","sourceRoot":"","sources":["../../src/components/AiImageButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAK5C,MAAM,WAAW,kBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,oBAAoB,CAAC,iBAAiB,CAAC;IACzC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,GAAG,WAAW,EACf,EAAE,kBAAkB,2CAyDpB"}
1
+ {"version":3,"file":"AiImageButton.d.ts","sourceRoot":"","sources":["../../src/components/AiImageButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAM5C,MAAM,WAAW,kBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,oBAAoB,CAAC,iBAAiB,CAAC;IACzC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,GAAG,WAAW,EACf,EAAE,kBAAkB,2CAmEpB"}
@@ -1,11 +1,13 @@
1
1
  "use client";
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { useAiCallImage } from "../hooks/useAiCallImage";
5
5
  import { useAiModels } from "../hooks/useAiModels";
6
6
  import { AiPromptPanel } from "./AiPromptPanel";
7
+ import { UsageToast, useUsageToast } from "./UsageToast";
7
8
  export function AiImageButton({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, onImage, onToast, disabled, className, children, ...buttonProps }) {
8
9
  const [isOpen, setIsOpen] = useState(false);
10
+ const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
9
11
  const { models } = useAiModels({ baseUrl, apiKeyId });
10
12
  const { generateImage, loading } = useAiCallImage({ baseUrl, apiKeyId });
11
13
  const handleOpenPanel = () => {
@@ -23,6 +25,7 @@ export function AiImageButton({ baseUrl, apiKeyId, uiMode = "modal", context, mo
23
25
  if (result.url) {
24
26
  onImage?.(result.url);
25
27
  onToast?.({ type: "success", message: "Image generated successfully" });
28
+ showUsageToast(result);
26
29
  }
27
30
  }
28
31
  catch (error) {
@@ -32,5 +35,5 @@ export function AiImageButton({ baseUrl, apiKeyId, uiMode = "modal", context, mo
32
35
  setIsOpen(false);
33
36
  }
34
37
  };
35
- return (_jsxs(_Fragment, { children: [_jsx("button", { ...buttonProps, onClick: handleOpenPanel, disabled: disabled || loading, className: className, "data-ai-image-button": true, children: loading ? "Generating..." : children || "Generate Image" }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: models?.filter((m) => m.type === "image") || [] }))] }));
38
+ return (_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ...buttonProps, onClick: handleOpenPanel, disabled: disabled || loading, className: className, "data-ai-image-button": true, children: loading ? "Generating..." : children || "Generate Image" }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: models?.filter((m) => m.type === "image") || [] })), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey))] }));
36
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AiInput.d.ts","sourceRoot":"","sources":["../../src/components/AiInput.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAoB,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAM5C,MAAM,WAAW,YACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,UAAU,EACd,EAAE,YAAY,2CAiKd"}
1
+ {"version":3,"file":"AiInput.d.ts","sourceRoot":"","sources":["../../src/components/AiInput.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAoB,KAAK,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAE1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAO5C,MAAM,WAAW,YACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,SAAS,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,UAAU,EACd,EAAE,YAAY,2CAsKd"}
@@ -1,9 +1,11 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useRef } from "react";
4
+ import { Sparkles } from "lucide-react";
4
5
  import { useAiCallText } from "../hooks/useAiCallText";
5
6
  import { useAiModels } from "../hooks/useAiModels";
6
7
  import { AiPromptPanel } from "./AiPromptPanel";
8
+ import { UsageToast, useUsageToast } from "./UsageToast";
7
9
  import { aiStyles } from "../styles/inline";
8
10
  export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, editMode = false, onValue, onToast, disabled, className, ...inputProps }) {
9
11
  const [isOpen, setIsOpen] = useState(false);
@@ -11,6 +13,7 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
11
13
  const [isFocused, setIsFocused] = useState(false);
12
14
  const [isButtonHovered, setIsButtonHovered] = useState(false);
13
15
  const inputRef = useRef(null);
16
+ const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
14
17
  const { models } = useAiModels({ baseUrl, apiKeyId });
15
18
  const { generateText, loading } = useAiCallText({ baseUrl, apiKeyId });
16
19
  const hasConfiguration = Boolean(model && prompt);
@@ -20,13 +23,18 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
20
23
  const handleClosePanel = () => {
21
24
  setIsOpen(false);
22
25
  };
23
- const handleSubmit = async (selectedModel, selectedPrompt) => {
26
+ const handleSubmit = async (selectedModel, selectedPrompt, promptId) => {
24
27
  try {
28
+ const resolvedContext = inputValue || context || undefined;
29
+ const hasContext = Boolean(resolvedContext && String(resolvedContext).trim());
30
+ const promptWithContext = hasContext
31
+ ? `${selectedPrompt}\n\nTexte:\n${String(resolvedContext)}`
32
+ : selectedPrompt;
25
33
  const result = await generateText({
26
34
  model: selectedModel,
27
- prompt: selectedPrompt,
28
- context: inputValue || context || undefined,
29
- actionType: "autocomplete",
35
+ prompt: promptWithContext,
36
+ context: resolvedContext,
37
+ actionType: hasContext ? "generate-text" : "autocomplete",
30
38
  });
31
39
  if (result.text) {
32
40
  setInputValue(result.text);
@@ -48,11 +56,16 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
48
56
  if (!model || !prompt)
49
57
  return;
50
58
  try {
59
+ const resolvedContext = inputValue || context || undefined;
60
+ const hasContext = Boolean(resolvedContext && String(resolvedContext).trim());
61
+ const promptWithContext = hasContext
62
+ ? `${prompt}\n\nTexte:\n${String(resolvedContext)}`
63
+ : prompt;
51
64
  const result = await generateText({
52
65
  model,
53
- prompt,
54
- context: inputValue || context || undefined,
55
- actionType: "autocomplete",
66
+ prompt: promptWithContext,
67
+ context: resolvedContext,
68
+ actionType: hasContext ? "generate-text" : "autocomplete",
56
69
  });
57
70
  if (result.text) {
58
71
  setInputValue(result.text);
@@ -87,5 +100,5 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
87
100
  ...(disabled || loading
88
101
  ? { opacity: 0.5, cursor: "not-allowed" }
89
102
  : {}),
90
- }, onClick: hasConfiguration ? handleQuickGenerate : handleOpenPanel, onMouseEnter: () => setIsButtonHovered(true), onMouseLeave: () => setIsButtonHovered(false), disabled: disabled || loading, type: "button", title: hasConfiguration ? "Generate with AI" : "Setup AI", children: loading ? (_jsx("svg", { style: aiStyles.spinner, width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83" }) })) : hasConfiguration ? (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M12 5v14M5 12h14" }) })) : (_jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" }) })) }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: models || [] }))] }));
103
+ }, onClick: hasConfiguration ? handleQuickGenerate : handleOpenPanel, onMouseEnter: () => setIsButtonHovered(true), onMouseLeave: () => setIsButtonHovered(false), disabled: disabled || loading, type: "button", title: hasConfiguration ? "Generate with AI" : "Setup AI", children: loading ? (_jsx("svg", { style: aiStyles.spinner, width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("path", { d: "M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83" }) })) : (_jsx(Sparkles, { size: 16 })) }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: models || [], sourceText: inputValue || undefined })), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey))] }));
91
104
  }
@@ -4,9 +4,10 @@ import type { UiMode } from "../types";
4
4
  export interface AiPromptPanelProps {
5
5
  isOpen: boolean;
6
6
  onClose: () => void;
7
- onSubmit: (model: string, prompt: string) => void;
7
+ onSubmit: (model: string, prompt: string, promptId?: string) => void;
8
8
  uiMode?: UiMode;
9
9
  models?: ModelRef[];
10
+ sourceText?: string;
10
11
  children?: (props: AiPromptPanelRenderProps) => ReactNode;
11
12
  }
12
13
  export interface AiPromptPanelRenderProps {
@@ -15,8 +16,9 @@ export interface AiPromptPanelRenderProps {
15
16
  setSelectedModel: (model: string) => void;
16
17
  prompt: string;
17
18
  setPrompt: (prompt: string) => void;
19
+ sourceText?: string;
18
20
  handleSubmit: () => void;
19
21
  handleClose: () => void;
20
22
  }
21
- export declare function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode, models, children, }: AiPromptPanelProps): import("react/jsx-runtime").JSX.Element | null;
23
+ export declare function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode: _uiMode, models, sourceText, children, }: AiPromptPanelProps): import("react/jsx-runtime").JSX.Element | null;
22
24
  //# sourceMappingURL=AiPromptPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AiPromptPanel.d.ts","sourceRoot":"","sources":["../../src/components/AiPromptPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,SAAS,CAAC;CAC3D;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,MAAW,EACX,QAAQ,GACT,EAAE,kBAAkB,kDA4JpB"}
1
+ {"version":3,"file":"AiPromptPanel.d.ts","sourceRoot":"","sources":["../../src/components/AiPromptPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAQvC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,SAAS,CAAC;CAC3D;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,OAAO,EACP,QAAQ,EACR,MAAM,EAAE,OAAiB,EACzB,MAAW,EACX,UAAU,EACV,QAAQ,GACT,EAAE,kBAAkB,kDA0sBpB"}
@@ -1,32 +1,76 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useState, useEffect } from "react";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useEffect, useRef, useLayoutEffect, } from "react";
4
+ import { BookOpen, Search, Sparkles, Star, Tag } from "lucide-react";
4
5
  import { aiStyles } from "../styles/inline";
5
- export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", models = [], children, }) {
6
- const [selectedModel, setSelectedModel] = useState(models[0]?.id || "");
6
+ import { usePrompts, } from "../hooks/usePrompts";
7
+ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode: _uiMode = "modal", models = [], sourceText, children, }) {
8
+ const [selectedModel, setSelectedModel] = useState("");
7
9
  const [prompt, setPrompt] = useState("");
10
+ const [promptId, setPromptId] = useState(undefined);
8
11
  const [isCloseHovered, setIsCloseHovered] = useState(false);
9
12
  const [isCancelHovered, setIsCancelHovered] = useState(false);
10
13
  const [isSubmitHovered, setIsSubmitHovered] = useState(false);
11
14
  const [promptFocused, setPromptFocused] = useState(false);
12
15
  const [modelFocused, setModelFocused] = useState(false);
16
+ const [showPromptLibrary, setShowPromptLibrary] = useState(false);
17
+ const [searchQuery, setSearchQuery] = useState("");
18
+ const [selectedTag, setSelectedTag] = useState("all");
19
+ const [isGenerating, setIsGenerating] = useState(false);
20
+ const [isClosing, setIsClosing] = useState(false);
21
+ const promptRef = useRef(null);
22
+ const closeTimeoutRef = useRef(null);
23
+ const { prompts, loading: promptsLoading, fetchPrompts, incrementStat, } = usePrompts();
24
+ // Fetch prompts when modal opens
13
25
  useEffect(() => {
14
- if (models.length > 0 && !selectedModel) {
15
- setSelectedModel(models[0].id);
26
+ if (isOpen && models.length > 0) {
27
+ const activeModelId = selectedModel || models[0]?.id;
28
+ const modelType = models.find((m) => m.id === activeModelId)?.type;
29
+ fetchPrompts({
30
+ type: modelType === "image" ? "image" : "text",
31
+ });
16
32
  }
17
- }, [models, selectedModel]);
18
- if (!isOpen)
19
- return null;
20
- const handleSubmit = () => {
21
- if (!selectedModel || !prompt.trim())
33
+ }, [isOpen, selectedModel, models, fetchPrompts]);
34
+ const handleSubmit = async () => {
35
+ const activeModelId = selectedModel || models[0]?.id;
36
+ if (!activeModelId || !prompt.trim())
22
37
  return;
23
- onSubmit(selectedModel, prompt);
24
- setPrompt("");
38
+ setIsGenerating(true);
39
+ try {
40
+ await Promise.resolve(onSubmit(activeModelId, prompt, promptId));
41
+ setPrompt("");
42
+ setPromptId(undefined);
43
+ }
44
+ finally {
45
+ setIsGenerating(false);
46
+ handleClose();
47
+ }
25
48
  };
26
- const handleClose = () => {
49
+ const finalizeClose = () => {
27
50
  onClose();
28
51
  setPrompt("");
52
+ setPromptId(undefined);
53
+ setShowPromptLibrary(false);
54
+ setSearchQuery("");
55
+ setSelectedTag("all");
56
+ setIsClosing(false);
57
+ };
58
+ const handleClose = () => {
59
+ if (isClosing)
60
+ return;
61
+ setIsClosing(true);
62
+ if (closeTimeoutRef.current) {
63
+ window.clearTimeout(closeTimeoutRef.current);
64
+ }
65
+ closeTimeoutRef.current = window.setTimeout(finalizeClose, 220);
29
66
  };
67
+ useEffect(() => {
68
+ return () => {
69
+ if (closeTimeoutRef.current) {
70
+ window.clearTimeout(closeTimeoutRef.current);
71
+ }
72
+ };
73
+ }, []);
30
74
  const handleKeyDown = (e) => {
31
75
  if (e.key === "Escape") {
32
76
  handleClose();
@@ -35,35 +79,308 @@ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", mod
35
79
  handleSubmit();
36
80
  }
37
81
  };
82
+ const handleSelectPrompt = (promptData) => {
83
+ setPrompt(promptData.content);
84
+ setPromptId(promptData.id);
85
+ incrementStat(promptData.id, "picked");
86
+ if (promptData.model) {
87
+ setSelectedModel(promptData.model);
88
+ }
89
+ setShowPromptLibrary(false);
90
+ };
91
+ const adjustPromptHeight = () => {
92
+ const element = promptRef.current;
93
+ if (!element) {
94
+ return;
95
+ }
96
+ element.style.height = "auto";
97
+ element.style.height = `${element.scrollHeight}px`;
98
+ };
99
+ useLayoutEffect(() => {
100
+ adjustPromptHeight();
101
+ }, [prompt]);
102
+ if (!isOpen)
103
+ return null;
104
+ const activeModelId = selectedModel || models[0]?.id || "";
105
+ const currentModelType = models.find((m) => m.id === activeModelId)?.type;
106
+ const filteredPrompts = prompts.filter((p) => {
107
+ const matchesType = currentModelType === "image" ? p.type === "image" : p.type !== "image";
108
+ return matchesType;
109
+ });
110
+ const availableTags = Array.from(new Set(filteredPrompts.flatMap((p) => (Array.isArray(p.tags) ? p.tags : [])))).sort((a, b) => a.localeCompare(b));
111
+ const normalizedSearch = searchQuery.trim().toLowerCase();
112
+ const visiblePrompts = filteredPrompts
113
+ .filter((promptData) => {
114
+ if (!normalizedSearch) {
115
+ return true;
116
+ }
117
+ return (promptData.title.toLowerCase().includes(normalizedSearch) ||
118
+ promptData.content.toLowerCase().includes(normalizedSearch));
119
+ })
120
+ .filter((promptData) => {
121
+ if (selectedTag === "all") {
122
+ return true;
123
+ }
124
+ return promptData.tags?.includes(selectedTag);
125
+ })
126
+ .slice()
127
+ .sort((a, b) => Number(b.favorite) - Number(a.favorite));
128
+ const favoritePrompts = visiblePrompts.filter((promptData) => Boolean(promptData.favorite));
129
+ const nonFavoritePrompts = visiblePrompts.filter((promptData) => !promptData.favorite);
38
130
  const renderProps = {
39
131
  models,
40
- selectedModel,
132
+ selectedModel: activeModelId,
41
133
  setSelectedModel,
42
134
  prompt,
43
135
  setPrompt,
136
+ sourceText,
44
137
  handleSubmit,
45
138
  handleClose,
46
139
  };
47
140
  if (children) {
48
141
  return (_jsx("div", { style: aiStyles.modal, onKeyDown: handleKeyDown, children: children(renderProps) }));
49
142
  }
50
- return (_jsxs("div", { style: aiStyles.modal, onKeyDown: handleKeyDown, children: [_jsx("div", { style: aiStyles.modalOverlay, onClick: handleClose }), _jsxs("div", { style: aiStyles.modalContent, children: [_jsxs("div", { style: aiStyles.modalHeader, children: [_jsx("h2", { style: aiStyles.modalTitle, children: "AI Prompt Configuration" }), _jsx("button", { style: {
143
+ return (_jsxs("div", { style: aiStyles.modal, onKeyDown: handleKeyDown, children: [_jsx("div", { style: {
144
+ ...aiStyles.modalOverlay,
145
+ opacity: isClosing ? 0 : 1,
146
+ transition: "opacity 200ms ease",
147
+ }, onClick: handleClose }), _jsxs("div", { style: {
148
+ ...aiStyles.modalContent,
149
+ opacity: isClosing ? 0 : 1,
150
+ transform: isClosing ? "translateY(12px)" : "translateY(0)",
151
+ transition: "opacity 200ms ease, transform 200ms ease",
152
+ }, children: [isGenerating && (_jsxs("div", { style: {
153
+ position: "absolute",
154
+ inset: 0,
155
+ background: "var(--ai-bg-tertiary)",
156
+ backdropFilter: "blur(6px)",
157
+ WebkitBackdropFilter: "blur(6px)",
158
+ display: "flex",
159
+ alignItems: "center",
160
+ justifyContent: "center",
161
+ flexDirection: "column",
162
+ gap: "12px",
163
+ zIndex: 10,
164
+ borderRadius: "12px",
165
+ }, children: [_jsx("div", { style: {
166
+ width: "64px",
167
+ height: "64px",
168
+ borderRadius: "999px",
169
+ border: "2px solid #8b5cf620",
170
+ borderTopColor: "#8b5cf6",
171
+ animation: "ai-spin 1.1s linear infinite",
172
+ display: "flex",
173
+ alignItems: "center",
174
+ justifyContent: "center",
175
+ boxShadow: "0 12px 24px rgba(139, 92, 246, 0.15)",
176
+ }, children: _jsx(Sparkles, { size: 20, color: "#8b5cf6" }) }), _jsx("div", { style: {
177
+ fontSize: "13px",
178
+ fontWeight: 600,
179
+ color: "#6b7280",
180
+ letterSpacing: "0.02em",
181
+ }, children: "G\u00E9n\u00E9ration en cours\u2026" })] })), _jsxs("div", { style: aiStyles.modalHeader, children: [_jsx("h2", { style: aiStyles.modalTitle, children: showPromptLibrary ? "Select a Prompt" : "AI Prompt Configuration" }), _jsx("button", { style: {
51
182
  ...aiStyles.modalCloseButton,
52
183
  ...(isCloseHovered && aiStyles.modalCloseButtonHover),
53
- }, onClick: handleClose, onMouseEnter: () => setIsCloseHovered(true), onMouseLeave: () => setIsCloseHovered(false), "aria-label": "Close", children: "\u00D7" })] }), _jsxs("div", { style: aiStyles.modalBody, children: [_jsxs("div", { style: aiStyles.modalInputGroup, children: [_jsx("label", { htmlFor: "model-select", style: aiStyles.modalLabel, children: "AI Model" }), _jsxs("select", { id: "model-select", value: selectedModel, onChange: (e) => setSelectedModel(e.target.value), onFocus: () => setModelFocused(true), onBlur: () => setModelFocused(false), style: {
54
- ...aiStyles.select,
55
- ...(modelFocused && aiStyles.selectFocus),
56
- }, children: [models.length === 0 && (_jsx("option", { value: "", children: "No models available" })), models.map((model) => (_jsx("option", { value: model.id, children: model.name }, model.id)))] })] }), _jsxs("div", { style: aiStyles.modalInputGroup, children: [_jsxs("label", { htmlFor: "prompt-input", style: aiStyles.modalLabel, children: ["Prompt", _jsx("span", { style: { color: aiStyles.textareaFocus.borderColor, marginLeft: "4px" }, children: "(Cmd/Ctrl + Enter to submit)" })] }), _jsx("textarea", { id: "prompt-input", value: prompt, onChange: (e) => setPrompt(e.target.value), onFocus: () => setPromptFocused(true), onBlur: () => setPromptFocused(false), placeholder: "Enter your AI prompt... e.g., 'Correct spelling and grammar'", rows: 6, style: {
57
- ...aiStyles.textarea,
58
- padding: "12px 16px",
59
- ...(promptFocused && aiStyles.textareaFocus),
60
- } })] })] }), _jsxs("div", { style: aiStyles.modalFooter, children: [_jsx("button", { onClick: handleClose, onMouseEnter: () => setIsCancelHovered(true), onMouseLeave: () => setIsCancelHovered(false), style: {
184
+ }, onClick: handleClose, onMouseEnter: () => setIsCloseHovered(true), onMouseLeave: () => setIsCloseHovered(false), "aria-label": "Close", children: "\u00D7" })] }), _jsx("div", { style: aiStyles.modalBody, children: !showPromptLibrary ? (_jsxs(_Fragment, { children: [sourceText && (_jsxs("div", { style: {
185
+ ...aiStyles.modalInputGroup,
186
+ marginBottom: "16px",
187
+ }, children: [_jsx("label", { style: aiStyles.modalLabel, children: "Source Text" }), _jsx("div", { style: {
188
+ padding: "12px",
189
+ background: aiStyles.textarea.background,
190
+ border: `1px solid ${aiStyles.input.border}`,
191
+ borderRadius: "8px",
192
+ fontSize: "13px",
193
+ color: aiStyles.textarea.color,
194
+ maxHeight: "120px",
195
+ overflow: "auto",
196
+ whiteSpace: "pre-wrap",
197
+ wordBreak: "break-word",
198
+ }, children: sourceText })] })), _jsxs("div", { style: aiStyles.modalInputGroup, children: [_jsx("label", { htmlFor: "model-select", style: aiStyles.modalLabel, children: "AI Model" }), _jsxs("select", { id: "model-select", value: activeModelId, onChange: (e) => setSelectedModel(e.target.value), onFocus: () => setModelFocused(true), onBlur: () => setModelFocused(false), style: {
199
+ ...aiStyles.select,
200
+ ...(modelFocused && aiStyles.selectFocus),
201
+ }, children: [models.length === 0 && (_jsx("option", { value: "", children: "Loading models..." })), models.map((model) => (_jsx("option", { value: model.id, children: model.name }, model.id)))] })] }), _jsxs("div", { style: aiStyles.modalInputGroup, children: [_jsxs("div", { style: {
202
+ display: "flex",
203
+ justifyContent: "space-between",
204
+ alignItems: "center",
205
+ marginBottom: "8px",
206
+ }, children: [_jsxs("label", { htmlFor: "prompt-input", style: aiStyles.modalLabel, children: ["Prompt", _jsx("span", { style: {
207
+ color: "#6b7280",
208
+ marginLeft: "4px",
209
+ fontSize: "12px",
210
+ fontWeight: 400,
211
+ }, children: "(Cmd/Ctrl + Enter to submit)" })] }), filteredPrompts.length > 0 && (_jsxs("button", { onClick: () => setShowPromptLibrary(true), style: {
212
+ padding: "4px 12px",
213
+ fontSize: "12px",
214
+ color: "#8b5cf6",
215
+ background: "#8b5cf610",
216
+ border: "1px solid #8b5cf630",
217
+ borderRadius: "6px",
218
+ cursor: "pointer",
219
+ transition: "all 0.2s",
220
+ display: "flex",
221
+ alignItems: "center",
222
+ gap: "6px",
223
+ }, onMouseEnter: (e) => {
224
+ e.currentTarget.style.background = "#8b5cf620";
225
+ }, onMouseLeave: (e) => {
226
+ e.currentTarget.style.background = "#8b5cf610";
227
+ }, children: [_jsx(BookOpen, { size: 14 }), "Browse Prompts (", filteredPrompts.length, ")"] }))] }), _jsx("textarea", { id: "prompt-input", ref: promptRef, value: prompt, onChange: (e) => setPrompt(e.target.value), onFocus: () => setPromptFocused(true), onBlur: () => setPromptFocused(false), placeholder: sourceText
228
+ ? "Enter your AI prompt... e.g., 'Correct spelling and grammar', 'Make it more professional', 'Translate to English'"
229
+ : "Enter your AI prompt... e.g., 'Write a blog post about AI', 'Generate product description'", rows: 6, style: {
230
+ ...aiStyles.textarea,
231
+ padding: "12px 16px",
232
+ ...(promptFocused && aiStyles.textareaFocus),
233
+ } })] })] })) : (_jsxs("div", { children: [_jsx("button", { onClick: () => setShowPromptLibrary(false), style: {
234
+ padding: "8px 0",
235
+ fontSize: "14px",
236
+ color: "#8b5cf6",
237
+ background: "transparent",
238
+ border: "none",
239
+ cursor: "pointer",
240
+ marginBottom: "16px",
241
+ display: "flex",
242
+ alignItems: "center",
243
+ gap: "4px",
244
+ }, children: "\u2190 Back to form" }), _jsxs("div", { style: { marginBottom: "12px" }, children: [_jsxs("div", { style: {
245
+ ...aiStyles.inputWrapper,
246
+ marginBottom: "10px",
247
+ }, children: [_jsx(Search, { size: 16, style: {
248
+ position: "absolute",
249
+ left: "12px",
250
+ top: "50%",
251
+ transform: "translateY(-50%)",
252
+ color: aiStyles.tooltipLabel.color,
253
+ } }), _jsx("input", { value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), placeholder: "Search prompts...", style: {
254
+ ...aiStyles.input,
255
+ padding: "10px 12px 10px 36px",
256
+ } })] }), availableTags.length > 0 && (_jsxs("div", { style: {
257
+ display: "flex",
258
+ flexWrap: "wrap",
259
+ gap: "8px",
260
+ alignItems: "center",
261
+ }, children: [_jsxs("span", { style: {
262
+ display: "inline-flex",
263
+ alignItems: "center",
264
+ gap: "6px",
265
+ fontSize: "12px",
266
+ color: aiStyles.tooltipLabel.color,
267
+ }, children: [_jsx(Tag, { size: 14 }), "Tags"] }), _jsx("button", { onClick: () => setSelectedTag("all"), style: {
268
+ ...aiStyles.chip,
269
+ borderColor: selectedTag === "all"
270
+ ? "#8b5cf6"
271
+ : aiStyles.chip.border,
272
+ background: selectedTag === "all"
273
+ ? "#8b5cf620"
274
+ : aiStyles.chip.background,
275
+ }, children: "All" }), availableTags.map((tag) => (_jsx("button", { onClick: () => setSelectedTag(tag), style: {
276
+ ...aiStyles.chip,
277
+ borderColor: selectedTag === tag
278
+ ? "#8b5cf6"
279
+ : aiStyles.chip.border,
280
+ background: selectedTag === tag
281
+ ? "#8b5cf620"
282
+ : aiStyles.chip.background,
283
+ }, children: tag }, tag)))] }))] }), promptsLoading ? (_jsx("div", { style: { textAlign: "center", padding: "40px 0" }, children: "Loading prompts..." })) : visiblePrompts.length === 0 ? (_jsx("div", { style: {
284
+ textAlign: "center",
285
+ padding: "40px 0",
286
+ color: "#6b7280",
287
+ }, children: "No prompts available for this model type" })) : (_jsxs("div", { style: {
288
+ display: "flex",
289
+ flexDirection: "column",
290
+ gap: "12px",
291
+ maxHeight: "400px",
292
+ overflow: "auto",
293
+ }, children: [favoritePrompts.length > 0 && (_jsxs("div", { children: [_jsx("div", { style: {
294
+ fontSize: "12px",
295
+ color: "#6b7280",
296
+ fontWeight: 600,
297
+ textTransform: "uppercase",
298
+ marginBottom: "8px",
299
+ }, children: "Favorites" }), _jsx("div", { style: {
300
+ display: "flex",
301
+ flexDirection: "column",
302
+ gap: "12px",
303
+ }, children: favoritePrompts.map((promptData) => (_jsxs("div", { onClick: () => handleSelectPrompt(promptData), style: {
304
+ padding: "16px",
305
+ border: `1px solid #e5e7eb`,
306
+ borderRadius: "8px",
307
+ cursor: "pointer",
308
+ transition: "all 0.2s",
309
+ }, onMouseEnter: (e) => {
310
+ e.currentTarget.style.background = "#8b5cf610";
311
+ e.currentTarget.style.borderColor = "#8b5cf6";
312
+ }, onMouseLeave: (e) => {
313
+ e.currentTarget.style.background = "transparent";
314
+ e.currentTarget.style.borderColor = "#e5e7eb";
315
+ }, children: [_jsxs("div", { style: {
316
+ display: "flex",
317
+ alignItems: "center",
318
+ gap: "8px",
319
+ fontWeight: 600,
320
+ marginBottom: "4px",
321
+ color: "#9780a5",
322
+ }, children: [_jsx(Star, { size: 14, color: "#8b5cf6" }), promptData.title] }), _jsx("div", { style: {
323
+ fontSize: "13px",
324
+ color: "#6b7280",
325
+ overflow: "hidden",
326
+ textOverflow: "ellipsis",
327
+ display: "-webkit-box",
328
+ WebkitLineClamp: 2,
329
+ WebkitBoxOrient: "vertical",
330
+ }, children: promptData.content }), "category" in promptData && promptData.category ? (_jsx("div", { style: {
331
+ marginTop: "8px",
332
+ fontSize: "11px",
333
+ color: "#8b5cf6",
334
+ }, children: String(promptData.category) })) : null] }, promptData.id))) })] })), nonFavoritePrompts.length > 0 && (_jsxs("div", { children: [_jsx("div", { style: {
335
+ fontSize: "12px",
336
+ color: "#6b7280",
337
+ fontWeight: 600,
338
+ textTransform: "uppercase",
339
+ marginTop: favoritePrompts.length > 0 ? "12px" : undefined,
340
+ marginBottom: "8px",
341
+ }, children: "All prompts" }), _jsx("div", { style: {
342
+ display: "flex",
343
+ flexDirection: "column",
344
+ gap: "12px",
345
+ }, children: nonFavoritePrompts.map((promptData) => (_jsxs("div", { onClick: () => handleSelectPrompt(promptData), style: {
346
+ padding: "16px",
347
+ border: `1px solid #e5e7eb`,
348
+ borderRadius: "8px",
349
+ cursor: "pointer",
350
+ transition: "all 0.2s",
351
+ }, onMouseEnter: (e) => {
352
+ e.currentTarget.style.background = "#8b5cf610";
353
+ e.currentTarget.style.borderColor = "#8b5cf6";
354
+ }, onMouseLeave: (e) => {
355
+ e.currentTarget.style.background = "transparent";
356
+ e.currentTarget.style.borderColor = "#e5e7eb";
357
+ }, children: [_jsx("div", { style: {
358
+ fontWeight: 600,
359
+ marginBottom: "4px",
360
+ color: "#9780a5",
361
+ }, children: promptData.title }), _jsx("div", { style: {
362
+ fontSize: "13px",
363
+ color: "#6b7280",
364
+ overflow: "hidden",
365
+ textOverflow: "ellipsis",
366
+ display: "-webkit-box",
367
+ WebkitLineClamp: 2,
368
+ WebkitBoxOrient: "vertical",
369
+ }, children: promptData.content }), "category" in promptData && promptData.category ? (_jsx("div", { style: {
370
+ marginTop: "8px",
371
+ fontSize: "11px",
372
+ color: "#8b5cf6",
373
+ }, children: String(promptData.category) })) : null] }, promptData.id))) })] }))] }))] })) }), _jsxs("div", { style: aiStyles.modalFooter, children: [_jsx("button", { onClick: handleClose, onMouseEnter: () => setIsCancelHovered(true), onMouseLeave: () => setIsCancelHovered(false), style: {
61
374
  ...aiStyles.button,
62
375
  ...aiStyles.buttonSecondary,
63
376
  ...(isCancelHovered && aiStyles.buttonSecondaryHover),
64
377
  }, children: "Cancel" }), _jsx("button", { onClick: handleSubmit, disabled: !selectedModel || !prompt.trim(), onMouseEnter: () => setIsSubmitHovered(true), onMouseLeave: () => setIsSubmitHovered(false), style: {
65
378
  ...aiStyles.button,
66
- ...(isSubmitHovered && !(!selectedModel || !prompt.trim()) && aiStyles.buttonHover),
67
- ...(!selectedModel || !prompt.trim() ? aiStyles.buttonDisabled : {}),
68
- }, children: "Generate with AI" })] })] })] }));
379
+ ...(isSubmitHovered &&
380
+ !(!selectedModel || !prompt.trim()) &&
381
+ aiStyles.buttonHover),
382
+ ...(!selectedModel || !prompt.trim()
383
+ ? aiStyles.buttonDisabled
384
+ : {}),
385
+ }, children: sourceText ? "Transform with AI" : "Generate with AI" })] })] })] }));
69
386
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AiSelect.d.ts","sourceRoot":"","sources":["../../src/components/AiSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAM5C,MAAM,WAAW,aACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC1D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,GAAG,WAAW,EACf,EAAE,aAAa,2CAqEf"}
1
+ {"version":3,"file":"AiSelect.d.ts","sourceRoot":"","sources":["../../src/components/AiSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAO5C,MAAM,WAAW,aACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC1D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,GAAG,WAAW,EACf,EAAE,aAAa,2CA+Ef"}
@@ -4,10 +4,12 @@ import { useState } from "react";
4
4
  import { useAiCallText } from "../hooks/useAiCallText";
5
5
  import { useAiModels } from "../hooks/useAiModels";
6
6
  import { AiPromptPanel } from "./AiPromptPanel";
7
+ import { UsageToast, useUsageToast } from "./UsageToast";
7
8
  import { aiStyles } from "../styles/inline";
8
9
  export function AiSelect({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, onValue, onToast, disabled, className, children, ...selectProps }) {
9
10
  const [isOpen, setIsOpen] = useState(false);
10
11
  const [isFocused, setIsFocused] = useState(false);
12
+ const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
11
13
  const { models } = useAiModels({ baseUrl, apiKeyId });
12
14
  const { generateText, loading } = useAiCallText({ baseUrl, apiKeyId });
13
15
  const handleOpenPanel = () => {
@@ -27,6 +29,7 @@ export function AiSelect({ baseUrl, apiKeyId, uiMode = "modal", context, model,
27
29
  if (result.text) {
28
30
  onValue?.(result.text);
29
31
  onToast?.({ type: "success", message: "AI suggestion ready" });
32
+ showUsageToast(result);
30
33
  }
31
34
  }
32
35
  catch (error) {
@@ -45,5 +48,5 @@ export function AiSelect({ baseUrl, apiKeyId, uiMode = "modal", context, model,
45
48
  }, onBlur: (e) => {
46
49
  setIsFocused(false);
47
50
  selectProps.onBlur?.(e);
48
- }, disabled: disabled || loading, children: children }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: models || [] }))] }));
51
+ }, disabled: disabled || loading, children: children }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: models || [] })), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey))] }));
49
52
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AiStatusButton.d.ts","sourceRoot":"","sources":["../../src/components/AiStatusButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAItD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,OAAe,EACf,SAAc,GACf,EAAE,mBAAmB,2CAgSrB"}
1
+ {"version":3,"file":"AiStatusButton.d.ts","sourceRoot":"","sources":["../../src/components/AiStatusButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAKtD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,OAAe,EACf,SAAc,GACf,EAAE,mBAAmB,2CAkZrB"}