@budibase/frontend-core 3.29.0 → 3.30.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@budibase/frontend-core",
3
- "version": "3.29.0",
3
+ "version": "3.30.0",
4
4
  "description": "Budibase frontend core libraries used in builder and client",
5
5
  "author": "Budibase",
6
6
  "license": "MPL-2.0",
@@ -24,5 +24,5 @@
24
24
  "devDependencies": {
25
25
  "vitest": "^3.2.4"
26
26
  },
27
- "gitHead": "d16e42b03ed3e4e7e1c1b055810fa54879aa8706"
27
+ "gitHead": "58456cc695d2c71a354bcf5c064943b247ad4969"
28
28
  }
@@ -3,9 +3,11 @@ import {
3
3
  ChatConversation,
4
4
  ChatConversationRequest,
5
5
  CreateChatConversationRequest,
6
+ FetchChatAppAgentsResponse,
6
7
  ChatApp,
7
8
  ChatAppAgent,
8
9
  FetchAgentHistoryResponse,
10
+ FetchPublishedChatAppsResponse,
9
11
  UpdateChatAppRequest,
10
12
  AgentMessageMetadata,
11
13
  } from "@budibase/types"
@@ -27,6 +29,7 @@ export interface ChatAppEndpoints {
27
29
  chatAppId: string,
28
30
  chatConversationId: string
29
31
  ) => Promise<ChatConversation>
32
+ fetchChatAppAgents: (chatAppId: string) => Promise<FetchChatAppAgentsResponse>
30
33
  fetchChatHistory: (chatAppId: string) => Promise<FetchAgentHistoryResponse>
31
34
  fetchChatApp: (workspaceId?: string) => Promise<ChatApp | null>
32
35
  setChatAppAgent: (chatAppId: string, agentId: string) => Promise<ChatAppAgent>
@@ -35,6 +38,9 @@ export interface ChatAppEndpoints {
35
38
  workspaceId?: string
36
39
  ) => Promise<ChatConversation>
37
40
  updateChatApp: (chatApp: UpdateChatAppRequest) => Promise<ChatApp>
41
+ getPublishedChatApps: () => Promise<
42
+ FetchPublishedChatAppsResponse["chatApps"]
43
+ >
38
44
  }
39
45
 
40
46
  const throwOnErrorChunk = () =>
@@ -112,6 +118,12 @@ export const buildChatAppEndpoints = (
112
118
  })
113
119
  },
114
120
 
121
+ fetchChatAppAgents: async (chatAppId: string) => {
122
+ return await API.get({
123
+ url: `/api/chatapps/${chatAppId}/agents`,
124
+ })
125
+ },
126
+
115
127
  fetchChatHistory: async (chatAppId: string) => {
116
128
  return await API.get({
117
129
  url: `/api/chatapps/${chatAppId}/conversations`,
@@ -189,4 +201,11 @@ export const buildChatAppEndpoints = (
189
201
  body: chatApp as any,
190
202
  })
191
203
  },
204
+
205
+ getPublishedChatApps: async () => {
206
+ const response = await API.get<FetchPublishedChatAppsResponse>({
207
+ url: "/api/client/chatapps",
208
+ })
209
+ return response.chatApps
210
+ },
192
211
  })
