@eeacms/volto-eea-chatbot 2.0.5 → 3.0.0
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/AGENTS.md +230 -0
- package/CHANGELOG.md +33 -2
- package/locales/de/LC_MESSAGES/volto.po +44 -0
- package/locales/en/LC_MESSAGES/volto.po +44 -0
- package/locales/it/LC_MESSAGES/volto.po +44 -0
- package/locales/ro/LC_MESSAGES/volto.po +44 -0
- package/locales/volto.pot +46 -2
- package/package.json +2 -1
- package/src/AISearchInput/AISearchInputEdit.jsx +37 -0
- package/src/AISearchInput/AISearchInputView.jsx +130 -0
- package/src/AISearchInput/components/DeepResearchToggle.jsx +35 -0
- package/src/AISearchInput/components/DisclaimerText.jsx +10 -0
- package/src/AISearchInput/components/IntroHeader.jsx +24 -0
- package/src/AISearchInput/components/PromptChips.jsx +22 -0
- package/src/AISearchInput/components/SearchInput.jsx +53 -0
- package/src/AISearchInput/index.js +32 -0
- package/src/AISearchInput/messages.js +38 -0
- package/src/AISearchInput/schema.jsx +215 -0
- package/src/AISearchInput/styles.less +320 -0
- package/src/ChatBlock/ChatBlockView.jsx +4 -0
- package/src/ChatBlock/chat/ChatWindow.tsx +23 -0
- package/src/icons/sparkle.svg +3 -0
- package/src/index.js +2 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
// AI Search Input styles — scoped under .ais-search-input
|
|
2
|
+
// Uses EEA Design System tokens
|
|
3
|
+
|
|
4
|
+
@import '@eeacms/volto-design-tokens/src/colors';
|
|
5
|
+
@import '@eeacms/volto-design-tokens/src/shapes';
|
|
6
|
+
@import '@eeacms/volto-design-tokens/src/borders';
|
|
7
|
+
@import '@eeacms/volto-design-tokens/src/fonts';
|
|
8
|
+
|
|
9
|
+
// Spacing tokens from @eeacms/volto-design-tokens/src/sizes
|
|
10
|
+
// (imported manually to avoid @1px Semantic UI dependency)
|
|
11
|
+
@spacer: 4px;
|
|
12
|
+
@space-025: @spacer * 0.25;
|
|
13
|
+
@space-05: @spacer * 0.5;
|
|
14
|
+
@space-1: @spacer * 1;
|
|
15
|
+
@space-2: @spacer * 2;
|
|
16
|
+
@space-3: @spacer * 3;
|
|
17
|
+
@space-4: @spacer * 4;
|
|
18
|
+
@space-5: @spacer * 5;
|
|
19
|
+
@space-6: @spacer * 6;
|
|
20
|
+
@space-8: @spacer * 8;
|
|
21
|
+
|
|
22
|
+
// Size tokens
|
|
23
|
+
@size-10: 120px;
|
|
24
|
+
|
|
25
|
+
.ais-search-input {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
padding: @space-6;
|
|
29
|
+
gap: @space-3;
|
|
30
|
+
|
|
31
|
+
// --- Dark variant (default) ---
|
|
32
|
+
&.ais-dark {
|
|
33
|
+
background-color: @blue-6;
|
|
34
|
+
color: @grey-0;
|
|
35
|
+
|
|
36
|
+
.ais-chip {
|
|
37
|
+
background-color: @blue-5;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.ais-search-input-field {
|
|
41
|
+
border-bottom-color: @grey-0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.ais-input-error {
|
|
45
|
+
color: @red-2;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// --- Light variant ---
|
|
50
|
+
&.ais-light {
|
|
51
|
+
background-color: @grey-1;
|
|
52
|
+
color: @grey-5;
|
|
53
|
+
|
|
54
|
+
.ais-chip {
|
|
55
|
+
background-color: @grey-2;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.ais-search-input-field {
|
|
59
|
+
border-bottom-color: @grey-5;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.ais-input-error {
|
|
63
|
+
color: @red-5;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// --- Accent variant (EEA green/teal) ---
|
|
68
|
+
&.ais-accent {
|
|
69
|
+
background-color: @green-5;
|
|
70
|
+
color: @grey-0;
|
|
71
|
+
|
|
72
|
+
.ais-chip {
|
|
73
|
+
background-color: @green-4;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.ais-search-input-field {
|
|
77
|
+
border-bottom-color: @grey-0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.ais-input-error {
|
|
81
|
+
color: @red-1;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// --- Intro header (Row 1) ---
|
|
86
|
+
.ais-intro-header {
|
|
87
|
+
display: flex;
|
|
88
|
+
align-items: flex-start;
|
|
89
|
+
gap: @space-2;
|
|
90
|
+
|
|
91
|
+
.ais-icon {
|
|
92
|
+
flex-shrink: 0;
|
|
93
|
+
margin-top: @space-05;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.ais-intro-content {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: column;
|
|
99
|
+
gap: @space-05;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.ais-block-title {
|
|
103
|
+
font-size: @font-size-1;
|
|
104
|
+
font-weight: @font-weight-6;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Slate-rendered intro text
|
|
108
|
+
:global(.slate-editor) {
|
|
109
|
+
margin: 0;
|
|
110
|
+
font-size: @font-size-0;
|
|
111
|
+
line-height: @font-lineheight-2;
|
|
112
|
+
|
|
113
|
+
p {
|
|
114
|
+
margin: 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
a {
|
|
118
|
+
color: inherit;
|
|
119
|
+
text-decoration: underline;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// --- Search input (Row 2) ---
|
|
125
|
+
.ais-search-input-field {
|
|
126
|
+
display: flex;
|
|
127
|
+
align-items: center;
|
|
128
|
+
padding-bottom: @space-1;
|
|
129
|
+
border-bottom: @border-size-2 solid currentColor;
|
|
130
|
+
|
|
131
|
+
input {
|
|
132
|
+
flex: 1;
|
|
133
|
+
padding: @space-1 0;
|
|
134
|
+
border: none;
|
|
135
|
+
background: transparent;
|
|
136
|
+
color: inherit;
|
|
137
|
+
font-family: inherit;
|
|
138
|
+
font-size: @font-size-1;
|
|
139
|
+
outline: none;
|
|
140
|
+
|
|
141
|
+
&::placeholder {
|
|
142
|
+
color: inherit;
|
|
143
|
+
opacity: 0.6;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.ais-submit-btn {
|
|
148
|
+
display: flex;
|
|
149
|
+
flex-shrink: 0;
|
|
150
|
+
align-items: center;
|
|
151
|
+
padding: @space-1;
|
|
152
|
+
border: none;
|
|
153
|
+
background: none;
|
|
154
|
+
color: inherit;
|
|
155
|
+
cursor: pointer;
|
|
156
|
+
transition: opacity 0.2s;
|
|
157
|
+
|
|
158
|
+
&:hover {
|
|
159
|
+
opacity: 0.8;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
&:focus-visible {
|
|
163
|
+
border-radius: @radius-1;
|
|
164
|
+
outline: @border-size-2 solid currentColor;
|
|
165
|
+
outline-offset: @space-05;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.ais-input-error {
|
|
171
|
+
width: 100%;
|
|
172
|
+
margin-top: @space-1;
|
|
173
|
+
font-size: @font-size-00;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// --- Controls row: chips (left) + deep research toggle (right) ---
|
|
177
|
+
.ais-controls-row {
|
|
178
|
+
display: flex;
|
|
179
|
+
flex-wrap: wrap;
|
|
180
|
+
align-items: center;
|
|
181
|
+
gap: @space-2;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// --- Prompt chips ---
|
|
185
|
+
.ais-prompt-chips {
|
|
186
|
+
display: flex;
|
|
187
|
+
flex: 1;
|
|
188
|
+
flex-wrap: wrap;
|
|
189
|
+
gap: @space-2;
|
|
190
|
+
|
|
191
|
+
.ais-chip {
|
|
192
|
+
padding: @space-1 @space-3;
|
|
193
|
+
border: none;
|
|
194
|
+
border-radius: @radius-0;
|
|
195
|
+
color: inherit;
|
|
196
|
+
cursor: pointer;
|
|
197
|
+
font-family: inherit;
|
|
198
|
+
font-size: @font-size-0;
|
|
199
|
+
transition: opacity 0.2s;
|
|
200
|
+
|
|
201
|
+
&:hover {
|
|
202
|
+
opacity: 0.85;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
&:focus-visible {
|
|
206
|
+
outline: @border-size-2 solid currentColor;
|
|
207
|
+
outline-offset: @space-05;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// --- Deep research toggle (right-aligned) ---
|
|
213
|
+
.ais-deep-research {
|
|
214
|
+
display: flex;
|
|
215
|
+
flex-shrink: 0;
|
|
216
|
+
align-items: center;
|
|
217
|
+
margin-left: auto;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.ais-deep-research-label {
|
|
221
|
+
font-size: @font-size-00;
|
|
222
|
+
opacity: 0.8;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Custom toggle switch
|
|
226
|
+
.ais-toggle {
|
|
227
|
+
display: inline-flex;
|
|
228
|
+
align-items: center;
|
|
229
|
+
cursor: pointer;
|
|
230
|
+
font-size: @font-size-0;
|
|
231
|
+
gap: @space-2;
|
|
232
|
+
|
|
233
|
+
input {
|
|
234
|
+
display: none;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.ais-toggle-slider {
|
|
238
|
+
position: relative;
|
|
239
|
+
display: inline-block;
|
|
240
|
+
width: 28px;
|
|
241
|
+
height: 16px;
|
|
242
|
+
border: @border-size-1 solid currentColor;
|
|
243
|
+
border-radius: @radius-3;
|
|
244
|
+
background-color: rgba(currentColor, 0.15);
|
|
245
|
+
transition: background-color 0.2s;
|
|
246
|
+
|
|
247
|
+
&::before {
|
|
248
|
+
position: absolute;
|
|
249
|
+
top: 1px;
|
|
250
|
+
left: 2px;
|
|
251
|
+
display: block;
|
|
252
|
+
width: 12px;
|
|
253
|
+
height: 12px;
|
|
254
|
+
border-radius: 50%;
|
|
255
|
+
background-color: currentColor;
|
|
256
|
+
content: '';
|
|
257
|
+
transition: left 0.2s;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
input:checked ~ .ais-toggle-slider {
|
|
262
|
+
border-color: @green-4;
|
|
263
|
+
background-color: @green-4;
|
|
264
|
+
|
|
265
|
+
&::before {
|
|
266
|
+
left: 13px;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// --- Disclaimer (Row 5) ---
|
|
272
|
+
.ais-disclaimer {
|
|
273
|
+
margin-top: @space-1;
|
|
274
|
+
font-size: @font-size-00;
|
|
275
|
+
opacity: 0.7;
|
|
276
|
+
|
|
277
|
+
:global(.slate-editor) {
|
|
278
|
+
font-size: inherit;
|
|
279
|
+
|
|
280
|
+
p {
|
|
281
|
+
margin: 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
a {
|
|
285
|
+
color: inherit;
|
|
286
|
+
text-decoration: underline;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// --- Responsive ---
|
|
292
|
+
@media (max-width: 768px) {
|
|
293
|
+
padding: @space-4;
|
|
294
|
+
gap: @space-2;
|
|
295
|
+
|
|
296
|
+
.ais-intro-header {
|
|
297
|
+
.ais-icon {
|
|
298
|
+
width: @space-5;
|
|
299
|
+
height: @space-5;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.ais-block-title {
|
|
303
|
+
font-size: @font-size-0;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
:global(.slate-editor) {
|
|
307
|
+
font-size: @font-size-00;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.ais-search-input-field input {
|
|
312
|
+
font-size: @font-size-0;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.ais-prompt-chips .ais-chip {
|
|
316
|
+
min-width: @size-10;
|
|
317
|
+
flex: 1 1 auto;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
@@ -13,6 +13,8 @@ function ChatBlockView(props) {
|
|
|
13
13
|
);
|
|
14
14
|
|
|
15
15
|
const isPlaywrightTest = query.playwright === 'yes';
|
|
16
|
+
const initialQuery = query.query || null;
|
|
17
|
+
const initialDeepResearch = query.deepResearch || null;
|
|
16
18
|
|
|
17
19
|
useEffect(() => {
|
|
18
20
|
if (isPlaywrightTest) {
|
|
@@ -29,6 +31,8 @@ function ChatBlockView(props) {
|
|
|
29
31
|
isEditMode={isEditMode}
|
|
30
32
|
isPlaywrightTest={isPlaywrightTest}
|
|
31
33
|
block_id={id}
|
|
34
|
+
initialQuery={initialQuery}
|
|
35
|
+
initialDeepResearch={initialDeepResearch}
|
|
32
36
|
{...data}
|
|
33
37
|
/>
|
|
34
38
|
) : (
|
|
@@ -5,6 +5,7 @@ import React, {
|
|
|
5
5
|
useMemo,
|
|
6
6
|
useCallback,
|
|
7
7
|
} from 'react';
|
|
8
|
+
import { useHistory } from 'react-router-dom';
|
|
8
9
|
import type { Persona } from '@eeacms/volto-eea-chatbot/ChatBlock/types/interfaces';
|
|
9
10
|
import { Button, Form, Segment, Checkbox } from 'semantic-ui-react';
|
|
10
11
|
import { injectLazyLibs } from '@plone/volto/helpers/Loadable';
|
|
@@ -50,6 +51,8 @@ interface ChatWindowProps {
|
|
|
50
51
|
maxContextSegments?: number;
|
|
51
52
|
onyxVersion?: '2' | '3';
|
|
52
53
|
isPlaywrightTest?: boolean;
|
|
54
|
+
initialQuery?: string | null;
|
|
55
|
+
initialDeepResearch?: string | null;
|
|
53
56
|
[key: string]: any;
|
|
54
57
|
}
|
|
55
58
|
|
|
@@ -61,6 +64,8 @@ function ChatWindow({
|
|
|
61
64
|
placeholderPrompt = 'Ask a question',
|
|
62
65
|
isEditMode,
|
|
63
66
|
isPlaywrightTest,
|
|
67
|
+
initialQuery,
|
|
68
|
+
initialDeepResearch,
|
|
64
69
|
...data
|
|
65
70
|
}: ChatWindowProps) {
|
|
66
71
|
const {
|
|
@@ -124,6 +129,7 @@ function ChatWindow({
|
|
|
124
129
|
|
|
125
130
|
const [showLandingPage, setShowLandingPage] = useState(true);
|
|
126
131
|
|
|
132
|
+
const history = useHistory();
|
|
127
133
|
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
|
|
128
134
|
const chatWindowRef = useRef(null);
|
|
129
135
|
const chatWindowEndRef = useRef(null);
|
|
@@ -132,6 +138,23 @@ function ChatWindow({
|
|
|
132
138
|
setShowLandingPage(messages.length === 0);
|
|
133
139
|
}, [messages]);
|
|
134
140
|
|
|
141
|
+
// Set deep research state from URL parameter
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (initialDeepResearch !== null && initialDeepResearch !== undefined) {
|
|
144
|
+
const enabled = initialDeepResearch.toLowerCase() === 'true';
|
|
145
|
+
setIsDeepResearchEnabled(enabled);
|
|
146
|
+
}
|
|
147
|
+
}, []);
|
|
148
|
+
|
|
149
|
+
// Auto-submit query from URL parameter on mount
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
if (initialQuery && messages.length === 0 && !isStreaming) {
|
|
152
|
+
onSubmit({ message: initialQuery });
|
|
153
|
+
setShowLandingPage(false);
|
|
154
|
+
history.replace(window.location.pathname);
|
|
155
|
+
}
|
|
156
|
+
}, []);
|
|
157
|
+
|
|
135
158
|
const handleStarterPromptChoice = useCallback(
|
|
136
159
|
(message: string) => {
|
|
137
160
|
if (enableMatomoTracking) {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
2
|
+
<path d="m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z"/>
|
|
3
|
+
</svg>
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import installChatBlock from './ChatBlock';
|
|
2
|
+
import installAISearchInputBlock from './AISearchInput';
|
|
2
3
|
import loadable from '@loadable/component';
|
|
3
4
|
|
|
4
5
|
const applyConfig = (config) => {
|
|
@@ -40,6 +41,7 @@ const applyConfig = (config) => {
|
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
installChatBlock(config);
|
|
44
|
+
installAISearchInputBlock(config);
|
|
43
45
|
|
|
44
46
|
return config;
|
|
45
47
|
};
|