@lastbrain/ai-ui-react 1.0.78 → 1.0.80

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,oBAAoB,CAAC;AAC5B,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;AAY5D,KAAK,WAAW,GACZ,MAAM,GACN,MAAM,GACN,OAAO,GACP,MAAM,GACN,OAAO,EAAE,GACT;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAE3B,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,kBAAkB,EAClB,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,IAAW,EACX,MAAe,EACf,OAAmB,EACnB,OAAO,EAAE,QAAQ,EACjB,GAAG,WAAW,EACf,EAAE,oBAAoB,2CA+TtB"}
1
+ {"version":3,"file":"AiContextButton.d.ts","sourceRoot":"","sources":["../../src/components/AiContextButton.tsx"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAC5B,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;AAY5D,KAAK,WAAW,GACZ,MAAM,GACN,MAAM,GACN,OAAO,GACP,MAAM,GACN,OAAO,EAAE,GACT;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,CAAC;AAE3B,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,kBAAkB,EAClB,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,IAAW,EACX,MAAe,EACf,OAAmB,EACnB,OAAO,EAAE,QAAQ,EACjB,GAAG,WAAW,EACf,EAAE,oBAAoB,2CAuUtB"}
@@ -23,21 +23,20 @@ export function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId,
23
23
  const resolvedContextDescription = contextDescription || t("ai.context.description", "Data to analyze");
24
24
  let lbStatus;
25
25
  let lbHasSession = false;
26
- let lbHasSelectedKey = false;
27
26
  let lbHasSelectedApiKeyCookie = false;
27
+ let lbHasSelectedKey = false;
28
28
  let hasLBProvider = false;
29
29
  try {
30
30
  const lbContext = useLB();
31
31
  lbStatus = lbContext.status;
32
32
  lbHasSession = Boolean(lbContext.session?.sessionToken);
33
- lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
34
33
  lbHasSelectedApiKeyCookie = lbContext.hasSelectedApiKeyCookie;
34
+ lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
35
35
  hasLBProvider = true;
36
36
  }
37
37
  catch {
38
38
  lbStatus = undefined;
39
39
  lbHasSession = false;
40
- lbHasSelectedKey = false;
41
40
  hasLBProvider = false;
42
41
  }
43
42
  const aiContext = useAiContext();
@@ -50,7 +49,8 @@ export function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId,
50
49
  const needsApiKeySelection = hasLBProvider &&
51
50
  lbStatus === "ready" &&
52
51
  lbHasSession &&
53
- (!lbHasSelectedKey || !lbHasSelectedApiKeyCookie);
52
+ !lbHasSelectedApiKeyCookie &&
53
+ !lbHasSelectedKey;
54
54
  const isAuthReady = !needsApiKeySelection &&
55
55
  (lbStatus === "ready" || Boolean(process.env.LB_API_KEY));
56
56
  const handleOpenPanel = () => {
@@ -156,9 +156,15 @@ export function AiContextButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId,
156
156
  const sizeClass = `ai-size-${size}`;
157
157
  const radiusClass = `ai-radius-${radius}`;
158
158
  const variantClass = variant === "light" ? "ai-btn--light" : "";
159
- 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
159
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "relative inline-block ai-glow", children: [_jsx("button", { ...buttonProps, onClick: () => {
160
+ if (!isAuthReady) {
161
+ setShowAuthModal(true);
162
+ return;
163
+ }
164
+ handleOpenPanel();
165
+ }, disabled: disabled || loading, className: `ai-btn ai-context-btn ${variantClass} ${sizeClass} ${radiusClass} ${className || ""}`, title: !isAuthReady
160
166
  ? t("auth.required", "Authentication required")
161
- : t("ai.analyze", "Analyze with AI"), children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 16, className: "ai-spinner" }), _jsx("span", { children: t("ai.analyzing", "Analyzing...") })] })) : !isAuthReady ? (_jsxs(_Fragment, { children: [_jsx(Lock, { size: 16 }), children || (_jsx("span", { children: t("auth.connectRequired", "Connection required") }))] })) : (_jsxs(_Fragment, { children: [_jsx(Sparkles, { size: 16 }), children || (_jsx("span", { children: t("ai.context.buttonAnalyze", "Analyze") }))] })) }), 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) => {
167
+ : t("ai.analyze", "Analyze with AI"), children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 16, className: "ai-spinner" }), _jsx("span", { children: t("ai.analyzing", "Analyzing...") })] })) : !isAuthReady ? (_jsxs(_Fragment, { children: [_jsx(Lock, { size: 16 }), children || (_jsx("span", { children: t("auth.connectRequired", "Connection required") }))] })) : (_jsxs(_Fragment, { children: [_jsx(Sparkles, { size: 16 }), children || (_jsx("span", { children: t("ai.context.buttonAnalyze", "Analyze") }))] })) }), isOpen ? (_jsx(AiPromptPanel, { isOpen: isOpen, onClose: () => setIsOpen(false), onSubmit: handleSubmit, uiMode: uiMode, models: [], enableModelManagement: true, modelCategory: "text", baseUrl: baseUrl, apiKey: apiKeyId, contextPreview: formatContextData(contextData), contextPreviewTitle: resolvedContextDescription })) : null] }), isResultOpen && analysisResult ? (_jsx("div", { className: "ai-signin-overlay ai-overlay-panel", onClick: (e) => {
162
168
  if (e.target === e.currentTarget) {
163
169
  setIsResultOpen(false);
164
170
  setAnalysisResult(null);
@@ -1 +1 @@
1
- {"version":3,"file":"AiImageButton.d.ts","sourceRoot":"","sources":["../../src/components/AiImageButton.tsx"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAC5B,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAS5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAY5D,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;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;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,IAAW,EACX,MAAe,EACf,OAAmB,EACnB,GAAG,WAAW,EACf,EAAE,kBAAkB,2CAsSpB"}
1
+ {"version":3,"file":"AiImageButton.d.ts","sourceRoot":"","sources":["../../src/components/AiImageButton.tsx"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAC5B,OAAO,EAAY,KAAK,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAS5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAY5D,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;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;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,IAAW,EACX,MAAe,EACf,OAAmB,EACnB,GAAG,WAAW,EACf,EAAE,kBAAkB,2CA4SpB"}
@@ -23,22 +23,21 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
23
23
  // Rendre l'authentification optionnelle
24
24
  let lbStatus;
25
25
  let lbHasSession = false;
26
- let lbHasSelectedKey = false;
27
26
  let lbHasSelectedApiKeyCookie = false;
27
+ let lbHasSelectedKey = false;
28
28
  let hasLBProvider = false;
29
29
  try {
30
30
  const lbContext = useLB();
31
31
  lbStatus = lbContext.status;
32
32
  lbHasSession = Boolean(lbContext.session?.sessionToken);
33
- lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
34
33
  lbHasSelectedApiKeyCookie = lbContext.hasSelectedApiKeyCookie;
34
+ lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
35
35
  hasLBProvider = true;
36
36
  }
37
37
  catch {
38
38
  // LBProvider n'est pas disponible, ignorer
39
39
  lbStatus = undefined;
40
40
  lbHasSession = false;
41
- lbHasSelectedKey = false;
42
41
  hasLBProvider = false;
43
42
  }
44
43
  // Récupérer le contexte AiProvider avec fallback sur les props
@@ -50,7 +49,8 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
50
49
  const needsApiKeySelection = hasLBProvider &&
51
50
  lbStatus === "ready" &&
52
51
  lbHasSession &&
53
- (!lbHasSelectedKey || !lbHasSelectedApiKeyCookie);
52
+ !lbHasSelectedApiKeyCookie &&
53
+ !lbHasSelectedKey;
54
54
  const isAuthReady = !needsApiKeySelection &&
55
55
  (lbStatus === "ready" || Boolean(process.env.LB_API_KEY));
56
56
  const handleOpenPanel = () => {
@@ -150,7 +150,13 @@ export function AiImageButton({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, ui
150
150
  const sizeClass = `ai-size-${size}`;
151
151
  const radiusClass = `ai-radius-${radius}`;
152
152
  const variantClass = variant === "light" ? "ai-btn--light" : "";
153
- return (_jsxs("div", { className: "flex items-start gap-4", children: [_jsxs("div", { className: "relative inline-block ai-glow", children: [_jsx("button", { ...buttonProps, onClick: handleOpenPanel, disabled: disabled || loading || !isAuthReady, className: `ai-btn ai-image-btn ${variantClass} ${sizeClass} ${radiusClass} ${className || ""}`, style: buttonProps.style, "data-ai-image-button": true, title: !isAuthReady
153
+ return (_jsxs("div", { className: "flex items-start gap-4", children: [_jsxs("div", { className: "relative inline-block ai-glow", children: [_jsx("button", { ...buttonProps, onClick: () => {
154
+ if (!isAuthReady) {
155
+ setShowAuthModal(true);
156
+ return;
157
+ }
158
+ handleOpenPanel();
159
+ }, disabled: disabled || loading, className: `ai-btn ai-image-btn ${variantClass} ${sizeClass} ${radiusClass} ${className || ""}`, style: buttonProps.style, "data-ai-image-button": true, title: !isAuthReady
154
160
  ? t("auth.required", "Authentication required")
155
161
  : t("ai.image.generate", "Generate image"), children: loading ? (_jsxs("span", { className: "ai-loading-stack", children: [_jsxs("span", { className: "ai-loading-row", children: [_jsx(Loader2, { size: 18, className: "ai-spinner" }), _jsx("span", { className: "ai-text-microtracking", children: t("ai.image.generating", "Generating...") })] }), _jsx("span", { className: "ai-loading-meta", children: t("ai.loading.elapsed", "{seconds}", {
156
162
  seconds: loadingElapsed,
@@ -23,22 +23,21 @@ export function AiInput({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMode =
23
23
  // Rendre l'authentification optionnelle
24
24
  let lbStatus;
25
25
  let lbHasSession = false;
26
- let lbHasSelectedKey = false;
27
26
  let lbHasSelectedApiKeyCookie = false;
27
+ let lbHasSelectedKey = false;
28
28
  let hasLBProvider = false;
29
29
  try {
30
30
  const lbContext = useLB();
31
31
  lbStatus = lbContext.status;
32
32
  lbHasSession = Boolean(lbContext.session?.sessionToken);
33
- lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
34
33
  lbHasSelectedApiKeyCookie = lbContext.hasSelectedApiKeyCookie;
34
+ lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
35
35
  hasLBProvider = true;
36
36
  }
37
37
  catch {
38
38
  // LBProvider n'est pas disponible, ignorer
39
39
  lbStatus = undefined;
40
40
  lbHasSession = false;
41
- lbHasSelectedKey = false;
42
41
  hasLBProvider = false;
43
42
  }
44
43
  let ctxBaseUrl;
@@ -65,7 +64,8 @@ export function AiInput({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMode =
65
64
  const needsApiKeySelection = hasLBProvider &&
66
65
  lbStatus === "ready" &&
67
66
  lbHasSession &&
68
- (!lbHasSelectedKey || !lbHasSelectedApiKeyCookie);
67
+ !lbHasSelectedApiKeyCookie &&
68
+ !lbHasSelectedKey;
69
69
  const isAuthReady = !needsApiKeySelection &&
70
70
  (lbStatus === "ready" || Boolean(process.env.LB_API_KEY));
71
71
  const shouldShowSparkles = isAuthReady && !disabled;
@@ -19,6 +19,8 @@ export interface AiPromptPanelProps {
19
19
  apiKey?: string;
20
20
  baseUrl?: string;
21
21
  showOnlyUserModels?: boolean;
22
+ contextPreview?: string;
23
+ contextPreviewTitle?: string;
22
24
  }
23
25
  export interface AiPromptPanelRenderProps {
24
26
  models?: ModelRef[];
@@ -1 +1 @@
1
- {"version":3,"file":"AiPromptPanel.d.ts","sourceRoot":"","sources":["../../src/components/AiPromptPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAWf,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AASvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAKrD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,SAAS,CAAC;IAE1D,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;IAExB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CA0BtD"}
1
+ {"version":3,"file":"AiPromptPanel.d.ts","sourceRoot":"","sources":["../../src/components/AiPromptPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAC5B,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAcf,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AASvC,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAkBrD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,SAAS,CAAC;IAE1D,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACjC,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,IAAI,CAAC;IAExB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,EAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,2CA0BtD"}
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  import "../styles/register";
4
- import { useState, useEffect, useRef, useLayoutEffect, } from "react";
4
+ import { useState, useEffect, useRef, useLayoutEffect, useMemo, } from "react";
5
5
  import { createPortal } from "react-dom";
6
- import { BookOpen, Search, Sparkles, Star, Tag, Settings, Loader2, } from "lucide-react";
6
+ import { BookOpen, Check, Copy, Eye, Search, Sparkles, Star, Tag, Settings, Loader2, } from "lucide-react";
7
7
  import { aiStyles } from "../styles/inline";
8
8
  import { handleAIError } from "../utils/errorHandler";
9
9
  import { usePrompts, } from "../hooks/usePrompts";
@@ -11,6 +11,19 @@ import { useModelManagement } from "../hooks/useModelManagement";
11
11
  import { AiProvider, useAiContext } from "../context/AiProvider";
12
12
  import { useI18n } from "../context/I18nContext";
13
13
  import { useLoadingTimer } from "../hooks/useLoadingTimer";
14
+ function tryFormatJson(input) {
15
+ const raw = (input || "").trim();
16
+ if (!raw) {
17
+ return { formatted: "", isJson: false };
18
+ }
19
+ try {
20
+ const parsed = JSON.parse(raw);
21
+ return { formatted: JSON.stringify(parsed, null, 2), isJson: true };
22
+ }
23
+ catch {
24
+ return { formatted: input || "", isJson: false };
25
+ }
26
+ }
14
27
  export function AiPromptPanel(props) {
15
28
  const { apiKey, baseUrl } = props;
16
29
  let hasContext = false;
@@ -32,7 +45,7 @@ export function AiPromptPanel(props) {
32
45
  // Sinon, utiliser le contexte existant
33
46
  return _jsx(AiPromptPanelInternal, { ...props });
34
47
  }
35
- function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", models = [], sourceText, children, enableModelManagement = true, modelCategory = "text", availableModels = [], userModels = [], onModelToggle, apiKey, baseUrl, showOnlyUserModels = false, }) {
48
+ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", models = [], sourceText, children, enableModelManagement = true, modelCategory = "text", availableModels = [], userModels = [], onModelToggle, apiKey, baseUrl, showOnlyUserModels = false, contextPreview, contextPreviewTitle, }) {
36
49
  const { t } = useI18n();
37
50
  const [selectedModel, setSelectedModel] = useState("");
38
51
  const [prompt, setPrompt] = useState("");
@@ -45,6 +58,8 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", mo
45
58
  const [selectedTag, setSelectedTag] = useState("all");
46
59
  const [isGenerating, setIsGenerating] = useState(false);
47
60
  const [isClosing, setIsClosing] = useState(false);
61
+ const [showContextPreview, setShowContextPreview] = useState(false);
62
+ const [contextCopied, setContextCopied] = useState(false);
48
63
  const [portalRoot, setPortalRoot] = useState(null);
49
64
  const promptRef = useRef(null);
50
65
  const closeTimeoutRef = useRef(null);
@@ -157,6 +172,8 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", mo
157
172
  setPrompt("");
158
173
  setPromptId(undefined);
159
174
  setShowPromptLibrary(false);
175
+ setShowContextPreview(false);
176
+ setContextCopied(false);
160
177
  setSearchQuery("");
161
178
  setSelectedTag("all");
162
179
  setIsClosing(false);
@@ -177,6 +194,12 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", mo
177
194
  }
178
195
  };
179
196
  }, []);
197
+ useEffect(() => {
198
+ if (!contextCopied)
199
+ return;
200
+ const timeout = window.setTimeout(() => setContextCopied(false), 1200);
201
+ return () => window.clearTimeout(timeout);
202
+ }, [contextCopied]);
180
203
  useEffect(() => {
181
204
  setPortalRoot(document.body);
182
205
  }, []);
@@ -221,6 +244,8 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", mo
221
244
  useLayoutEffect(() => {
222
245
  adjustPromptHeight();
223
246
  }, [prompt]);
247
+ const contextPreviewData = useMemo(() => tryFormatJson(contextPreview), [contextPreview]);
248
+ const contextPreviewLines = useMemo(() => contextPreviewData.formatted.split("\n"), [contextPreviewData.formatted]);
224
249
  if (!isOpen)
225
250
  return null;
226
251
  const activeModelId = selectedModel || modelOptions[0]?.id || "";
@@ -270,6 +295,8 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", mo
270
295
  return null;
271
296
  }
272
297
  const isDrawer = uiMode === "drawer";
298
+ const hasContextPreview = Boolean(contextPreview?.trim());
299
+ const contextCharCount = contextPreview?.length || 0;
273
300
  const panelContainerStyle = isDrawer
274
301
  ? {
275
302
  ...aiStyles.modal,
@@ -288,6 +315,40 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", mo
288
315
  borderRadius: "16px 0 0 16px",
289
316
  }
290
317
  : aiStyles.modalContent;
318
+ const renderContextLine = (line, lineIndex) => {
319
+ if (!contextPreviewData.isJson) {
320
+ return (_jsx("span", { style: { color: "var(--ai-text-secondary)" }, children: line || " " }, `line-${lineIndex}`));
321
+ }
322
+ const tokenRegex = /("(?:\\.|[^"\\])*"(?=\s*:)|"(?:\\.|[^"\\])*"|true|false|null|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[{}[\],:])/g;
323
+ const parts = [];
324
+ let lastIndex = 0;
325
+ let match;
326
+ while ((match = tokenRegex.exec(line)) !== null) {
327
+ const token = match[0];
328
+ const index = match.index;
329
+ if (index > lastIndex) {
330
+ parts.push(_jsx("span", { style: { color: "var(--ai-text-secondary)" }, children: line.slice(lastIndex, index) }, `txt-${lineIndex}-${lastIndex}`));
331
+ }
332
+ const isKey = /^".*"$/.test(token) && line.slice(match.index).includes(":");
333
+ const color = isKey
334
+ ? "#7cc5ff"
335
+ : /^".*"$/.test(token)
336
+ ? "#9ad07f"
337
+ : /^(true|false)$/.test(token)
338
+ ? "#f4a259"
339
+ : token === "null"
340
+ ? "#d3869b"
341
+ : /^-?\d/.test(token)
342
+ ? "#f7dc6f"
343
+ : "var(--ai-text-secondary)";
344
+ parts.push(_jsx("span", { style: { color }, children: token }, `tok-${lineIndex}-${index}`));
345
+ lastIndex = index + token.length;
346
+ }
347
+ if (lastIndex < line.length) {
348
+ parts.push(_jsx("span", { style: { color: "var(--ai-text-secondary)" }, children: line.slice(lastIndex) }, `txt-end-${lineIndex}`));
349
+ }
350
+ return (_jsx("span", { style: { whiteSpace: "pre" }, children: parts.length > 0 ? parts : " " }, `line-${lineIndex}`));
351
+ };
291
352
  if (children) {
292
353
  return createPortal(_jsx("div", { style: panelContainerStyle, onKeyDown: handleKeyDown, children: children(renderProps) }), portalRoot);
293
354
  }
@@ -417,7 +478,13 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", mo
417
478
  marginLeft: "4px",
418
479
  fontSize: "12px",
419
480
  fontWeight: 400,
420
- }, children: t("prompt.modal.promptHint", "(Cmd/Ctrl + Enter to submit)") })] }), promptsLoading ? (_jsx("span", { className: "ai-inline-skeleton", "aria-hidden": "true" })) : filteredPrompts.length > 0 ? (_jsxs("button", { onClick: () => setShowPromptLibrary(true), className: "ai-inline-btn", children: [_jsx(BookOpen, { size: 14 }), t("prompt.modal.browsePrompts", "Browse Prompts"), " (", filteredPrompts.length, ")"] })) : null] }), _jsx("textarea", { id: "prompt-input", ref: promptRef, value: prompt, onChange: (e) => setPrompt(e.target.value), onFocus: () => setPromptFocused(true), onBlur: () => setPromptFocused(false), placeholder: sourceText
481
+ }, children: t("prompt.modal.promptHint", "(Cmd/Ctrl + Enter to submit)") })] }), _jsxs("div", { style: {
482
+ display: "flex",
483
+ alignItems: "center",
484
+ flexWrap: "wrap",
485
+ justifyContent: "flex-end",
486
+ gap: "8px",
487
+ }, children: [hasContextPreview ? (_jsxs("button", { type: "button", onClick: () => setShowContextPreview(true), className: "ai-inline-btn", style: { whiteSpace: "nowrap" }, children: [_jsx(Eye, { size: 14 }), t("prompt.modal.contextPreview", "Context preview")] })) : null, promptsLoading ? (_jsx("span", { className: "ai-inline-skeleton", "aria-hidden": "true" })) : filteredPrompts.length > 0 ? (_jsxs("button", { onClick: () => setShowPromptLibrary(true), className: "ai-inline-btn", style: { whiteSpace: "nowrap" }, children: [_jsx(BookOpen, { size: 14 }), t("prompt.modal.browsePrompts", "Browse Prompts"), " (", filteredPrompts.length, ")"] })) : null] })] }), _jsx("textarea", { id: "prompt-input", ref: promptRef, value: prompt, onChange: (e) => setPrompt(e.target.value), onFocus: () => setPromptFocused(true), onBlur: () => setPromptFocused(false), placeholder: sourceText
421
488
  ? t("prompt.modal.promptPlaceholderWithSource", "Enter your AI prompt... e.g., 'Fix grammar', 'Make it more professional', 'Translate to English'")
422
489
  : t("prompt.modal.promptPlaceholderNoSource", "Enter your AI prompt... e.g., 'Write a blog post about AI', 'Generate product description'"), rows: 6, style: {
423
490
  ...aiStyles.textarea,
@@ -575,7 +642,73 @@ function AiPromptPanelInternal({ isOpen, onClose, onSubmit, uiMode = "modal", mo
575
642
  marginTop: "8px",
576
643
  fontSize: "11px",
577
644
  color: "var(--ai-primary)",
578
- }, children: String(promptData.category) })) : null] }, promptData.id))) })] }))] }))] })) }), _jsxs("div", { style: {
645
+ }, children: String(promptData.category) })) : null] }, promptData.id))) })] }))] }))] })) }), showContextPreview ? (_jsx("div", { style: {
646
+ position: "absolute",
647
+ inset: 0,
648
+ zIndex: 12,
649
+ background: "var(--ai-overlay)",
650
+ backdropFilter: "blur(3px)",
651
+ WebkitBackdropFilter: "blur(3px)",
652
+ display: "flex",
653
+ alignItems: "stretch",
654
+ justifyContent: "center",
655
+ padding: "10px",
656
+ }, onClick: () => setShowContextPreview(false), children: _jsxs("div", { style: {
657
+ width: "min(980px, 100%)",
658
+ maxHeight: "100%",
659
+ background: "var(--ai-bg-secondary)",
660
+ border: "1px solid var(--ai-border)",
661
+ borderRadius: "12px",
662
+ boxShadow: "var(--ai-shadow-lg)",
663
+ overflow: "hidden",
664
+ display: "flex",
665
+ flexDirection: "column",
666
+ }, onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { style: {
667
+ padding: "12px 14px",
668
+ borderBottom: "1px solid var(--ai-border)",
669
+ display: "flex",
670
+ alignItems: "center",
671
+ justifyContent: "space-between",
672
+ gap: "10px",
673
+ }, children: [_jsxs("div", { style: { minWidth: 0 }, children: [_jsx("div", { style: { fontSize: "14px", fontWeight: 600 }, children: contextPreviewTitle ||
674
+ t("prompt.modal.contextPreview", "Context preview") }), _jsx("div", { style: {
675
+ marginTop: "2px",
676
+ fontSize: "12px",
677
+ color: "var(--ai-text-secondary)",
678
+ }, children: t("prompt.modal.contextChars", "{count} chars", {
679
+ count: contextCharCount.toLocaleString(),
680
+ }) })] }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [_jsxs("button", { type: "button", className: "ai-inline-btn", onClick: async () => {
681
+ try {
682
+ await navigator.clipboard.writeText(contextPreviewData.formatted || "");
683
+ setContextCopied(true);
684
+ }
685
+ catch {
686
+ setContextCopied(false);
687
+ }
688
+ }, style: { whiteSpace: "nowrap" }, children: [contextCopied ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }), contextCopied
689
+ ? t("common.copied", "Copied")
690
+ : t("common.copy", "Copy")] }), _jsx("button", { type: "button", className: "ai-icon-btn", onClick: () => setShowContextPreview(false), "aria-label": t("common.closeLabel", "Close"), children: "\u00D7" })] })] }), _jsx("pre", { style: {
691
+ margin: 0,
692
+ padding: "14px",
693
+ flex: 1,
694
+ overflow: "auto",
695
+ background: "color-mix(in srgb, var(--ai-bg) 70%, transparent)",
696
+ borderTop: "1px solid var(--ai-border)",
697
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
698
+ fontSize: "12px",
699
+ lineHeight: 1.5,
700
+ }, children: contextPreviewLines.map((line, index) => (_jsxs("div", { style: {
701
+ display: "grid",
702
+ gridTemplateColumns: "44px 1fr",
703
+ gap: "12px",
704
+ minHeight: "18px",
705
+ }, children: [_jsx("span", { style: {
706
+ color: "var(--ai-text-tertiary)",
707
+ textAlign: "right",
708
+ userSelect: "none",
709
+ paddingRight: "8px",
710
+ borderRight: "1px solid var(--ai-border)",
711
+ }, children: index + 1 }), renderContextLine(line, index)] }, `context-line-${index}`))) })] }) })) : null, _jsxs("div", { style: {
579
712
  ...aiStyles.modalFooter,
580
713
  position: "sticky",
581
714
  bottom: 0,
@@ -20,22 +20,21 @@ export function AiSelect({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMode
20
20
  // Rendre l'authentification optionnelle
21
21
  let lbStatus;
22
22
  let lbHasSession = false;
23
- let lbHasSelectedKey = false;
24
23
  let lbHasSelectedApiKeyCookie = false;
24
+ let lbHasSelectedKey = false;
25
25
  let hasLBProvider = false;
26
26
  try {
27
27
  const lbContext = useLB();
28
28
  lbStatus = lbContext.status;
29
29
  lbHasSession = Boolean(lbContext.session?.sessionToken);
30
- lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
31
30
  lbHasSelectedApiKeyCookie = lbContext.hasSelectedApiKeyCookie;
31
+ lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
32
32
  hasLBProvider = true;
33
33
  }
34
34
  catch {
35
35
  // LBProvider n'est pas disponible, ignorer
36
36
  lbStatus = undefined;
37
37
  lbHasSession = false;
38
- lbHasSelectedKey = false;
39
38
  hasLBProvider = false;
40
39
  }
41
40
  let ctxBaseUrl;
@@ -60,7 +59,8 @@ export function AiSelect({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMode
60
59
  const needsApiKeySelection = hasLBProvider &&
61
60
  lbStatus === "ready" &&
62
61
  lbHasSession &&
63
- (!lbHasSelectedKey || !lbHasSelectedApiKeyCookie);
62
+ !lbHasSelectedApiKeyCookie &&
63
+ !lbHasSelectedKey;
64
64
  const isAuthReady = !needsApiKeySelection &&
65
65
  (lbStatus === "ready" || Boolean(process.env.LB_API_KEY));
66
66
  const shouldShowSparkles = isAuthReady && !disabled;
@@ -135,8 +135,8 @@ export function AiStatusButton({ status, loading = false, className = "", size =
135
135
  const hasLbSession = Boolean(lbSessionToken);
136
136
  const requiresApiKeySelection = lbStatus === "ready" &&
137
137
  hasLbSession &&
138
- (!lbHasSelectedApiKeyCookie || !hasApiKeySelected) &&
139
- apiKeys.length > 0;
138
+ !lbHasSelectedApiKeyCookie &&
139
+ !hasApiKeySelected;
140
140
  const isApiKeyAuthMode = authTypeValue === "api_key";
141
141
  const [tooltipStyle, setTooltipStyle] = useState({});
142
142
  useEffect(() => {
@@ -337,7 +337,7 @@ export function AiStatusButton({ status, loading = false, className = "", size =
337
337
  }
338
338
  }, disabled: loading || isSelectingApiKey, title: requiresApiKeySelection
339
339
  ? t("status.selectApiKey", "Select an API key")
340
- : t("status.view", "View status"), "aria-label": t("status.aiStatusAria", "AI status"), children: renderTriggerIcon() }), showCornerLoading ? (_jsx("span", { className: "ai-status-loading-dot", "aria-hidden": "true", children: _jsx(Loader2, { size: 7, className: "ai-spinner" }) })) : null] }), tooltipNode, showApiKeySelector && apiKeys.length > 0 ? (_jsx(LBApiKeySelector, { isOpen: showApiKeySelector, apiKeys: apiKeys, onSelect: async (keyId) => {
340
+ : t("status.view", "View status"), "aria-label": t("status.aiStatusAria", "AI status"), children: renderTriggerIcon() }), showCornerLoading ? (_jsx("span", { className: "ai-status-loading-dot", "aria-hidden": "true", children: _jsx(Loader2, { size: 7, className: "ai-spinner" }) })) : null] }), tooltipNode, showApiKeySelector ? (_jsx(LBApiKeySelector, { isOpen: showApiKeySelector, apiKeys: apiKeys, onSelect: async (keyId) => {
341
341
  setIsSelectingApiKey(true);
342
342
  try {
343
343
  if (!switchApiKey) {
@@ -1 +1 @@
1
- {"version":3,"file":"AiTextarea.d.ts","sourceRoot":"","sources":["../../src/components/AiTextarea.tsx"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAC5B,OAAc,EAIZ,KAAK,sBAAsB,EAC5B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAY9D,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;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,IAAW,EACX,MAAa,EACb,iBAAiB,EACjB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAQ,EAAE,SAAiB,EAC3B,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,aAAa,EACjB,EAAE,eAAe,2CAqQjB"}
1
+ {"version":3,"file":"AiTextarea.d.ts","sourceRoot":"","sources":["../../src/components/AiTextarea.tsx"],"names":[],"mappings":"AAEA,OAAO,oBAAoB,CAAC;AAC5B,OAAc,EAIZ,KAAK,sBAAsB,EAC5B,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAY9D,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;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC/C;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,YAAY,EACtB,MAAgB,EAChB,IAAW,EACX,MAAa,EACb,iBAAiB,EACjB,OAAO,EACP,KAAK,EACL,MAAM,EACN,QAAQ,EAAE,SAAiB,EAC3B,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,OAAO,EACP,OAAO,EACP,QAAQ,EACR,SAAS,EACT,GAAG,aAAa,EACjB,EAAE,eAAe,2CAgRjB"}
@@ -25,15 +25,15 @@ export function AiTextarea({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMod
25
25
  // Rendre l'authentification optionnelle
26
26
  let lbStatus;
27
27
  let lbHasSession = false;
28
- let lbHasSelectedKey = false;
29
28
  let lbHasSelectedApiKeyCookie = false;
29
+ let lbHasSelectedKey = false;
30
30
  let hasLBProvider = false;
31
31
  try {
32
32
  const lbContext = useLB();
33
33
  lbStatus = lbContext.status;
34
34
  lbHasSession = Boolean(lbContext.session?.sessionToken);
35
- lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
36
35
  lbHasSelectedApiKeyCookie = lbContext.hasSelectedApiKeyCookie;
36
+ lbHasSelectedKey = Boolean(lbContext.selectedKey?.id);
37
37
  hasLBProvider = true;
38
38
  }
39
39
  catch {
@@ -57,7 +57,8 @@ export function AiTextarea({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMod
57
57
  const needsApiKeySelection = hasLBProvider &&
58
58
  lbStatus === "ready" &&
59
59
  lbHasSession &&
60
- (!lbHasSelectedKey || !lbHasSelectedApiKeyCookie);
60
+ !lbHasSelectedApiKeyCookie &&
61
+ !lbHasSelectedKey;
61
62
  const { models: _models } = useAiModels({
62
63
  baseUrl,
63
64
  apiKeyId,
@@ -177,7 +178,17 @@ export function AiTextarea({ baseUrl: propBaseUrl, apiKeyId: propApiKeyId, uiMod
177
178
  adjustHeight();
178
179
  }, onBlur: (e) => {
179
180
  textareaProps.onBlur?.(e);
180
- }, "aria-invalid": Boolean(textareaProps["aria-invalid"]), disabled: disabled || loading }), _jsx("button", { className: `ai-control-action ai-spark ${sizeClass} ${radiusClass}`, onClick: hasConfiguration ? handleQuickGenerate : handleOpenPanel, disabled: disabled || loading || !isAuthReady, type: "button", title: !isAuthReady
181
+ }, "aria-invalid": Boolean(textareaProps["aria-invalid"]), disabled: disabled || loading }), _jsx("button", { className: `ai-control-action ai-spark ${sizeClass} ${radiusClass}`, onClick: () => {
182
+ if (!isAuthReady) {
183
+ setShowAuthModal(true);
184
+ return;
185
+ }
186
+ if (hasConfiguration) {
187
+ void handleQuickGenerate();
188
+ return;
189
+ }
190
+ handleOpenPanel();
191
+ }, disabled: disabled || loading, type: "button", title: !isAuthReady
181
192
  ? t("auth.required", "Authentication required")
182
193
  : hasConfiguration
183
194
  ? t("ai.generate", "Generate with AI")
@@ -1 +1 @@
1
- {"version":3,"file":"LBApiKeySelector.d.ts","sourceRoot":"","sources":["../../src/components/LBApiKeySelector.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,UAAU,qBAAqB;IAC7B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,MAAM,GACP,EAAE,qBAAqB,kDAwJvB"}
1
+ {"version":3,"file":"LBApiKeySelector.d.ts","sourceRoot":"","sources":["../../src/components/LBApiKeySelector.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAGtD,UAAU,qBAAqB;IAC7B,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,MAAM,GACP,EAAE,qBAAqB,kDAmKvB"}
@@ -1,13 +1,19 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { useState } from "react";
3
+ import { useEffect, useState } from "react";
4
4
  import { CheckCircle2, KeyRound, Loader2, XCircle } from "lucide-react";
5
+ import { createPortal } from "react-dom";
5
6
  import { useI18n } from "../context/I18nContext";
6
7
  export function LBApiKeySelector({ apiKeys, onSelect, onCancel, isOpen, }) {
7
8
  const { t } = useI18n();
9
+ const [canPortal, setCanPortal] = useState(false);
8
10
  const [selectedKeyId, setSelectedKeyId] = useState(apiKeys.find((k) => k.isActive)?.id || apiKeys[0]?.id || "");
9
11
  const [loading, setLoading] = useState(false);
10
12
  const [error, setError] = useState("");
13
+ useEffect(() => {
14
+ setCanPortal(true);
15
+ return () => setCanPortal(false);
16
+ }, []);
11
17
  if (!isOpen)
12
18
  return null;
13
19
  const handleSubmit = async (e) => {
@@ -30,7 +36,7 @@ export function LBApiKeySelector({ apiKeys, onSelect, onCancel, isOpen, }) {
30
36
  setLoading(false);
31
37
  }
32
38
  };
33
- return (_jsx("div", { className: "ai-signin-overlay", onClick: onCancel, children: _jsxs("div", { className: "ai-signin-panel ai-key-modal-panel", onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { className: "ai-signin-header", children: [_jsx("div", { className: "ai-center mb-3", children: _jsx("span", { className: "ai-icon-badge", children: _jsx(KeyRound, { size: 20 }) }) }), _jsx("h2", { className: "ai-signin-title", children: t("status.selectApiKey", "Select an API key") }), _jsx("p", { className: "ai-signin-subtitle", children: t("status.selectApiKeySubtitle", "Choose the API key to use for your AI requests.") })] }), _jsx("div", { className: "ai-signin-content", children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsx("div", { className: "ai-model-mgmt-list", style: { maxHeight: 300, overflowY: "auto", marginBottom: 16 }, children: apiKeys.map((key) => {
39
+ const modal = (_jsx("div", { className: "ai-signin-overlay", onClick: onCancel, children: _jsxs("div", { className: "ai-signin-panel ai-key-modal-panel", onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { className: "ai-signin-header", children: [_jsx("div", { className: "ai-center mb-3", children: _jsx("span", { className: "ai-icon-badge", children: _jsx(KeyRound, { size: 20 }) }) }), _jsx("h2", { className: "ai-signin-title", children: t("status.selectApiKey", "Select an API key") }), _jsx("p", { className: "ai-signin-subtitle", children: t("status.selectApiKeySubtitle", "Choose the API key to use for your AI requests.") })] }), _jsx("div", { className: "ai-signin-content", children: _jsxs("form", { onSubmit: handleSubmit, children: [_jsx("div", { className: "ai-model-mgmt-list", style: { maxHeight: 300, overflowY: "auto", marginBottom: 16 }, children: apiKeys.map((key) => {
34
40
  const isSelected = key.id === selectedKeyId;
35
41
  const isActive = key.isActive;
36
42
  const rawEnv = key.env;
@@ -38,4 +44,8 @@ export function LBApiKeySelector({ apiKeys, onSelect, onCancel, isOpen, }) {
38
44
  const isDev = rawEnv === "dev";
39
45
  return (_jsxs("label", { className: `ai-model-item ${isSelected ? "ai-model-item--active" : ""} ${!isActive ? "ai-model-item--disabled" : ""}`, children: [_jsxs("div", { className: "ai-model-item-main", children: [_jsx("input", { type: "radio", name: "apiKey", value: key.id, checked: isSelected, disabled: !isActive, onChange: (e) => setSelectedKeyId(e.target.value), className: "ai-key-radio" }), _jsxs("div", { children: [_jsx("div", { className: "ai-model-item-title", children: key.name }), _jsxs("div", { className: "ai-model-item-meta", children: [_jsx("span", { children: key.keyPrefix || key.id.substring(0, 12) + "..." }), _jsx("span", { className: `ai-pill ai-pill--cost ${isDev ? "ai-pill--warning" : ""}`, style: { marginLeft: 8 }, children: keyEnv })] })] })] }), isActive ? (_jsxs("span", { className: "ai-pill ai-pill--cost", children: [_jsx(CheckCircle2, { size: 12 }), t("common.active", "Active")] })) : (_jsxs("span", { className: "ai-pill ai-pill--cost", children: [_jsx(XCircle, { size: 12 }), t("common.inactive", "Inactive")] }))] }, key.id));
40
46
  }) }), error ? (_jsxs("div", { className: "ai-signin-error", role: "alert", children: [_jsx(XCircle, { size: 16 }), _jsx("span", { children: error })] })) : null, _jsxs("div", { className: "ai-signin-actions", children: [_jsx("button", { type: "button", onClick: onCancel, disabled: loading, className: "ai-btn ai-btn--ghost", children: t("common.cancel", "Cancel") }), _jsx("button", { type: "submit", disabled: loading || !selectedKeyId, className: "ai-btn ai-btn--primary", children: loading ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { size: 16, className: "ai-spinner" }), t("auth.modal.connecting", "Signing in...")] })) : (t("common.continue", "Continue")) })] })] }) })] }) }));
47
+ if (!canPortal) {
48
+ return modal;
49
+ }
50
+ return createPortal(modal, document.body);
41
51
  }
@@ -100,7 +100,7 @@ export function UsageToast({ result, position = "bottom-right", onComplete, }) {
100
100
  padding: "4px 6px",
101
101
  borderRadius: "6px",
102
102
  marginBottom: "4px",
103
- right: "6px",
103
+ right: "52px",
104
104
  background: "rgba(22, 163, 74, 0.12)",
105
105
  border: "1px solid rgba(22, 163, 74, 0.3)",
106
106
  color: "#16a34a",
@@ -25,6 +25,8 @@ export interface BasicStatus {
25
25
  used?: number;
26
26
  total?: number;
27
27
  percentage?: number;
28
+ remaining?: number;
29
+ providerBudget?: number;
28
30
  };
29
31
  storage?: StorageStatus["storage"];
30
32
  }
@@ -88,7 +90,7 @@ interface LBContextValue extends LBAuthState {
88
90
  isLoadingStatus: boolean;
89
91
  /** Indique si le storage est en cours de chargement */
90
92
  isLoadingStorage: boolean;
91
- /** True si le cookie api_key_selected est présent */
93
+ /** True si le cookie api_key_selected est présent (info backend) */
92
94
  hasSelectedApiKeyCookie: boolean;
93
95
  }
94
96
  declare const LBContext: import("react").Context<LBContextValue | undefined>;
@@ -1 +1 @@
1
- {"version":3,"file":"LBAuthProvider.d.ts","sourceRoot":"","sources":["../../src/context/LBAuthProvider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"LBAuthProvider.d.ts","sourceRoot":"","sources":["../../src/context/LBAuthProvider.tsx"],"names":[],"mappings":"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"}