@lastbrain/ai-ui-react 1.0.72 → 1.0.74
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.map +1 -1
- package/dist/components/AiChipLabel.js +10 -7
- package/dist/components/AiContextButton.d.ts +1 -1
- package/dist/components/AiContextButton.d.ts.map +1 -1
- package/dist/components/AiContextButton.js +25 -12
- package/dist/components/AiImageButton.d.ts.map +1 -1
- package/dist/components/AiImageButton.js +32 -16
- package/dist/components/AiInput.d.ts.map +1 -1
- package/dist/components/AiInput.js +15 -5
- package/dist/components/AiModelSelect.d.ts.map +1 -1
- package/dist/components/AiModelSelect.js +3 -1
- package/dist/components/AiPromptPanel.d.ts.map +1 -1
- package/dist/components/AiPromptPanel.js +72 -47
- package/dist/components/AiSelect.d.ts.map +1 -1
- package/dist/components/AiSelect.js +8 -3
- package/dist/components/AiStatusButton.d.ts.map +1 -1
- package/dist/components/AiStatusButton.js +55 -28
- package/dist/components/AiTextarea.d.ts.map +1 -1
- package/dist/components/AiTextarea.js +19 -6
- package/dist/components/ErrorToast.d.ts.map +1 -1
- package/dist/components/ErrorToast.js +4 -2
- package/dist/components/LBApiKeySelector.d.ts.map +1 -1
- package/dist/components/LBApiKeySelector.js +13 -5
- package/dist/components/LBConnectButton.d.ts.map +1 -1
- package/dist/components/LBConnectButton.js +8 -3
- package/dist/components/LBKeyPicker.d.ts.map +1 -1
- package/dist/components/LBKeyPicker.js +8 -4
- package/dist/components/LBSigninModal.d.ts.map +1 -1
- package/dist/components/LBSigninModal.js +13 -7
- package/dist/components/UsageToast.d.ts.map +1 -1
- package/dist/components/UsageToast.js +4 -2
- package/dist/context/I18nContext.d.ts +15 -0
- package/dist/context/I18nContext.d.ts.map +1 -0
- package/dist/context/I18nContext.js +44 -0
- package/dist/context/LBAuthProvider.d.ts +4 -1
- package/dist/context/LBAuthProvider.d.ts.map +1 -1
- package/dist/context/LBAuthProvider.js +3 -2
- package/dist/hooks/useAiCallImage.d.ts.map +1 -1
- package/dist/hooks/useAiCallImage.js +1 -107
- package/dist/hooks/useAiCallText.d.ts.map +1 -1
- package/dist/hooks/useAiCallText.js +1 -25
- package/dist/hooks/useLoadingTimer.d.ts +5 -0
- package/dist/hooks/useLoadingTimer.d.ts.map +1 -0
- package/dist/hooks/useLoadingTimer.js +27 -0
- package/dist/i18n/de.json +62 -0
- package/dist/i18n/en.json +128 -0
- package/dist/i18n/es.json +70 -0
- package/dist/i18n/fr.json +128 -0
- package/dist/i18n/it.json +62 -0
- package/dist/i18n/pt.json +62 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/styles.css +142 -1
- package/package.json +3 -3
- package/src/components/AiChipLabel.tsx +17 -8
- package/src/components/AiContextButton.tsx +44 -20
- package/src/components/AiImageButton.tsx +52 -25
- package/src/components/AiInput.tsx +20 -5
- package/src/components/AiModelSelect.tsx +3 -1
- package/src/components/AiPromptPanel.tsx +177 -59
- package/src/components/AiSelect.tsx +8 -3
- package/src/components/AiStatusButton.tsx +100 -57
- package/src/components/AiTextarea.tsx +24 -6
- package/src/components/ErrorToast.tsx +4 -2
- package/src/components/LBApiKeySelector.tsx +33 -13
- package/src/components/LBConnectButton.tsx +9 -3
- package/src/components/LBKeyPicker.tsx +10 -4
- package/src/components/LBSigninModal.tsx +31 -15
- package/src/components/UsageToast.tsx +4 -2
- package/src/context/I18nContext.tsx +71 -0
- package/src/context/LBAuthProvider.tsx +9 -1
- package/src/hooks/useAiCallImage.ts +1 -149
- package/src/hooks/useAiCallText.ts +1 -30
- package/src/hooks/useLoadingTimer.ts +32 -0
- package/src/i18n/de.json +62 -0
- package/src/i18n/en.json +128 -0
- package/src/i18n/es.json +70 -0
- package/src/i18n/fr.json +128 -0
- package/src/i18n/it.json +62 -0
- package/src/i18n/pt.json +62 -0
- package/src/index.ts +2 -0
- package/src/styles.css +142 -1
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"common.close": "Chiudi",
|
|
3
|
+
"common.cancel": "Annulla",
|
|
4
|
+
"common.loading": "Caricamento...",
|
|
5
|
+
"common.search": "Cerca...",
|
|
6
|
+
"common.all": "Tutti",
|
|
7
|
+
"common.unknown": "Sconosciuto",
|
|
8
|
+
"common.error": "Si è verificato un errore",
|
|
9
|
+
"common.inactive": "Inattivo",
|
|
10
|
+
"common.active": "Attivo",
|
|
11
|
+
"common.save": "Salva",
|
|
12
|
+
"common.download": "Scarica",
|
|
13
|
+
"common.continue": "Continua",
|
|
14
|
+
"common.errorTitle": "Errore",
|
|
15
|
+
"auth.signIn": "Accedi",
|
|
16
|
+
"auth.signOut": "Disconnetti",
|
|
17
|
+
"auth.required": "Autenticazione richiesta",
|
|
18
|
+
"auth.connectRequired": "Connessione richiesta",
|
|
19
|
+
"auth.modal.title": "Accesso LastBrain",
|
|
20
|
+
"auth.modal.subtitle": "Accedi per attivare i componenti IA nella tua app.",
|
|
21
|
+
"auth.modal.email": "Email",
|
|
22
|
+
"auth.modal.password": "Password",
|
|
23
|
+
"auth.modal.connecting": "Accesso in corso...",
|
|
24
|
+
"auth.modal.createAccount": "Crea account",
|
|
25
|
+
"status.title": "Stato API",
|
|
26
|
+
"status.view": "Vedi stato",
|
|
27
|
+
"status.selectApiKey": "Seleziona una chiave API",
|
|
28
|
+
"status.user": "Utente",
|
|
29
|
+
"status.apiKey": "Chiave API",
|
|
30
|
+
"status.env": "Ambiente",
|
|
31
|
+
"status.rateLimit": "Rate Limit",
|
|
32
|
+
"status.auth": "Auth",
|
|
33
|
+
"status.wallet": "Portafoglio",
|
|
34
|
+
"status.storage": "Storage",
|
|
35
|
+
"status.total": "Totale",
|
|
36
|
+
"status.changeApiKey": "Cambia chiave API",
|
|
37
|
+
"status.dashboard": "Dashboard",
|
|
38
|
+
"status.history": "Cronologia",
|
|
39
|
+
"status.settings": "Impostazioni",
|
|
40
|
+
"status.prompts": "Prompt",
|
|
41
|
+
"status.folders": "Cartelle",
|
|
42
|
+
"status.logout": "Disconnetti",
|
|
43
|
+
"prompt.modal.title": "Configurazione Prompt IA",
|
|
44
|
+
"prompt.modal.aiModel": "Modello IA",
|
|
45
|
+
"prompt.modal.manageModels": "Gestisci modelli",
|
|
46
|
+
"prompt.modal.loadingModels": "Caricamento modelli...",
|
|
47
|
+
"prompt.modal.prompt": "Prompt",
|
|
48
|
+
"prompt.modal.browsePrompts": "Sfoglia prompt",
|
|
49
|
+
"prompt.modal.cancel": "Annulla",
|
|
50
|
+
"prompt.modal.generate": "Genera con IA",
|
|
51
|
+
"prompt.modal.generating": "Generazione...",
|
|
52
|
+
"prompt.modal.transforming": "Trasformazione...",
|
|
53
|
+
"ai.setup": "Configura IA",
|
|
54
|
+
"ai.generate": "Genera con IA",
|
|
55
|
+
"ai.loading.elapsed": "{seconds}",
|
|
56
|
+
"ai.generationSuccess": "Generazione IA completata",
|
|
57
|
+
"ai.generationError": "Errore durante la generazione del testo",
|
|
58
|
+
"ai.image.generate": "Genera immagine",
|
|
59
|
+
"ai.image.generating": "Generazione...",
|
|
60
|
+
"ai.image.generatedSuccess": "Immagine generata con successo",
|
|
61
|
+
"usage.toast.used": "{amount}$ usati"
|
|
62
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"common.close": "Fechar",
|
|
3
|
+
"common.cancel": "Cancelar",
|
|
4
|
+
"common.loading": "Carregando...",
|
|
5
|
+
"common.search": "Pesquisar...",
|
|
6
|
+
"common.all": "Todos",
|
|
7
|
+
"common.unknown": "Desconhecido",
|
|
8
|
+
"common.error": "Ocorreu um erro",
|
|
9
|
+
"common.inactive": "Inativo",
|
|
10
|
+
"common.active": "Ativo",
|
|
11
|
+
"common.save": "Salvar",
|
|
12
|
+
"common.download": "Baixar",
|
|
13
|
+
"common.continue": "Continuar",
|
|
14
|
+
"common.errorTitle": "Erro",
|
|
15
|
+
"auth.signIn": "Entrar",
|
|
16
|
+
"auth.signOut": "Sair",
|
|
17
|
+
"auth.required": "Autenticação obrigatória",
|
|
18
|
+
"auth.connectRequired": "Conexão obrigatória",
|
|
19
|
+
"auth.modal.title": "Login LastBrain",
|
|
20
|
+
"auth.modal.subtitle": "Entre para ativar os componentes de IA no seu app.",
|
|
21
|
+
"auth.modal.email": "Email",
|
|
22
|
+
"auth.modal.password": "Senha",
|
|
23
|
+
"auth.modal.connecting": "Entrando...",
|
|
24
|
+
"auth.modal.createAccount": "Criar conta",
|
|
25
|
+
"status.title": "Status da API",
|
|
26
|
+
"status.view": "Ver status",
|
|
27
|
+
"status.selectApiKey": "Selecionar chave API",
|
|
28
|
+
"status.user": "Usuário",
|
|
29
|
+
"status.apiKey": "Chave API",
|
|
30
|
+
"status.env": "Ambiente",
|
|
31
|
+
"status.rateLimit": "Limite",
|
|
32
|
+
"status.auth": "Auth",
|
|
33
|
+
"status.wallet": "Carteira",
|
|
34
|
+
"status.storage": "Armazenamento",
|
|
35
|
+
"status.total": "Total",
|
|
36
|
+
"status.changeApiKey": "Trocar chave API",
|
|
37
|
+
"status.dashboard": "Painel",
|
|
38
|
+
"status.history": "Histórico",
|
|
39
|
+
"status.settings": "Configurações",
|
|
40
|
+
"status.prompts": "Prompts",
|
|
41
|
+
"status.folders": "Pastas",
|
|
42
|
+
"status.logout": "Sair",
|
|
43
|
+
"prompt.modal.title": "Configuração de Prompt IA",
|
|
44
|
+
"prompt.modal.aiModel": "Modelo IA",
|
|
45
|
+
"prompt.modal.manageModels": "Gerenciar modelos",
|
|
46
|
+
"prompt.modal.loadingModels": "Carregando modelos...",
|
|
47
|
+
"prompt.modal.prompt": "Prompt",
|
|
48
|
+
"prompt.modal.browsePrompts": "Ver prompts",
|
|
49
|
+
"prompt.modal.cancel": "Cancelar",
|
|
50
|
+
"prompt.modal.generate": "Gerar com IA",
|
|
51
|
+
"prompt.modal.generating": "Gerando...",
|
|
52
|
+
"prompt.modal.transforming": "Transformando...",
|
|
53
|
+
"ai.setup": "Configurar IA",
|
|
54
|
+
"ai.generate": "Gerar com IA",
|
|
55
|
+
"ai.loading.elapsed": "{seconds}",
|
|
56
|
+
"ai.generationSuccess": "Geração de IA concluída",
|
|
57
|
+
"ai.generationError": "Falha ao gerar texto",
|
|
58
|
+
"ai.image.generate": "Gerar imagem",
|
|
59
|
+
"ai.image.generating": "Gerando...",
|
|
60
|
+
"ai.image.generatedSuccess": "Imagem gerada com sucesso",
|
|
61
|
+
"usage.toast.used": "{amount}$ usado"
|
|
62
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import "./styles.css";
|
|
|
2
2
|
export * from "./types";
|
|
3
3
|
export * from "./context/AiProvider";
|
|
4
4
|
export * from "./context/LBAuthProvider";
|
|
5
|
+
export * from "./context/I18nContext";
|
|
5
6
|
export * from "./hooks/useAiClient";
|
|
6
7
|
export * from "./hooks/useAiModels";
|
|
7
8
|
export * from "./hooks/useAiStatus";
|
|
@@ -10,6 +11,7 @@ export * from "./hooks/useAiCallImage";
|
|
|
10
11
|
export * from "./hooks/usePrompts";
|
|
11
12
|
export * from "./hooks/useModelManagement";
|
|
12
13
|
export * from "./hooks/useLB";
|
|
14
|
+
export * from "./hooks/useLoadingTimer";
|
|
13
15
|
export * from "./components/AiPromptPanel";
|
|
14
16
|
export * from "./components/AiModelSelect";
|
|
15
17
|
export * from "./components/AiInput";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAGtB,cAAc,SAAS,CAAC;AAGxB,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAGtB,cAAc,SAAS,CAAC;AAGxB,cAAc,sBAAsB,CAAC;AACrC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,eAAe,CAAC;AAC9B,cAAc,yBAAyB,CAAC;AAGxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,0BAA0B,CAAC;AAGzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAG9B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,kCAAkC,CAAC;AACjD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from "./types";
|
|
|
4
4
|
// Context
|
|
5
5
|
export * from "./context/AiProvider";
|
|
6
6
|
export * from "./context/LBAuthProvider";
|
|
7
|
+
export * from "./context/I18nContext";
|
|
7
8
|
// Hooks
|
|
8
9
|
export * from "./hooks/useAiClient";
|
|
9
10
|
export * from "./hooks/useAiModels";
|
|
@@ -13,6 +14,7 @@ export * from "./hooks/useAiCallImage";
|
|
|
13
14
|
export * from "./hooks/usePrompts";
|
|
14
15
|
export * from "./hooks/useModelManagement";
|
|
15
16
|
export * from "./hooks/useLB";
|
|
17
|
+
export * from "./hooks/useLoadingTimer";
|
|
16
18
|
// Components
|
|
17
19
|
export * from "./components/AiPromptPanel";
|
|
18
20
|
export * from "./components/AiModelSelect";
|
package/dist/styles.css
CHANGED
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
/* Base surface */
|
|
123
123
|
.ai-surface {
|
|
124
124
|
border: 1px solid var(--ai-border);
|
|
125
|
-
border-radius:
|
|
125
|
+
border-radius: 6px;
|
|
126
126
|
color: var(--ai-foreground);
|
|
127
127
|
background:
|
|
128
128
|
linear-gradient(180deg, var(--ai-bg2), var(--ai-bg2)),
|
|
@@ -518,6 +518,7 @@
|
|
|
518
518
|
display: flex;
|
|
519
519
|
flex-wrap: wrap;
|
|
520
520
|
gap: 8px;
|
|
521
|
+
margin-top: 6px;
|
|
521
522
|
}
|
|
522
523
|
|
|
523
524
|
.ai-chip {
|
|
@@ -600,6 +601,14 @@
|
|
|
600
601
|
margin-bottom: 10px;
|
|
601
602
|
}
|
|
602
603
|
|
|
604
|
+
.ai-popover-header--sub {
|
|
605
|
+
font-size: 12px;
|
|
606
|
+
font-weight: 700;
|
|
607
|
+
letter-spacing: 0.01em;
|
|
608
|
+
margin-bottom: 8px;
|
|
609
|
+
color: var(--ai-foreground);
|
|
610
|
+
}
|
|
611
|
+
|
|
603
612
|
.ai-popover-section {
|
|
604
613
|
padding: 12px 0;
|
|
605
614
|
border-top: 1px solid color-mix(in srgb, var(--ai-border) 72%, transparent);
|
|
@@ -647,6 +656,7 @@
|
|
|
647
656
|
}
|
|
648
657
|
|
|
649
658
|
.ai-status-action-btn {
|
|
659
|
+
position: relative;
|
|
650
660
|
border: 1px solid color-mix(in srgb, var(--ai-primary) 34%, var(--ai-border));
|
|
651
661
|
border-radius: 12px;
|
|
652
662
|
width: 34px;
|
|
@@ -666,6 +676,34 @@
|
|
|
666
676
|
transform: translateY(-1px);
|
|
667
677
|
}
|
|
668
678
|
|
|
679
|
+
.ai-status-action-btn[data-ai-tip]::after {
|
|
680
|
+
content: attr(data-ai-tip);
|
|
681
|
+
position: absolute;
|
|
682
|
+
left: 50%;
|
|
683
|
+
bottom: calc(100% + 8px);
|
|
684
|
+
transform: translate(-50%, 4px);
|
|
685
|
+
white-space: nowrap;
|
|
686
|
+
opacity: 0;
|
|
687
|
+
pointer-events: none;
|
|
688
|
+
z-index: 2147483647;
|
|
689
|
+
padding: 4px 8px;
|
|
690
|
+
border-radius: 8px;
|
|
691
|
+
border: 1px solid var(--ai-border);
|
|
692
|
+
background: var(--ai-bg2);
|
|
693
|
+
color: var(--ai-foreground);
|
|
694
|
+
font-size: 11px;
|
|
695
|
+
font-weight: 600;
|
|
696
|
+
box-shadow: var(--ai-shadow-sm);
|
|
697
|
+
transition:
|
|
698
|
+
opacity var(--ai-transition),
|
|
699
|
+
transform var(--ai-transition);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
.ai-status-action-btn[data-ai-tip]:hover::after {
|
|
703
|
+
opacity: 1;
|
|
704
|
+
transform: translate(-50%, 0);
|
|
705
|
+
}
|
|
706
|
+
|
|
669
707
|
.ai-status-trigger {
|
|
670
708
|
position: relative;
|
|
671
709
|
border: 1px solid var(--ai-border);
|
|
@@ -725,6 +763,7 @@
|
|
|
725
763
|
display: inline-flex;
|
|
726
764
|
align-items: center;
|
|
727
765
|
justify-content: center;
|
|
766
|
+
color: var(--ai-primary);
|
|
728
767
|
pointer-events: none;
|
|
729
768
|
}
|
|
730
769
|
|
|
@@ -1144,6 +1183,12 @@
|
|
|
1144
1183
|
background: color-mix(in srgb, var(--ai-bg2) 82%, transparent);
|
|
1145
1184
|
}
|
|
1146
1185
|
|
|
1186
|
+
.ai-pill--warning {
|
|
1187
|
+
color: #f59e0b;
|
|
1188
|
+
border-color: color-mix(in srgb, #f59e0b 40%, var(--ai-border));
|
|
1189
|
+
background: color-mix(in srgb, #f59e0b 14%, var(--ai-bg2));
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1147
1192
|
.ai-toggle {
|
|
1148
1193
|
position: relative;
|
|
1149
1194
|
display: inline-flex;
|
|
@@ -1368,6 +1413,41 @@
|
|
|
1368
1413
|
letter-spacing: 0.01em;
|
|
1369
1414
|
}
|
|
1370
1415
|
|
|
1416
|
+
.ai-control-timer {
|
|
1417
|
+
position: absolute;
|
|
1418
|
+
right: 10px;
|
|
1419
|
+
top: calc(100% + 5px);
|
|
1420
|
+
font-size: 11px;
|
|
1421
|
+
line-height: 1;
|
|
1422
|
+
color: var(--ai-tertiary);
|
|
1423
|
+
pointer-events: none;
|
|
1424
|
+
z-index: 2;
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
.ai-loading-stack {
|
|
1428
|
+
display: inline-flex;
|
|
1429
|
+
flex-direction: column;
|
|
1430
|
+
align-items: center;
|
|
1431
|
+
justify-content: center;
|
|
1432
|
+
gap: 2px;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
.ai-loading-row {
|
|
1436
|
+
display: inline-flex;
|
|
1437
|
+
align-items: center;
|
|
1438
|
+
justify-content: center;
|
|
1439
|
+
gap: 8px;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
.ai-loading-meta {
|
|
1443
|
+
display: inline-flex;
|
|
1444
|
+
align-items: center;
|
|
1445
|
+
justify-content: center;
|
|
1446
|
+
font-size: 11px;
|
|
1447
|
+
line-height: 1;
|
|
1448
|
+
color: color-mix(in srgb, var(--ai-foreground) 68%, transparent);
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1371
1451
|
.ai-inline-icon {
|
|
1372
1452
|
color: var(--ai-muted);
|
|
1373
1453
|
}
|
|
@@ -1379,6 +1459,67 @@
|
|
|
1379
1459
|
animation: ai-pulse 1.4s ease-in-out infinite;
|
|
1380
1460
|
}
|
|
1381
1461
|
|
|
1462
|
+
.ai-kv-skeleton--48 {
|
|
1463
|
+
width: 48px;
|
|
1464
|
+
}
|
|
1465
|
+
|
|
1466
|
+
.ai-kv-skeleton--92 {
|
|
1467
|
+
width: 92px;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
.ai-kv-skeleton--110 {
|
|
1471
|
+
width: 110px;
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
.ai-kv-skeleton--120 {
|
|
1475
|
+
width: 120px;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
.ai-kv-skeleton--circle {
|
|
1479
|
+
width: 28px;
|
|
1480
|
+
height: 28px;
|
|
1481
|
+
border-radius: 999px;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
.ai-inline-skeleton {
|
|
1485
|
+
display: inline-flex;
|
|
1486
|
+
align-items: center;
|
|
1487
|
+
min-width: 124px;
|
|
1488
|
+
height: 30px;
|
|
1489
|
+
border-radius: 10px;
|
|
1490
|
+
background: color-mix(in srgb, var(--ai-primary) 12%, var(--ai-bg2));
|
|
1491
|
+
animation: ai-pulse 1.4s ease-in-out infinite;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
.ai-list-skeleton {
|
|
1495
|
+
border: 1px solid var(--ai-border);
|
|
1496
|
+
border-radius: 12px;
|
|
1497
|
+
background:
|
|
1498
|
+
linear-gradient(180deg, var(--ai-bg2), var(--ai-bg2)),
|
|
1499
|
+
radial-gradient(
|
|
1500
|
+
120% 120% at 100% 0%,
|
|
1501
|
+
rgba(var(--ai-glow-rgb), 0.05),
|
|
1502
|
+
transparent 76%
|
|
1503
|
+
);
|
|
1504
|
+
padding: 14px 16px;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
.ai-list-skeleton__line {
|
|
1508
|
+
height: 12px;
|
|
1509
|
+
border-radius: 6px;
|
|
1510
|
+
background: color-mix(in srgb, var(--ai-primary) 14%, var(--ai-bg2));
|
|
1511
|
+
animation: ai-pulse 1.4s ease-in-out infinite;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
.ai-list-skeleton__line--lg {
|
|
1515
|
+
width: 56%;
|
|
1516
|
+
margin-bottom: 10px;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
.ai-list-skeleton__line--md {
|
|
1520
|
+
width: 34%;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1382
1523
|
.ai-spinner,
|
|
1383
1524
|
.ai-spin {
|
|
1384
1525
|
animation: ai-spin 1s linear infinite;
|
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.74",
|
|
4
4
|
"description": "Headless React components for LastBrain AI UI Kit",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"lucide-react": "^0.257.0",
|
|
54
|
-
"@lastbrain/ai-ui-core": "1.0.
|
|
54
|
+
"@lastbrain/ai-ui-core": "1.0.54"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/react": "^19.2.0",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"dev": "tsc -p tsconfig.json --watch",
|
|
65
|
-
"build": "tsc -p tsconfig.json && cp src/styles.css dist/styles.css && cp styles.d.ts dist/styles.d.ts",
|
|
65
|
+
"build": "tsc -p tsconfig.json && mkdir -p dist/i18n && cp src/i18n/*.json dist/i18n/ && cp src/styles.css dist/styles.css && cp styles.d.ts dist/styles.d.ts",
|
|
66
66
|
"lint": "eslint ."
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -11,6 +11,7 @@ import { useAiContext } from "../context/AiProvider";
|
|
|
11
11
|
import { useLB } from "../context/LBAuthProvider";
|
|
12
12
|
import { handleAIError } from "../utils/errorHandler";
|
|
13
13
|
import type { AiRadius, AiSize } from "../types";
|
|
14
|
+
import { useI18n } from "../context/I18nContext";
|
|
14
15
|
|
|
15
16
|
export interface AiChipLabelProps {
|
|
16
17
|
children: React.ReactNode;
|
|
@@ -67,7 +68,7 @@ export interface AiChipInputProps {
|
|
|
67
68
|
export function AiChipInput({
|
|
68
69
|
value = [],
|
|
69
70
|
onChange,
|
|
70
|
-
placeholder
|
|
71
|
+
placeholder,
|
|
71
72
|
context,
|
|
72
73
|
maxChips,
|
|
73
74
|
allowDuplicates = false,
|
|
@@ -79,6 +80,7 @@ export function AiChipInput({
|
|
|
79
80
|
size = "md",
|
|
80
81
|
radius = "full",
|
|
81
82
|
}: AiChipInputProps) {
|
|
83
|
+
const { t } = useI18n();
|
|
82
84
|
const [inputValue, setInputValue] = useState("");
|
|
83
85
|
const [showPromptPanel, setShowPromptPanel] = useState(false);
|
|
84
86
|
const [showSigninModal, setShowSigninModal] = useState(false);
|
|
@@ -156,7 +158,8 @@ Exemple de réponse attendue: javascript, react, frontend, api, development`;
|
|
|
156
158
|
model,
|
|
157
159
|
prompt: instruction,
|
|
158
160
|
storeOutputs,
|
|
159
|
-
artifactTitle:
|
|
161
|
+
artifactTitle:
|
|
162
|
+
artifactTitle || t("ai.chips.artifactTitle", "AI generated tags"),
|
|
160
163
|
});
|
|
161
164
|
|
|
162
165
|
const chips = parseChipsFromResponse(response.text);
|
|
@@ -207,7 +210,13 @@ Exemple de réponse attendue: javascript, react, frontend, api, development`;
|
|
|
207
210
|
value={inputValue}
|
|
208
211
|
onChange={(e) => setInputValue(e.target.value)}
|
|
209
212
|
onKeyDown={handleKeyDown}
|
|
210
|
-
placeholder={
|
|
213
|
+
placeholder={
|
|
214
|
+
placeholder ||
|
|
215
|
+
t(
|
|
216
|
+
"ai.chips.placeholder",
|
|
217
|
+
"Type and press Enter to add tags..."
|
|
218
|
+
)
|
|
219
|
+
}
|
|
211
220
|
className={`ai-control ai-control-input ai-control-input--with-action ${sizeClass} ${radiusClass}`}
|
|
212
221
|
/>
|
|
213
222
|
<button
|
|
@@ -221,13 +230,13 @@ Exemple de réponse attendue: javascript, react, frontend, api, development`;
|
|
|
221
230
|
className={`ai-control-action ai-spark ${sizeClass} ${radiusClass}`}
|
|
222
231
|
aria-label={
|
|
223
232
|
isAuthenticated
|
|
224
|
-
? "
|
|
225
|
-
: "
|
|
233
|
+
? t("ai.chips.generate", "Generate tags with AI")
|
|
234
|
+
: t("auth.connectRequired", "Connection required")
|
|
226
235
|
}
|
|
227
236
|
title={
|
|
228
237
|
isAuthenticated
|
|
229
|
-
? "
|
|
230
|
-
: "
|
|
238
|
+
? t("ai.chips.generate", "Generate tags with AI")
|
|
239
|
+
: t("auth.connectToUseAi", "Sign in to use AI")
|
|
231
240
|
}
|
|
232
241
|
>
|
|
233
242
|
{isAuthenticated ? <Sparkles size={16} /> : <Lock size={16} />}
|
|
@@ -247,7 +256,7 @@ Exemple de réponse attendue: javascript, react, frontend, api, development`;
|
|
|
247
256
|
<button
|
|
248
257
|
onClick={() => removeChip(index)}
|
|
249
258
|
className="ai-chip-remover"
|
|
250
|
-
title="
|
|
259
|
+
title={t("ai.chips.remove", "Remove")}
|
|
251
260
|
>
|
|
252
261
|
<X size={14} />
|
|
253
262
|
</button>
|
|
@@ -13,6 +13,7 @@ import { useAiContext } from "../context/AiProvider";
|
|
|
13
13
|
import { handleAIError } from "../utils/errorHandler";
|
|
14
14
|
import { useLB } from "../context/LBAuthProvider";
|
|
15
15
|
import { LBSigninModal } from "./LBSigninModal";
|
|
16
|
+
import { useI18n } from "../context/I18nContext";
|
|
16
17
|
|
|
17
18
|
// Types pour les données de contexte
|
|
18
19
|
type ContextData =
|
|
@@ -49,19 +50,22 @@ export function AiContextButton({
|
|
|
49
50
|
apiKeyId: propApiKeyId,
|
|
50
51
|
uiMode = "modal",
|
|
51
52
|
contextData,
|
|
52
|
-
contextDescription
|
|
53
|
+
contextDescription,
|
|
53
54
|
onResult,
|
|
54
55
|
onToast,
|
|
55
56
|
disabled,
|
|
56
57
|
className,
|
|
57
58
|
children,
|
|
58
|
-
resultModalTitle
|
|
59
|
+
resultModalTitle,
|
|
60
|
+
storeOutputs,
|
|
61
|
+
artifactTitle,
|
|
59
62
|
size = "md",
|
|
60
63
|
radius = "full",
|
|
61
64
|
variant = "default",
|
|
62
65
|
context: _context,
|
|
63
66
|
...buttonProps
|
|
64
67
|
}: AiContextButtonProps) {
|
|
68
|
+
const { t, lang } = useI18n();
|
|
65
69
|
const [isOpen, setIsOpen] = useState(false);
|
|
66
70
|
const [showAuthModal, setShowAuthModal] = useState(false);
|
|
67
71
|
const [isResultOpen, setIsResultOpen] = useState(false);
|
|
@@ -75,6 +79,8 @@ export function AiContextButton({
|
|
|
75
79
|
|
|
76
80
|
const { showUsageToast } = useUsageToast();
|
|
77
81
|
const { showErrorToast, errorData, errorKey, clearError } = useErrorToast();
|
|
82
|
+
const resolvedContextDescription =
|
|
83
|
+
contextDescription || t("ai.context.description", "Data to analyze");
|
|
78
84
|
|
|
79
85
|
let lbStatus: string | undefined;
|
|
80
86
|
try {
|
|
@@ -119,7 +125,7 @@ export function AiContextButton({
|
|
|
119
125
|
) => {
|
|
120
126
|
try {
|
|
121
127
|
const contextString = formatContextData(contextData);
|
|
122
|
-
const fullPrompt = `${selectedPrompt}\n\nCONTEXTE (${
|
|
128
|
+
const fullPrompt = `${selectedPrompt}\n\nCONTEXTE (${resolvedContextDescription}):\n${contextString}\n\n${t("ai.context.analyzeStructured", "Analyze this data and respond in a clear, structured way.")}`;
|
|
123
129
|
|
|
124
130
|
const result = await callText({
|
|
125
131
|
prompt: fullPrompt,
|
|
@@ -127,6 +133,8 @@ export function AiContextButton({
|
|
|
127
133
|
context: _context || undefined,
|
|
128
134
|
maxTokens: 4000,
|
|
129
135
|
temperature: 0.7,
|
|
136
|
+
storeOutputs,
|
|
137
|
+
artifactTitle,
|
|
130
138
|
});
|
|
131
139
|
|
|
132
140
|
if (!result.text) {
|
|
@@ -156,7 +164,9 @@ export function AiContextButton({
|
|
|
156
164
|
|
|
157
165
|
onToast?.({
|
|
158
166
|
type: "success",
|
|
159
|
-
message:
|
|
167
|
+
message: t("ai.analysisDoneCost", "Analysis completed - Cost: {cost}", {
|
|
168
|
+
cost: `$${(apiKeyId?.includes("dev") ? 0 : actualCost).toFixed(6)}`,
|
|
169
|
+
}),
|
|
160
170
|
});
|
|
161
171
|
|
|
162
172
|
showUsageToast({
|
|
@@ -182,18 +192,23 @@ export function AiContextButton({
|
|
|
182
192
|
return;
|
|
183
193
|
}
|
|
184
194
|
|
|
195
|
+
const locale = lang === "fr" ? "fr-FR" : "en-US";
|
|
185
196
|
const currentDate = new Date()
|
|
186
|
-
.toLocaleDateString(
|
|
197
|
+
.toLocaleDateString(locale)
|
|
187
198
|
.replace(/\//g, "-");
|
|
188
|
-
const defaultName =
|
|
189
|
-
|
|
199
|
+
const defaultName = t("ai.context.fileNameBase", "analysis-{date}.txt", {
|
|
200
|
+
date: currentDate,
|
|
201
|
+
});
|
|
202
|
+
const fileName =
|
|
203
|
+
prompt(t("ai.context.saveFileNamePrompt", "File name:"), defaultName) ||
|
|
204
|
+
defaultName;
|
|
190
205
|
|
|
191
|
-
const content =
|
|
206
|
+
const content = `${t("ai.context.fileHeader", "DATA ANALYSIS")} - ${new Date().toLocaleString(locale)}\n\n${t("common.promptUsed", "Prompt used").toUpperCase()} :\n${analysisResult.prompt}\n\n${t("common.result", "Result").toUpperCase()} :\n${analysisResult.content}\n\n--- ${t("ai.context.metadata", "METADATA")} ---\n${t("ai.context.tokensUsed", "Tokens used")}: ${analysisResult.tokens.toLocaleString()}\n${t("ai.context.cost", "Cost")}: $${(apiKeyId?.includes(
|
|
192
207
|
"dev"
|
|
193
208
|
)
|
|
194
209
|
? 0
|
|
195
210
|
: analysisResult.cost
|
|
196
|
-
).toFixed(6)}\
|
|
211
|
+
).toFixed(6)}\n${t("ai.context.requestId", "Request ID")}: ${analysisResult.requestId || "N/A"}`;
|
|
197
212
|
|
|
198
213
|
const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
|
|
199
214
|
const url = URL.createObjectURL(blob);
|
|
@@ -219,23 +234,27 @@ export function AiContextButton({
|
|
|
219
234
|
disabled={disabled || loading || !isAuthReady}
|
|
220
235
|
className={`ai-btn ai-context-btn ${variantClass} ${sizeClass} ${radiusClass} ${className || ""}`}
|
|
221
236
|
title={
|
|
222
|
-
!isAuthReady
|
|
237
|
+
!isAuthReady
|
|
238
|
+
? t("auth.required", "Authentication required")
|
|
239
|
+
: t("ai.analyze", "Analyze with AI")
|
|
223
240
|
}
|
|
224
241
|
>
|
|
225
242
|
{loading ? (
|
|
226
243
|
<>
|
|
227
244
|
<Loader2 size={16} className="ai-spinner" />
|
|
228
|
-
<span>
|
|
245
|
+
<span>{t("ai.analyzing", "Analyzing...")}</span>
|
|
229
246
|
</>
|
|
230
247
|
) : !isAuthReady ? (
|
|
231
248
|
<>
|
|
232
249
|
<Lock size={16} />
|
|
233
|
-
{children ||
|
|
250
|
+
{children || (
|
|
251
|
+
<span>{t("auth.connectRequired", "Connection required")}</span>
|
|
252
|
+
)}
|
|
234
253
|
</>
|
|
235
254
|
) : (
|
|
236
255
|
<>
|
|
237
256
|
<Sparkles size={16} />
|
|
238
|
-
{children || <span>
|
|
257
|
+
{children || <span>{t("ai.context.buttonAnalyze", "Analyze")}</span>}
|
|
239
258
|
</>
|
|
240
259
|
)}
|
|
241
260
|
</button>
|
|
@@ -272,7 +291,9 @@ export function AiContextButton({
|
|
|
272
291
|
<div className="ai-result-header">
|
|
273
292
|
<div className="ai-row">
|
|
274
293
|
<FileText size={18} />
|
|
275
|
-
<h2 className="ai-result-title">
|
|
294
|
+
<h2 className="ai-result-title">
|
|
295
|
+
{resultModalTitle || t("ai.context.resultTitle", "Analysis result")}
|
|
296
|
+
</h2>
|
|
276
297
|
</div>
|
|
277
298
|
<div className="ai-row">
|
|
278
299
|
<button
|
|
@@ -281,7 +302,7 @@ export function AiContextButton({
|
|
|
281
302
|
onClick={saveToFile}
|
|
282
303
|
>
|
|
283
304
|
<Download size={14} />
|
|
284
|
-
|
|
305
|
+
{t("common.save", "Save")}
|
|
285
306
|
</button>
|
|
286
307
|
<button
|
|
287
308
|
type="button"
|
|
@@ -290,7 +311,7 @@ export function AiContextButton({
|
|
|
290
311
|
setIsResultOpen(false);
|
|
291
312
|
setAnalysisResult(null);
|
|
292
313
|
}}
|
|
293
|
-
aria-label="
|
|
314
|
+
aria-label={t("common.closeLabel", "Close")}
|
|
294
315
|
>
|
|
295
316
|
<X size={16} />
|
|
296
317
|
</button>
|
|
@@ -299,12 +320,12 @@ export function AiContextButton({
|
|
|
299
320
|
|
|
300
321
|
<div className="ai-result-body">
|
|
301
322
|
<div className="ai-result-block">
|
|
302
|
-
<h3 className="ai-result-subtitle">Prompt
|
|
323
|
+
<h3 className="ai-result-subtitle">{t("common.promptUsed", "Prompt used")}</h3>
|
|
303
324
|
<pre className="ai-result-code">{analysisResult.prompt}</pre>
|
|
304
325
|
</div>
|
|
305
326
|
|
|
306
327
|
<div className="ai-result-block">
|
|
307
|
-
<h3 className="ai-result-subtitle">
|
|
328
|
+
<h3 className="ai-result-subtitle">{t("common.result", "Result")}</h3>
|
|
308
329
|
<div className="ai-result-content">
|
|
309
330
|
{analysisResult.content}
|
|
310
331
|
</div>
|
|
@@ -312,13 +333,16 @@ export function AiContextButton({
|
|
|
312
333
|
|
|
313
334
|
<div className="ai-result-meta ai-between">
|
|
314
335
|
<span>
|
|
315
|
-
|
|
336
|
+
{t("ai.context.cost", "Cost")}: $
|
|
316
337
|
{(apiKeyId?.includes("dev")
|
|
317
338
|
? 0
|
|
318
339
|
: analysisResult.cost
|
|
319
340
|
).toFixed(6)}
|
|
320
341
|
</span>
|
|
321
|
-
<span>
|
|
342
|
+
<span>
|
|
343
|
+
{t("ai.context.requestId", "Request ID")}:{" "}
|
|
344
|
+
{analysisResult.requestId?.slice(-8) || "N/A"}
|
|
345
|
+
</span>
|
|
322
346
|
</div>
|
|
323
347
|
</div>
|
|
324
348
|
</div>
|