@lastbrain/ai-ui-react 1.0.68 → 1.0.70

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.
Files changed (76) hide show
  1. package/dist/components/AiChipLabel.d.ts +8 -3
  2. package/dist/components/AiChipLabel.d.ts.map +1 -1
  3. package/dist/components/AiChipLabel.js +23 -70
  4. package/dist/components/AiContextButton.d.ts +10 -2
  5. package/dist/components/AiContextButton.d.ts.map +1 -1
  6. package/dist/components/AiContextButton.js +73 -291
  7. package/dist/components/AiImageButton.d.ts +5 -1
  8. package/dist/components/AiImageButton.d.ts.map +1 -1
  9. package/dist/components/AiImageButton.js +6 -142
  10. package/dist/components/AiInput.d.ts +5 -3
  11. package/dist/components/AiInput.d.ts.map +1 -1
  12. package/dist/components/AiInput.js +13 -25
  13. package/dist/components/AiPromptPanel.d.ts.map +1 -1
  14. package/dist/components/AiPromptPanel.js +64 -212
  15. package/dist/components/AiSelect.d.ts +5 -3
  16. package/dist/components/AiSelect.d.ts.map +1 -1
  17. package/dist/components/AiSelect.js +21 -30
  18. package/dist/components/AiStatusButton.d.ts +4 -1
  19. package/dist/components/AiStatusButton.d.ts.map +1 -1
  20. package/dist/components/AiStatusButton.js +211 -676
  21. package/dist/components/AiTextarea.d.ts +4 -2
  22. package/dist/components/AiTextarea.d.ts.map +1 -1
  23. package/dist/components/AiTextarea.js +14 -26
  24. package/dist/components/LBApiKeySelector.d.ts.map +1 -1
  25. package/dist/components/LBApiKeySelector.js +5 -166
  26. package/dist/components/LBConnectButton.d.ts +4 -7
  27. package/dist/components/LBConnectButton.d.ts.map +1 -1
  28. package/dist/components/LBConnectButton.js +17 -86
  29. package/dist/components/LBSigninModal.d.ts +1 -1
  30. package/dist/components/LBSigninModal.d.ts.map +1 -1
  31. package/dist/components/LBSigninModal.js +42 -320
  32. package/dist/context/LBAuthProvider.d.ts +35 -3
  33. package/dist/context/LBAuthProvider.d.ts.map +1 -1
  34. package/dist/context/LBAuthProvider.js +2 -0
  35. package/dist/examples/AiUiPremiumShowcase.d.ts +2 -0
  36. package/dist/examples/AiUiPremiumShowcase.d.ts.map +1 -0
  37. package/dist/examples/AiUiPremiumShowcase.js +15 -0
  38. package/dist/hooks/useAiModels.d.ts.map +1 -1
  39. package/dist/hooks/useModelManagement.d.ts.map +1 -1
  40. package/dist/index.d.ts +2 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +2 -0
  43. package/dist/styles/inline.d.ts +1 -0
  44. package/dist/styles/inline.d.ts.map +1 -1
  45. package/dist/styles/inline.js +25 -129
  46. package/dist/styles.css +1268 -369
  47. package/dist/types.d.ts +3 -0
  48. package/dist/types.d.ts.map +1 -1
  49. package/dist/utils/errorHandler.d.ts +2 -2
  50. package/dist/utils/errorHandler.d.ts.map +1 -1
  51. package/dist/utils/errorHandler.js +8 -1
  52. package/dist/utils/modelManagement.d.ts +13 -10
  53. package/dist/utils/modelManagement.d.ts.map +1 -1
  54. package/dist/utils/modelManagement.js +19 -2
  55. package/package.json +2 -2
  56. package/src/components/AiChipLabel.tsx +68 -101
  57. package/src/components/AiContextButton.tsx +142 -413
  58. package/src/components/AiImageButton.tsx +29 -190
  59. package/src/components/AiInput.tsx +49 -74
  60. package/src/components/AiPromptPanel.tsx +81 -260
  61. package/src/components/AiSelect.tsx +61 -69
  62. package/src/components/AiStatusButton.tsx +496 -1327
  63. package/src/components/AiTextarea.tsx +50 -63
  64. package/src/components/LBApiKeySelector.tsx +93 -271
  65. package/src/components/LBConnectButton.tsx +39 -336
  66. package/src/components/LBSigninModal.tsx +141 -472
  67. package/src/context/LBAuthProvider.tsx +45 -6
  68. package/src/examples/AiUiPremiumShowcase.tsx +94 -0
  69. package/src/hooks/useAiModels.ts +2 -1
  70. package/src/hooks/useModelManagement.ts +2 -1
  71. package/src/index.ts +3 -0
  72. package/src/styles/inline.ts +27 -148
  73. package/src/styles.css +1268 -369
  74. package/src/types.ts +3 -0
  75. package/src/utils/errorHandler.ts +16 -3
  76. package/src/utils/modelManagement.ts +53 -15
@@ -1,11 +1,14 @@
1
1
  import React from "react";
