@lastbrain/ai-ui-react 1.0.36 → 1.0.38
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.d.ts.map +1 -1
- package/dist/components/AiContextButton.js +1 -9
- package/dist/components/AiImageButton.d.ts.map +1 -1
- package/dist/components/AiImageButton.js +1 -16
- package/dist/components/AiInput.d.ts.map +1 -1
- package/dist/components/AiInput.js +2 -2
- package/dist/components/AiPromptPanel.d.ts +1 -0
- package/dist/components/AiPromptPanel.d.ts.map +1 -1
- package/dist/components/AiPromptPanel.js +278 -169
- package/dist/components/AiTextarea.d.ts.map +1 -1
- package/dist/components/AiTextarea.js +1 -1
- package/dist/components/ErrorToast.js +14 -14
- package/dist/context/AiProvider.d.ts.map +1 -1
- package/dist/context/AiProvider.js +87 -26
- package/dist/hooks/useAiClient.d.ts +1 -0
- package/dist/hooks/useAiClient.d.ts.map +1 -1
- package/dist/hooks/useAiModels.d.ts.map +1 -1
- package/dist/hooks/useAiModels.js +1 -2
- package/dist/hooks/useModelManagement.d.ts.map +1 -1
- package/dist/hooks/useModelManagement.js +24 -3
- package/dist/hooks/usePrompts.d.ts.map +1 -1
- package/dist/hooks/usePrompts.js +19 -3
- package/package.json +2 -2
- package/src/components/AiContextButton.tsx +2 -9
- package/src/components/AiImageButton.tsx +5 -17
- package/src/components/AiInput.tsx +3 -2
- package/src/components/AiPromptPanel.tsx +332 -192
- package/src/components/AiTextarea.tsx +2 -1
- package/src/components/ErrorToast.tsx +16 -16
- package/src/context/AiProvider.tsx +116 -31
- package/src/hooks/useAiModels.ts +1 -2
- package/src/hooks/useModelManagement.ts +33 -3
- package/src/hooks/usePrompts.ts +21 -3
|
@@ -31,6 +31,7 @@ export interface AiPromptPanelProps {
|
|
|
31
31
|
children?: (props: AiPromptPanelRenderProps) => ReactNode;
|
|
32
32
|
// Nouvelles props pour la gestion avancée des modèles
|
|
33
33
|
enableModelManagement?: boolean;
|
|
34
|
+
modelCategory?: "text" | "image"; // Catégorie de modèles à gérer
|
|
34
35
|
availableModels?: AIModel[];
|
|
35
36
|
userModels?: string[];
|
|
36
37
|
onModelToggle?: (modelId: string, isActive: boolean) => Promise<void>;
|
|
@@ -80,7 +81,8 @@ function AiPromptPanelInternal({
|
|
|
80
81
|
models = [],
|
|
81
82
|
sourceText,
|
|
82
83
|
children,
|
|
83
|
-
enableModelManagement =
|
|
84
|
+
enableModelManagement = true,
|
|
85
|
+
modelCategory = "text",
|
|
84
86
|
availableModels = [],
|
|
85
87
|
userModels = [],
|
|
86
88
|
onModelToggle,
|
|
@@ -107,6 +109,7 @@ function AiPromptPanelInternal({
|
|
|
107
109
|
const [showAllModels, setShowAllModels] = useState(false);
|
|
108
110
|
const [isModelManagementOpen, setIsModelManagementOpen] = useState(false);
|
|
109
111
|
const [loadingModels, setLoadingModels] = useState<string[]>([]);
|
|
112
|
+
const [modelSearchQuery, setModelSearchQuery] = useState("");
|
|
110
113
|
|
|
111
114
|
const {
|
|
112
115
|
prompts,
|
|
@@ -119,7 +122,7 @@ function AiPromptPanelInternal({
|
|
|
119
122
|
const autoModelManagement = useModelManagement({
|
|
120
123
|
apiKey,
|
|
121
124
|
baseUrl,
|
|
122
|
-
category:
|
|
125
|
+
category: modelCategory, // Utiliser la catégorie spécifiée
|
|
123
126
|
autoFetch:
|
|
124
127
|
enableModelManagement &&
|
|
125
128
|
models.length === 0 &&
|
|
@@ -173,27 +176,37 @@ function AiPromptPanelInternal({
|
|
|
173
176
|
}));
|
|
174
177
|
}
|
|
175
178
|
|
|
176
|
-
const
|
|
177
|
-
(m) => m.category ===
|
|
179
|
+
const categoryModels = effectiveAvailableModels.filter(
|
|
180
|
+
(m) => m.category === modelCategory
|
|
178
181
|
);
|
|
179
182
|
|
|
180
183
|
if (showAllModels) {
|
|
181
|
-
return
|
|
184
|
+
return categoryModels;
|
|
182
185
|
} else {
|
|
183
|
-
return
|
|
186
|
+
return categoryModels.filter((m) => effectiveUserModels.includes(m.id));
|
|
184
187
|
}
|
|
185
188
|
};
|
|
186
189
|
|
|
187
190
|
// Fetch prompts when modal opens
|
|
188
191
|
useEffect(() => {
|
|
189
|
-
if (isOpen && models.length > 0) {
|
|
190
|
-
|
|
191
|
-
const modelType =
|
|
192
|
+
if (isOpen && (models.length > 0 || enableModelManagement)) {
|
|
193
|
+
// Déterminer le type de modèle à partir de modelCategory si enableModelManagement
|
|
194
|
+
const modelType = enableModelManagement
|
|
195
|
+
? modelCategory
|
|
196
|
+
: models.find((m) => m.id === selectedModel)?.type || models[0]?.type;
|
|
197
|
+
|
|
192
198
|
fetchPrompts({
|
|
193
199
|
type: modelType === "image" ? "image" : "text",
|
|
194
200
|
});
|
|
195
201
|
}
|
|
196
|
-
}, [
|
|
202
|
+
}, [
|
|
203
|
+
isOpen,
|
|
204
|
+
selectedModel,
|
|
205
|
+
models,
|
|
206
|
+
fetchPrompts,
|
|
207
|
+
enableModelManagement,
|
|
208
|
+
modelCategory,
|
|
209
|
+
]);
|
|
197
210
|
|
|
198
211
|
const handleSubmit = async () => {
|
|
199
212
|
const activeModelId = selectedModel || models[0]?.id;
|
|
@@ -354,6 +367,10 @@ function AiPromptPanelInternal({
|
|
|
354
367
|
opacity: isClosing ? 0 : 1,
|
|
355
368
|
transform: isClosing ? "translateY(12px)" : "translateY(0)",
|
|
356
369
|
transition: "opacity 200ms ease, transform 200ms ease",
|
|
370
|
+
display: "flex",
|
|
371
|
+
flexDirection: "column",
|
|
372
|
+
maxHeight: "85vh",
|
|
373
|
+
overflow: "hidden",
|
|
357
374
|
}}
|
|
358
375
|
>
|
|
359
376
|
{isGenerating && (
|
|
@@ -401,7 +418,17 @@ function AiPromptPanelInternal({
|
|
|
401
418
|
</div>
|
|
402
419
|
</div>
|
|
403
420
|
)}
|
|
404
|
-
<div
|
|
421
|
+
<div
|
|
422
|
+
style={{
|
|
423
|
+
...aiStyles.modalHeader,
|
|
424
|
+
position: "sticky",
|
|
425
|
+
top: 0,
|
|
426
|
+
zIndex: 5,
|
|
427
|
+
background: "var(--ai-bg-primary, #1f2937)",
|
|
428
|
+
borderBottom: "1px solid var(--ai-border-primary, #374151)",
|
|
429
|
+
backdropFilter: "blur(8px)",
|
|
430
|
+
}}
|
|
431
|
+
>
|
|
405
432
|
<h2 style={aiStyles.modalTitle}>
|
|
406
433
|
{showPromptLibrary ? "Select a Prompt" : "AI Prompt Configuration"}
|
|
407
434
|
</h2>
|
|
@@ -419,7 +446,13 @@ function AiPromptPanelInternal({
|
|
|
419
446
|
</button>
|
|
420
447
|
</div>
|
|
421
448
|
|
|
422
|
-
<div
|
|
449
|
+
<div
|
|
450
|
+
style={{
|
|
451
|
+
...aiStyles.modalBody,
|
|
452
|
+
flex: 1,
|
|
453
|
+
overflow: "auto",
|
|
454
|
+
}}
|
|
455
|
+
>
|
|
423
456
|
{!showPromptLibrary ? (
|
|
424
457
|
<>
|
|
425
458
|
{sourceText && (
|
|
@@ -464,66 +497,11 @@ function AiPromptPanelInternal({
|
|
|
464
497
|
<label htmlFor="model-select" style={aiStyles.modalLabel}>
|
|
465
498
|
AI Model
|
|
466
499
|
</label>
|
|
467
|
-
|
|
468
|
-
style={{
|
|
469
|
-
display: "flex",
|
|
470
|
-
alignItems: "center",
|
|
471
|
-
gap: "8px",
|
|
472
|
-
}}
|
|
473
|
-
>
|
|
474
|
-
{effectiveAvailableModels.length > 0 && (
|
|
475
|
-
<button
|
|
476
|
-
onClick={() => setShowAllModels(!showAllModels)}
|
|
477
|
-
style={{
|
|
478
|
-
padding: "4px 8px",
|
|
479
|
-
fontSize: "12px",
|
|
480
|
-
color: "#8b5cf6",
|
|
481
|
-
background: "#8b5cf610",
|
|
482
|
-
border: "1px solid #8b5cf630",
|
|
483
|
-
borderRadius: "6px",
|
|
484
|
-
cursor: "pointer",
|
|
485
|
-
transition: "all 0.2s",
|
|
486
|
-
}}
|
|
487
|
-
onMouseEnter={(e) => {
|
|
488
|
-
e.currentTarget.style.background = "#8b5cf620";
|
|
489
|
-
}}
|
|
490
|
-
onMouseLeave={(e) => {
|
|
491
|
-
e.currentTarget.style.background = "#8b5cf610";
|
|
492
|
-
}}
|
|
493
|
-
>
|
|
494
|
-
{showAllModels ? "Mes modèles" : "Tous les modèles"}
|
|
495
|
-
{!showAllModels &&
|
|
496
|
-
effectiveAvailableModels.filter(
|
|
497
|
-
(m) =>
|
|
498
|
-
m.category === "text" &&
|
|
499
|
-
!effectiveUserModels.includes(m.id)
|
|
500
|
-
).length > 0 && (
|
|
501
|
-
<span
|
|
502
|
-
style={{
|
|
503
|
-
marginLeft: "4px",
|
|
504
|
-
padding: "2px 6px",
|
|
505
|
-
fontSize: "10px",
|
|
506
|
-
background: "#8b5cf6",
|
|
507
|
-
color: "white",
|
|
508
|
-
borderRadius: "10px",
|
|
509
|
-
}}
|
|
510
|
-
>
|
|
511
|
-
+
|
|
512
|
-
{
|
|
513
|
-
effectiveAvailableModels.filter(
|
|
514
|
-
(m) =>
|
|
515
|
-
m.category === "text" &&
|
|
516
|
-
!effectiveUserModels.includes(m.id)
|
|
517
|
-
).length
|
|
518
|
-
}
|
|
519
|
-
</span>
|
|
520
|
-
)}
|
|
521
|
-
</button>
|
|
522
|
-
)}
|
|
500
|
+
{effectiveAvailableModels.length > 0 && (
|
|
523
501
|
<button
|
|
524
502
|
onClick={() => setIsModelManagementOpen(true)}
|
|
525
503
|
style={{
|
|
526
|
-
padding: "4px
|
|
504
|
+
padding: "4px 12px",
|
|
527
505
|
fontSize: "12px",
|
|
528
506
|
color: "#8b5cf6",
|
|
529
507
|
background: "#8b5cf610",
|
|
@@ -533,7 +511,7 @@ function AiPromptPanelInternal({
|
|
|
533
511
|
transition: "all 0.2s",
|
|
534
512
|
display: "flex",
|
|
535
513
|
alignItems: "center",
|
|
536
|
-
gap: "
|
|
514
|
+
gap: "6px",
|
|
537
515
|
}}
|
|
538
516
|
onMouseEnter={(e) => {
|
|
539
517
|
e.currentTarget.style.background = "#8b5cf620";
|
|
@@ -543,10 +521,36 @@ function AiPromptPanelInternal({
|
|
|
543
521
|
}}
|
|
544
522
|
title="Gérer les modèles"
|
|
545
523
|
>
|
|
546
|
-
<Settings size={
|
|
547
|
-
Gérer
|
|
524
|
+
<Settings size={14} />
|
|
525
|
+
Gérer les modèles
|
|
526
|
+
{effectiveAvailableModels.filter(
|
|
527
|
+
(m) =>
|
|
528
|
+
m.category === modelCategory &&
|
|
529
|
+
!effectiveUserModels.includes(m.id)
|
|
530
|
+
).length > 0 && (
|
|
531
|
+
<span
|
|
532
|
+
style={{
|
|
533
|
+
marginLeft: "2px",
|
|
534
|
+
padding: "2px 6px",
|
|
535
|
+
fontSize: "10px",
|
|
536
|
+
background: "#8b5cf6",
|
|
537
|
+
color: "white",
|
|
538
|
+
borderRadius: "10px",
|
|
539
|
+
fontWeight: "600",
|
|
540
|
+
}}
|
|
541
|
+
>
|
|
542
|
+
+
|
|
543
|
+
{
|
|
544
|
+
effectiveAvailableModels.filter(
|
|
545
|
+
(m) =>
|
|
546
|
+
m.category === modelCategory &&
|
|
547
|
+
!effectiveUserModels.includes(m.id)
|
|
548
|
+
).length
|
|
549
|
+
}
|
|
550
|
+
</span>
|
|
551
|
+
)}
|
|
548
552
|
</button>
|
|
549
|
-
|
|
553
|
+
)}
|
|
550
554
|
</div>
|
|
551
555
|
<select
|
|
552
556
|
id="model-select"
|
|
@@ -993,7 +997,17 @@ function AiPromptPanelInternal({
|
|
|
993
997
|
)}
|
|
994
998
|
</div>
|
|
995
999
|
|
|
996
|
-
<div
|
|
1000
|
+
<div
|
|
1001
|
+
style={{
|
|
1002
|
+
...aiStyles.modalFooter,
|
|
1003
|
+
position: "sticky",
|
|
1004
|
+
bottom: 0,
|
|
1005
|
+
zIndex: 5,
|
|
1006
|
+
background: "var(--ai-bg-primary, #1f2937)",
|
|
1007
|
+
borderTop: "1px solid var(--ai-border-primary, #374151)",
|
|
1008
|
+
backdropFilter: "blur(8px)",
|
|
1009
|
+
}}
|
|
1010
|
+
>
|
|
997
1011
|
<button
|
|
998
1012
|
onClick={handleClose}
|
|
999
1013
|
onMouseEnter={() => setIsCancelHovered(true)}
|
|
@@ -1037,36 +1051,52 @@ function AiPromptPanelInternal({
|
|
|
1037
1051
|
<div
|
|
1038
1052
|
style={{
|
|
1039
1053
|
...aiStyles.modalOverlay,
|
|
1040
|
-
backgroundColor: "rgba(0, 0, 0, 0.
|
|
1054
|
+
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
|
1055
|
+
}}
|
|
1056
|
+
onClick={() => {
|
|
1057
|
+
setIsModelManagementOpen(false);
|
|
1058
|
+
setModelSearchQuery("");
|
|
1041
1059
|
}}
|
|
1042
|
-
onClick={() => setIsModelManagementOpen(false)}
|
|
1043
1060
|
/>
|
|
1044
1061
|
<div
|
|
1045
1062
|
style={{
|
|
1046
1063
|
...aiStyles.modalContent,
|
|
1047
|
-
maxWidth: "
|
|
1048
|
-
maxHeight: "
|
|
1049
|
-
overflow: "
|
|
1064
|
+
maxWidth: "700px",
|
|
1065
|
+
maxHeight: "85vh",
|
|
1066
|
+
overflow: "hidden",
|
|
1067
|
+
display: "flex",
|
|
1068
|
+
flexDirection: "column",
|
|
1069
|
+
background: "var(--ai-bg-primary, #1f2937)",
|
|
1070
|
+
boxShadow: "0 20px 40px rgba(0, 0, 0, 0.5)",
|
|
1050
1071
|
}}
|
|
1051
1072
|
>
|
|
1052
1073
|
<div style={aiStyles.modalHeader}>
|
|
1053
1074
|
<h2 style={aiStyles.modalTitle}>Gestion des modèles IA</h2>
|
|
1054
1075
|
<button
|
|
1055
1076
|
style={aiStyles.modalCloseButton}
|
|
1056
|
-
onClick={() =>
|
|
1077
|
+
onClick={() => {
|
|
1078
|
+
setIsModelManagementOpen(false);
|
|
1079
|
+
setModelSearchQuery("");
|
|
1080
|
+
}}
|
|
1057
1081
|
aria-label="Close"
|
|
1058
1082
|
>
|
|
1059
1083
|
×
|
|
1060
1084
|
</button>
|
|
1061
1085
|
</div>
|
|
1062
1086
|
|
|
1063
|
-
<div
|
|
1087
|
+
<div
|
|
1088
|
+
style={{
|
|
1089
|
+
...aiStyles.modalBody,
|
|
1090
|
+
flex: 1,
|
|
1091
|
+
overflow: "auto",
|
|
1092
|
+
}}
|
|
1093
|
+
>
|
|
1064
1094
|
<div style={{ marginBottom: "16px" }}>
|
|
1065
1095
|
<p
|
|
1066
1096
|
style={{
|
|
1067
1097
|
fontSize: "14px",
|
|
1068
|
-
color: "#6b7280",
|
|
1069
|
-
margin: "0 0
|
|
1098
|
+
color: "var(--ai-text-secondary, #6b7280)",
|
|
1099
|
+
margin: "0 0 8px 0",
|
|
1070
1100
|
}}
|
|
1071
1101
|
>
|
|
1072
1102
|
Activez ou désactivez les modèles selon vos besoins
|
|
@@ -1074,36 +1104,73 @@ function AiPromptPanelInternal({
|
|
|
1074
1104
|
<p
|
|
1075
1105
|
style={{
|
|
1076
1106
|
fontSize: "12px",
|
|
1077
|
-
color: "#9ca3af",
|
|
1078
|
-
margin: "0",
|
|
1107
|
+
color: "var(--ai-text-tertiary, #9ca3af)",
|
|
1108
|
+
margin: "0 0 16px 0",
|
|
1079
1109
|
}}
|
|
1080
1110
|
>
|
|
1081
1111
|
{
|
|
1082
1112
|
effectiveAvailableModels.filter(
|
|
1083
|
-
(m) => m.category ===
|
|
1113
|
+
(m) => m.category === modelCategory
|
|
1084
1114
|
).length
|
|
1085
1115
|
}{" "}
|
|
1086
1116
|
modèles disponibles •{" "}
|
|
1087
1117
|
{
|
|
1088
1118
|
effectiveUserModels.filter((id) =>
|
|
1089
1119
|
effectiveAvailableModels.some(
|
|
1090
|
-
(m) => m.id === id && m.category ===
|
|
1120
|
+
(m) => m.id === id && m.category === modelCategory
|
|
1091
1121
|
)
|
|
1092
1122
|
).length
|
|
1093
1123
|
}{" "}
|
|
1094
1124
|
activés
|
|
1095
1125
|
</p>
|
|
1126
|
+
{/* Champ de recherche */}
|
|
1127
|
+
<div
|
|
1128
|
+
style={{
|
|
1129
|
+
...aiStyles.inputWrapper,
|
|
1130
|
+
marginBottom: "16px",
|
|
1131
|
+
}}
|
|
1132
|
+
>
|
|
1133
|
+
<Search
|
|
1134
|
+
size={16}
|
|
1135
|
+
style={{
|
|
1136
|
+
position: "absolute",
|
|
1137
|
+
left: "12px",
|
|
1138
|
+
top: "50%",
|
|
1139
|
+
transform: "translateY(-50%)",
|
|
1140
|
+
color: "var(--ai-text-tertiary, #9ca3af)",
|
|
1141
|
+
}}
|
|
1142
|
+
/>
|
|
1143
|
+
<input
|
|
1144
|
+
value={modelSearchQuery}
|
|
1145
|
+
onChange={(e) => setModelSearchQuery(e.target.value)}
|
|
1146
|
+
placeholder="Rechercher un modèle..."
|
|
1147
|
+
style={{
|
|
1148
|
+
...aiStyles.input,
|
|
1149
|
+
padding: "10px 12px 10px 36px",
|
|
1150
|
+
background: "var(--ai-bg-secondary, #f9fafb)",
|
|
1151
|
+
}}
|
|
1152
|
+
/>
|
|
1153
|
+
</div>
|
|
1096
1154
|
</div>
|
|
1097
1155
|
|
|
1098
1156
|
<div
|
|
1099
1157
|
style={{
|
|
1100
1158
|
display: "flex",
|
|
1101
1159
|
flexDirection: "column",
|
|
1102
|
-
gap: "
|
|
1160
|
+
gap: "8px",
|
|
1103
1161
|
}}
|
|
1104
1162
|
>
|
|
1105
1163
|
{effectiveAvailableModels
|
|
1106
|
-
.filter((model) =>
|
|
1164
|
+
.filter((model) => {
|
|
1165
|
+
if (model.category !== modelCategory) return false;
|
|
1166
|
+
if (!modelSearchQuery.trim()) return true;
|
|
1167
|
+
const query = modelSearchQuery.toLowerCase();
|
|
1168
|
+
return (
|
|
1169
|
+
model.name.toLowerCase().includes(query) ||
|
|
1170
|
+
model.provider.toLowerCase().includes(query) ||
|
|
1171
|
+
model.description?.toLowerCase().includes(query)
|
|
1172
|
+
);
|
|
1173
|
+
})
|
|
1107
1174
|
.map((modelData) => {
|
|
1108
1175
|
const isActive = effectiveUserModels.includes(modelData.id);
|
|
1109
1176
|
const isLoading = loadingModels.includes(modelData.id);
|
|
@@ -1115,41 +1182,78 @@ function AiPromptPanelInternal({
|
|
|
1115
1182
|
display: "flex",
|
|
1116
1183
|
alignItems: "center",
|
|
1117
1184
|
justifyContent: "space-between",
|
|
1118
|
-
padding: "16px",
|
|
1119
|
-
border: "
|
|
1120
|
-
|
|
1121
|
-
|
|
1185
|
+
padding: "16px 18px",
|
|
1186
|
+
border: "2px solid",
|
|
1187
|
+
borderColor: isActive
|
|
1188
|
+
? "#10b981"
|
|
1189
|
+
: "var(--ai-border-primary, #374151)",
|
|
1190
|
+
borderRadius: "10px",
|
|
1191
|
+
backgroundColor: isActive
|
|
1192
|
+
? "rgba(16, 185, 129, 0.08)"
|
|
1193
|
+
: "var(--ai-bg-secondary, rgba(31, 41, 55, 0.5))",
|
|
1122
1194
|
transition: "all 0.2s",
|
|
1195
|
+
cursor: "pointer",
|
|
1196
|
+
backdropFilter: "blur(8px)",
|
|
1197
|
+
}}
|
|
1198
|
+
onClick={() =>
|
|
1199
|
+
!isLoading &&
|
|
1200
|
+
handleModelToggle(modelData.id, !isActive)
|
|
1201
|
+
}
|
|
1202
|
+
onMouseEnter={(e) => {
|
|
1203
|
+
e.currentTarget.style.borderColor = isActive
|
|
1204
|
+
? "#059669"
|
|
1205
|
+
: "#4b5563";
|
|
1206
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
1207
|
+
e.currentTarget.style.boxShadow = isActive
|
|
1208
|
+
? "0 8px 16px rgba(16, 185, 129, 0.2)"
|
|
1209
|
+
: "0 8px 16px rgba(0, 0, 0, 0.15)";
|
|
1210
|
+
}}
|
|
1211
|
+
onMouseLeave={(e) => {
|
|
1212
|
+
e.currentTarget.style.borderColor = isActive
|
|
1213
|
+
? "#10b981"
|
|
1214
|
+
: "var(--ai-border-primary, #374151)";
|
|
1215
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
1216
|
+
e.currentTarget.style.boxShadow = "none";
|
|
1123
1217
|
}}
|
|
1124
1218
|
>
|
|
1125
1219
|
<div
|
|
1126
1220
|
style={{
|
|
1127
1221
|
display: "flex",
|
|
1128
1222
|
alignItems: "center",
|
|
1129
|
-
gap: "
|
|
1223
|
+
gap: "14px",
|
|
1224
|
+
flex: 1,
|
|
1130
1225
|
}}
|
|
1131
1226
|
>
|
|
1227
|
+
{/* Status indicator */}
|
|
1132
1228
|
<div
|
|
1133
1229
|
style={{
|
|
1134
|
-
width: "
|
|
1135
|
-
height: "
|
|
1230
|
+
width: "8px",
|
|
1231
|
+
height: "8px",
|
|
1136
1232
|
borderRadius: "50%",
|
|
1137
|
-
backgroundColor: isActive ? "#10b981" : "#
|
|
1233
|
+
backgroundColor: isActive ? "#10b981" : "#6b7280",
|
|
1234
|
+
boxShadow: isActive
|
|
1235
|
+
? "0 0 8px rgba(16, 185, 129, 0.6)"
|
|
1236
|
+
: "none",
|
|
1237
|
+
transition: "all 0.3s",
|
|
1138
1238
|
}}
|
|
1139
1239
|
/>
|
|
1140
|
-
<div>
|
|
1240
|
+
<div style={{ flex: 1 }}>
|
|
1141
1241
|
<div
|
|
1142
1242
|
style={{
|
|
1143
1243
|
display: "flex",
|
|
1144
1244
|
alignItems: "center",
|
|
1145
|
-
gap: "
|
|
1146
|
-
marginBottom: "
|
|
1245
|
+
gap: "10px",
|
|
1246
|
+
marginBottom: "6px",
|
|
1147
1247
|
}}
|
|
1148
1248
|
>
|
|
1149
1249
|
<span
|
|
1150
1250
|
style={{
|
|
1151
|
-
fontWeight: "
|
|
1152
|
-
|
|
1251
|
+
fontWeight: "600",
|
|
1252
|
+
fontSize: "15px",
|
|
1253
|
+
color: isActive
|
|
1254
|
+
? "#10b981"
|
|
1255
|
+
: "var(--ai-text-primary, #f3f4f6)",
|
|
1256
|
+
letterSpacing: "-0.01em",
|
|
1153
1257
|
}}
|
|
1154
1258
|
>
|
|
1155
1259
|
{modelData.name}
|
|
@@ -1157,132 +1261,168 @@ function AiPromptPanelInternal({
|
|
|
1157
1261
|
{modelData.isPro && (
|
|
1158
1262
|
<span
|
|
1159
1263
|
style={{
|
|
1160
|
-
padding: "
|
|
1161
|
-
fontSize: "
|
|
1264
|
+
padding: "3px 10px",
|
|
1265
|
+
fontSize: "10px",
|
|
1162
1266
|
backgroundColor: "#8b5cf6",
|
|
1163
1267
|
color: "white",
|
|
1164
1268
|
borderRadius: "12px",
|
|
1165
|
-
fontWeight: "
|
|
1269
|
+
fontWeight: "700",
|
|
1270
|
+
textTransform: "uppercase",
|
|
1271
|
+
letterSpacing: "0.05em",
|
|
1272
|
+
boxShadow:
|
|
1273
|
+
"0 2px 8px rgba(139, 92, 246, 0.3)",
|
|
1166
1274
|
}}
|
|
1167
1275
|
>
|
|
1168
1276
|
PRO
|
|
1169
1277
|
</span>
|
|
1170
1278
|
)}
|
|
1171
1279
|
</div>
|
|
1172
|
-
{modelData.description && (
|
|
1173
|
-
<p
|
|
1174
|
-
style={{
|
|
1175
|
-
fontSize: "13px",
|
|
1176
|
-
color: "#6b7280",
|
|
1177
|
-
margin: "0 0 4px 0",
|
|
1178
|
-
}}
|
|
1179
|
-
>
|
|
1180
|
-
{modelData.description}
|
|
1181
|
-
</p>
|
|
1182
|
-
)}
|
|
1183
1280
|
<div
|
|
1184
1281
|
style={{
|
|
1185
1282
|
display: "flex",
|
|
1186
1283
|
alignItems: "center",
|
|
1187
1284
|
gap: "16px",
|
|
1188
|
-
fontSize: "
|
|
1189
|
-
color:
|
|
1285
|
+
fontSize: "13px",
|
|
1286
|
+
color: isActive
|
|
1287
|
+
? "#6ee7b7"
|
|
1288
|
+
: "var(--ai-text-secondary, #d1d5db)",
|
|
1289
|
+
fontWeight: "500",
|
|
1190
1290
|
}}
|
|
1191
1291
|
>
|
|
1192
|
-
<span
|
|
1292
|
+
<span
|
|
1293
|
+
style={{
|
|
1294
|
+
display: "flex",
|
|
1295
|
+
alignItems: "center",
|
|
1296
|
+
gap: "6px",
|
|
1297
|
+
}}
|
|
1298
|
+
>
|
|
1299
|
+
<span
|
|
1300
|
+
style={{
|
|
1301
|
+
display: "inline-block",
|
|
1302
|
+
width: "4px",
|
|
1303
|
+
height: "4px",
|
|
1304
|
+
borderRadius: "50%",
|
|
1305
|
+
backgroundColor: "currentColor",
|
|
1306
|
+
}}
|
|
1307
|
+
/>
|
|
1308
|
+
{modelData.provider}
|
|
1309
|
+
</span>
|
|
1193
1310
|
{modelData.costPer1M && (
|
|
1194
|
-
<span
|
|
1195
|
-
|
|
1311
|
+
<span
|
|
1312
|
+
style={{
|
|
1313
|
+
padding: "2px 8px",
|
|
1314
|
+
background: isActive
|
|
1315
|
+
? "rgba(16, 185, 129, 0.15)"
|
|
1316
|
+
: "rgba(107, 114, 128, 0.2)",
|
|
1317
|
+
borderRadius: "6px",
|
|
1318
|
+
fontSize: "12px",
|
|
1319
|
+
}}
|
|
1320
|
+
>
|
|
1321
|
+
${modelData.costPer1M}/1M
|
|
1196
1322
|
</span>
|
|
1197
1323
|
)}
|
|
1198
1324
|
</div>
|
|
1199
1325
|
</div>
|
|
1200
1326
|
</div>
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
handleModelToggle(modelData.id, !isActive)
|
|
1204
|
-
}
|
|
1205
|
-
disabled={isLoading}
|
|
1327
|
+
{/* Toggle Switch CSS amélioré */}
|
|
1328
|
+
<label
|
|
1206
1329
|
style={{
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
border: "1px solid",
|
|
1330
|
+
position: "relative",
|
|
1331
|
+
display: "inline-block",
|
|
1332
|
+
width: "54px",
|
|
1333
|
+
height: "28px",
|
|
1212
1334
|
cursor: isLoading ? "not-allowed" : "pointer",
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
...(isActive
|
|
1216
|
-
? {
|
|
1217
|
-
backgroundColor: "#fef2f2",
|
|
1218
|
-
borderColor: "#fecaca",
|
|
1219
|
-
color: "#dc2626",
|
|
1220
|
-
}
|
|
1221
|
-
: {
|
|
1222
|
-
backgroundColor: "#f0fdf4",
|
|
1223
|
-
borderColor: "#bbf7d0",
|
|
1224
|
-
color: "#16a34a",
|
|
1225
|
-
}),
|
|
1226
|
-
opacity: isLoading ? 0.6 : 1,
|
|
1227
|
-
}}
|
|
1228
|
-
onMouseEnter={(e) => {
|
|
1229
|
-
if (!isLoading) {
|
|
1230
|
-
if (isActive) {
|
|
1231
|
-
e.currentTarget.style.backgroundColor =
|
|
1232
|
-
"#fee2e2";
|
|
1233
|
-
} else {
|
|
1234
|
-
e.currentTarget.style.backgroundColor =
|
|
1235
|
-
"#dcfce7";
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
}}
|
|
1239
|
-
onMouseLeave={(e) => {
|
|
1240
|
-
if (!isLoading) {
|
|
1241
|
-
if (isActive) {
|
|
1242
|
-
e.currentTarget.style.backgroundColor =
|
|
1243
|
-
"#fef2f2";
|
|
1244
|
-
} else {
|
|
1245
|
-
e.currentTarget.style.backgroundColor =
|
|
1246
|
-
"#f0fdf4";
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1335
|
+
opacity: isLoading ? 0.5 : 1,
|
|
1336
|
+
flexShrink: 0,
|
|
1249
1337
|
}}
|
|
1338
|
+
onClick={(e) => e.stopPropagation()}
|
|
1250
1339
|
>
|
|
1251
|
-
|
|
1252
|
-
|
|
1340
|
+
<input
|
|
1341
|
+
type="checkbox"
|
|
1342
|
+
checked={isActive}
|
|
1343
|
+
disabled={isLoading}
|
|
1344
|
+
onChange={() =>
|
|
1345
|
+
handleModelToggle(modelData.id, !isActive)
|
|
1346
|
+
}
|
|
1347
|
+
style={{
|
|
1348
|
+
opacity: 0,
|
|
1349
|
+
width: 0,
|
|
1350
|
+
height: 0,
|
|
1351
|
+
position: "absolute",
|
|
1352
|
+
}}
|
|
1353
|
+
/>
|
|
1354
|
+
<span
|
|
1355
|
+
style={{
|
|
1356
|
+
position: "absolute",
|
|
1357
|
+
cursor: isLoading ? "not-allowed" : "pointer",
|
|
1358
|
+
top: 0,
|
|
1359
|
+
left: 0,
|
|
1360
|
+
right: 0,
|
|
1361
|
+
bottom: 0,
|
|
1362
|
+
backgroundColor: isActive ? "#10b981" : "#4b5563",
|
|
1363
|
+
transition: "0.3s",
|
|
1364
|
+
borderRadius: "28px",
|
|
1365
|
+
boxShadow: isActive
|
|
1366
|
+
? "0 0 12px rgba(16, 185, 129, 0.4), inset 0 1px 3px rgba(0, 0, 0, 0.2)"
|
|
1367
|
+
: "inset 0 1px 3px rgba(0, 0, 0, 0.3)",
|
|
1368
|
+
border: isActive
|
|
1369
|
+
? "2px solid #059669"
|
|
1370
|
+
: "2px solid #374151",
|
|
1371
|
+
}}
|
|
1372
|
+
>
|
|
1373
|
+
<span
|
|
1253
1374
|
style={{
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1375
|
+
position: "absolute",
|
|
1376
|
+
content: "",
|
|
1377
|
+
height: "22px",
|
|
1378
|
+
width: "22px",
|
|
1379
|
+
left: isActive ? "28px" : "2px",
|
|
1380
|
+
bottom: "2px",
|
|
1381
|
+
backgroundColor: "white",
|
|
1382
|
+
transition: "0.3s cubic-bezier(0.4, 0, 0.2, 1)",
|
|
1383
|
+
borderRadius: "50%",
|
|
1384
|
+
boxShadow: isActive
|
|
1385
|
+
? "0 3px 8px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(16, 185, 129, 0.1)"
|
|
1386
|
+
: "0 3px 8px rgba(0, 0, 0, 0.3)",
|
|
1258
1387
|
}}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
width: "12px",
|
|
1263
|
-
height: "12px",
|
|
1264
|
-
border: "2px solid currentColor",
|
|
1265
|
-
borderTop: "2px solid transparent",
|
|
1266
|
-
borderRadius: "50%",
|
|
1267
|
-
animation: "ai-spin 1s linear infinite",
|
|
1268
|
-
}}
|
|
1269
|
-
/>
|
|
1270
|
-
</div>
|
|
1271
|
-
) : isActive ? (
|
|
1272
|
-
"Désactiver"
|
|
1273
|
-
) : (
|
|
1274
|
-
"Activer"
|
|
1275
|
-
)}
|
|
1276
|
-
</button>
|
|
1388
|
+
/>
|
|
1389
|
+
</span>
|
|
1390
|
+
</label>
|
|
1277
1391
|
</div>
|
|
1278
1392
|
);
|
|
1279
1393
|
})}
|
|
1394
|
+
{effectiveAvailableModels.filter((model) => {
|
|
1395
|
+
if (model.category !== modelCategory) return false;
|
|
1396
|
+
if (!modelSearchQuery.trim()) return true;
|
|
1397
|
+
const query = modelSearchQuery.toLowerCase();
|
|
1398
|
+
return (
|
|
1399
|
+
model.name.toLowerCase().includes(query) ||
|
|
1400
|
+
model.provider.toLowerCase().includes(query) ||
|
|
1401
|
+
model.description?.toLowerCase().includes(query)
|
|
1402
|
+
);
|
|
1403
|
+
}).length === 0 && (
|
|
1404
|
+
<div
|
|
1405
|
+
style={{
|
|
1406
|
+
textAlign: "center",
|
|
1407
|
+
padding: "32px 16px",
|
|
1408
|
+
color: "var(--ai-text-tertiary, #9ca3af)",
|
|
1409
|
+
fontSize: "14px",
|
|
1410
|
+
}}
|
|
1411
|
+
>
|
|
1412
|
+
{modelSearchQuery.trim()
|
|
1413
|
+
? "Aucun modèle ne correspond à votre recherche"
|
|
1414
|
+
: "Aucun modèle disponible"}
|
|
1415
|
+
</div>
|
|
1416
|
+
)}
|
|
1280
1417
|
</div>
|
|
1281
1418
|
</div>
|
|
1282
1419
|
|
|
1283
1420
|
<div style={aiStyles.modalFooter}>
|
|
1284
1421
|
<button
|
|
1285
|
-
onClick={() =>
|
|
1422
|
+
onClick={() => {
|
|
1423
|
+
setIsModelManagementOpen(false);
|
|
1424
|
+
setModelSearchQuery("");
|
|
1425
|
+
}}
|
|
1286
1426
|
style={{
|
|
1287
1427
|
...aiStyles.button,
|
|
1288
1428
|
...aiStyles.buttonSecondary,
|