@lastbrain/ai-ui-react 1.0.40 → 1.0.42

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":"AiContextButton.d.ts","sourceRoot":"","sources":["../../src/components/AiContextButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAS5C,MAAM,WAAW,oBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAEvE,WAAW,EAAE,GAAG,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CACT,MAAM,EAAE,MAAM,EACd,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,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,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,eAAe,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,WAAW,EACX,kBAAyC,EACzC,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,gBAA0C,EAC1C,YAAY,EACZ,aAAa,EACb,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,GAAG,WAAW,EACf,EAAE,oBAAoB,2CAwftB"}
1
+ {"version":3,"file":"AiContextButton.d.ts","sourceRoot":"","sources":["../../src/components/AiContextButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAW5C,MAAM,WAAW,oBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IAEvE,WAAW,EAAE,GAAG,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,CACT,MAAM,EAAE,MAAM,EACd,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,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,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,eAAe,CAAC,EAC9B,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,WAAW,EACX,kBAAyC,EACzC,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,gBAA0C,EAC1C,YAAY,EACZ,aAAa,EACb,OAAO,EAAE,QAAQ,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,EACf,GAAG,WAAW,EACf,EAAE,oBAAoB,2CAqiBtB"}
@@ -9,12 +9,25 @@ import { useErrorToast, ErrorToast } from "./ErrorToast";
9
9
  import { aiStyles } from "../styles/inline";
10
10
  import { useAiContext } from "../context/AiProvider";
11
11
  import { handleAIError } from "../utils/errorHandler";
12
+ import { useLB } from "../context/LBAuthProvider";
13
+ import { LBSigninModal } from "./LBSigninModal";
12
14
  export function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMode = "modal", contextData, contextDescription = "Données à analyser", onResult, onToast, disabled, className, children, resultModalTitle = "Résultat de l'analyse", storeOutputs, artifactTitle, context: _context, model: _model, prompt: _prompt, ...buttonProps }) {
13
15
  const [isOpen, setIsOpen] = useState(false);
16
+ const [showAuthModal, setShowAuthModal] = useState(false);
14
17
  const [isResultOpen, setIsResultOpen] = useState(false);
15
18
  const [analysisResult, setAnalysisResult] = useState(null);
16
19
  const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
17
20
  const { showErrorToast, errorData, errorKey, clearError } = useErrorToast();
21
+ // Rendre l'authentification optionnelle
22
+ let lbStatus;
23
+ try {
24
+ const lbContext = useLB();
25
+ lbStatus = lbContext.status;
26
+ }
27
+ catch {
28
+ // LBProvider n'est pas disponible, ignorer
29
+ lbStatus = undefined;
30
+ }
18
31
  // Récupérer le contexte AiProvider avec fallback sur les props
19
32
  const aiContext = useAiContext();
20
33
  const baseUrl = propBaseUrl ?? aiContext.baseUrl;
@@ -23,7 +36,12 @@ export function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId,
23
36
  baseUrl,
24
37
  apiKeyId,
25
38
  });
39
+ const isAuthReady = lbStatus === "ready" || Boolean(process.env.LB_API_KEY);
26
40
  const handleOpenPanel = () => {
41
+ if (!isAuthReady) {
42
+ setShowAuthModal(true);
43
+ return;
44
+ }
27
45
  setIsOpen(true);
28
46
  };
29
47
  const handleClosePanel = () => {
@@ -160,14 +178,18 @@ Analyse ces données et réponds de manière structurée et claire.`;
160
178
  setIsOpen(false);
161
179
  }
162
180
  };
163
- return (_jsxs(_Fragment, { children: [_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ...buttonProps, onClick: handleOpenPanel, disabled: disabled || loading, className: className, style: {
181
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ...buttonProps, onClick: handleOpenPanel, disabled: disabled || loading || !isAuthReady, className: className, style: {
164
182
  ...aiStyles.button,
165
183
  display: "flex",
166
184
  alignItems: "center",
167
185
  gap: "8px",
168
- cursor: disabled || loading ? "not-allowed" : "pointer",
169
- opacity: disabled || loading ? 0.6 : 1,
170
- backgroundColor: loading ? "#8b5cf6" : "#7c3aed",
186
+ cursor: disabled || loading || !isAuthReady ? "not-allowed" : "pointer",
187
+ opacity: disabled || loading || !isAuthReady ? 0.6 : 1,
188
+ backgroundColor: loading
189
+ ? "#8b5cf6"
190
+ : !isAuthReady
191
+ ? "#94a3b8"
192
+ : "#7c3aed",
171
193
  color: "white",
172
194
  border: "none",
173
195
  borderRadius: "12px",
@@ -188,30 +210,30 @@ Analyse ces données et réponds de manière structurée et claire.`;
188
210
  }),