@@ -0,0 +1,442 @@
1
+ <script lang="ts">
2
+ import { createEventDispatcher, onMount } from "svelte"
3
+ import { Body, Button, Icon, ProgressCircle } from "@budibase/bbui"
4
+ import type { ChatConversation, DraftChatConversation } from "@budibase/types"
5
+ import Chatbox from "./index.svelte"
6
+
7
+ type ChatConversationLike = ChatConversation | DraftChatConversation
8
+
9
+ type EnabledAgentListItem = {
10
+ agentId: string
11
+ name?: string
12
+ icon?: string
13
+ iconColor?: string
14
+ }
15
+
16
+ export let selectedAgentId: string | null = null
17
+ export let selectedAgentName: string = ""
18
+ export let enabledAgentList: EnabledAgentListItem[] = []
19
+ export let conversationStarters: { prompt: string }[] = []
20
+ export let isAgentKnown: boolean = true
21
+ export let isAgentLive: boolean = true
22
+
23
+ export let chat: ChatConversationLike
24
+ export let loading: boolean = false
25
+ export let deletingChat: boolean = false
26
+ export let workspaceId: string
27
+ export let initialPrompt: string = ""
28
+ export let userName: string = ""
29
+
30
+ const dispatch = createEventDispatcher<{
31
+ chatSaved: { chatId?: string; chat: ChatConversationLike }
32
+ deleteChat: undefined
33
+ agentSelected: { agentId: string }
34
+ startChat: { agentId: string; prompt: string }
35
+ }>()
36
+
37
+ const hasChatId = (value: ChatConversationLike) =>
38
+ value && "_id" in value && Boolean(value._id)
39
+
40
+ const buildGreeting = (name: string) => {
41
+ const currentDate = new Date()
42
+ const suffix = name ? `, ${name}` : ""
43
+
44
+ if (currentDate.getDay() === 1) {
45
+ return `Happy Monday${suffix}`
46
+ }
47
+
48
+ const isMorning = currentDate.getHours() < 12
49
+ return `${isMorning ? "Good Morning" : "Good Afternoon"}${suffix}`
50
+ }
51
+
52
+ let readOnlyReason: "disabled" | "deleted" | "offline" | undefined
53
+
54
+ let draftPrompt = ""
55
+ let draftPromptInput: HTMLInputElement | null = null
56
+
57
+ $: greetingText = buildGreeting(userName)
58
+
59
+ $: visibleAgentList = enabledAgentList.slice(0, 3)
60
+ $: hasEnabledAgents = enabledAgentList.length > 0
61
+
62
+ const getAgentStatus = (
63
+ agentId: string | null,
64
+ agents: EnabledAgentListItem[],
65
+ agentKnown: boolean,
66
+ agentLive: boolean
67
+ ): {
68
+ isAgentEnabled: boolean
69
+ readOnlyReason: "disabled" | "deleted" | "offline" | undefined
70
+ } => {
71
+ if (!agentId) {
72
+ return { isAgentEnabled: false, readOnlyReason: undefined }
73
+ }
74
+
75
+ if (!agentKnown) {
76
+ return { isAgentEnabled: false, readOnlyReason: "deleted" }
77
+ }
78
+
79
+ if (!agentLive) {
80
+ return { isAgentEnabled: false, readOnlyReason: "offline" }
81
+ }
82
+
83
+ const isAgentEnabled = agents.some(agent => agent.agentId === agentId)
84
+ return {
85
+ isAgentEnabled,
86
+ readOnlyReason: isAgentEnabled ? undefined : "disabled",
87
+ }
88
+ }
89
+
90
+ $: ({ readOnlyReason } = getAgentStatus(
91
+ selectedAgentId,
92
+ enabledAgentList,
93
+ isAgentKnown,
94
+ isAgentLive
95
+ ))
96
+
97
+ const deleteChat = () => {
98
+ dispatch("deleteChat")
99
+ }
100
+
101
+ const selectAgent = (agentId: string) => {
102
+ dispatch("agentSelected", { agentId })
103
+ }
104
+
105
+ const startChat = () => {
106
+ const prompt = draftPrompt.trim()
107
+ if (!prompt) {
108
+ return
109
+ }
110
+
111
+ const agentId = enabledAgentList[0]?.agentId
112
+ if (!agentId) {
113
+ return
114
+ }
115
+
116
+ dispatch("startChat", { agentId, prompt })
117
+ draftPrompt = ""
118
+ }
119
+
120
+ const handlePromptKeyDown = (event: KeyboardEvent) => {
121
+ if (event.key !== "Enter") {
122
+ return
123
+ }
124
+
125
+ event.preventDefault()
126
+ startChat()
127
+ }
128
+
129
+ onMount(() => {
130
+ draftPromptInput?.focus()
131
+ })
132
+ </script>
133
+
134
+ <div class="chat-wrapper">
135
+ {#if selectedAgentId}
136
+ <div class="chat-header">
137
+ <div class="chat-header-agent">
138
+ <Body size="S">
139
+ {selectedAgentName || "Unknown agent"}
140
+ </Body>
141
+ </div>
142
+
143
+ {#if hasChatId(chat)}
144
+ <Button
145
+ quiet
146
+ warning
147
+ disabled={deletingChat || loading}
148
+ on:click={deleteChat}
149
+ >
150
+ <span class="delete-button-content">
151
+ {#if deletingChat}
152
+ <ProgressCircle size="S" />
153
+ Deleting...
154
+ {:else}
155
+ <Icon name="trash" size="S" />
156
+ Delete chat
157
+ {/if}
158
+ </span>
159
+ </Button>
160
+ {/if}
161
+ </div>
162
+
163
+ <Chatbox
164
+ bind:chat
165
+ {workspaceId}
166
+ {conversationStarters}
167
+ {initialPrompt}
168
+ readOnly={Boolean(readOnlyReason)}
169
+ {readOnlyReason}
170
+ onchatsaved={event => dispatch("chatSaved", event.detail)}
171
+ />
172
+ {:else}
173
+ <div class="chat-empty">
174
+ <div class="chat-empty-greeting">
175
+ <Body size="XL" weight="600" serif>
176
+ {greetingText}
177
+ </Body>
178
+ </div>
179
+ <div class="chat-empty-input" role="presentation">
180
+ <input
181
+ class="chat-empty-input-field"
182
+ type="text"
183
+ placeholder="How can I help you today?"
184
+ bind:this={draftPromptInput}
185
+ bind:value={draftPrompt}
186
+ on:keydown={handlePromptKeyDown}
187
+ disabled={!hasEnabledAgents}
188
+ />
189
+ <button
190
+ class="chat-empty-input-action"
191
+ type="button"
192
+ on:click={startChat}
193
+ disabled={!hasEnabledAgents}
194
+ aria-label="Start chat"
195
+ >
196
+ <Icon name="arrow-up" size="S" />
197
+ </button>
198
+ </div>
199
+ <div class="chat-empty-grid">
200
+ {#if visibleAgentList.length}
201
+ {#each visibleAgentList as agent (agent.agentId)}
202
+ <button
203
+ class="chat-empty-card"
204
+ class:chat-empty-card-single={visibleAgentList.length === 1}
205
+ on:click={() => selectAgent(agent.agentId)}
206
+ style={`--agent-icon-color:${
207
+ agent.iconColor ||
208
+ "var(--spectrum-semantic-cta-color-background-default)"
209
+ };`}
210
+ >
211
+ <div class="chat-empty-card-head">
212
+ <div class="chat-empty-card-icon">
213
+ <Icon
214
+ name={agent.icon || "SideKick"}
215
+ size="S"
216
+ color="var(--agent-icon-color)"
217
+ />
218
+ </div>
219
+ <Body size="S" weight="500">
220
+ {agent.name || "Unknown agent"}
221
+ </Body>
222
+ </div>
223
+ <div class="chat-empty-card-subtitle">
224
+ <Body size="XS" color="var(--spectrum-global-color-gray-600)">
225
+ Start a chat with this agent.
226
+ </Body>
227
+ </div>
228
+ </button>
229
+ {/each}
230
+ {:else}
231
+ <Body size="S" color="var(--spectrum-global-color-gray-500)">
232
+ No enabled agents
233
+ </Body>
234
+ {/if}
235
+ </div>
236
+ </div>
237
+ {/if}
238
+ </div>
239
+
240
+ <style>
241
+ .chat-wrapper {
242
+ flex: 1 1 auto;
243
+ display: flex;
244
+ flex-direction: column;
245
+ padding: 0 32px 32px 32px;
246
+ box-sizing: border-box;
247
+ min-width: 0;
248
+ min-height: 0;
249
+ }
250
+
251
+ .chat-header {
252
+ width: 100%;
253
+ padding: var(--spacing-l) 0 var(--spacing-l);
254
+ display: flex;
255
+ align-items: center;
256
+ justify-content: space-between;
257
+ gap: var(--spacing-m);
258
+ border-bottom: var(--border-dark);
259
+ }
260
+
261
+ .chat-header-agent {
262
+ display: flex;
263
+ align-items: center;
264
+ }
265
+
266
+ .chat-header-agent :global(p) {
267
+ font-size: 14px;
268
+ line-height: 17px;
269
+ letter-spacing: 0;
270
+ font-weight: 400;
271
+ color: var(--spectrum-alias-text-color);
272
+ }
273
+
274
+ .delete-button-content {
275
+ display: flex;
276
+ align-items: center;
277
+ gap: var(--spacing-xs);
278
+ }
279
+
280
+ .chat-empty {
281
+ flex: 1 1 auto;
282
+ display: flex;
283
+ flex-direction: column;
284
+ justify-content: center;
285
+ align-items: center;
286
+ gap: 32px;
287
+ padding: var(--spacing-xxl);
288
+ text-align: center;
289
+ }
290
+
291
+ .chat-empty-greeting :global(p) {
292
+ color: var(--spectrum-alias-text-color);
293
+ font-size: 28px;
294
+ line-height: 34px;
295
+ }
296
+
297
+ .chat-empty-input {
298
+ display: flex;
299
+ align-items: center;
300
+ gap: var(--spacing-m);
301
+ width: 600px;
302
+ padding: 10px;
303
+ padding-left: 20px;
304
+ border-radius: 999px;
305
+ background: var(--spectrum-alias-background-color-secondary);
306
+ color: var(--spectrum-alias-text-color);
307
+ border: 1px solid var(--spectrum-alias-border-color);
308
+ }
309
+
310
+ .chat-empty-input-field {
311
+ flex: 1;
312
+ font-size: 16px;
313
+ color: var(--spectrum-alias-text-color);
314
+ background: transparent;
315
+ border: none;
316
+ outline: none;
317
+ font: inherit;
318
+ }
319
+
320
+ .chat-empty-input-field::placeholder {
321
+ color: var(--spectrum-alias-text-color-disabled);
322
+ }
323
+
324
+ .chat-empty-input-action {
325
+ width: 32px;
326
+ height: 32px;
327
+ border-radius: 999px;
328
+ background: var(--spectrum-semantic-cta-color-background-default);
329
+ color: var(--spectrum-global-color-gray-50);
330
+ display: inline-flex;
331
+ align-items: center;
332
+ justify-content: center;
333
+ border: none;
334
+ cursor: pointer;
335
+ }
336
+
337
+ .chat-empty-input-action:disabled,
338
+ .chat-empty-input-field:disabled {
339
+ opacity: 0.5;
340
+ cursor: not-allowed;
341
+ }
342
+
343
+ .chat-empty-input-action:hover {
344
+ background: var(--spectrum-semantic-cta-color-background-hover);
345
+ }
346
+
347
+ .chat-empty-grid {
348
+ display: flex;
349
+ flex-direction: row;
350
+ gap: 16px;
351
+ width: min(720px, 100%);
352
+ align-items: center;
353
+ justify-content: center;
354
+ }
355
+
356
+ .chat-empty-card {
357
+ border: 1px solid var(--spectrum-alias-border-color);
358
+ width: 240px;
359
+ border-radius: 16px;
360
+ padding: 0;
361
+ background: var(--spectrum-alias-background-color-primary);
362
+ color: var(--spectrum-alias-text-color);
363
+ font: inherit;
364
+ cursor: pointer;
365
+ text-align: left;
366
+ overflow: hidden;
367
+ transform: translateY(var(--card-offset, 0px))
368
+ rotate(var(--card-rotation, 0deg));
369
+ transition:
370
+ border-color 150ms ease,
371
+ transform 150ms ease;
372
+ }
373
+
374
+ .chat-empty-card:hover {
375
+ border-color: var(--spectrum-alias-border-color-hover);
376
+ transform: translateY(calc(var(--card-offset, 0px) - 3px))
377
+ rotate(var(--card-rotation, 0deg));
378
+ }
379
+
380
+ .chat-empty-card:first-child {
381
+ --card-rotation: -6deg;
382
+ --card-offset: 12px;
383
+ }
384
+
385
+ .chat-empty-card:last-child {
386
+ --card-rotation: 6deg;
387
+ --card-offset: 12px;
388
+ }
389
+
390
+ .chat-empty-card.chat-empty-card-single {
391
+ --card-rotation: 0deg;
392
+ --card-offset: 0px;
393
+ }
394
+
395
+ .chat-empty-card-head {
396
+ display: flex;
397
+ align-items: center;
398
+ gap: var(--spacing-s);
399
+ padding: var(--spacing-m);
400
+ background-color: var(--spectrum-alias-background-color-secondary);
401
+ color: var(--spectrum-alias-text-color);
402
+ border-bottom: 1px solid var(--spectrum-alias-border-color);
403
+ }
404
+
405
+ .chat-empty-card-icon {
406
+ width: 28px;
407
+ height: 28px;
408
+ border-radius: 8px;
409
+ display: inline-flex;
410
+ align-items: center;
411
+ justify-content: center;
412
+ background: transparent;
413
+ }
414
+
415
+ .chat-empty-card-subtitle {
416
+ padding: var(--spacing-m);
417
+ }
418
+
419
+ @media (max-width: 1000px) {
420
+ .chat-wrapper {
421
+ padding: 0 var(--spacing-l) var(--spacing-l);
422
+ }
423
+
424
+ .chat-empty-input {
425
+ width: min(600px, 100%);
426
+ }
427
+
428
+ .chat-empty-grid {
429
+ flex-direction: column;
430
+ }
431
+
432
+ .chat-empty-card {
433
+ width: min(360px, 100%);
434
+ }
435
+
436
+ .chat-empty-card:first-child,
437
+ .chat-empty-card:last-child {
438
+ --card-rotation: 0deg;
439
+ --card-offset: 0px;
440
+ }
441
+ }
442
+ </style>
@@ -0,0 +1,203 @@
1
+ <script lang="ts">
2
+ import { Body, Icon } from "@budibase/bbui"
3
+ import { createEventDispatcher } from "svelte"
4
+
5
+ type EnabledAgentListItem = {
6
+ agentId: string
7
+ name?: string
8
+ isDefault?: boolean
9
+ icon?: string
10
+ iconColor?: string
11
+ }
12
+
13
+ type ConversationListItem = {
14
+ _id?: string
15
+ title?: string
16
+ }
17
+
18
+ export let enabledAgentList: EnabledAgentListItem[] = []
19
+ export let conversationHistory: ConversationListItem[] = []
20
+ export let selectedConversationId: string | undefined
21
+
22
+ $: defaultAgent =
23
+ enabledAgentList.find(agent => agent.isDefault) || enabledAgentList[0]
24
+
25
+ const dispatch = createEventDispatcher<{
26
+ agentSelected: { agentId: string }
27
+ conversationSelected: { conversationId: string }
28
+ }>()
29
+
30
+ const selectAgent = (agentId: string) => {
31
+ dispatch("agentSelected", { agentId })
32
+ }
33
+
34
+ const selectConversation = (conversationId: string) => {
35
+ dispatch("conversationSelected", { conversationId })
36
+ }
37
+ </script>
38
+
39
+ <div class="chat-nav-shell">
40
+ <div class="chat-nav-content">
41
+ {#if defaultAgent?.agentId}
42
+ <div class="list-section">
43
+ <button
44
+ class="new-chat"
45
+ on:click={() => selectAgent(defaultAgent.agentId)}
46
+ >
47
+ <span class="new-chat-icon">
48
+ <Icon name="plus" size="S" />
49
+ </span>
50
+ <span class="new-chat-label">New chat</span>
51
+ </button>
52
+ </div>
53
+ {/if}
54
+
55
+ <div class="list-section">
56
+ <div class="list-title">Agents</div>
57
+ {#if enabledAgentList.length}
58
+ {#each enabledAgentList as agent (agent.agentId)}
59
+ <button
60
+ class="list-item list-item-button"
61
+ on:click={() => selectAgent(agent.agentId)}
62
+ >
63
+ <span class="list-item-icon">
64
+ <Icon name={agent.icon || "robot"} size="S" />
65
+ </span>
66
+ {agent.name}
67
+ </button>
68
+ {/each}
69
+ {:else}
70
+ <Body size="XS" color="var(--spectrum-global-color-gray-500)">
71
+ No agents
72
+ </Body>
73
+ {/if}
74
+ </div>
75
+
76
+ <div class="list-section">
77
+ <div class="list-title">Recent Chats</div>
78
+ {#if conversationHistory.length}
79
+ {#each conversationHistory as conversation}
80
+ {#if conversation._id}
81
+ <button
82
+ class="list-item list-item-button"
83
+ class:selected={selectedConversationId === conversation._id}
84
+ on:click={() => selectConversation(conversation._id!)}
85
+ >
86
+ {conversation.title || "Untitled Chat"}
87
+ </button>
88
+ {/if}
89
+ {/each}
90
+ {:else}
91
+ <Body size="XS" color="var(--spectrum-global-color-gray-500)">
92
+ No recent chats
93
+ </Body>
94
+ {/if}
95
+ </div>
96
+ </div>
97
+ </div>
98
+
99
+ <style>
100
+ .chat-nav-shell {
101
+ display: flex;
102
+ width: 260px;
103
+ min-width: 260px;
104
+ border-right: var(--border-light);
105
+ background: transparent;
106
+ }
107
+
108
+ .chat-nav-content {
109
+ display: flex;
110
+ flex-direction: column;
111
+ gap: var(--spacing-xl);
112
+ width: 100%;
113
+ }
114
+
115
+ .list-section {
116
+ padding: var(--spacing-m);
117
+ display: flex;
118
+ flex-direction: column;
119
+ gap: var(--spacing-xxs);
120
+ }
121
+
122
+ .list-section + .list-section {
123
+ padding-top: 0;
124
+ }
125
+
126
+ .new-chat {
127
+ display: flex;
128
+ align-items: center;
129
+ gap: var(--spacing-s);
130
+ background: transparent;
131
+ border: none;
132
+ padding: var(--spacing-xs) 0;
133
+ font: inherit;
134
+ color: var(--spectrum-global-color-gray-700);
135
+ text-align: left;
136
+ width: 100%;
137
+ cursor: pointer;
138
+ }
139
+
140
+ .new-chat-icon {
141
+ display: inline-flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ width: 28px;
145
+ height: 28px;
146
+ border-radius: 50%;
147
+ background: var(--spectrum-semantic-cta-color-background-default);
148
+ color: var(--spectrum-global-color-gray-50);
149
+ }
150
+
151
+ .new-chat-label {
152
+ font-size: 14px;
153
+ color: var(--spectrum-global-color-gray-800);
154
+ }
155
+
156
+ .new-chat:hover .new-chat-icon {
157
+ background: var(--spectrum-semantic-cta-color-background-hover);
158
+ }
159
+
160
+ .list-item {
161
+ display: flex;
162
+ align-items: center;
163
+ gap: var(--spacing-s);
164
+ background: transparent;
165
+ border: none;
166
+ padding: var(--spacing-xs) 0;
167
+ font: inherit;
168
+ color: var(--spectrum-global-color-gray-700);
169
+ text-align: left;
170
+ width: 100%;
171
+ white-space: nowrap;
172
+ overflow: hidden;
173
+ text-overflow: ellipsis;
174
+ }
175
+
176
+ .list-item-icon {
177
+ display: inline-flex;
178
+ align-items: center;
179
+ justify-content: center;
180
+ }
181
+
182
+ .list-item-button {
183
+ cursor: pointer;
184
+ }
185
+
186
+ .list-item-button:hover {
187
+ color: var(--spectrum-global-color-gray-900);
188
+ }
189
+
190
+ .list-item.selected {
191
+ color: var(--spectrum-global-color-gray-900);
192
+ font-weight: 600;
193
+ }
194
+
195
+ .list-title {
196
+ font-size: 14px;
197
+ line-height: 17px;
198
+ letter-spacing: 0;
199
+ color: var(--spectrum-global-color-gray-600);
200
+ font-weight: 400;
201
+ margin-bottom: var(--spacing-xs);
202
+ }
203
+ </style>
@@ -758,7 +758,7 @@
758
758
  .message.user {
759
759
  border-radius: 8px;
760
760
  align-self: flex-end;
761
- background-color: #215f9e33;
761
+ background-color: var(--spectrum-alias-background-color-secondary);
762
762
  font-size: 14px;
763
763
  color: var(--spectrum-global-color-gray-800);
764
764
  }
@@ -805,7 +805,7 @@
805
805
  padding: 20px;
806
806
  font-size: 16px;
807
807
  background-color: var(--spectrum-global-color-gray-200);
808
- color: var(--grey-9);
808
+ color: var(--spectrum-alias-text-color);
809
809
  border-radius: 10px;
810
810
  border: 1px solid var(--spectrum-global-color-gray-300) !important;
811
811
  outline: none;
@@ -813,7 +813,7 @@
813
813
  }
814
814
 
815
815
  .input:focus {
816
- border: 1px solid #215f9e33 !important;
816
+ border: 1px solid var(--spectrum-alias-border-color-mouse-focus) !important;
817
817
  }
818
818
 
819
819
  .input::placeholder {
@@ -11,3 +11,5 @@ export { default as ChangePasswordModal } from "./ChangePasswordModal.svelte"
11
11
  export { default as ProfileModal } from "./ProfileModal.svelte"
12
12
  export { default as PasswordRepeatInput } from "./PasswordRepeatInput.svelte"
13
13
  export { default as Chatbox } from "./Chatbox/index.svelte"
14
+ export { default as ChatNavigationPanel } from "./Chatbox/ChatNavigationPanel.svelte"
15
+ export { default as ChatConversationPanel } from "./Chatbox/ChatConversationPanel.svelte"