2
+ import type { AiRadius, AiSize } from "../types";
2
3
  export interface AiChipLabelProps {
3
4
  children: React.ReactNode;
4
- variant?: "default" | "success" | "warning" | "danger";
5
+ variant?: "default" | "selected" | "warning" | "success" | "danger";
6
+ size?: AiSize;
7
+ radius?: AiRadius;
5
8
  className?: string;
6
9
  style?: React.CSSProperties;
7
10
  }
8
- export declare function AiChipLabel({ children, variant, className, style: customStyle, }: AiChipLabelProps): import("react/jsx-runtime").JSX.Element;
11
+ export declare function AiChipLabel({ children, variant, size, radius, className, style: customStyle, }: AiChipLabelProps): import("react/jsx-runtime").JSX.Element;
9
12
  export interface AiChipInputProps {
10
13
  value?: string[];
11
14
  onChange?: (chips: string[]) => void;
@@ -18,6 +21,8 @@ export interface AiChipInputProps {
18
21
  artifactTitle?: string;
19
22
  baseUrl?: string;
20
23
  apiKeyId?: string;
24
+ size?: AiSize;
25
+ radius?: AiRadius;
21
26
  }
22
- export declare function AiChipInput({ value, onChange, placeholder, context, maxChips, allowDuplicates, className, storeOutputs, artifactTitle, baseUrl: propBaseUrl, apiKeyId: propApiKeyId, }: AiChipInputProps): import("react/jsx-runtime").JSX.Element;
27
+ export declare function AiChipInput({ value, onChange, placeholder, context, maxChips, allowDuplicates, className, storeOutputs, artifactTitle, baseUrl: propBaseUrl, apiKeyId: propApiKeyId, size, radius, }: AiChipInputProps): import("react/jsx-runtime").JSX.Element;
23
28
  //# sourceMappingURL=AiChipLabel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AiChipLabel.d.ts","sourceRoot":"","sources":["../../src/components/AiChipLabel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAW/D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAmB,EACnB,SAAS,EACT,KAAK,EAAE,WAAW,GACnB,EAAE,gBAAgB,2CAgClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,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,WAAW,CAAC,EAC1B,KAAU,EACV,QAAQ,EACR,WAAoE,EACpE,OAAO,EACP,QAAQ,EACR,eAAuB,EACvB,SAAS,EACT,YAAY,EACZ,aAAa,EACb,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,GACvB,EAAE,gBAAgB,2CA+NlB"}
1
+ {"version":3,"file":"AiChipLabel.d.ts","sourceRoot":"","sources":["../../src/components/AiChipLabel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA0C,MAAM,OAAO,CAAC;AAS/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,wBAAgB,WAAW,CAAC,EAC1B,QAAQ,EACR,OAAmB,EACnB,IAAW,EACX,MAAe,EACf,SAAS,EACT,KAAK,EAAE,WAAW,GACnB,EAAE,gBAAgB,2CAiBlB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAU,EACV,QAAQ,EACR,WAAoE,EACpE,OAAO,EACP,QAAQ,EACR,eAAuB,EACvB,SAAS,EACT,YAAY,EACZ,aAAa,EACb,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,IAAW,EACX,MAAe,GAChB,EAAE,gBAAgB,2CAqMlB"}
@@ -2,7 +2,6 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useState, useRef } from "react";
4
4
  import { X, Sparkles, Lock } from "lucide-react";
5
- import { aiStyles } from "../styles/inline";
6
5
  import { AiPromptPanel } from "./AiPromptPanel";
7
6
  import { LBSigninModal } from "./LBSigninModal";
8
7
  import { useAiCallText } from "../hooks/useAiCallText";
@@ -10,32 +9,17 @@ import { useAiModels } from "../hooks/useAiModels";
10
9
  import { useAiContext } from "../context/AiProvider";
11
10
  import { useLB } from "../context/LBAuthProvider";
12
11
  import { handleAIError } from "../utils/errorHandler";
13
- export function AiChipLabel({ children, variant = "default", className, style: customStyle, }) {
14
- const variantStyles = {
15
- default: {},
16
- success: {
17
- background: "#10b98110",
18
- color: "#10b981",
19
- borderColor: "#10b98130",
20
- },
21
- warning: {
22
- background: "#f59e0b10",
23
- color: "#f59e0b",
24
- borderColor: "#f59e0b30",
25
- },
26
- danger: {
27
- background: "#ef444410",
28
- color: "#ef4444",
29
- borderColor: "#ef444430",
30
- },
12
+ export function AiChipLabel({ children, variant = "default", size = "md", radius = "full", className, style: customStyle, }) {
13
+ const variantClassMap = {
14
+ default: "",
15
+ selected: "ai-chip--selected",
16
+ warning: "ai-chip--success",
17
+ success: "ai-chip--success",
18
+ danger: "ai-chip--danger",
31
19
  };
32
- return (_jsx("span", { style: {
33
- ...aiStyles.chip,
34
- ...variantStyles[variant],
35
- ...customStyle,
36
- }, className: className, children: children }));
20
+ return (_jsx("span", { style: customStyle, className: `ai-chip ai-size-${size} ai-radius-${radius} ${variantClassMap[variant]} ${className || ""}`, children: children }));
37
21
  }
38
- export function AiChipInput({ value = [], onChange, placeholder = "Tapez et appuyez sur Entrée pour ajouter des tags...", context, maxChips, allowDuplicates = false, className, storeOutputs, artifactTitle, baseUrl: propBaseUrl, apiKeyId: propApiKeyId, }) {
22
+ export function AiChipInput({ value = [], onChange, placeholder = "Tapez et appuyez sur Entrée pour ajouter des tags...", context, maxChips, allowDuplicates = false, className, storeOutputs, artifactTitle, baseUrl: propBaseUrl, apiKeyId: propApiKeyId, size = "md", radius = "full", }) {
39
23
  const [inputValue, setInputValue] = useState("");
40
24
  const [showPromptPanel, setShowPromptPanel] = useState(false);
41
25
  const [showSigninModal, setShowSigninModal] = useState(false);
@@ -138,49 +122,18 @@ Exemple de réponse attendue: javascript, react, frontend, api, development`;
138
122
  });
139
123
  onChange?.(updatedChips);
140
124
  };
141
- console.log("AiChipInput render - value:", value, "length:", value.length);
142
- return (_jsxs("div", { className: className, children: [_jsxs("div", { style: { position: "relative", marginBottom: "8px" }, children: [_jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, style: {
143
- ...aiStyles.input,
144
- paddingRight: "40px", // Space for button
145
- } }), _jsx("button", { onClick: () => {
146
- if (isAuthenticated) {
147
- handleGenerateChips();
148
- }
149
- else {
150
- setShowSigninModal(true);
151
- }
152
- }, style: {
153
- position: "absolute",
154
- right: "8px",
155
- top: "50%",
156
- transform: "translateY(-50%)",
157
- background: "none",
158
- border: "none",
159
- cursor: "pointer",
160
- padding: "4px",
161
- borderRadius: "4px",
162
- display: "flex",
163
- alignItems: "center",
164
- color: isAuthenticated ? "#6366f1" : "#ef4444",
165
- }, title: isAuthenticated
166
- ? "Générer des tags avec l'IA"
167
- : "Se connecter pour utiliser l'IA", children: isAuthenticated ? _jsx(Sparkles, { size: 16 }) : _jsx(Lock, { size: 16 }) })] }), value.length > 0 && (_jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: value.map((chip, index) => {
168
- console.log("Rendering chip:", chip, "at index:", index);
169
- return (_jsxs("div", { style: {
170
- ...aiStyles.chip,
171
- display: "flex",
172
- alignItems: "center",
173
- gap: "6px",
174
- paddingRight: "6px",
175
- }, children: [_jsx("span", { children: chip }), _jsx("button", { onClick: () => removeChip(index), style: {
176
- background: "none",
177
- border: "none",
178
- cursor: "pointer",
179
- padding: "0",
180
- display: "flex",
181
- alignItems: "center",
182
- color: "currentColor",
183
- opacity: 0.7,
184
- }, title: "Supprimer", children: _jsx(X, { size: 14 }) })] }, index));
185
- }) })), _jsx(AiPromptPanel, { isOpen: showPromptPanel, onClose: () => setShowPromptPanel(false), onSubmit: handlePromptSubmit, models: models || undefined, baseUrl: baseUrl, sourceText: context ? `Contexte: ${context}` : undefined, enableModelManagement: true, showOnlyUserModels: true }), _jsx(LBSigninModal, { isOpen: showSigninModal, onClose: () => setShowSigninModal(false) })] }));
125
+ const sizeClass = `ai-size-${size}`;
126
+ const radiusClass = `ai-radius-${radius}`;
127
+ return (_jsxs("div", { className: className, children: [_jsx("div", { className: "ai-control-group ai-glow mb-2", children: _jsxs("div", { className: `ai-shell ${sizeClass} ${radiusClass}`, children: [_jsx("input", { ref: inputRef, type: "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), onKeyDown: handleKeyDown, placeholder: placeholder, className: `ai-control ai-control-input ai-control-input--with-action ${sizeClass} ${radiusClass}` }), _jsx("button", { onClick: () => {
128
+ if (isAuthenticated) {
129
+ handleGenerateChips();
130
+ }
131
+ else {
132
+ setShowSigninModal(true);
133
+ }
134
+ }, className: `ai-control-action ai-spark ${sizeClass} ${radiusClass}`, "aria-label": isAuthenticated
135
+ ? "Générer des tags avec l'IA"
136
+ : "Connexion requise", title: isAuthenticated
137
+ ? "Générer des tags avec l'IA"
138
+ : "Se connecter pour utiliser l'IA", children: isAuthenticated ? _jsx(Sparkles, { size: 16 }) : _jsx(Lock, { size: 16 }) })] }) }), value.length > 0 && (_jsx("div", { className: "ai-chip-input", children: value.map((chip, index) => (_jsxs("div", { className: `ai-chip ai-chip--with-close ${sizeClass} ${radiusClass}`, children: [_jsx("span", { children: chip }), _jsx("button", { onClick: () => removeChip(index), className: "ai-chip-remover", title: "Supprimer", children: _jsx(X, { size: 14 }) })] }, index))) })), _jsx(AiPromptPanel, { isOpen: showPromptPanel, onClose: () => setShowPromptPanel(false), onSubmit: handlePromptSubmit, models: models || undefined, baseUrl: baseUrl, sourceText: context ? `Contexte: ${context}` : undefined, enableModelManagement: true, showOnlyUserModels: true }), _jsx(LBSigninModal, { isOpen: showSigninModal, onClose: () => setShowSigninModal(false) })] }));
186
139
  }
@@ -1,7 +1,11 @@
1
1
  import { type ButtonHTMLAttributes } from "react";
2
2
  import type { BaseAiProps } from "../types";
3
+ import type { AiRadius, AiSize, AiVariant } from "../types";
4
+ type ContextData = string | number | boolean | object | unknown[] | {
5
+ [key: string]: unknown;
6
+ };
3
7
  export interface AiContextButtonProps extends Omit<BaseAiProps, "onValue" | "type">, Omit<ButtonHTMLAttributes<HTMLButtonElement>, "baseUrl" | "apiKeyId"> {
4
- contextData: any;
8
+ contextData: ContextData;
5
9
  contextDescription?: string;
6
10
  onResult?: (result: string, metadata?: {
7
11
  requestId: string;
@@ -13,6 +17,10 @@ export interface AiContextButtonProps extends Omit<BaseAiProps, "onValue" | "typ
13
17
  artifactTitle?: string;
14
18
  baseUrl?: string;
15
19
  apiKeyId?: string;
20
+ size?: AiSize;
21
+ radius?: AiRadius;
22
+ variant?: AiVariant;
16
23
  }
17
- export declare function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMode, contextData, contextDescription, onResult, onToast, disabled, className, children, resultModalTitle, storeOutputs, artifactTitle, context: _context, model: _model, prompt: _prompt, ...buttonProps }: AiContextButtonProps): import("react/jsx-runtime").JSX.Element;
24
+ export declare function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMode, contextData, contextDescription, onResult, onToast, disabled, className, children, resultModalTitle, size, radius, variant, context: _context, ...buttonProps }: AiContextButtonProps): import("react/jsx-runtime").JSX.Element;
25
+ export {};
18
26
  //# sourceMappingURL=AiContextButton.d.ts.map
@@ -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;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,2CAiiBtB"}
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;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAW5D,KAAK,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAE/F,MAAM,WAAW,oBACf,SACE,IAAI,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC,EACrC,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;IACvE,WAAW,EAAE,WAAW,CAAC;IACzB,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;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;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,IAAW,EACX,MAAe,EACf,OAAmB,EACnB,OAAO,EAAE,QAAQ,EACjB,GAAG,WAAW,EACf,EAAE,oBAAoB,2CA+QtB"}
@@ -1,34 +1,30 @@
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 { Loader2, X, FileText, Sparkle, Download, Lock } from "lucide-react";
4
+ import { Download, FileText, Loader2, Lock, Sparkles, X } from "lucide-react";
5
5
  import { useAiCallText } from "../hooks/useAiCallText";
6
6
  import { AiPromptPanel } from "./AiPromptPanel";
7
7
  import { useUsageToast } from "./UsageToast";
8
8
  import { useErrorToast, ErrorToast } from "./ErrorToast";
9
- import { aiStyles } from "../styles/inline";
10
9
  import { useAiContext } from "../context/AiProvider";
11
10
  import { handleAIError } from "../utils/errorHandler";
12
11
  import { useLB } from "../context/LBAuthProvider";
13
12
  import { LBSigninModal } from "./LBSigninModal";
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
+ 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", size = "md", radius = "full", variant = "default", context: _context, ...buttonProps }) {
15
14
  const [isOpen, setIsOpen] = useState(false);
16
15
  const [showAuthModal, setShowAuthModal] = useState(false);
17
16
  const [isResultOpen, setIsResultOpen] = useState(false);
18
17
  const [analysisResult, setAnalysisResult] = useState(null);
19
- const { showUsageToast, toastData, toastKey, clearToast } = useUsageToast();
18
+ const { showUsageToast } = useUsageToast();
20
19
  const { showErrorToast, errorData, errorKey, clearError } = useErrorToast();
21
- // Rendre l'authentification optionnelle
22
20
  let lbStatus;
23
21
  try {
24
22
  const lbContext = useLB();
25
23
  lbStatus = lbContext.status;
26
24
  }
27
25
  catch {
28
- // LBProvider n'est pas disponible, ignorer
29
26
  lbStatus = undefined;
30
27
  }
31
- // Récupérer le contexte AiProvider avec fallback sur les props
32
28
  const aiContext = useAiContext();
33
29
  const baseUrl = propBaseUrl ?? aiContext.baseUrl;
34
30
  const apiKeyId = propApiKeyId ?? aiContext.apiKeyId;
@@ -44,73 +40,10 @@ export function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId,
44
40
  }
45
41
  setIsOpen(true);
46
42
  };
47
- const handleClosePanel = () => {
48
- setIsOpen(false);
49
- };
50
- const handleCloseResult = () => {
51
- setIsResultOpen(false);
52
- setAnalysisResult(null);
53
- };
54
- const saveToFile = () => {
55
- if (!analysisResult)
56
- return;
57
- const currentDate = new Date()
58
- .toLocaleDateString("fr-FR")
59
- .replace(/\//g, "-");
60
- const defaultName = `analyse-${currentDate}.txt`;
61
- const fileName = prompt("Nom du fichier :", defaultName) || defaultName;
62
- const content = `ANALYSE DES DONNÉES - ${new Date().toLocaleString("fr-FR")}
63
-
64
- PROMPT UTILISÉ :
65
- ${analysisResult.prompt}
66
-
67
- RÉSULTAT DE L'ANALYSE :
68
- ${analysisResult.content}
69
-
70
- --- MÉTADONNÉES ---
71
- Tokens utilisés: ${analysisResult.tokens.toLocaleString()}
72
- Coût: $${(apiKeyId?.includes("dev") ? 0 : analysisResult.cost).toFixed(6)}
73
- ID de requête: ${analysisResult.requestId || "N/A"}
74
- Date: ${new Date().toLocaleString("fr-FR")}`;
75
- const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
76
- const url = URL.createObjectURL(blob);
77
- const a = document.createElement("a");
78
- a.href = url;
79
- a.download = fileName.endsWith(".txt") ? fileName : `${fileName}.txt`;
80
- document.body.appendChild(a);
81
- a.click();
82
- document.body.removeChild(a);
83
- URL.revokeObjectURL(url);
84
- };
85
- // Styles selon le thème
86
- const getThemeStyles = () => {
87
- const isDark = typeof document !== "undefined" &&
88
- (document.documentElement.classList.contains("dark") ||
89
- (!document.documentElement.classList.contains("light") &&
90
- window.matchMedia("(prefers-color-scheme: dark)").matches));
91
- return {
92
- modal: {
93
- backgroundColor: isDark ? "#1f2937" : "white",
94
- border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
95
- color: isDark ? "#f3f4f6" : "#374151",
96
- },
97
- header: {
98
- color: isDark ? "#f9fafb" : "#1f2937",
99
- borderBottom: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
100
- },
101
- content: {
102
- backgroundColor: isDark ? "#111827" : "#f9fafb",
103
- border: `1px solid ${isDark ? "#374151" : "#e5e7eb"}`,
104
- },
105
- closeButton: {
106
- color: isDark ? "#9ca3af" : "#6b7280",
107
- hoverColor: isDark ? "#d1d5db" : "#374151",
108
- },
109
- };
110
- };
111
43
  const formatContextData = (data) => {
112
- if (typeof data === "string")
44
+ if (typeof data === "string") {
113
45
  return data;
46
+ }
114
47
  if (typeof data === "object" && data !== null) {
115
48
  return JSON.stringify(data, null, 2);
116
49
  }
@@ -118,14 +51,8 @@ Date: ${new Date().toLocaleString("fr-FR")}`;
118
51
  };
119
52
  const handleSubmit = async (selectedModel, selectedPrompt) => {
120
53
  try {
121
- // Construire le prompt avec le contexte
122
54
  const contextString = formatContextData(contextData);
123
- const fullPrompt = `${selectedPrompt}
124
-
125
- CONTEXTE (${contextDescription}):
126
- ${contextString}
127
-
128
- Analyse ces données et réponds de manière structurée et claire.`;
55
+ const fullPrompt = `${selectedPrompt}\n\nCONTEXTE (${contextDescription}):\n${contextString}\n\nAnalyse ces données et réponds de manière structurée et claire.`;
129
56
  const result = await callText({
130
57
  prompt: fullPrompt,
131
58
  model: selectedModel || "gpt-4o-mini",
@@ -133,42 +60,40 @@ Analyse ces données et réponds de manière structurée et claire.`;
133
60
  maxTokens: 4000,
134
61
  temperature: 0.7,
135
62
  });
136
- if (result.text) {
137
- // Calculer le total des tokens depuis la réponse réelle
138
- const resultAny = result;
139
- const totalTokens = (resultAny.inputTokens || 0) + (resultAny.outputTokens || 0) ||
140
- result.debitTokens ||
141
- 0;
142
- const actualCost = resultAny.cost || 0;
143
- const resultData = {
144
- content: result.text,
145
- prompt: selectedPrompt,
146
- requestId: result.requestId,
147
- tokens: totalTokens,
148
- cost: actualCost,
149
- };
150
- setAnalysisResult(resultData);
151
- setIsResultOpen(true);
152
- onResult?.(result.text, {
153
- requestId: result.requestId,
154
- tokens: result.debitTokens || 0,
155
- });
156
- onToast?.({
157
- type: "success",
158
- message: `Analyse terminée - Coût: $${(apiKeyId?.includes("dev") ? 0 : actualCost).toFixed(6)}`,
159
- });
160
- // Afficher le toast de coût
161
- showUsageToast({
162
- requestId: result.requestId,
163
- debitTokens: totalTokens,
164
- usage: {
165
- total_tokens: totalTokens,
166
- prompt_tokens: resultAny.inputTokens || 0,
167
- completion_tokens: resultAny.outputTokens || 0,
168
- },
169
- cost: apiKeyId?.includes("dev") ? 0 : actualCost,
170
- });
63
+ if (!result.text) {
64
+ return;
171
65
  }
66
+ const resultAny = result;
67
+ const totalTokens = (resultAny.inputTokens || 0) + (resultAny.outputTokens || 0) ||
68
+ result.debitTokens ||
69
+ 0;
70
+ const actualCost = resultAny.cost || 0;
71
+ setAnalysisResult({
72
+ content: result.text,
73
+ prompt: selectedPrompt,
74
+ requestId: result.requestId,
75
+ tokens: totalTokens,
76
+ cost: actualCost,
77
+ });
78
+ setIsResultOpen(true);
79
+ onResult?.(result.text, {
80
+ requestId: result.requestId,
81
+ tokens: result.debitTokens || 0,
82
+ });
83
+ onToast?.({
84
+ type: "success",
85
+ message: `Analyse terminée - Coût: $${(apiKeyId?.includes("dev") ? 0 : actualCost).toFixed(6)}`,
86
+ });
87
+ showUsageToast({
88
+ requestId: result.requestId,
89
+ debitTokens: totalTokens,
90
+ usage: {
91
+ total_tokens: totalTokens,
92
+ prompt_tokens: resultAny.inputTokens || 0,
93
+ completion_tokens: resultAny.outputTokens || 0,
94
+ },
95
+ cost: apiKeyId?.includes("dev") ? 0 : actualCost,
96
+ });
172
97
  }
173
98
  catch (error) {
174
99
  console.error("AiContextButton error:", error);
@@ -178,183 +103,40 @@ Analyse ces données et réponds de manière structurée et claire.`;
178
103
  setIsOpen(false);
179
104
  }
180
105
  };
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: {
182
- ...aiStyles.button,
183
- display: "flex",
184
- alignItems: "center",
185
- gap: "8px",
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",
193
- color: "white",
194
- border: "none",
195
- borderRadius: "12px",
196
- // padding: "12px 20px",
197
- fontSize: "14px",
198
- fontWeight: "600",
199
- minWidth: "20px",
200
- height: "44px",
201
- transition: "all 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
202
- boxShadow: loading
203
- ? "0 4px 12px rgba(139, 92, 246, 0.3)"
204
- : "0 2px 8px rgba(124, 58, 237, 0.2)",
205
- transform: "scale(1)",
206
- ...(loading && {
207
- background: "linear-gradient(135deg, #7c3aed, #8b5cf6)",
208
- animation: "pulse 2s ease-in-out infinite",
209
- }),
210
- ...buttonProps.style,
211
- }, onMouseEnter: (e) => {
212
- if (!disabled && !loading && isAuthReady) {
213
- e.currentTarget.style.transform = "scale(1.02)";
214
- e.currentTarget.style.boxShadow =
215
- "0 6px 16px rgba(124, 58, 237, 0.3)";
216
- }
217
- }, onMouseLeave: (e) => {
218
- if (!disabled && !loading && isAuthReady) {
219
- e.currentTarget.style.transform = "scale(1)";
220
- e.currentTarget.style.boxShadow = loading
221
- ? "0 4px 12px rgba(139, 92, 246, 0.3)"
222
- : "0 2px 8px rgba(124, 58, 237, 0.2)";
223
- }
224
- }, onMouseDown: (e) => {
225
- if (!disabled && !loading && isAuthReady) {
226
- e.currentTarget.style.transform = "scale(0.98)";
227
- }
228
- }, onMouseUp: (e) => {
229
- if (!disabled && !loading && isAuthReady) {
230
- e.currentTarget.style.transform = "scale(1.02)";
231
- }
232
- }, "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: {
233
- color: "white",
234
- filter: "drop-shadow(0 0 2px rgba(255,255,255,0.3))",
235
- } }), _jsx("span", { style: { letterSpacing: "0.025em" }, children: "Analyse..." })] })) : !isAuthReady ? (_jsxs(_Fragment, { children: [_jsx(Lock, { size: 18, style: {
236
- color: "white",
237
- filter: "drop-shadow(0 0 2px rgba(255,255,255,0.2))",
238
- } }), children || _jsx("span", { children: "Connexion requise" })] })) : (_jsx(_Fragment, { children: _jsx(Sparkle, { size: 18, style: {
239
- color: "white",
240
- filter: "drop-shadow(0 0 2px rgba(255,255,255,0.2))",
241
- } }) })) }), 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: {
242
- position: "fixed",
243
- top: 0,
244
- left: 0,
245
- right: 0,
246
- bottom: 0,
247
- backgroundColor: "rgba(0, 0, 0, 0.5)",
248
- backdropFilter: "blur(8px)",
249
- display: "flex",
250
- alignItems: "center",
251
- justifyContent: "center",
252
- zIndex: 1000,
253
- padding: "20px",
254
- }, onClick: (e) => {
106
+ const saveToFile = () => {
107
+ if (!analysisResult) {
108
+ return;
109
+ }
110
+ const currentDate = new Date()
111
+ .toLocaleDateString("fr-FR")
112
+ .replace(/\//g, "-");
113
+ const defaultName = `analyse-${currentDate}.txt`;
114
+ const fileName = prompt("Nom du fichier :", defaultName) || defaultName;
115
+ const content = `ANALYSE DES DONNÉES - ${new Date().toLocaleString("fr-FR")}\n\nPROMPT UTILISÉ :\n${analysisResult.prompt}\n\nRÉSULTAT DE L'ANALYSE :\n${analysisResult.content}\n\n--- MÉTADONNÉES ---\nTokens utilisés: ${analysisResult.tokens.toLocaleString()}\nCoût: $${(apiKeyId?.includes("dev")
116
+ ? 0
117
+ : analysisResult.cost).toFixed(6)}\nID de requête: ${analysisResult.requestId || "N/A"}`;
118
+ const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
119
+ const url = URL.createObjectURL(blob);
120
+ const anchor = document.createElement("a");
121
+ anchor.href = url;
122
+ anchor.download = fileName.endsWith(".txt") ? fileName : `${fileName}.txt`;
123
+ document.body.appendChild(anchor);
124
+ anchor.click();
125
+ document.body.removeChild(anchor);
126
+ URL.revokeObjectURL(url);
127
+ };
128
+ const sizeClass = `ai-size-${size}`;
129
+ const radiusClass = `ai-radius-${radius}`;
130
+ const variantClass = variant === "light" ? "ai-btn--light" : "";
131
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative inline-block ai-glow", children: [_jsx("button", { ...buttonProps, onClick: handleOpenPanel, disabled: disabled || loading || !isAuthReady, className: `ai-btn ai-context-btn ${variantClass} ${sizeClass} ${radiusClass} ${className || ""}`, title: !isAuthReady ? "Authentication required" : "Analyser avec l'IA", children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 16, className: "ai-spinner" }), _jsx("span", { children: "Analyse..." })] })) : !isAuthReady ? (_jsxs(_Fragment, { children: [_jsx(Lock, { size: 16 }), children || _jsx("span", { children: "Connexion requise" })] })) : (_jsxs(_Fragment, { children: [_jsx(Sparkles, { size: 16 }), children || _jsx("span", { children: "Analyser" })] })) }), isOpen ? (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: () => setIsOpen(false), onSubmit: handleSubmit, uiMode: uiMode, models: [], enableModelManagement: true, modelCategory: "text", baseUrl: baseUrl, apiKey: apiKeyId })) : null] }), isResultOpen && analysisResult ? (_jsx("div", { className: "ai-signin-overlay ai-overlay-panel", onClick: (e) => {
255
132
  if (e.target === e.currentTarget) {
256
- handleCloseResult();
133
+ setIsResultOpen(false);
134
+ setAnalysisResult(null);
257
135
  }
258
- }, children: _jsx("div", { style: {
259
- maxWidth: "800px",
260
- position: "relative",
261
- width: "100%",
262
- maxHeight: "90vh",
263
- borderRadius: "16px",
264
- boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1)",
265
- overflow: "hidden",
266
- ...getThemeStyles().modal,
267
- }, children: _jsxs("div", { style: {
268
- padding: "20px 24px 16px",
269
- marginBottom: "12px",
270
- display: "flex",
271
- alignItems: "center",
272
- gap: "12px",
273
- flexDirection: "column",
274
- justifyContent: "space-between",
275
- ...getThemeStyles().header,
276
- }, children: [_jsxs("div", { style: {
277
- display: "flex",
278
- alignItems: "center",
279
- gap: "12px",
280
- }, children: [_jsx(FileText, { size: 20 }), _jsx("h2", { style: {
281
- fontSize: "18px",
282
- fontWeight: "600",
283
- margin: 0,
284
- }, children: resultModalTitle })] }), _jsxs("div", { style: { display: "flex", gap: "8px" }, children: [_jsxs("button", { onClick: saveToFile, style: {
285
- padding: "8px 12px",
286
- borderRadius: "6px",
287
- backgroundColor: "transparent",
288
- border: `1px solid ${getThemeStyles().closeButton.color}30`,
289
- cursor: "pointer",
290
- color: getThemeStyles().closeButton.color,
291
- transition: "all 0.2s",
292
- display: "flex",
293
- alignItems: "center",
294
- gap: "6px",
295
- fontSize: "12px",
296
- }, onMouseEnter: (e) => {
297
- e.currentTarget.style.backgroundColor =
298
- getThemeStyles().closeButton.hoverColor + "10";
299
- e.currentTarget.style.color =
300
- getThemeStyles().closeButton.hoverColor;
301
- }, onMouseLeave: (e) => {
302
- e.currentTarget.style.backgroundColor = "transparent";
303
- e.currentTarget.style.color =
304
- getThemeStyles().closeButton.color;
305
- }, title: "T\u00E9l\u00E9charger l'analyse", children: [_jsx(Download, { size: 14 }), "Sauvegarder"] }), _jsx("button", { onClick: handleCloseResult, style: {
306
- position: "absolute",
307
- top: "16px",
308
- right: "16px",
309
- padding: "4px",
310
- borderRadius: "6px",
311
- backgroundColor: "transparent",
312
- border: "none",
313
- cursor: "pointer",
314
- color: getThemeStyles().closeButton.color,
315
- transition: "color 0.2s",
316
- }, onMouseEnter: (e) => {
317
- e.currentTarget.style.color =
318
- getThemeStyles().closeButton.hoverColor;
319
- }, onMouseLeave: (e) => {
320
- e.currentTarget.style.color =
321
- getThemeStyles().closeButton.color;
322
- }, children: _jsx(X, { size: 18 }) })] }), _jsxs("div", { style: {
323
- padding: "0 24px 24px",
324
- overflow: "auto",
325
- maxHeight: "calc(90vh - 80px)",
326
- }, children: [_jsxs("div", { style: { marginBottom: "20px" }, children: [_jsx("h3", { style: {
327
- fontSize: "14px",
328
- fontWeight: "600",
329
- marginBottom: "8px",
330
- color: getThemeStyles().modal.color,
331
- }, children: "Prompt utilis\u00E9 :" }), _jsx("div", { style: {
332
- padding: "12px",
333
- borderRadius: "8px",
334
- fontSize: "13px",
335
- fontFamily: "monospace",
336
- ...getThemeStyles().content,
337
- }, children: analysisResult.prompt })] }), _jsxs("div", { children: [_jsx("h3", { style: {
338
- fontSize: "14px",
339
- fontWeight: "600",
340
- marginBottom: "12px",
341
- color: getThemeStyles().modal.color,
342
- }, children: "R\u00E9sultat de l'analyse :" }), _jsx("div", { style: {
343
- padding: "16px",
344
- borderRadius: "8px",
345
- lineHeight: "1.6",
346
- fontSize: "14px",
347
- whiteSpace: "pre-wrap",
348
- ...getThemeStyles().content,
349
- }, children: analysisResult.content })] }), _jsx("div", { style: { height: "120px" }, children: _jsxs("div", { style: {
350
- marginTop: "20px",
351
- padding: "12px",
352
- fontSize: "12px",
353
- borderRadius: "8px",
354
- display: "flex",
355
- justifyContent: "space-between",
356
- ...getThemeStyles().content,
357
- }, children: [_jsxs("span", { children: ["Co\u00FBt: $", (apiKeyId?.includes("dev")
358
- ? 0
359
- : 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)] }));
136
+ }, children: _jsxs("div", { className: "ai-popover ai-result-modal", onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { className: "ai-result-header", children: [_jsxs("div", { className: "ai-row", children: [_jsx(FileText, { size: 18 }), _jsx("h2", { className: "ai-result-title", children: resultModalTitle })] }), _jsxs("div", { className: "ai-row", children: [_jsxs("button", { type: "button", className: `ai-btn ai-btn--ghost ai-btn--compact ${sizeClass} ${radiusClass}`, onClick: saveToFile, children: [_jsx(Download, { size: 14 }), "Sauvegarder"] }), _jsx("button", { type: "button", className: "ai-icon-btn", onClick: () => {
137
+ setIsResultOpen(false);
138
+ setAnalysisResult(null);
139
+ }, "aria-label": "Fermer", children: _jsx(X, { size: 16 }) })] })] }), _jsxs("div", { className: "ai-result-body", children: [_jsxs("div", { className: "ai-result-block", children: [_jsx("h3", { className: "ai-result-subtitle", children: "Prompt utilis\u00E9" }), _jsx("pre", { className: "ai-result-code", children: analysisResult.prompt })] }), _jsxs("div", { className: "ai-result-block", children: [_jsx("h3", { className: "ai-result-subtitle", children: "R\u00E9sultat" }), _jsx("div", { className: "ai-result-content", children: analysisResult.content })] }), _jsxs("div", { className: "ai-result-meta ai-between", children: [_jsxs("span", { children: ["Co\u00FBt: $", (apiKeyId?.includes("dev")
140
+ ? 0
141
+ : analysisResult.cost).toFixed(6)] }), _jsxs("span", { children: ["ID: ", analysisResult.requestId?.slice(-8) || "N/A"] })] })] })] }) })) : null, _jsx(LBSigninModal, { isOpen: showAuthModal, onClose: () => setShowAuthModal(false) }), _jsx(ErrorToast, { error: errorData, onComplete: clearError }, errorKey)] }));
360
142
  }