189
211
  ...buttonProps.style,
190
212
  }, onMouseEnter: (e) => {
191
- if (!disabled && !loading) {
213
+ if (!disabled && !loading && isAuthReady) {
192
214
  e.currentTarget.style.transform = "scale(1.02)";
193
215
  e.currentTarget.style.boxShadow =
194
216
  "0 6px 16px rgba(124, 58, 237, 0.3)";
195
217
  }
196
218
  }, onMouseLeave: (e) => {
197
- if (!disabled && !loading) {
219
+ if (!disabled && !loading && isAuthReady) {
198
220
  e.currentTarget.style.transform = "scale(1)";
199
221
  e.currentTarget.style.boxShadow = loading
200
222
  ? "0 4px 12px rgba(139, 92, 246, 0.3)"
201
223
  : "0 2px 8px rgba(124, 58, 237, 0.2)";
202
224
  }
203
225
  }, onMouseDown: (e) => {
204
- if (!disabled && !loading) {
226
+ if (!disabled && !loading && isAuthReady) {
205
227
  e.currentTarget.style.transform = "scale(0.98)";
206
228
  }
207
229
  }, onMouseUp: (e) => {
208
- if (!disabled && !loading) {
230
+ if (!disabled && !loading && isAuthReady) {
209
231
  e.currentTarget.style.transform = "scale(1.02)";
210
232
  }
211
- }, "data-ai-context-button": true, children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 18, className: "animate-spin", style: {
233
+ }, "data-ai-context-button": true, title: !isAuthReady ? "Authentication required" : "Analyser avec l'IA", children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 18, className: "animate-spin", style: {
212
234
  color: "white",
213
235
  filter: "drop-shadow(0 0 2px rgba(255,255,255,0.3))",
214
- } }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: "Analyse..." })] })) : (_jsx(_Fragment, { children: _jsx(Sparkle, { size: 18, style: {
236
+ } }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: "Analyse..." })] })) : !isAuthReady ? (_jsxs(_Fragment, { children: [_jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }), _jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })] }), children || _jsx("span", { children: "Connexion requise" })] })) : (_jsx(_Fragment, { children: _jsx(Sparkle, { size: 18, style: {
215
237
  color: "white",
216
238
  filter: "drop-shadow(0 0 2px rgba(255,255,255,0.2))",
217
239
  } }) })) }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: [], enableModelManagement: true, modelCategory: "text", baseUrl: baseUrl, apiKey: apiKeyId }))] }), isResultOpen && analysisResult && (_jsx("div", { style: {
@@ -332,5 +354,5 @@ Analyse ces données et réponds de manière structurée et claire.`;
332
354
  ...getThemeStyles().content,
333
355
  }, children: [_jsxs("span", { children: ["Co\u00FBt: $", (apiKeyId?.includes("dev")
334
356
  ? 0
335
- : analysisResult.cost).toFixed(6)] }), _jsxs("span", { children: ["ID: ", analysisResult.requestId?.slice(-8) || "N/A"] })] }) })] })] }) }) })), _jsx(ErrorToast, { error: errorData, onComplete: clearError }, errorKey)] }));
357
+ : analysisResult.cost).toFixed(6)] }), _jsxs("span", { children: ["ID: ", analysisResult.requestId?.slice(-8) || "N/A"] })] }) })] })] }) }) })), _jsx(LBSigninModal, { isOpen: showAuthModal, onClose: () => setShowAuthModal(false) }), _jsx(ErrorToast, { error: errorData, onComplete: clearError }, errorKey)] }));
336
358
  }
@@ -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;AAE5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAS5C,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,2CAqXpB"}
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;AAW5C,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,2CAgapB"}
@@ -9,17 +9,35 @@ import { useErrorToast, ErrorToast } from "./ErrorToast";
9
9
  import { aiStyles } from "../styles/inline";
10
10
  import { useAiContext } from "../context/AiProvider";
11
11
  import { handleAIError } from "../utils/errorHandler";
12
+ import { useLB } from "../context/LBAuthProvider";
13
+ import { LBSigninModal } from "./LBSigninModal";
12
14
  export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMode = "modal", context: _context, model: _model, prompt: _prompt, onImage, onToast, disabled, className, children, showImageCard = true, onImageSave, storeOutputs, artifactTitle, ...buttonProps }) {
13
15
  const [isOpen, setIsOpen] = useState(false);
16
+ const [showAuthModal, setShowAuthModal] = useState(false);
14
17
  const [generatedImage, setGeneratedImage] = useState(null);
15
18
  const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
16
19
  const { showErrorToast, errorData, errorKey, clearError } = useErrorToast();
20
+ // Rendre l'authentification optionnelle
21
+ let lbStatus;
22
+ try {
23
+ const lbContext = useLB();
24
+ lbStatus = lbContext.status;
25
+ }
26
+ catch {
27
+ // LBProvider n'est pas disponible, ignorer
28
+ lbStatus = undefined;
29
+ }
17
30
  // Récupérer le contexte AiProvider avec fallback sur les props
18
31
  const aiContext = useAiContext();
19
32
  const baseUrl = propBaseUrl ?? aiContext.baseUrl;
20
33
  const apiKeyId = propApiKeyId ?? aiContext.apiKeyId;
21
34
  const { generateImage, loading } = useAiCallImage({ baseUrl, apiKeyId });
35
+ const isAuthReady = lbStatus === "ready" || Boolean(process.env.LB_API_KEY);
22
36
  const handleOpenPanel = () => {
37
+ if (!isAuthReady) {
38
+ setShowAuthModal(true);
39
+ return;
40
+ }
23
41
  setIsOpen(true);
24
42
  };
25
43
  const handleClosePanel = () => {
@@ -134,14 +152,18 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
134
152
  setIsOpen(false);
135
153
  }
136
154
  };
137
- return (_jsxs("div", { className: "flex items-start gap-4", children: [_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ...buttonProps, onClick: handleOpenPanel, disabled: disabled || loading, className: className, style: {
155
+ return (_jsxs("div", { className: "flex items-start gap-4", children: [_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ...buttonProps, onClick: handleOpenPanel, disabled: disabled || loading || !isAuthReady, className: className, style: {
138
156
  ...aiStyles.button,
139
157
  display: "flex",
140
158
  alignItems: "center",
141
159
  gap: "8px",
142
- cursor: disabled || loading ? "not-allowed" : "pointer",
143
- opacity: disabled || loading ? 0.6 : 1,
144
- backgroundColor: loading ? "#8b5cf6" : "#6366f1",
160
+ cursor: disabled || loading || !isAuthReady ? "not-allowed" : "pointer",
161
+ opacity: disabled || loading || !isAuthReady ? 0.6 : 1,
162
+ backgroundColor: loading
163
+ ? "#8b5cf6"
164
+ : !isAuthReady
165
+ ? "#94a3b8"
166
+ : "#6366f1",
145
167
  color: "white",
146
168
  border: "none",
147
169
  borderRadius: "12px",
@@ -161,30 +183,30 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
161
183
  }),
162
184
  ...buttonProps.style,
163
185
  }, onMouseEnter: (e) => {
164
- if (!disabled && !loading) {
186
+ if (!disabled && !loading && isAuthReady) {
165
187
  e.currentTarget.style.transform = "scale(1.02)";
166
188
  e.currentTarget.style.boxShadow =
167
189
  "0 6px 16px rgba(99, 102, 241, 0.3)";
168
190
  }
169
191
  }, onMouseLeave: (e) => {
170
- if (!disabled && !loading) {
192
+ if (!disabled && !loading && isAuthReady) {
171
193
  e.currentTarget.style.transform = "scale(1)";
172
194
  e.currentTarget.style.boxShadow = loading
173
195
  ? "0 4px 12px rgba(139, 92, 246, 0.3)"
174
196
  : "0 2px 8px rgba(99, 102, 241, 0.2)";
175
197
  }
176
198
  }, onMouseDown: (e) => {
177
- if (!disabled && !loading) {
199
+ if (!disabled && !loading && isAuthReady) {
178
200
  e.currentTarget.style.transform = "scale(0.98)";
179
201
  }
180
202
  }, onMouseUp: (e) => {
181
- if (!disabled && !loading) {
203
+ if (!disabled && !loading && isAuthReady) {
182
204
  e.currentTarget.style.transform = "scale(1.02)";
183
205
  }
184
- }, "data-ai-image-button": true, children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 18, className: "animate-spin", style: {
206
+ }, "data-ai-image-button": true, title: !isAuthReady ? "Authentication required" : "Générer une image", children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 18, className: "animate-spin", style: {
185
207
  color: "white",
186
208
  filter: "drop-shadow(0 0 2px rgba(255,255,255,0.3))",
187
- } }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: "G\u00E9n\u00E9ration..." })] })) : (_jsxs(_Fragment, { children: [_jsx(ImageIcon, { size: 18, style: {
209
+ } }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: "G\u00E9n\u00E9ration..." })] })) : !isAuthReady ? (_jsxs(_Fragment, { children: [_jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }), _jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })] }), children || _jsx("span", { children: "Connexion requise" })] })) : (_jsxs(_Fragment, { children: [_jsx(ImageIcon, { size: 18, style: {
188
210
  color: "white",
189
211
  filter: "drop-shadow(0 0 2px rgba(255,255,255,0.2))",
190
212
  } }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: children || "Générer une image" })] })) }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, enableModelManagement: true, modelCategory: "image", baseUrl: baseUrl, apiKey: apiKeyId, models: [] }))] }), showImageCard && generatedImage && (_jsxs("div", { className: "relative", style: {
@@ -231,5 +253,5 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
231
253
  e.currentTarget.style.boxShadow = "";
232
254
  }, 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: {
233
255
  ...getThemeStyles().metadata,
234
- }, children: _jsx("div", { className: "flex justify-center", children: _jsxs("span", { children: ["ID: ", generatedImage.requestId.slice(-8)] }) }) })] })), _jsx(ErrorToast, { error: errorData, onComplete: clearError }, errorKey)] }));
256
+ }, children: _jsx("div", { className: "flex justify-center", children: _jsxs("span", { children: ["ID: ", generatedImage.requestId.slice(-8)] }) }) })] })), _jsx(LBSigninModal, { isOpen: showAuthModal, onClose: () => setShowAuthModal(false) }), _jsx(ErrorToast, { error: errorData, onComplete: clearError }, errorKey)] }));
235
257
  }
@@ -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,qBAA4B,EAC5B,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,UAAU,EACd,EAAE,YAAY,2CAkLd"}
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;AAU5C,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,qBAA4B,EAC5B,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,UAAU,EACd,EAAE,YAAY,2CAyNd"}
@@ -8,13 +8,26 @@ 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
+ import { useLB } from "../context/LBAuthProvider";
12
+ import { LBSigninModal } from "./LBSigninModal";
11
13
  export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, editMode = false, enableModelManagement = true, storeOutputs, artifactTitle, onValue, onToast, disabled, className, ...inputProps }) {
12
14
  const [isOpen, setIsOpen] = useState(false);
15
+ const [showAuthModal, setShowAuthModal] = useState(false);
13
16
  const [inputValue, setInputValue] = useState(inputProps.value?.toString() || inputProps.defaultValue?.toString() || "");
14
17
  const [isFocused, setIsFocused] = useState(false);
15
18
  const [isButtonHovered, setIsButtonHovered] = useState(false);
16
19
  const inputRef = useRef(null);
17
20
  const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
21
+ // Rendre l'authentification optionnelle
22
+ let lbStatus;
23
+ try {
24
+ const lbContext = useLB();
25
+ lbStatus = lbContext.status;
26
+ }
27
+ catch {
28
+ // LBProvider n'est pas disponible, ignorer
29
+ lbStatus = undefined;
30
+ }
18
31
  const { models } = useAiModels({
19
32
  baseUrl,
20
33
  apiKeyId,
@@ -22,7 +35,13 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
22
35
  });
23
36
  const { generateText, loading } = useAiCallText({ baseUrl, apiKeyId });
24
37
  const hasConfiguration = Boolean(model && prompt);
38
+ const isAuthReady = lbStatus === "ready" || Boolean(process.env.LB_API_KEY);
39
+ const shouldShowSparkles = isAuthReady && !disabled;
25
40
  const handleOpenPanel = () => {
41
+ if (!isAuthReady) {
42
+ setShowAuthModal(true);
43
+ return;
44
+ }
26
45
  setIsOpen(true);
27
46
  };
28
47
  const handleClosePanel = () => {
@@ -109,5 +128,9 @@ export function AiInput({ baseUrl, apiKeyId, uiMode = "modal", context, model, p
109
128
  ...(disabled || loading
110
129
  ? { opacity: 0.5, cursor: "not-allowed" }
111
130
  : {}),
112
- }, 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: [], modelCategory: "text", sourceText: inputValue || undefined, apiKey: apiKeyId, baseUrl: baseUrl, enableModelManagement: enableModelManagement })), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey))] }));
131
+ }, onClick: hasConfiguration ? handleQuickGenerate : handleOpenPanel, onMouseEnter: () => setIsButtonHovered(true), onMouseLeave: () => setIsButtonHovered(false), disabled: disabled || loading || !isAuthReady, type: "button", title: !isAuthReady
132
+ ? "Authentication required"
133
+ : hasConfiguration
134
+ ? "Generate with AI"
135
+ : "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" }) })) : shouldShowSparkles ? (_jsx(Sparkles, { size: 16 })) : (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }), _jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })] })) }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: [], modelCategory: "text", sourceText: inputValue || undefined, apiKey: apiKeyId, baseUrl: baseUrl, enableModelManagement: enableModelManagement })), _jsx(LBSigninModal, { isOpen: showAuthModal, onClose: () => setShowAuthModal(false) }), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey))] }));
113
136
  }
@@ -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;AAYtD,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,2CAiiBrB"}
1
+ {"version":3,"file":"AiStatusButton.d.ts","sourceRoot":"","sources":["../../src/components/AiStatusButton.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAetD,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,2CA41BrB"}
@@ -1,10 +1,29 @@
1
1
  "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import { useState, useRef, useLayoutEffect } from "react";
4
4
  import { createPortal } from "react-dom";
5
- import { BarChart3, Settings, FileText, History as HistoryIcon, FolderPlus, } from "lucide-react";
5
+ import { BarChart3, Settings, FileText, History as HistoryIcon, FolderPlus, Power, } from "lucide-react";
6
6
  import { aiStyles, calculateTooltipPosition } from "../styles/inline";
7
+ import { useLB } from "../context/LBAuthProvider";
8
+ import { LBSigninModal } from "./LBSigninModal";
7
9
  export function AiStatusButton({ status, loading = false, className = "", }) {
10
+ // Rendre l'authentification optionnelle
11
+ let lbStatus;
12
+ let user;
13
+ let logout;
14
+ try {
15
+ const lbContext = useLB();
16
+ lbStatus = lbContext.status;
17
+ user = lbContext.user;
18
+ logout = lbContext.logout;
19
+ }
20
+ catch {
21
+ // LBProvider n'est pas disponible, ignorer
22
+ lbStatus = undefined;
23
+ user = undefined;
24
+ logout = undefined;
25
+ }
26
+ const [showSigninModal, setShowSigninModal] = useState(false);
8
27
  const formatNumber = (value) => typeof value === "number" ? value.toLocaleString() : "0";
9
28
  const formatFixed = (value, digits) => typeof value === "number" ? value.toFixed(digits) : "0.00";
10
29
  const formatStorage = (valueMb) => {
@@ -139,17 +158,172 @@ export function AiStatusButton({ status, loading = false, className = "", }) {
139
158
  }, className: className, disabled: true, children: _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" }) }) }));
140
159
  }
141
160
  if (!status) {
142
- return (_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ref: buttonRef, style: {
143
- ...aiStyles.statusButton,
144
- color: "#ef4444",
145
- ...(isHovered && aiStyles.statusButtonHover),
146
- }, className: className, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("polyline", { points: "22 12 18 12 15 21 9 3 6 12 2 12" }) }) }), showTooltip &&
147
- canPortal &&
148
- createPortal(_jsx("div", { ref: tooltipRef, style: {
149
- ...aiStyles.tooltip,
150
- ...tooltipPosition,
151
- zIndex: 50,
152
- }, onMouseEnter: () => setShowTooltip(true), onMouseLeave: handleMouseLeave, children: "No status available" }), document.body)] }));
161
+ // Si pas de statut API et pas de LBProvider, afficher message simple
162
+ if (!lbStatus && lbStatus !== "ready") {
163
+ return (_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ref: buttonRef, style: {
164
+ ...aiStyles.statusButton,
165
+ color: "#ef4444",
166
+ ...(isHovered && aiStyles.statusButtonHover),
167
+ }, className: className, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("polyline", { points: "22 12 18 12 15 21 9 3 6 12 2 12" }) }) }), showTooltip &&
168
+ canPortal &&
169
+ createPortal(_jsx("div", { ref: tooltipRef, style: {
170
+ ...aiStyles.tooltip,
171
+ ...tooltipPosition,
172
+ zIndex: 50,
173
+ }, onMouseEnter: () => setShowTooltip(true), onMouseLeave: handleMouseLeave, children: "No status available" }), document.body)] }));
174
+ }
175
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ref: buttonRef, style: {
176
+ ...aiStyles.statusButton,
177
+ color: lbStatus === "ready" ? "#10b981" : "#ef4444",
178
+ ...(isHovered && aiStyles.statusButtonHover),
179
+ }, className: className, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onClick: () => {
180
+ if (lbStatus !== "ready") {
181
+ setShowSigninModal(true);
182
+ }
183
+ }, children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", children: _jsx("polyline", { points: "22 12 18 12 15 21 9 3 6 12 2 12" }) }) }), showTooltip &&
184
+ canPortal &&
185
+ createPortal(_jsx("div", { ref: tooltipRef, style: {
186
+ ...aiStyles.tooltip,
187
+ ...tooltipPosition,
188
+ zIndex: 50,
189
+ }, onMouseEnter: () => setShowTooltip(true), onMouseLeave: handleMouseLeave, children: lbStatus === "ready" && user ? (_jsxs(_Fragment, { children: [_jsx("div", { style: aiStyles.tooltipHeader, children: "LastBrain Connected" }), _jsx("div", { style: {
190
+ ...aiStyles.tooltipSection,
191
+ paddingBottom: "8px",
192
+ }, children: _jsxs("div", { style: aiStyles.tooltipRow, children: [_jsx("span", { style: aiStyles.tooltipLabel, children: "User:" }), _jsx("span", { style: aiStyles.tooltipValue, children: user.email })] }) }), _jsxs("div", { style: {
193
+ display: "flex",
194
+ gap: "8px",
195
+ borderTop: "1px solid var(--ai-border-primary, #374151)",
196
+ paddingTop: "12px",
197
+ }, children: [_jsx("button", { onClick: () => window.open("https://lastbrain.io/metrics", "_blank"), style: {
198
+ flex: 1,
199
+ background: "transparent",
200
+ border: "none",
201
+ padding: "14px",
202
+ cursor: "pointer",
203
+ display: "flex",
204
+ alignItems: "center",
205
+ justifyContent: "center",
206
+ color: "#8b5cf6",
207
+ transition: "all 0.2s ease",
208
+ }, onMouseEnter: (e) => {
209
+ Object.assign(e.currentTarget.style, {
210
+ background: "rgba(139, 92, 246, 0.1)",
211
+ });
212
+ }, onMouseLeave: (e) => {
213
+ Object.assign(e.currentTarget.style, {
214
+ background: "transparent",
215
+ });
216
+ }, title: "View Metrics", children: _jsx(BarChart3, { size: 18 }) }), _jsx("button", { onClick: () => window.open("https://lastbrain.io/settings", "_blank"), style: {
217
+ flex: 1,
218
+ background: "transparent",
219
+ border: "none",
220
+ padding: "14px",
221
+ cursor: "pointer",
222
+ display: "flex",
223
+ alignItems: "center",
224
+ justifyContent: "center",
225
+ color: "#8b5cf6",
226
+ transition: "all 0.2s ease",
227
+ }, onMouseEnter: (e) => {
228
+ Object.assign(e.currentTarget.style, {
229
+ background: "rgba(139, 92, 246, 0.1)",
230
+ });
231
+ }, onMouseLeave: (e) => {
232
+ Object.assign(e.currentTarget.style, {
233
+ background: "transparent",
234
+ });
235
+ }, title: "Settings", children: _jsx(Settings, { size: 18 }) }), _jsx("button", { onClick: () => window.open("https://prompt.lastbrain.io/auth/prompts", "_blank"), style: {
236
+ flex: 1,
237
+ background: "transparent",
238
+ border: "none",
239
+ padding: "14px",
240
+ cursor: "pointer",
241
+ display: "flex",
242
+ alignItems: "center",
243
+ justifyContent: "center",
244
+ color: "#8b5cf6",
245
+ transition: "all 0.2s ease",
246
+ }, onMouseEnter: (e) => {
247
+ Object.assign(e.currentTarget.style, {
248
+ background: "rgba(139, 92, 246, 0.1)",
249
+ });
250
+ }, onMouseLeave: (e) => {
251
+ Object.assign(e.currentTarget.style, {
252
+ background: "transparent",
253
+ });
254
+ }, title: "My Prompts", children: _jsx(FileText, { size: 18 }) }), _jsx("button", { onClick: () => window.open("https://prompt.lastbrain.io/auth/folder", "_blank"), style: {
255
+ flex: 1,
256
+ background: "transparent",
257
+ border: "none",
258
+ padding: "14px",
259
+ cursor: "pointer",
260
+ display: "flex",
261
+ alignItems: "center",
262
+ justifyContent: "center",
263
+ color: "#8b5cf6",
264
+ transition: "all 0.2s ease",
265
+ }, onMouseEnter: (e) => {
266
+ Object.assign(e.currentTarget.style, {
267
+ background: "rgba(139, 92, 246, 0.1)",
268
+ });
269
+ }, onMouseLeave: (e) => {
270
+ Object.assign(e.currentTarget.style, {
271
+ background: "transparent",
272
+ });
273
+ }, title: "New Folder", children: _jsx(FolderPlus, { size: 18 }) }), _jsx("button", { onClick: async () => {
274
+ if (logout) {
275
+ await logout();
276
+ }
277
+ setShowTooltip(false);
278
+ }, style: {
279
+ flex: 1,
280
+ background: "transparent",
281
+ border: "none",
282
+ padding: "14px",
283
+ cursor: "pointer",
284
+ display: "flex",
285
+ alignItems: "center",
286
+ justifyContent: "center",
287
+ color: "#ef4444",
288
+ transition: "all 0.2s ease",
289
+ }, onMouseEnter: (e) => {
290
+ Object.assign(e.currentTarget.style, {
291
+ background: "rgba(239, 68, 68, 0.1)",
292
+ });
293
+ }, onMouseLeave: (e) => {
294
+ Object.assign(e.currentTarget.style, {
295
+ background: "transparent",
296
+ });
297
+ }, title: "Logout", children: _jsx(Power, { size: 18 }) })] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { style: aiStyles.tooltipHeader, children: "LastBrain Authentication" }), _jsx("div", { style: {
298
+ ...aiStyles.tooltipSection,
299
+ paddingBottom: "12px",
300
+ }, children: _jsx("p", { style: {
301
+ margin: 0,
302
+ fontSize: "13px",
303
+ color: "var(--ai-text-secondary, #9ca3af)",
304
+ lineHeight: "1.5",
305
+ }, children: "Connectez-vous pour acc\u00E9der aux fonctionnalit\u00E9s IA" }) }), _jsx("button", { onClick: () => {
306
+ setShowSigninModal(true);
307
+ setShowTooltip(false);
308
+ }, style: {
309
+ width: "100%",
310
+ padding: "10px",
311
+ background: "linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%)",
312
+ border: "none",
313
+ borderRadius: "6px",
314
+ color: "#ffffff",
315
+ fontSize: "13px",
316
+ fontWeight: 600,
317
+ cursor: "pointer",
318
+ transition: "all 0.2s ease",
319
+ }, onMouseEnter: (e) => {
320
+ e.currentTarget.style.transform = "translateY(-1px)";
321
+ e.currentTarget.style.boxShadow =
322
+ "0 4px 12px rgba(139, 92, 246, 0.3)";
323
+ }, onMouseLeave: (e) => {
324
+ e.currentTarget.style.transform = "translateY(0)";
325
+ e.currentTarget.style.boxShadow = "none";
326
+ }, children: "\uD83D\uDD10 Se connecter" })] })) }), document.body)] }), _jsx(LBSigninModal, { isOpen: showSigninModal, onClose: () => setShowSigninModal(false) })] }));
153
327
  }
154
328
  return (_jsxs("div", { style: { position: "relative", display: "inline-block" }, children: [_jsx("button", { ref: buttonRef, style: {
155
329
  ...aiStyles.statusButton,
@@ -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,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,aAAa,EACjB,EAAE,eAAe,2CAmMjB"}
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;AAU5C,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,2CA0OjB"}
@@ -8,8 +8,11 @@ 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
+ import { useLB } from "../context/LBAuthProvider";
12
+ import { LBSigninModal } from "./LBSigninModal";
11
13
  export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model, prompt, editMode = false, enableModelManagement, storeOutputs, artifactTitle, onValue, onToast, disabled, className, ...textareaProps }) {
12
14
  const [isOpen, setIsOpen] = useState(false);
15
+ const [showAuthModal, setShowAuthModal] = useState(false);
13
16
  const [textareaValue, setTextareaValue] = useState(textareaProps.value?.toString() ||
14
17
  textareaProps.defaultValue?.toString() ||
15
18
  "");
@@ -17,6 +20,16 @@ export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model
17
20
  const [isButtonHovered, setIsButtonHovered] = useState(false);
18
21
  const textareaRef = useRef(null);
19
22
  const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
23
+ // Rendre l'authentification optionnelle
24
+ let lbStatus;
25
+ try {
26
+ const lbContext = useLB();
27
+ lbStatus = lbContext.status;
28
+ }
29
+ catch {
30
+ // LBProvider n'est pas disponible, ignorer
31
+ lbStatus = undefined;
32
+ }
20
33
  const { models } = useAiModels({
21
34
  baseUrl,
22
35
  apiKeyId,
@@ -24,7 +37,13 @@ export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model
24
37
  });
25
38
  const { generateText, loading } = useAiCallText({ baseUrl, apiKeyId });
26
39
  const hasConfiguration = Boolean(model && prompt);
40
+ const isAuthReady = lbStatus === "ready" || Boolean(process.env.LB_API_KEY);
41
+ const shouldShowSparkles = isAuthReady && !disabled;
27
42
  const handleOpenPanel = () => {
43
+ if (!isAuthReady) {
44
+ setShowAuthModal(true);
45
+ return;
46
+ }
28
47
  setIsOpen(true);
29
48
  };
30
49
  const handleClosePanel = () => {
@@ -123,5 +142,9 @@ export function AiTextarea({ baseUrl, apiKeyId, uiMode = "modal", context, model
123
142
  ...(disabled || loading
124
143
  ? { opacity: 0.5, cursor: "not-allowed" }
125
144
  : {}),
126
- }, 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: [], modelCategory: "text", sourceText: textareaValue || undefined, baseUrl: baseUrl, apiKey: apiKeyId, enableModelManagement: enableModelManagement })), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey))] }));
145
+ }, onClick: hasConfiguration ? handleQuickGenerate : handleOpenPanel, onMouseEnter: () => setIsButtonHovered(true), onMouseLeave: () => setIsButtonHovered(false), disabled: disabled || loading || !isAuthReady, type: "button", title: !isAuthReady
146
+ ? "Authentication required"
147
+ : hasConfiguration
148
+ ? "Generate with AI"
149
+ : "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" }) })) : shouldShowSparkles ? (_jsx(Sparkles, { size: 16 })) : (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [_jsx("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2", ry: "2" }), _jsx("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })] })) }), isOpen && (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: handleClosePanel, onSubmit: handleSubmit, uiMode: uiMode, models: [], modelCategory: "text", sourceText: textareaValue || undefined, baseUrl: baseUrl, apiKey: apiKeyId, enableModelManagement: enableModelManagement })), Boolean(toastData) && (_jsx(UsageToast, { result: toastData, position: "bottom-right", onComplete: clearToast }, toastKey)), _jsx(LBSigninModal, { isOpen: showAuthModal, onClose: () => setShowAuthModal(false) })] }));
127
150
  }
@@ -1 +1 @@
1
- {"version":3,"file":"LBConnectButton.d.ts","sourceRoot":"","sources":["../../src/components/LBConnectButton.tsx"],"names":[],"mappings":"AAUA,UAAU,oBAAoB;IAC5B,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAkC,EAClC,SAAc,EACd,WAAW,EACX,WAAW,GACZ,EAAE,oBAAoB,2CA0CtB;AAED;;GAEG;AACH,UAAU,gBAAgB;IACxB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC;AAED,iBAAS,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,gBAAgB,2CAsJjD;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"LBConnectButton.d.ts","sourceRoot":"","sources":["../../src/components/LBConnectButton.tsx"],"names":[],"mappings":"AAWA,UAAU,oBAAoB;IAC5B,sBAAsB;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,yCAAyC;IACzC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,wBAAgB,eAAe,CAAC,EAC9B,KAAkC,EAClC,SAAc,EACd,WAAW,EACX,WAAW,GACZ,EAAE,oBAAoB,2CA4CtB;AAED;;GAEG;AACH,UAAU,gBAAgB;IACxB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC;AAED,iBAAS,WAAW,CAAC,EAAE,OAAO,EAAE,EAAE,gBAAgB,2CA+RjD;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}