@lastbrain/ai-ui-react 1.0.10 → 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,2CAmKd"}
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);
@@ -22,11 +25,16 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
22
25
  };
23
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 || [], sourceText: inputValue || undefined }))] }));
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
  }
@@ -20,5 +20,5 @@ export interface AiPromptPanelRenderProps {
20
20
  handleSubmit: () => void;
21
21
  handleClose: () => void;
22
22
  }
23
- export declare function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode, models, sourceText, 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;
24
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;AAIvC,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,MAAgB,EAChB,MAAW,EACX,UAAU,EACV,QAAQ,GACT,EAAE,kBAAkB,kDA0VpB"}
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,9 +1,10 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState, useEffect } from "react";
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
- import { usePrompts } from "../hooks/usePrompts";
6
- export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", models = [], sourceText, children, }) {
6
+ import { usePrompts, } from "../hooks/usePrompts";
7
+ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode: _uiMode = "modal", models = [], sourceText, children, }) {
7
8
  const [selectedModel, setSelectedModel] = useState("");
8
9
  const [prompt, setPrompt] = useState("");
9
10
  const [promptId, setPromptId] = useState(undefined);
@@ -13,37 +14,63 @@ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", mod
13
14
  const [promptFocused, setPromptFocused] = useState(false);
14
15
  const [modelFocused, setModelFocused] = useState(false);
15
16
  const [showPromptLibrary, setShowPromptLibrary] = useState(false);
16
- const { prompts, loading: promptsLoading, fetchPrompts, incrementStat } = usePrompts();
17
- // Set initial model when models change
18
- useEffect(() => {
19
- if (models.length > 0 && !selectedModel) {
20
- setSelectedModel(models[0].id);
21
- }
22
- }, [models, selectedModel]);
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();
23
24
  // Fetch prompts when modal opens
24
25
  useEffect(() => {
25
26
  if (isOpen && models.length > 0) {
26
- const modelType = models.find((m) => m.id === selectedModel)?.type;
27
+ const activeModelId = selectedModel || models[0]?.id;
28
+ const modelType = models.find((m) => m.id === activeModelId)?.type;
27
29
  fetchPrompts({
28
30
  type: modelType === "image" ? "image" : "text",
29
31
  });
30
32
  }
31
33
  }, [isOpen, selectedModel, models, fetchPrompts]);
32
- if (!isOpen)
33
- return null;
34
- const handleSubmit = () => {
35
- if (!selectedModel || !prompt.trim())
34
+ const handleSubmit = async () => {
35
+ const activeModelId = selectedModel || models[0]?.id;
36
+ if (!activeModelId || !prompt.trim())
36
37
  return;
37
- onSubmit(selectedModel, prompt, promptId);
38
- setPrompt("");
39
- setPromptId(undefined);
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
+ }
40
48
  };
41
- const handleClose = () => {
49
+ const finalizeClose = () => {
42
50
  onClose();
43
51
  setPrompt("");
44
52
  setPromptId(undefined);
45
53
  setShowPromptLibrary(false);
54
+ setSearchQuery("");
55
+ setSelectedTag("all");
56
+ setIsClosing(false);
46
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);
66
+ };
67
+ useEffect(() => {
68
+ return () => {
69
+ if (closeTimeoutRef.current) {
70
+ window.clearTimeout(closeTimeoutRef.current);
71
+ }
72
+ };
73
+ }, []);
47
74
  const handleKeyDown = (e) => {
48
75
  if (e.key === "Escape") {
49
76
  handleClose();
@@ -56,16 +83,53 @@ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", mod
56
83
  setPrompt(promptData.content);
57
84
  setPromptId(promptData.id);
58
85
  incrementStat(promptData.id, "picked");
86
+ if (promptData.model) {
87
+ setSelectedModel(promptData.model);
88
+ }
59
89
  setShowPromptLibrary(false);
60
90
  };
61
- const currentModelType = models.find((m) => m.id === selectedModel)?.type;
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;
62
106
  const filteredPrompts = prompts.filter((p) => {
63
107
  const matchesType = currentModelType === "image" ? p.type === "image" : p.type !== "image";
64
108
  return matchesType;
65
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);
66
130
  const renderProps = {
67
131
  models,
68
- selectedModel,
132
+ selectedModel: activeModelId,
69
133
  setSelectedModel,
70
134
  prompt,
71
135
  setPrompt,
@@ -76,7 +140,45 @@ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", mod
76
140
  if (children) {
77
141
  return (_jsx("div", { style: aiStyles.modal, onKeyDown: handleKeyDown, children: children(renderProps) }));
78
142
  }
79
- 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: showPromptLibrary ? "Select a Prompt" : "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: {
80
182
  ...aiStyles.modalCloseButton,
81
183
  ...(isCloseHovered && aiStyles.modalCloseButtonHover),
82
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: {
@@ -93,7 +195,7 @@ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", mod
93
195
  overflow: "auto",
94
196
  whiteSpace: "pre-wrap",
95
197
  wordBreak: "break-word",
96
- }, 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: selectedModel, onChange: (e) => setSelectedModel(e.target.value), onFocus: () => setModelFocused(true), onBlur: () => setModelFocused(false), style: {
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: {
97
199
  ...aiStyles.select,
98
200
  ...(modelFocused && aiStyles.selectFocus),
99
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: {
@@ -109,17 +211,20 @@ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", mod
109
211
  }, children: "(Cmd/Ctrl + Enter to submit)" })] }), filteredPrompts.length > 0 && (_jsxs("button", { onClick: () => setShowPromptLibrary(true), style: {
110
212
  padding: "4px 12px",
111
213
  fontSize: "12px",
112
- color: "#ffffff",
113
- background: "#8b5cf620",
114
- border: "none",
214
+ color: "#8b5cf6",
215
+ background: "#8b5cf610",
216
+ border: "1px solid #8b5cf630",
115
217
  borderRadius: "6px",
116
218
  cursor: "pointer",
117
219
  transition: "all 0.2s",
220
+ display: "flex",
221
+ alignItems: "center",
222
+ gap: "6px",
118
223
  }, onMouseEnter: (e) => {
119
- e.currentTarget.style.background = "#8b5cf630";
120
- }, onMouseLeave: (e) => {
121
224
  e.currentTarget.style.background = "#8b5cf620";
122
- }, children: ["\uD83D\uDCDA Browse Prompts (", filteredPrompts.length, ")"] }))] }), _jsx("textarea", { id: "prompt-input", value: prompt, onChange: (e) => setPrompt(e.target.value), onFocus: () => setPromptFocused(true), onBlur: () => setPromptFocused(false), placeholder: sourceText
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
123
228
  ? "Enter your AI prompt... e.g., 'Correct spelling and grammar', 'Make it more professional', 'Translate to English'"
124
229
  : "Enter your AI prompt... e.g., 'Write a blog post about AI', 'Generate product description'", rows: 6, style: {
125
230
  ...aiStyles.textarea,
@@ -136,47 +241,146 @@ export function AiPromptPanel({ isOpen, onClose, onSubmit, uiMode = "modal", mod
136
241
  display: "flex",
137
242
  alignItems: "center",
138
243
  gap: "4px",
139
- }, children: "\u2190 Back to form" }), promptsLoading ? (_jsx("div", { style: { textAlign: "center", padding: "40px 0" }, children: "Loading prompts..." })) : filteredPrompts.length === 0 ? (_jsx("div", { style: { textAlign: "center", padding: "40px 0", color: "#6b7280" }, children: "No prompts available for this model type" })) : (_jsx("div", { style: {
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: {
140
288
  display: "flex",
141
289
  flexDirection: "column",
142
290
  gap: "12px",
143
291
  maxHeight: "400px",
144
292
  overflow: "auto",
145
- }, children: filteredPrompts.map((promptData) => (_jsxs("div", { onClick: () => handleSelectPrompt(promptData), style: {
146
- padding: "16px",
147
- border: `1px solid #e5e7eb`,
148
- borderRadius: "8px",
149
- cursor: "pointer",
150
- transition: "all 0.2s",
151
- }, onMouseEnter: (e) => {
152
- e.currentTarget.style.background = "#8b5cf610";
153
- e.currentTarget.style.borderColor = "#8b5cf6";
154
- }, onMouseLeave: (e) => {
155
- e.currentTarget.style.background = "transparent";
156
- e.currentTarget.style.borderColor = "#e5e7eb";
157
- }, children: [_jsx("div", { style: {
158
- fontWeight: 600,
159
- marginBottom: "4px",
160
- color: "#111827",
161
- }, children: promptData.title }), _jsx("div", { style: {
162
- fontSize: "13px",
163
- color: "#6b7280",
164
- overflow: "hidden",
165
- textOverflow: "ellipsis",
166
- display: "-webkit-box",
167
- WebkitLineClamp: 2,
168
- WebkitBoxOrient: "vertical",
169
- }, children: promptData.content }), ("category" in promptData && promptData.category) ? (_jsx("div", { style: {
170
- marginTop: "8px",
171
- fontSize: "11px",
172
- color: "#8b5cf6",
173
- }, children: String(promptData.category) })) : null] }, promptData.id))) }))] })) }), _jsxs("div", { style: aiStyles.modalFooter, children: [_jsx("button", { onClick: handleClose, onMouseEnter: () => setIsCancelHovered(true), onMouseLeave: () => setIsCancelHovered(false), style: {
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: {
174
374
  ...aiStyles.button,
175
375
  ...aiStyles.buttonSecondary,
176
376
  ...(isCancelHovered && aiStyles.buttonSecondaryHover),
177
377
  }, children: "Cancel" }), _jsx("button", { onClick: handleSubmit, disabled: !selectedModel || !prompt.trim(), onMouseEnter: () => setIsSubmitHovered(true), onMouseLeave: () => setIsSubmitHovered(false), style: {
178
378
  ...aiStyles.button,
179
- ...(isSubmitHovered && !(!selectedModel || !prompt.trim()) && aiStyles.buttonHover),
180
- ...(!selectedModel || !prompt.trim() ? aiStyles.buttonDisabled : {}),
379
+ ...(isSubmitHovered &&
380
+ !(!selectedModel || !prompt.trim()) &&
381
+ aiStyles.buttonHover),
382
+ ...(!selectedModel || !prompt.trim()
383
+ ? aiStyles.buttonDisabled
384
+ : {}),
181
385
  }, children: sourceText ? "Transform with AI" : "Generate with AI" })] })] })] }));
182
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"}