@lastbrain/ai-ui-react 1.0.30 → 1.0.32
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/components/AiContextButton.js +10 -6
- package/dist/components/AiImageButton.d.ts.map +1 -1
- package/dist/components/AiImageButton.js +24 -35
- package/dist/components/AiInput.d.ts +1 -1
- package/dist/components/AiInput.d.ts.map +1 -1
- package/dist/components/AiInput.js +3 -1
- package/dist/components/AiSelect.d.ts +1 -1
- package/dist/components/AiSelect.d.ts.map +1 -1
- package/dist/components/AiSelect.js +3 -1
- package/dist/components/AiTextarea.d.ts +1 -1
- package/dist/components/AiTextarea.d.ts.map +1 -1
- package/dist/components/AiTextarea.js +4 -2
- package/dist/components/ErrorToast.d.ts.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/components/AiContextButton.tsx +13 -13
- package/src/components/AiImageButton.tsx +29 -61
- package/src/components/AiInput.tsx +5 -1
- package/src/components/AiSelect.tsx +4 -0
- package/src/components/AiTextarea.tsx +8 -0
- package/src/components/ErrorToast.tsx +5 -3
- package/src/types.ts +3 -0
|
@@ -16,15 +16,19 @@ export function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId,
|
|
|
16
16
|
const [analysisResult, setAnalysisResult] = useState(null);
|
|
17
17
|
const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
|
|
18
18
|
const { showErrorToast, errorData, errorKey, clearError } = useErrorToast();
|
|
19
|
-
//
|
|
19
|
+
// Utiliser directement les props pour les hooks (pas de context pour éviter les appels inutiles)
|
|
20
|
+
const { models, loading: modelsLoading } = useAiModels({
|
|
21
|
+
baseUrl: propBaseUrl,
|
|
22
|
+
apiKeyId: propApiKeyId,
|
|
23
|
+
});
|
|
24
|
+
const { generateText: callText, loading } = useAiCallText({
|
|
25
|
+
baseUrl: propBaseUrl,
|
|
26
|
+
apiKeyId: propApiKeyId,
|
|
27
|
+
});
|
|
28
|
+
// Récupérer le contexte AiProvider avec fallback sur les props pour l'affichage
|
|
20
29
|
const aiContext = useAiContext();
|
|
21
30
|
const baseUrl = propBaseUrl ?? aiContext.baseUrl;
|
|
22
31
|
const apiKeyId = propApiKeyId ?? aiContext.apiKeyId;
|
|
23
|
-
const { models, loading: modelsLoading } = useAiModels({ baseUrl, apiKeyId });
|
|
24
|
-
const { generateText: callText, loading } = useAiCallText({
|
|
25
|
-
baseUrl,
|
|
26
|
-
apiKeyId,
|
|
27
|
-
});
|
|
28
32
|
const handleOpenPanel = () => {
|
|
29
33
|
console.log("Opening panel, models:", models, "loading:", modelsLoading);
|
|
30
34
|
setIsOpen(true);
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"AiImageButton.d.ts","sourceRoot":"","sources":["../../src/components/AiImageButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAU5C,MAAM,WAAW,kBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACvE,OAAO,CAAC,EAAE,CACR,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAC7C,IAAI,CAAC;IACV,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,aAAoB,EACpB,WAAW,EACX,YAAY,EACZ,aAAa,EACb,GAAG,WAAW,EACf,EAAE,kBAAkB,2CAkXpB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState } from "react";
|
|
4
|
-
import { ImageIcon, Loader2, Download,
|
|
4
|
+
import { ImageIcon, Loader2, Download, ExternalLink, X } from "lucide-react";
|
|
5
5
|
import { useAiCallImage } from "../hooks/useAiCallImage";
|
|
6
6
|
import { useAiModels } from "../hooks/useAiModels";
|
|
7
7
|
import { AiPromptPanel } from "./AiPromptPanel";
|
|
@@ -36,20 +36,6 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
|
|
|
36
36
|
link.download = `ai-image-${generatedImage.requestId}.png`;
|
|
37
37
|
link.click();
|
|
38
38
|
};
|
|
39
|
-
const handleCopyUrl = async () => {
|
|
40
|
-
if (!generatedImage)
|
|
41
|
-
return;
|
|
42
|
-
try {
|
|
43
|
-
await navigator.clipboard.writeText(generatedImage.url);
|
|
44
|
-
onToast?.({
|
|
45
|
-
type: "success",
|
|
46
|
-
message: "URL copiée dans le presse-papier",
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
catch (_error) {
|
|
50
|
-
onToast?.({ type: "error", message: "Erreur lors de la copie" });
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
39
|
const handleSave = async () => {
|
|
54
40
|
if (!generatedImage || !onImageSave)
|
|
55
41
|
return;
|
|
@@ -106,6 +92,14 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
|
|
|
106
92
|
model: selectedModel,
|
|
107
93
|
prompt: selectedPrompt,
|
|
108
94
|
size: "1024x1024", // Taille par défaut
|
|
95
|
+
storeOutputs,
|
|
96
|
+
artifactTitle,
|
|
97
|
+
});
|
|
98
|
+
console.log("[AiImageButton] Image generation result:", {
|
|
99
|
+
hasUrl: !!result.url,
|
|
100
|
+
urlLength: result.url?.length,
|
|
101
|
+
urlPreview: result.url?.substring(0, 100),
|
|
102
|
+
requestId: result.requestId,
|
|
109
103
|
});
|
|
110
104
|
if (result.url) {
|
|
111
105
|
// Stocker l'image générée
|
|
@@ -116,6 +110,7 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
|
|
|
116
110
|
tokens: result.debitTokens,
|
|
117
111
|
};
|
|
118
112
|
setGeneratedImage(imageData);
|
|
113
|
+
console.log("[AiImageButton] Image data stored:", imageData);
|
|
119
114
|
onImage?.(result.url, {
|
|
120
115
|
requestId: result.requestId,
|
|
121
116
|
tokens: result.debitTokens,
|
|
@@ -222,27 +217,21 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
|
|
|
222
217
|
maxHeight: "200px",
|
|
223
218
|
objectFit: "contain",
|
|
224
219
|
display: "block",
|
|
225
|
-
} }) }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsxs("button", { onClick: handleDownload, className: "flex items-center gap-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
},
|
|
231
|
-
e.currentTarget.style.backgroundColor =
|
|
232
|
-
|
|
233
|
-
e.currentTarget.style.
|
|
234
|
-
|
|
235
|
-
}, title: "T\u00E9l\u00E9charger l'image", children: [_jsx(Download, { size: 14 }), "T\u00E9l\u00E9charger"] }), _jsxs("button", { onClick: handleCopyUrl, className: "flex items-center gap-1 px-3 py-2 text-xs font-medium rounded-lg transition-colors", style: getThemeStyles().actionButton, onMouseEnter: (e) => {
|
|
236
|
-
e.currentTarget.style.backgroundColor =
|
|
237
|
-
getThemeStyles().actionButton.hoverBackground;
|
|
238
|
-
e.currentTarget.style.color =
|
|
239
|
-
getThemeStyles().actionButton.hoverColor;
|
|
220
|
+
} }) }), _jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [_jsxs("button", { onClick: handleDownload, className: "flex items-center gap-2 px-4 py-2.5 text-sm font-semibold rounded-lg transition-all shadow-sm", style: {
|
|
221
|
+
backgroundColor: "#10b981",
|
|
222
|
+
color: "white",
|
|
223
|
+
border: "none",
|
|
224
|
+
cursor: "pointer",
|
|
225
|
+
}, onMouseEnter: (e) => {
|
|
226
|
+
e.currentTarget.style.backgroundColor = "#059669";
|
|
227
|
+
e.currentTarget.style.transform = "translateY(-1px)";
|
|
228
|
+
e.currentTarget.style.boxShadow =
|
|
229
|
+
"0 4px 12px rgba(16, 185, 129, 0.3)";
|
|
240
230
|
}, onMouseLeave: (e) => {
|
|
241
|
-
e.currentTarget.style.backgroundColor =
|
|
242
|
-
|
|
243
|
-
e.currentTarget.style.
|
|
244
|
-
|
|
245
|
-
}, title: "Copier l'URL", children: [_jsx(Copy, { size: 14 }), "Copier URL"] }), onImageSave && (_jsxs("button", { onClick: handleSave, className: "flex items-center gap-1 px-3 py-2 text-xs font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-lg transition-colors", title: "Sauvegarder en base", children: [_jsx(ExternalLink, { size: 14 }), "Sauvegarder"] }))] }), _jsx("div", { className: "mt-3 pt-3 text-xs", style: {
|
|
231
|
+
e.currentTarget.style.backgroundColor = "#10b981";
|
|
232
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
233
|
+
e.currentTarget.style.boxShadow = "";
|
|
234
|
+
}, title: "T\u00E9l\u00E9charger l'image", children: [_jsx(Download, { size: 16 }), "T\u00E9l\u00E9charger l'image"] }), onImageSave && (_jsxs("button", { onClick: handleSave, className: "flex items-center gap-1 px-3 py-2 text-xs font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-lg transition-colors", title: "Sauvegarder en base", children: [_jsx(ExternalLink, { size: 14 }), "Sauvegarder"] }))] }), _jsx("div", { className: "mt-3 pt-3 text-xs", style: {
|
|
246
235
|
...getThemeStyles().metadata,
|
|
247
236
|
}, children: _jsx("div", { className: "flex justify-center", children: _jsxs("span", { children: ["ID: ", generatedImage.requestId.slice(-8)] }) }) })] })), _jsx(ErrorToast, { error: errorData, onComplete: clearError }, errorKey)] }));
|
|
248
237
|
}
|
|
@@ -4,5 +4,5 @@ export interface AiInputProps extends Omit<BaseAiProps, "type">, Omit<InputHTMLA
|
|
|
4
4
|
uiMode?: "modal" | "drawer";
|
|
5
5
|
enableModelManagement?: boolean;
|
|
6
6
|
}
|
|
7
|
-
export declare function AiInput({ baseUrl, apiKeyId, uiMode, context, model, prompt, editMode, onValue, onToast, disabled, className,
|
|
7
|
+
export declare function AiInput({ baseUrl, apiKeyId, uiMode, context, model, prompt, editMode, enableModelManagement, storeOutputs, artifactTitle, onValue, onToast, disabled, className, ...inputProps }: AiInputProps): import("react/jsx-runtime").JSX.Element;
|
|
8
8
|
//# sourceMappingURL=AiInput.d.ts.map
|
|
@@ -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;AAE1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,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;IAC5B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;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,
|
|
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;AAQ5C,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;IAC5B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED,wBAAgB,OAAO,CAAC,EACtB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,qBAA6B,EAC7B,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,UAAU,EACd,EAAE,YAAY,2CA6Kd"}
|
|
@@ -8,7 +8,7 @@ import { AiPromptPanel } from "./AiPromptPanel";
|
|
|
8
8
|
import { UsageToast, useUsageToast } from "./UsageToast";
|
|
9
9
|
import { aiStyles } from "../styles/inline";
|
|
10
10
|
import { handleAIError } from "../utils/errorHandler";
|
|
11
|
-
export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, editMode = false, onValue, onToast, disabled, className,
|
|
11
|
+
export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, editMode = false, enableModelManagement = false, storeOutputs, artifactTitle, onValue, onToast, disabled, className, ...inputProps }) {
|
|
12
12
|
const [isOpen, setIsOpen] = useState(false);
|
|
13
13
|
const [inputValue, setInputValue] = useState(inputProps.value?.toString() || inputProps.defaultValue?.toString() || "");
|
|
14
14
|
const [isFocused, setIsFocused] = useState(false);
|
|
@@ -36,6 +36,8 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
|
|
|
36
36
|
prompt: promptWithContext,
|
|
37
37
|
context: resolvedContext,
|
|
38
38
|
actionType: hasContext ? "generate-text" : "autocomplete",
|
|
39
|
+
storeOutputs,
|
|
40
|
+
artifactTitle,
|
|
39
41
|
});
|
|
40
42
|
if (result.text) {
|
|
41
43
|
setInputValue(result.text);
|
|
@@ -4,5 +4,5 @@ export interface AiSelectProps extends Omit<BaseAiProps, "type">, Omit<SelectHTM
|
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
uiMode?: "modal" | "drawer";
|
|
6
6
|
}
|
|
7
|
-
export declare function AiSelect({ baseUrl, apiKeyId, uiMode, context, model, prompt, onValue, onToast, disabled, className, children, ...selectProps }: AiSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export declare function AiSelect({ baseUrl, apiKeyId, uiMode, context, model, prompt, storeOutputs, artifactTitle, onValue, onToast, disabled, className, children, ...selectProps }: AiSelectProps): import("react/jsx-runtime").JSX.Element;
|
|
8
8
|
//# sourceMappingURL=AiSelect.d.ts.map
|
|
@@ -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;AAQ5C,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,
|
|
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;AAQ5C,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,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,GAAG,WAAW,EACf,EAAE,aAAa,2CAiFf"}
|
|
@@ -7,7 +7,7 @@ import { AiPromptPanel } from "./AiPromptPanel";
|
|
|
7
7
|
import { UsageToast, useUsageToast } from "./UsageToast";
|
|
8
8
|
import { aiStyles } from "../styles/inline";
|
|
9
9
|
import { handleAIError } from "../utils/errorHandler";
|
|
10
|
-
export function AiSelect({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, onValue, onToast, disabled, className, children, ...selectProps }) {
|
|
10
|
+
export function AiSelect({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, storeOutputs, artifactTitle, onValue, onToast, disabled, className, children, ...selectProps }) {
|
|
11
11
|
const [isOpen, setIsOpen] = useState(false);
|
|
12
12
|
const [isFocused, setIsFocused] = useState(false);
|
|
13
13
|
const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
|
|
@@ -26,6 +26,8 @@ export function AiSelect({ baseUrl, apiKeyId, uiMode = "modal", context, model,
|
|
|
26
26
|
prompt: selectedPrompt,
|
|
27
27
|
context: context || undefined,
|
|
28
28
|
actionType: "autocomplete",
|
|
29
|
+
storeOutputs,
|
|
30
|
+
artifactTitle,
|
|
29
31
|
});
|
|
30
32
|
if (result.text) {
|
|
31
33
|
onValue?.(result.text);
|
|
@@ -3,5 +3,5 @@ import type { BaseAiProps } from "../types";
|
|
|
3
3
|
export interface AiTextareaProps extends Omit<BaseAiProps, "type">, Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, "onValue"> {
|
|
4
4
|
uiMode?: "modal" | "drawer";
|
|
5
5
|
}
|
|
6
|
-
export declare function AiTextarea({ baseUrl, apiKeyId, uiMode, context, model, prompt, editMode, onValue, onToast, disabled, className, ...textareaProps }: AiTextareaProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export declare function AiTextarea({ baseUrl, apiKeyId, uiMode, context, model, prompt, editMode, enableModelManagement, storeOutputs, artifactTitle, onValue, onToast, disabled, className, ...textareaProps }: AiTextareaProps): import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
//# sourceMappingURL=AiTextarea.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AiTextarea.d.ts","sourceRoot":"","sources":["../../src/components/AiTextarea.tsx"],"names":[],"mappings":"AAEA,OAAc,EAIZ,KAAK,sBAAsB,EAC5B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,eACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAC9D,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,aAAa,EACjB,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"AiTextarea.d.ts","sourceRoot":"","sources":["../../src/components/AiTextarea.tsx"],"names":[],"mappings":"AAEA,OAAc,EAIZ,KAAK,sBAAsB,EAC5B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAQ5C,MAAM,WAAW,eACf,SACE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EACzB,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAC9D,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,QAAQ,EACR,MAAgB,EAChB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,aAAa,EACjB,EAAE,eAAe,2CA8LjB"}
|
|
@@ -8,7 +8,7 @@ import { AiPromptPanel } from "./AiPromptPanel";
|
|
|
8
8
|
import { UsageToast, useUsageToast } from "./UsageToast";
|
|
9
9
|
import { aiStyles } from "../styles/inline";
|
|
10
10
|
import { handleAIError } from "../utils/errorHandler";
|
|
11
|
-
export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, editMode = false, onValue, onToast, disabled, className, ...textareaProps }) {
|
|
11
|
+
export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, editMode = false, enableModelManagement, storeOutputs, artifactTitle, onValue, onToast, disabled, className, ...textareaProps }) {
|
|
12
12
|
const [isOpen, setIsOpen] = useState(false);
|
|
13
13
|
const [textareaValue, setTextareaValue] = useState(textareaProps.value?.toString() ||
|
|
14
14
|
textareaProps.defaultValue?.toString() ||
|
|
@@ -38,6 +38,8 @@ export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model
|
|
|
38
38
|
prompt: promptWithContext,
|
|
39
39
|
context: resolvedContext,
|
|
40
40
|
actionType: hasContext ? "generate-text" : "autocomplete",
|
|
41
|
+
storeOutputs,
|
|
42
|
+
artifactTitle,
|
|
41
43
|
});
|
|
42
44
|
if (result.text) {
|
|
43
45
|
setTextareaValue(result.text);
|
|
@@ -117,5 +119,5 @@ export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model
|
|
|
117
119
|
...(disabled || loading
|
|
118
120
|
? { opacity: 0.5, cursor: "not-allowed" }
|
|
119
121
|
: {}),
|
|
120
|
-
}, 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: textareaValue || undefined })), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey))] }));
|
|
122
|
+
}, 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: textareaValue || undefined, baseUrl: baseUrl, apiKey: apiKeyId, enableModelManagement: enableModelManagement })), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey))] }));
|
|
121
123
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorToast.d.ts","sourceRoot":"","sources":["../../src/components/ErrorToast.tsx"],"names":[],"mappings":"AAKA,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,eAAe;IACvB,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;IACrE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAyB,EACzB,UAAU,GACX,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"ErrorToast.d.ts","sourceRoot":"","sources":["../../src/components/ErrorToast.tsx"],"names":[],"mappings":"AAKA,UAAU,cAAc;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,eAAe;IACvB,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;IACrE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAyB,EACzB,UAAU,GACX,EAAE,eAAe,kDA4IjB;AAED,wBAAgB,aAAa;4BAII,cAAc;;;;EAgB9C"}
|
package/dist/types.d.ts
CHANGED
|
@@ -12,6 +12,9 @@ export interface BaseAiProps {
|
|
|
12
12
|
model?: string | null;
|
|
13
13
|
prompt?: string | null;
|
|
14
14
|
editMode?: boolean;
|
|
15
|
+
enableModelManagement?: boolean;
|
|
16
|
+
storeOutputs?: boolean;
|
|
17
|
+
artifactTitle?: string;
|
|
15
18
|
onValue?: (value: string) => void;
|
|
16
19
|
onToast?: (toast: ToastType) => void;
|
|
17
20
|
disabled?: boolean;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAExC,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lastbrain/ai-ui-react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.32",
|
|
4
4
|
"description": "Headless React components for LastBrain AI UI Kit",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"lucide-react": "^0.257.0",
|
|
51
|
-
"@lastbrain/ai-ui-core": "1.0.
|
|
51
|
+
"@lastbrain/ai-ui-core": "1.0.21"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/react": "^19.2.0",
|
|
@@ -63,17 +63,21 @@ export function AiContextButton({
|
|
|
63
63
|
const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
|
|
64
64
|
const { showErrorToast, errorData, errorKey, clearError } = useErrorToast();
|
|
65
65
|
|
|
66
|
-
//
|
|
66
|
+
// Utiliser directement les props pour les hooks (pas de context pour éviter les appels inutiles)
|
|
67
|
+
const { models, loading: modelsLoading } = useAiModels({
|
|
68
|
+
baseUrl: propBaseUrl,
|
|
69
|
+
apiKeyId: propApiKeyId,
|
|
70
|
+
});
|
|
71
|
+
const { generateText: callText, loading } = useAiCallText({
|
|
72
|
+
baseUrl: propBaseUrl,
|
|
73
|
+
apiKeyId: propApiKeyId,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Récupérer le contexte AiProvider avec fallback sur les props pour l'affichage
|
|
67
77
|
const aiContext = useAiContext();
|
|
68
78
|
const baseUrl = propBaseUrl ?? aiContext.baseUrl;
|
|
69
79
|
const apiKeyId = propApiKeyId ?? aiContext.apiKeyId;
|
|
70
80
|
|
|
71
|
-
const { models, loading: modelsLoading } = useAiModels({ baseUrl, apiKeyId });
|
|
72
|
-
const { generateText: callText, loading } = useAiCallText({
|
|
73
|
-
baseUrl,
|
|
74
|
-
apiKeyId,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
81
|
const handleOpenPanel = () => {
|
|
78
82
|
console.log("Opening panel, models:", models, "loading:", modelsLoading);
|
|
79
83
|
setIsOpen(true);
|
|
@@ -550,13 +554,9 @@ Analyse ces données et réponds de manière structurée et claire.`;
|
|
|
550
554
|
</div>
|
|
551
555
|
</div>
|
|
552
556
|
)}
|
|
553
|
-
|
|
557
|
+
|
|
554
558
|
{/* Error Toast */}
|
|
555
|
-
<ErrorToast
|
|
556
|
-
key={errorKey}
|
|
557
|
-
error={errorData}
|
|
558
|
-
onComplete={clearError}
|
|
559
|
-
/>
|
|
559
|
+
<ErrorToast key={errorKey} error={errorData} onComplete={clearError} />
|
|
560
560
|
</>
|
|
561
561
|
);
|
|
562
562
|
}
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState, type ButtonHTMLAttributes } from "react";
|
|
4
|
-
import {
|
|
5
|
-
ImageIcon,
|
|
6
|
-
Loader2,
|
|
7
|
-
Download,
|
|
8
|
-
Copy,
|
|
9
|
-
ExternalLink,
|
|
10
|
-
X,
|
|
11
|
-
} from "lucide-react";
|
|
4
|
+
import { ImageIcon, Loader2, Download, ExternalLink, X } from "lucide-react";
|
|
12
5
|
import type { BaseAiProps } from "../types";
|
|
13
6
|
import { useAiCallImage } from "../hooks/useAiCallImage";
|
|
14
7
|
import { useAiModels } from "../hooks/useAiModels";
|
|
@@ -90,19 +83,6 @@ export function AiImageButton({
|
|
|
90
83
|
link.click();
|
|
91
84
|
};
|
|
92
85
|
|
|
93
|
-
const handleCopyUrl = async () => {
|
|
94
|
-
if (!generatedImage) return;
|
|
95
|
-
try {
|
|
96
|
-
await navigator.clipboard.writeText(generatedImage.url);
|
|
97
|
-
onToast?.({
|
|
98
|
-
type: "success",
|
|
99
|
-
message: "URL copiée dans le presse-papier",
|
|
100
|
-
});
|
|
101
|
-
} catch (_error) {
|
|
102
|
-
onToast?.({ type: "error", message: "Erreur lors de la copie" });
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
86
|
const handleSave = async () => {
|
|
107
87
|
if (!generatedImage || !onImageSave) return;
|
|
108
88
|
try {
|
|
@@ -165,6 +145,15 @@ export function AiImageButton({
|
|
|
165
145
|
model: selectedModel,
|
|
166
146
|
prompt: selectedPrompt,
|
|
167
147
|
size: "1024x1024", // Taille par défaut
|
|
148
|
+
storeOutputs,
|
|
149
|
+
artifactTitle,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
console.log("[AiImageButton] Image generation result:", {
|
|
153
|
+
hasUrl: !!result.url,
|
|
154
|
+
urlLength: result.url?.length,
|
|
155
|
+
urlPreview: result.url?.substring(0, 100),
|
|
156
|
+
requestId: result.requestId,
|
|
168
157
|
});
|
|
169
158
|
|
|
170
159
|
if (result.url) {
|
|
@@ -176,6 +165,7 @@ export function AiImageButton({
|
|
|
176
165
|
tokens: result.debitTokens,
|
|
177
166
|
};
|
|
178
167
|
setGeneratedImage(imageData);
|
|
168
|
+
console.log("[AiImageButton] Image data stored:", imageData);
|
|
179
169
|
|
|
180
170
|
onImage?.(result.url, {
|
|
181
171
|
requestId: result.requestId,
|
|
@@ -373,46 +363,28 @@ export function AiImageButton({
|
|
|
373
363
|
<div className="flex items-center gap-2 flex-wrap">
|
|
374
364
|
<button
|
|
375
365
|
onClick={handleDownload}
|
|
376
|
-
className="flex items-center gap-
|
|
377
|
-
style={
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
getThemeStyles().actionButton.hoverColor;
|
|
383
|
-
}}
|
|
384
|
-
onMouseLeave={(e) => {
|
|
385
|
-
e.currentTarget.style.backgroundColor =
|
|
386
|
-
getThemeStyles().actionButton.backgroundColor;
|
|
387
|
-
e.currentTarget.style.color =
|
|
388
|
-
getThemeStyles().actionButton.color;
|
|
366
|
+
className="flex items-center gap-2 px-4 py-2.5 text-sm font-semibold rounded-lg transition-all shadow-sm"
|
|
367
|
+
style={{
|
|
368
|
+
backgroundColor: "#10b981",
|
|
369
|
+
color: "white",
|
|
370
|
+
border: "none",
|
|
371
|
+
cursor: "pointer",
|
|
389
372
|
}}
|
|
390
|
-
title="Télécharger l'image"
|
|
391
|
-
>
|
|
392
|
-
<Download size={14} />
|
|
393
|
-
Télécharger
|
|
394
|
-
</button>
|
|
395
|
-
|
|
396
|
-
<button
|
|
397
|
-
onClick={handleCopyUrl}
|
|
398
|
-
className="flex items-center gap-1 px-3 py-2 text-xs font-medium rounded-lg transition-colors"
|
|
399
|
-
style={getThemeStyles().actionButton}
|
|
400
373
|
onMouseEnter={(e) => {
|
|
401
|
-
e.currentTarget.style.backgroundColor =
|
|
402
|
-
|
|
403
|
-
e.currentTarget.style.
|
|
404
|
-
|
|
374
|
+
e.currentTarget.style.backgroundColor = "#059669";
|
|
375
|
+
e.currentTarget.style.transform = "translateY(-1px)";
|
|
376
|
+
e.currentTarget.style.boxShadow =
|
|
377
|
+
"0 4px 12px rgba(16, 185, 129, 0.3)";
|
|
405
378
|
}}
|
|
406
379
|
onMouseLeave={(e) => {
|
|
407
|
-
e.currentTarget.style.backgroundColor =
|
|
408
|
-
|
|
409
|
-
e.currentTarget.style.
|
|
410
|
-
getThemeStyles().actionButton.color;
|
|
380
|
+
e.currentTarget.style.backgroundColor = "#10b981";
|
|
381
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
382
|
+
e.currentTarget.style.boxShadow = "";
|
|
411
383
|
}}
|
|
412
|
-
title="
|
|
384
|
+
title="Télécharger l'image"
|
|
413
385
|
>
|
|
414
|
-
<
|
|
415
|
-
|
|
386
|
+
<Download size={16} />
|
|
387
|
+
Télécharger l'image
|
|
416
388
|
</button>
|
|
417
389
|
|
|
418
390
|
{onImageSave && (
|
|
@@ -440,13 +412,9 @@ export function AiImageButton({
|
|
|
440
412
|
</div>
|
|
441
413
|
</div>
|
|
442
414
|
)}
|
|
443
|
-
|
|
415
|
+
|
|
444
416
|
{/* Error Toast */}
|
|
445
|
-
<ErrorToast
|
|
446
|
-
key={errorKey}
|
|
447
|
-
error={errorData}
|
|
448
|
-
onComplete={clearError}
|
|
449
|
-
/>
|
|
417
|
+
<ErrorToast key={errorKey} error={errorData} onComplete={clearError} />
|
|
450
418
|
</div>
|
|
451
419
|
);
|
|
452
420
|
}
|
|
@@ -26,11 +26,13 @@ export function AiInput({
|
|
|
26
26
|
model,
|
|
27
27
|
prompt,
|
|
28
28
|
editMode = false,
|
|
29
|
+
enableModelManagement = false,
|
|
30
|
+
storeOutputs,
|
|
31
|
+
artifactTitle,
|
|
29
32
|
onValue,
|
|
30
33
|
onToast,
|
|
31
34
|
disabled,
|
|
32
35
|
className,
|
|
33
|
-
enableModelManagement = false,
|
|
34
36
|
...inputProps
|
|
35
37
|
}: AiInputProps) {
|
|
36
38
|
const [isOpen, setIsOpen] = useState(false);
|
|
@@ -73,6 +75,8 @@ export function AiInput({
|
|
|
73
75
|
prompt: promptWithContext,
|
|
74
76
|
context: resolvedContext,
|
|
75
77
|
actionType: hasContext ? "generate-text" : "autocomplete",
|
|
78
|
+
storeOutputs,
|
|
79
|
+
artifactTitle,
|
|
76
80
|
});
|
|
77
81
|
|
|
78
82
|
if (result.text) {
|
|
@@ -24,6 +24,8 @@ export function AiSelect({
|
|
|
24
24
|
context,
|
|
25
25
|
model,
|
|
26
26
|
prompt,
|
|
27
|
+
storeOutputs,
|
|
28
|
+
artifactTitle,
|
|
27
29
|
onValue,
|
|
28
30
|
onToast,
|
|
29
31
|
disabled,
|
|
@@ -56,6 +58,8 @@ export function AiSelect({
|
|
|
56
58
|
prompt: selectedPrompt,
|
|
57
59
|
context: context || undefined,
|
|
58
60
|
actionType: "autocomplete",
|
|
61
|
+
storeOutputs,
|
|
62
|
+
artifactTitle,
|
|
59
63
|
});
|
|
60
64
|
|
|
61
65
|
if (result.text) {
|
|
@@ -30,6 +30,9 @@ export function AiTextarea({
|
|
|
30
30
|
model,
|
|
31
31
|
prompt,
|
|
32
32
|
editMode = false,
|
|
33
|
+
enableModelManagement,
|
|
34
|
+
storeOutputs,
|
|
35
|
+
artifactTitle,
|
|
33
36
|
onValue,
|
|
34
37
|
onToast,
|
|
35
38
|
disabled,
|
|
@@ -78,6 +81,8 @@ export function AiTextarea({
|
|
|
78
81
|
prompt: promptWithContext,
|
|
79
82
|
context: resolvedContext,
|
|
80
83
|
actionType: hasContext ? "generate-text" : "autocomplete",
|
|
84
|
+
storeOutputs,
|
|
85
|
+
artifactTitle,
|
|
81
86
|
});
|
|
82
87
|
|
|
83
88
|
if (result.text) {
|
|
@@ -208,6 +213,9 @@ export function AiTextarea({
|
|
|
208
213
|
uiMode={uiMode}
|
|
209
214
|
models={models || []}
|
|
210
215
|
sourceText={textareaValue || undefined}
|
|
216
|
+
baseUrl={baseUrl}
|
|
217
|
+
apiKey={apiKeyId}
|
|
218
|
+
enableModelManagement={enableModelManagement}
|
|
211
219
|
/>
|
|
212
220
|
)}
|
|
213
221
|
{Boolean(toastData) && (
|
|
@@ -50,12 +50,12 @@ export function ErrorToast({
|
|
|
50
50
|
|
|
51
51
|
const handleClose = () => {
|
|
52
52
|
if (isClosing) return;
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
// Clear auto-close timeout if user closes manually
|
|
55
55
|
if (autoCloseTimeoutRef.current) {
|
|
56
56
|
window.clearTimeout(autoCloseTimeoutRef.current);
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
setIsClosing(true);
|
|
60
60
|
fadeTimeoutRef.current = window.setTimeout(() => {
|
|
61
61
|
setIsVisible(false);
|
|
@@ -125,7 +125,9 @@ export function ErrorToast({
|
|
|
125
125
|
</span>
|
|
126
126
|
)}
|
|
127
127
|
</div>
|
|
128
|
-
<div
|
|
128
|
+
<div
|
|
129
|
+
style={{ fontSize: "12px", opacity: 0.9, wordBreak: "break-word" }}
|
|
130
|
+
>
|
|
129
131
|
{error.message}
|
|
130
132
|
</div>
|
|
131
133
|
</div>
|
package/src/types.ts
CHANGED
|
@@ -13,6 +13,9 @@ export interface BaseAiProps {
|
|
|
13
13
|
model?: string | null;
|
|
14
14
|
prompt?: string | null;
|
|
15
15
|
editMode?: boolean;
|
|
16
|
+
enableModelManagement?: boolean;
|
|
17
|
+
storeOutputs?: boolean; // Whether to store outputs (images in bucket, text in database)
|
|
18
|
+
artifactTitle?: string; // Title for stored artifacts
|
|
16
19
|
onValue?: (value: string) => void;
|
|
17
20
|
onToast?: (toast: ToastType) => void;
|
|
18
21
|
disabled?: boolean;
|