@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.
- package/dist/components/AiChipLabel.d.ts +8 -3
- package/dist/components/AiChipLabel.d.ts.map +1 -1
- package/dist/components/AiChipLabel.js +23 -70
- package/dist/components/AiContextButton.d.ts +10 -2
- package/dist/components/AiContextButton.d.ts.map +1 -1
- package/dist/components/AiContextButton.js +73 -291
- package/dist/components/AiImageButton.d.ts +5 -1
- package/dist/components/AiImageButton.d.ts.map +1 -1
- package/dist/components/AiImageButton.js +6 -142
- package/dist/components/AiInput.d.ts +5 -3
- package/dist/components/AiInput.d.ts.map +1 -1
- package/dist/components/AiInput.js +13 -25
- package/dist/components/AiPromptPanel.d.ts.map +1 -1
- package/dist/components/AiPromptPanel.js +64 -212
- package/dist/components/AiSelect.d.ts +5 -3
- package/dist/components/AiSelect.d.ts.map +1 -1
- package/dist/components/AiSelect.js +21 -30
- package/dist/components/AiStatusButton.d.ts +4 -1
- package/dist/components/AiStatusButton.d.ts.map +1 -1
- package/dist/components/AiStatusButton.js +211 -676
- package/dist/components/AiTextarea.d.ts +4 -2
- package/dist/components/AiTextarea.d.ts.map +1 -1
- package/dist/components/AiTextarea.js +14 -26
- package/dist/components/LBApiKeySelector.d.ts.map +1 -1
- package/dist/components/LBApiKeySelector.js +5 -166
- package/dist/components/LBConnectButton.d.ts +4 -7
- package/dist/components/LBConnectButton.d.ts.map +1 -1
- package/dist/components/LBConnectButton.js +17 -86
- package/dist/components/LBSigninModal.d.ts +1 -1
- package/dist/components/LBSigninModal.d.ts.map +1 -1
- package/dist/components/LBSigninModal.js +42 -320
- package/dist/context/LBAuthProvider.d.ts +35 -3
- package/dist/context/LBAuthProvider.d.ts.map +1 -1
- package/dist/context/LBAuthProvider.js +2 -0
- package/dist/examples/AiUiPremiumShowcase.d.ts +2 -0
- package/dist/examples/AiUiPremiumShowcase.d.ts.map +1 -0
- package/dist/examples/AiUiPremiumShowcase.js +15 -0
- package/dist/hooks/useAiModels.d.ts.map +1 -1
- package/dist/hooks/useModelManagement.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/styles/inline.d.ts +1 -0
- package/dist/styles/inline.d.ts.map +1 -1
- package/dist/styles/inline.js +25 -129
- package/dist/styles.css +1268 -369
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/errorHandler.d.ts +2 -2
- package/dist/utils/errorHandler.d.ts.map +1 -1
- package/dist/utils/errorHandler.js +8 -1
- package/dist/utils/modelManagement.d.ts +13 -10
- package/dist/utils/modelManagement.d.ts.map +1 -1
- package/dist/utils/modelManagement.js +19 -2
- package/package.json +2 -2
- package/src/components/AiChipLabel.tsx +68 -101
- package/src/components/AiContextButton.tsx +142 -413
- package/src/components/AiImageButton.tsx +29 -190
- package/src/components/AiInput.tsx +49 -74
- package/src/components/AiPromptPanel.tsx +81 -260
- package/src/components/AiSelect.tsx +61 -69
- package/src/components/AiStatusButton.tsx +496 -1327
- package/src/components/AiTextarea.tsx +50 -63
- package/src/components/LBApiKeySelector.tsx +93 -271
- package/src/components/LBConnectButton.tsx +39 -336
- package/src/components/LBSigninModal.tsx +141 -472
- package/src/context/LBAuthProvider.tsx +45 -6
- package/src/examples/AiUiPremiumShowcase.tsx +94 -0
- package/src/hooks/useAiModels.ts +2 -1
- package/src/hooks/useModelManagement.ts +2 -1
- package/src/index.ts +3 -0
- package/src/styles/inline.ts +27 -148
- package/src/styles.css +1268 -369
- package/src/types.ts +3 -0
- package/src/utils/errorHandler.ts +16 -3
- package/src/utils/modelManagement.ts +53 -15
package/dist/types.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export type ToastType = {
|
|
|
4
4
|
code?: string;
|
|
5
5
|
};
|
|
6
6
|
export type UiMode = "modal" | "drawer";
|
|
7
|
+
export type AiSize = "sm" | "md" | "lg";
|
|
8
|
+
export type AiRadius = "none" | "sm" | "md" | "lg" | "full";
|
|
9
|
+
export type AiVariant = "default" | "light";
|
|
7
10
|
export interface BaseAiProps {
|
|
8
11
|
baseUrl?: string;
|
|
9
12
|
apiKeyId?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AACF,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AACxC,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACxC,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAC5D,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -6,7 +6,7 @@ export interface ParsedError {
|
|
|
6
6
|
/**
|
|
7
7
|
* Parse et uniformise la gestion des erreurs des composants AI
|
|
8
8
|
*/
|
|
9
|
-
export declare function parseAIError(error:
|
|
9
|
+
export declare function parseAIError(error: unknown): ParsedError;
|
|
10
10
|
/**
|
|
11
11
|
* Interface pour la callback de gestion d'erreur uniforme
|
|
12
12
|
*/
|
|
@@ -23,7 +23,7 @@ export interface ErrorToastCallback {
|
|
|
23
23
|
* @param onToast Callback externe optionnelle fournie par le parent
|
|
24
24
|
* @param showInternalToast Callback interne optionnelle pour afficher un toast dans le composant
|
|
25
25
|
*/
|
|
26
|
-
export declare function handleAIError(error:
|
|
26
|
+
export declare function handleAIError(error: unknown, onToast?: ErrorToastCallback, showInternalToast?: (error: {
|
|
27
27
|
message: string;
|
|
28
28
|
code?: string;
|
|
29
29
|
}) => void): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/utils/errorHandler.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"errorHandler.d.ts","sourceRoot":"","sources":["../../src/utils/errorHandler.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;CACzB;AAeD;;GAEG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CA8CxD;AAyFD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAClE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,kBAAkB,EAC5B,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,GACtE,IAAI,CAuBN"}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { ErrorCode } from "@lastbrain/ai-ui-core";
|
|
3
|
+
function isNormalizedErrorLike(value) {
|
|
4
|
+
if (!value || typeof value !== "object") {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
const v = value;
|
|
8
|
+
return typeof v.code === "string" && typeof v.message === "string";
|
|
9
|
+
}
|
|
3
10
|
/**
|
|
4
11
|
* Parse et uniformise la gestion des erreurs des composants AI
|
|
5
12
|
*/
|
|
6
13
|
export function parseAIError(error) {
|
|
7
14
|
// Si l'erreur est déjà un objet normalisé
|
|
8
|
-
if (error
|
|
15
|
+
if (isNormalizedErrorLike(error)) {
|
|
9
16
|
return {
|
|
10
17
|
message: getUserFriendlyMessage(error.code, error.message),
|
|
11
18
|
code: error.code,
|
|
@@ -5,25 +5,28 @@ export interface ModelToggleOptions {
|
|
|
5
5
|
apiKey?: string;
|
|
6
6
|
baseUrl?: string;
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*/
|
|
11
|
-
export declare function toggleUserModel(modelId: string, isActive: boolean, options?: ModelToggleOptions): Promise<void>;
|
|
12
|
-
/**
|
|
13
|
-
* Récupère tous les modèles disponibles avec API key ou via proxy
|
|
14
|
-
*/
|
|
15
|
-
export declare function getAvailableModels(options?: ModelToggleOptions): Promise<Array<{
|
|
8
|
+
type ModelCategory = "text" | "image" | "audio" | "video";
|
|
9
|
+
interface ModelInfo {
|
|
16
10
|
id: string;
|
|
17
11
|
name: string;
|
|
18
12
|
description?: string;
|
|
19
13
|
provider: string;
|
|
20
|
-
category:
|
|
14
|
+
category: ModelCategory;
|
|
21
15
|
isActive?: boolean;
|
|
22
16
|
isPro?: boolean;
|
|
23
17
|
costPer1M?: number;
|
|
24
|
-
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Active ou désactive un modèle pour l'utilisateur courant
|
|
21
|
+
*/
|
|
22
|
+
export declare function toggleUserModel(modelId: string, isActive: boolean, options?: ModelToggleOptions): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Récupère tous les modèles disponibles avec API key ou via proxy
|
|
25
|
+
*/
|
|
26
|
+
export declare function getAvailableModels(options?: ModelToggleOptions): Promise<ModelInfo[]>;
|
|
25
27
|
/**
|
|
26
28
|
* Récupère les modèles activés par l'utilisateur avec API key
|
|
27
29
|
*/
|
|
28
30
|
export declare function getUserModels(options?: ModelToggleOptions): Promise<string[]>;
|
|
31
|
+
export {};
|
|
29
32
|
//# sourceMappingURL=modelManagement.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modelManagement.d.ts","sourceRoot":"","sources":["../../src/utils/modelManagement.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"modelManagement.d.ts","sourceRoot":"","sources":["../../src/utils/modelManagement.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAcD,KAAK,aAAa,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1D,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8BD;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,OAAO,EACjB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,SAAS,EAAE,CAAC,CA0DtB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,EAAE,CAAC,CAkDnB"}
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utilitaires pour la gestion des modèles IA
|
|
3
3
|
*/
|
|
4
|
+
function isModelCategory(value) {
|
|
5
|
+
return (value === "text" ||
|
|
6
|
+
value === "image" ||
|
|
7
|
+
value === "audio" ||
|
|
8
|
+
value === "video");
|
|
9
|
+
}
|
|
10
|
+
function isModelInfo(value) {
|
|
11
|
+
if (!value || typeof value !== "object")
|
|
12
|
+
return false;
|
|
13
|
+
const v = value;
|
|
14
|
+
return (typeof v.id === "string" &&
|
|
15
|
+
typeof v.name === "string" &&
|
|
16
|
+
typeof v.provider === "string" &&
|
|
17
|
+
isModelCategory(v.category));
|
|
18
|
+
}
|
|
4
19
|
function isAuthTokenCandidate(value) {
|
|
5
20
|
if (!value)
|
|
6
21
|
return false;
|
|
@@ -76,10 +91,12 @@ export async function getAvailableModels(options = {}) {
|
|
|
76
91
|
}
|
|
77
92
|
const data = await response.json();
|
|
78
93
|
if (Array.isArray(data?.models)) {
|
|
79
|
-
return data.models;
|
|
94
|
+
return data.models.filter(isModelInfo);
|
|
80
95
|
}
|
|
81
96
|
if (Array.isArray(data?.providers)) {
|
|
82
|
-
return data.providers
|
|
97
|
+
return (data.providers?.flatMap((provider) => Array.isArray(provider.models)
|
|
98
|
+
? provider.models.filter(isModelInfo)
|
|
99
|
+
: []) || []);
|
|
83
100
|
}
|
|
84
101
|
return [];
|
|
85
102
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lastbrain/ai-ui-react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.70",
|
|
4
4
|
"description": "Headless React components for LastBrain AI UI Kit",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"lucide-react": "^0.257.0",
|
|
51
|
-
"@lastbrain/ai-ui-core": "1.0.
|
|
51
|
+
"@lastbrain/ai-ui-core": "1.0.53"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/react": "^19.2.0",
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import React, { useState, useRef, KeyboardEvent } 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,10 +9,13 @@ 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";
|
|
12
|
+
import type { AiRadius, AiSize } from "../types";
|
|
13
13
|
|
|
14
14
|
export interface AiChipLabelProps {
|
|
15
15
|
children: React.ReactNode;
|
|
16
|
-
variant?: "default" | "
|
|
16
|
+
variant?: "default" | "selected" | "warning" | "success" | "danger";
|
|
17
|
+
size?: AiSize;
|
|
18
|
+
radius?: AiRadius;
|
|
17
19
|
className?: string;
|
|
18
20
|
style?: React.CSSProperties;
|
|
19
21
|
}
|
|
@@ -21,36 +23,23 @@ export interface AiChipLabelProps {
|
|
|
21
23
|
export function AiChipLabel({
|
|
22
24
|
children,
|
|
23
25
|
variant = "default",
|
|
26
|
+
size = "md",
|
|
27
|
+
radius = "full",
|
|
24
28
|
className,
|
|
25
29
|
style: customStyle,
|
|
26
30
|
}: AiChipLabelProps) {
|
|
27
|
-
const
|
|
28
|
-
default:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
warning: {
|
|
35
|
-
background: "#f59e0b10",
|
|
36
|
-
color: "#f59e0b",
|
|
37
|
-
borderColor: "#f59e0b30",
|
|
38
|
-
},
|
|
39
|
-
danger: {
|
|
40
|
-
background: "#ef444410",
|
|
41
|
-
color: "#ef4444",
|
|
42
|
-
borderColor: "#ef444430",
|
|
43
|
-
},
|
|
31
|
+
const variantClassMap: Record<string, string> = {
|
|
32
|
+
default: "",
|
|
33
|
+
selected: "ai-chip--selected",
|
|
34
|
+
warning: "ai-chip--success",
|
|
35
|
+
success: "ai-chip--success",
|
|
36
|
+
danger: "ai-chip--danger",
|
|
44
37
|
};
|
|
45
38
|
|
|
46
39
|
return (
|
|
47
40
|
<span
|
|
48
|
-
style={
|
|
49
|
-
|
|
50
|
-
...variantStyles[variant],
|
|
51
|
-
...customStyle,
|
|
52
|
-
}}
|
|
53
|
-
className={className}
|
|
41
|
+
style={customStyle}
|
|
42
|
+
className={`ai-chip ai-size-${size} ai-radius-${radius} ${variantClassMap[variant]} ${className || ""}`}
|
|
54
43
|
>
|
|
55
44
|
{children}
|
|
56
45
|
</span>
|
|
@@ -70,6 +59,8 @@ export interface AiChipInputProps {
|
|
|
70
59
|
// Props optionnelles pour override du contexte (si nécessaire)
|
|
71
60
|
baseUrl?: string;
|
|
72
61
|
apiKeyId?: string;
|
|
62
|
+
size?: AiSize;
|
|
63
|
+
radius?: AiRadius;
|
|
73
64
|
}
|
|
74
65
|
|
|
75
66
|
export function AiChipInput({
|
|
@@ -84,6 +75,8 @@ export function AiChipInput({
|
|
|
84
75
|
artifactTitle,
|
|
85
76
|
baseUrl: propBaseUrl,
|
|
86
77
|
apiKeyId: propApiKeyId,
|
|
78
|
+
size = "md",
|
|
79
|
+
radius = "full",
|
|
87
80
|
}: AiChipInputProps) {
|
|
88
81
|
const [inputValue, setInputValue] = useState("");
|
|
89
82
|
const [showPromptPanel, setShowPromptPanel] = useState(false);
|
|
@@ -199,92 +192,66 @@ Exemple de réponse attendue: javascript, react, frontend, api, development`;
|
|
|
199
192
|
onChange?.(updatedChips);
|
|
200
193
|
};
|
|
201
194
|
|
|
202
|
-
|
|
195
|
+
const sizeClass = `ai-size-${size}`;
|
|
196
|
+
const radiusClass = `ai-radius-${radius}`;
|
|
203
197
|
|
|
204
198
|
return (
|
|
205
199
|
<div className={className}>
|
|
206
200
|
{/* Input avec bouton génération */}
|
|
207
|
-
<div
|
|
208
|
-
<
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
201
|
+
<div className="ai-control-group ai-glow mb-2">
|
|
202
|
+
<div className={`ai-shell ${sizeClass} ${radiusClass}`}>
|
|
203
|
+
<input
|
|
204
|
+
ref={inputRef}
|
|
205
|
+
type="text"
|
|
206
|
+
value={inputValue}
|
|
207
|
+
onChange={(e) => setInputValue(e.target.value)}
|
|
208
|
+
onKeyDown={handleKeyDown}
|
|
209
|
+
placeholder={placeholder}
|
|
210
|
+
className={`ai-control ai-control-input ai-control-input--with-action ${sizeClass} ${radiusClass}`}
|
|
211
|
+
/>
|
|
212
|
+
<button
|
|
213
|
+
onClick={() => {
|
|
214
|
+
if (isAuthenticated) {
|
|
215
|
+
handleGenerateChips();
|
|
216
|
+
} else {
|
|
217
|
+
setShowSigninModal(true);
|
|
218
|
+
}
|
|
219
|
+
}}
|
|
220
|
+
className={`ai-control-action ai-spark ${sizeClass} ${radiusClass}`}
|
|
221
|
+
aria-label={
|
|
222
|
+
isAuthenticated
|
|
223
|
+
? "Générer des tags avec l'IA"
|
|
224
|
+
: "Connexion requise"
|
|
226
225
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
padding: "4px",
|
|
237
|
-
borderRadius: "4px",
|
|
238
|
-
display: "flex",
|
|
239
|
-
alignItems: "center",
|
|
240
|
-
color: isAuthenticated ? "#6366f1" : "#ef4444",
|
|
241
|
-
}}
|
|
242
|
-
title={
|
|
243
|
-
isAuthenticated
|
|
244
|
-
? "Générer des tags avec l'IA"
|
|
245
|
-
: "Se connecter pour utiliser l'IA"
|
|
246
|
-
}
|
|
247
|
-
>
|
|
248
|
-
{isAuthenticated ? <Sparkles size={16} /> : <Lock size={16} />}
|
|
249
|
-
</button>
|
|
226
|
+
title={
|
|
227
|
+
isAuthenticated
|
|
228
|
+
? "Générer des tags avec l'IA"
|
|
229
|
+
: "Se connecter pour utiliser l'IA"
|
|
230
|
+
}
|
|
231
|
+
>
|
|
232
|
+
{isAuthenticated ? <Sparkles size={16} /> : <Lock size={16} />}
|
|
233
|
+
</button>
|
|
234
|
+
</div>
|
|
250
235
|
</div>
|
|
251
236
|
|
|
252
237
|
{/* Chips affichées */}
|
|
253
238
|
{value.length > 0 && (
|
|
254
|
-
<div
|
|
255
|
-
{value.map((chip, index) =>
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
paddingRight: "6px",
|
|
266
|
-
}}
|
|
239
|
+
<div className="ai-chip-input">
|
|
240
|
+
{value.map((chip, index) => (
|
|
241
|
+
<div
|
|
242
|
+
key={index}
|
|
243
|
+
className={`ai-chip ai-chip--with-close ${sizeClass} ${radiusClass}`}
|
|
244
|
+
>
|
|
245
|
+
<span>{chip}</span>
|
|
246
|
+
<button
|
|
247
|
+
onClick={() => removeChip(index)}
|
|
248
|
+
className="ai-chip-remover"
|
|
249
|
+
title="Supprimer"
|
|
267
250
|
>
|
|
268
|
-
<
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
background: "none",
|
|
273
|
-
border: "none",
|
|
274
|
-
cursor: "pointer",
|
|
275
|
-
padding: "0",
|
|
276
|
-
display: "flex",
|
|
277
|
-
alignItems: "center",
|
|
278
|
-
color: "currentColor",
|
|
279
|
-
opacity: 0.7,
|
|
280
|
-
}}
|
|
281
|
-
title="Supprimer"
|
|
282
|
-
>
|
|
283
|
-
<X size={14} />
|
|
284
|
-
</button>
|
|
285
|
-
</div>
|
|
286
|
-
);
|
|
287
|
-
})}
|
|
251
|
+
<X size={14} />
|
|
252
|
+
</button>
|
|
253
|
+
</div>
|
|
254
|
+
))}
|
|
288
255
|
</div>
|
|
289
256
|
)}
|
|
290
257
|
|