@budibase/frontend-core 3.42.0 → 3.44.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 +2 -2
- package/src/api/agents.ts +26 -57
- package/src/api/ai.ts +26 -0
- package/src/api/chatLinks.ts +26 -6
- package/src/api/escalations.ts +6 -2
- package/src/api/index.ts +17 -5
- package/src/api/restTemplates.ts +74 -0
- package/src/api/types.ts +3 -2
- package/src/components/Chatbox/index.svelte +63 -323
- package/src/components/UserAvatars.svelte +1 -1
- package/src/components/grid/cells/DateCell.svelte +1 -1
- package/src/components/index.ts +0 -2
- package/src/utils/download.test.js +34 -0
- package/src/api/chatApps.ts +0 -268
- package/src/components/Chatbox/ChatConversationPanel.svelte +0 -401
- package/src/components/Chatbox/ChatNavigationPanel.svelte +0 -326
package/src/api/chatApps.ts
DELETED
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ChatAgentRequest,
|
|
3
|
-
ChatConversation,
|
|
4
|
-
ChatConversationRequest,
|
|
5
|
-
CreateChatConversationRequest,
|
|
6
|
-
FetchChatAppAgentsResponse,
|
|
7
|
-
ChatApp,
|
|
8
|
-
ChatAppAgent,
|
|
9
|
-
FetchAgentHistoryResponse,
|
|
10
|
-
FetchPublishedChatAppsResponse,
|
|
11
|
-
UpdateChatAppRequest,
|
|
12
|
-
AgentMessageMetadata,
|
|
13
|
-
FetchAgentFileUrlResponse,
|
|
14
|
-
} from "@budibase/types"
|
|
15
|
-
import { Header } from "@budibase/shared-core"
|
|
16
|
-
import { BaseAPIClient } from "./types"
|
|
17
|
-
import { readUIMessageStream, UIMessage, UIMessageChunk } from "ai"
|
|
18
|
-
import { createSseToJsonTransformStream } from "../utils/utils"
|
|
19
|
-
|
|
20
|
-
export interface ChatAppEndpoints {
|
|
21
|
-
streamChatConversation: (
|
|
22
|
-
chat: ChatConversationRequest,
|
|
23
|
-
workspaceId: string
|
|
24
|
-
) => Promise<AsyncIterable<UIMessage<AgentMessageMetadata>>>
|
|
25
|
-
deleteChatConversation: (
|
|
26
|
-
chatConversationId: string,
|
|
27
|
-
chatAppId: string,
|
|
28
|
-
agentId?: string
|
|
29
|
-
) => Promise<void>
|
|
30
|
-
fetchChatConversation: (
|
|
31
|
-
chatAppId: string,
|
|
32
|
-
chatConversationId: string,
|
|
33
|
-
agentId?: string
|
|
34
|
-
) => Promise<ChatConversation>
|
|
35
|
-
fetchChatAppAgents: (chatAppId: string) => Promise<FetchChatAppAgentsResponse>
|
|
36
|
-
fetchChatHistory: (
|
|
37
|
-
chatAppId: string,
|
|
38
|
-
agentId?: string
|
|
39
|
-
) => Promise<FetchAgentHistoryResponse>
|
|
40
|
-
fetchChatApp: (workspaceId?: string) => Promise<ChatApp | null>
|
|
41
|
-
setChatAppAgent: (chatAppId: string, agentId: string) => Promise<ChatAppAgent>
|
|
42
|
-
fetchChatAppAgentFileUrl: (
|
|
43
|
-
chatAppId: string,
|
|
44
|
-
agentId: string,
|
|
45
|
-
fileId: string,
|
|
46
|
-
operationId: string
|
|
47
|
-
) => Promise<FetchAgentFileUrlResponse>
|
|
48
|
-
createChatConversation: (
|
|
49
|
-
chat: CreateChatConversationRequest,
|
|
50
|
-
workspaceId?: string
|
|
51
|
-
) => Promise<ChatConversation>
|
|
52
|
-
updateChatApp: (chatApp: UpdateChatAppRequest) => Promise<ChatApp>
|
|
53
|
-
getPublishedChatApps: () => Promise<
|
|
54
|
-
FetchPublishedChatAppsResponse["chatApps"]
|
|
55
|
-
>
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const getBrowserTimezone = () => {
|
|
59
|
-
try {
|
|
60
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
61
|
-
} catch {
|
|
62
|
-
return undefined
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const throwOnErrorChunk = () =>
|
|
67
|
-
new TransformStream<UIMessageChunk, UIMessageChunk>({
|
|
68
|
-
transform(chunk, controller) {
|
|
69
|
-
if (chunk.type === "error") {
|
|
70
|
-
throw new Error(chunk.errorText || "Agent action failed")
|
|
71
|
-
}
|
|
72
|
-
controller.enqueue(chunk)
|
|
73
|
-
},
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
const withAgentIdQuery = (url: string, agentId?: string) => {
|
|
77
|
-
if (!agentId) {
|
|
78
|
-
return url
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const query = new URLSearchParams({ agentId })
|
|
82
|
-
return `${url}?${query.toString()}`
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export const buildChatAppEndpoints = (
|
|
86
|
-
API: BaseAPIClient
|
|
87
|
-
): ChatAppEndpoints => ({
|
|
88
|
-
streamChatConversation: async (chat, workspaceId) => {
|
|
89
|
-
if (!chat.chatAppId) {
|
|
90
|
-
throw new Error("chatAppId is required to stream a chat conversation")
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const body: ChatAgentRequest = {
|
|
94
|
-
...chat,
|
|
95
|
-
timezone: chat.timezone ?? getBrowserTimezone(),
|
|
96
|
-
}
|
|
97
|
-
const conversationId = chat._id || "new"
|
|
98
|
-
|
|
99
|
-
const response = await fetch(
|
|
100
|
-
`/api/chatapps/${chat.chatAppId}/conversations/${conversationId}/stream`,
|
|
101
|
-
{
|
|
102
|
-
method: "POST",
|
|
103
|
-
headers: {
|
|
104
|
-
"Content-Type": "application/json",
|
|
105
|
-
Accept: "application/json",
|
|
106
|
-
[Header.WORKSPACE_ID]: workspaceId,
|
|
107
|
-
},
|
|
108
|
-
body: JSON.stringify(body),
|
|
109
|
-
credentials: "same-origin",
|
|
110
|
-
}
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
if (!response.ok) {
|
|
114
|
-
const errorBody = await response.json()
|
|
115
|
-
throw new Error(
|
|
116
|
-
errorBody.message || `HTTP error! status: ${response.status}`
|
|
117
|
-
)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (!response.body) {
|
|
121
|
-
throw new Error("Failed to get response body")
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const chunkStream = response.body
|
|
125
|
-
.pipeThrough(new TextDecoderStream())
|
|
126
|
-
.pipeThrough(createSseToJsonTransformStream<UIMessageChunk>())
|
|
127
|
-
.pipeThrough(throwOnErrorChunk())
|
|
128
|
-
|
|
129
|
-
return readUIMessageStream({
|
|
130
|
-
stream: chunkStream,
|
|
131
|
-
terminateOnError: true,
|
|
132
|
-
})
|
|
133
|
-
},
|
|
134
|
-
|
|
135
|
-
deleteChatConversation: async (
|
|
136
|
-
chatConversationId: string,
|
|
137
|
-
chatAppId: string,
|
|
138
|
-
agentId?: string
|
|
139
|
-
) => {
|
|
140
|
-
return await API.delete({
|
|
141
|
-
url: withAgentIdQuery(
|
|
142
|
-
`/api/chatapps/${chatAppId}/conversations/${chatConversationId}`,
|
|
143
|
-
agentId
|
|
144
|
-
),
|
|
145
|
-
})
|
|
146
|
-
},
|
|
147
|
-
|
|
148
|
-
fetchChatConversation: async (
|
|
149
|
-
chatAppId: string,
|
|
150
|
-
chatConversationId: string,
|
|
151
|
-
agentId?: string
|
|
152
|
-
) => {
|
|
153
|
-
return await API.get({
|
|
154
|
-
url: withAgentIdQuery(
|
|
155
|
-
`/api/chatapps/${chatAppId}/conversations/${chatConversationId}`,
|
|
156
|
-
agentId
|
|
157
|
-
),
|
|
158
|
-
})
|
|
159
|
-
},
|
|
160
|
-
|
|
161
|
-
fetchChatAppAgents: async (chatAppId: string) => {
|
|
162
|
-
return await API.get({
|
|
163
|
-
url: `/api/chatapps/${chatAppId}/agents`,
|
|
164
|
-
})
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
fetchChatHistory: async (chatAppId: string, agentId?: string) => {
|
|
168
|
-
return await API.get({
|
|
169
|
-
url: withAgentIdQuery(
|
|
170
|
-
`/api/chatapps/${chatAppId}/conversations`,
|
|
171
|
-
agentId
|
|
172
|
-
),
|
|
173
|
-
})
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
fetchChatApp: async (workspaceId?: string) => {
|
|
177
|
-
const url = "/api/chatapps"
|
|
178
|
-
const headers = workspaceId
|
|
179
|
-
? {
|
|
180
|
-
[Header.WORKSPACE_ID]: workspaceId,
|
|
181
|
-
}
|
|
182
|
-
: undefined
|
|
183
|
-
return await API.get({
|
|
184
|
-
url,
|
|
185
|
-
...(headers && { headers }),
|
|
186
|
-
})
|
|
187
|
-
},
|
|
188
|
-
|
|
189
|
-
setChatAppAgent: async (chatAppId: string, agentId: string) => {
|
|
190
|
-
if (!chatAppId) {
|
|
191
|
-
throw new Error("chatAppId is required to set chat app agent")
|
|
192
|
-
}
|
|
193
|
-
if (!agentId) {
|
|
194
|
-
throw new Error("agentId is required to set chat app agent")
|
|
195
|
-
}
|
|
196
|
-
return await API.post({
|
|
197
|
-
url: `/api/chatapps/${chatAppId}/agent`,
|
|
198
|
-
body: { agentId } as any,
|
|
199
|
-
})
|
|
200
|
-
},
|
|
201
|
-
|
|
202
|
-
fetchChatAppAgentFileUrl: async (
|
|
203
|
-
chatAppId: string,
|
|
204
|
-
agentId: string,
|
|
205
|
-
fileId: string,
|
|
206
|
-
operationId: string
|
|
207
|
-
) => {
|
|
208
|
-
if (!operationId) {
|
|
209
|
-
throw new Error("operationId is required to fetch a chat app agent file")
|
|
210
|
-
}
|
|
211
|
-
return await API.get<FetchAgentFileUrlResponse>({
|
|
212
|
-
url: `/api/chatapps/${chatAppId}/agents/${agentId}/operations/${operationId}/files/${fileId}/url`,
|
|
213
|
-
})
|
|
214
|
-
},
|
|
215
|
-
|
|
216
|
-
createChatConversation: async (
|
|
217
|
-
chat: CreateChatConversationRequest,
|
|
218
|
-
workspaceId?: string
|
|
219
|
-
) => {
|
|
220
|
-
const resolvedWorkspaceId = workspaceId || API.getAppID()
|
|
221
|
-
const { chatAppId } = chat
|
|
222
|
-
if (!chatAppId) {
|
|
223
|
-
throw new Error("chatAppId is required to create a chat conversation")
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const headers: Record<string, string> = {
|
|
227
|
-
"Content-Type": "application/json",
|
|
228
|
-
Accept: "application/json",
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (resolvedWorkspaceId) {
|
|
232
|
-
headers[Header.WORKSPACE_ID] = resolvedWorkspaceId
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const response = await fetch(`/api/chatapps/${chatAppId}/conversations`, {
|
|
236
|
-
method: "POST",
|
|
237
|
-
headers,
|
|
238
|
-
credentials: "same-origin",
|
|
239
|
-
body: JSON.stringify(chat),
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
if (!response.ok) {
|
|
243
|
-
const errorBody = await response.json().catch(() => null)
|
|
244
|
-
throw new Error(
|
|
245
|
-
errorBody?.message || `HTTP error! status: ${response.status}`
|
|
246
|
-
)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
return (await response.json()) as ChatConversation
|
|
250
|
-
},
|
|
251
|
-
|
|
252
|
-
updateChatApp: async (chatApp: UpdateChatAppRequest) => {
|
|
253
|
-
if (!chatApp._id) {
|
|
254
|
-
throw new Error("chatAppId is required to update a chat app")
|
|
255
|
-
}
|
|
256
|
-
return await API.put({
|
|
257
|
-
url: `/api/chatapps/${chatApp._id}`,
|
|
258
|
-
body: chatApp as any,
|
|
259
|
-
})
|
|
260
|
-
},
|
|
261
|
-
|
|
262
|
-
getPublishedChatApps: async () => {
|
|
263
|
-
const response = await API.get<FetchPublishedChatAppsResponse>({
|
|
264
|
-
url: "/api/client/chatapps",
|
|
265
|
-
})
|
|
266
|
-
return response.chatApps
|
|
267
|
-
},
|
|
268
|
-
})
|
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { createEventDispatcher, onMount } from "svelte"
|
|
3
|
-
import { Body, Icon } from "@budibase/bbui"
|
|
4
|
-
import type { ChatConversation, DraftChatConversation } from "@budibase/types"
|
|
5
|
-
import Chatbox from "./index.svelte"
|
|
6
|
-
|
|
7
|
-
type AgentAvailability =
|
|
8
|
-
| "no_selection"
|
|
9
|
-
| "deleted"
|
|
10
|
-
| "offline"
|
|
11
|
-
| "disabled"
|
|
12
|
-
| "ready"
|
|
13
|
-
|
|
14
|
-
type ChatConversationLike = ChatConversation | DraftChatConversation
|
|
15
|
-
|
|
16
|
-
type EnabledAgentListItem = {
|
|
17
|
-
agentId: string
|
|
18
|
-
name?: string
|
|
19
|
-
icon?: string
|
|
20
|
-
iconColor?: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export let selectedAgentId: string | null = null
|
|
24
|
-
export let enabledAgentList: EnabledAgentListItem[] = []
|
|
25
|
-
export let conversationStarters: { prompt: string }[] = []
|
|
26
|
-
export let agentAvailability: AgentAvailability = "ready"
|
|
27
|
-
|
|
28
|
-
export let chat: ChatConversationLike
|
|
29
|
-
export let suppressAgentPicker: boolean = false
|
|
30
|
-
export let workspaceId: string
|
|
31
|
-
export let initialPrompt: string = ""
|
|
32
|
-
export let userName: string = ""
|
|
33
|
-
|
|
34
|
-
const dispatch = createEventDispatcher<{
|
|
35
|
-
chatSaved: { chatId?: string; chat: ChatConversationLike }
|
|
36
|
-
agentSelected: { agentId: string }
|
|
37
|
-
startChat: { agentId: string; prompt: string }
|
|
38
|
-
}>()
|
|
39
|
-
|
|
40
|
-
const hasChatId = (value: ChatConversationLike) =>
|
|
41
|
-
value && "_id" in value && Boolean(value._id)
|
|
42
|
-
|
|
43
|
-
const buildGreeting = (name: string) => {
|
|
44
|
-
const currentDate = new Date()
|
|
45
|
-
const suffix = name ? `, ${name}` : ""
|
|
46
|
-
|
|
47
|
-
if (currentDate.getDay() === 1) {
|
|
48
|
-
return `Happy Monday${suffix}`
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const isMorning = currentDate.getHours() < 12
|
|
52
|
-
return `${isMorning ? "Good Morning" : "Good Afternoon"}${suffix}`
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
let readOnlyReason: "disabled" | "deleted" | "offline" | undefined
|
|
56
|
-
|
|
57
|
-
let draftPrompt = ""
|
|
58
|
-
let draftPromptInput: HTMLInputElement | null = null
|
|
59
|
-
|
|
60
|
-
$: greetingText = buildGreeting(userName)
|
|
61
|
-
|
|
62
|
-
$: visibleAgentList = enabledAgentList.slice(0, 3)
|
|
63
|
-
$: hasEnabledAgents = enabledAgentList.length > 0
|
|
64
|
-
|
|
65
|
-
const getReadOnlyReason = (
|
|
66
|
-
availability: AgentAvailability
|
|
67
|
-
): "disabled" | "deleted" | "offline" | undefined => {
|
|
68
|
-
switch (availability) {
|
|
69
|
-
case "deleted":
|
|
70
|
-
return "deleted"
|
|
71
|
-
case "offline":
|
|
72
|
-
return "offline"
|
|
73
|
-
case "disabled":
|
|
74
|
-
return "disabled"
|
|
75
|
-
default:
|
|
76
|
-
return undefined
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
$: readOnlyReason = getReadOnlyReason(agentAvailability)
|
|
81
|
-
|
|
82
|
-
const selectAgent = (agentId: string) => {
|
|
83
|
-
dispatch("agentSelected", { agentId })
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const startChat = () => {
|
|
87
|
-
const prompt = draftPrompt.trim()
|
|
88
|
-
if (!prompt) {
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const agentId = enabledAgentList[0]?.agentId
|
|
93
|
-
if (!agentId) {
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
dispatch("startChat", { agentId, prompt })
|
|
98
|
-
draftPrompt = ""
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const handlePromptKeyDown = (event: KeyboardEvent) => {
|
|
102
|
-
if (event.key !== "Enter") {
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
event.preventDefault()
|
|
107
|
-
startChat()
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
onMount(() => {
|
|
111
|
-
draftPromptInput?.focus()
|
|
112
|
-
})
|
|
113
|
-
</script>
|
|
114
|
-
|
|
115
|
-
<div class="chat-wrapper">
|
|
116
|
-
{#if selectedAgentId}
|
|
117
|
-
{#if hasChatId(chat)}
|
|
118
|
-
<div class="chat-header">
|
|
119
|
-
<div class="chat-header-title">
|
|
120
|
-
<Body size="S">{chat.title || "Untitled Chat"}</Body>
|
|
121
|
-
</div>
|
|
122
|
-
</div>
|
|
123
|
-
{/if}
|
|
124
|
-
|
|
125
|
-
<Chatbox
|
|
126
|
-
bind:chat
|
|
127
|
-
{workspaceId}
|
|
128
|
-
{conversationStarters}
|
|
129
|
-
{initialPrompt}
|
|
130
|
-
readOnly={Boolean(readOnlyReason)}
|
|
131
|
-
{readOnlyReason}
|
|
132
|
-
onchatsaved={event => dispatch("chatSaved", event.detail)}
|
|
133
|
-
/>
|
|
134
|
-
{:else if !suppressAgentPicker}
|
|
135
|
-
<div class="chat-empty">
|
|
136
|
-
<div class="chat-empty-greeting">
|
|
137
|
-
<Body size="XL" weight="600">
|
|
138
|
-
{greetingText}
|
|
139
|
-
</Body>
|
|
140
|
-
</div>
|
|
141
|
-
<div class="chat-empty-input" role="presentation">
|
|
142
|
-
<input
|
|
143
|
-
class="chat-empty-input-field"
|
|
144
|
-
type="text"
|
|
145
|
-
placeholder="How can I help you today?"
|
|
146
|
-
bind:this={draftPromptInput}
|
|
147
|
-
bind:value={draftPrompt}
|
|
148
|
-
on:keydown={handlePromptKeyDown}
|
|
149
|
-
disabled={!hasEnabledAgents}
|
|
150
|
-
/>
|
|
151
|
-
<button
|
|
152
|
-
class="chat-empty-input-action"
|
|
153
|
-
type="button"
|
|
154
|
-
on:click={startChat}
|
|
155
|
-
disabled={!hasEnabledAgents}
|
|
156
|
-
aria-label="Start chat"
|
|
157
|
-
>
|
|
158
|
-
<Icon name="arrow-up" size="S" />
|
|
159
|
-
</button>
|
|
160
|
-
</div>
|
|
161
|
-
<div class="chat-empty-grid">
|
|
162
|
-
{#if visibleAgentList.length}
|
|
163
|
-
{#each visibleAgentList as agent (agent.agentId)}
|
|
164
|
-
<button
|
|
165
|
-
class="chat-empty-card"
|
|
166
|
-
class:chat-empty-card-single={visibleAgentList.length === 1}
|
|
167
|
-
on:click={() => selectAgent(agent.agentId)}
|
|
168
|
-
style={`--agent-icon-color:${
|
|
169
|
-
agent.iconColor ||
|
|
170
|
-
"var(--spectrum-semantic-cta-color-background-default)"
|
|
171
|
-
};`}
|
|
172
|
-
>
|
|
173
|
-
<div class="chat-empty-card-head">
|
|
174
|
-
<div class="chat-empty-card-icon">
|
|
175
|
-
<Icon
|
|
176
|
-
name={agent.icon || "SideKick"}
|
|
177
|
-
size="S"
|
|
178
|
-
color="var(--agent-icon-color)"
|
|
179
|
-
/>
|
|
180
|
-
</div>
|
|
181
|
-
<Body size="S" weight="500">
|
|
182
|
-
{agent.name || "Unknown agent"}
|
|
183
|
-
</Body>
|
|
184
|
-
</div>
|
|
185
|
-
<div class="chat-empty-card-subtitle">
|
|
186
|
-
<Body size="XS" color="var(--spectrum-global-color-gray-600)">
|
|
187
|
-
Start a chat with this agent.
|
|
188
|
-
</Body>
|
|
189
|
-
</div>
|
|
190
|
-
</button>
|
|
191
|
-
{/each}
|
|
192
|
-
{:else}
|
|
193
|
-
<Body size="S" color="var(--spectrum-global-color-gray-500)">
|
|
194
|
-
No enabled agents
|
|
195
|
-
</Body>
|
|
196
|
-
{/if}
|
|
197
|
-
</div>
|
|
198
|
-
</div>
|
|
199
|
-
{/if}
|
|
200
|
-
</div>
|
|
201
|
-
|
|
202
|
-
<style>
|
|
203
|
-
.chat-wrapper {
|
|
204
|
-
flex: 1 1 auto;
|
|
205
|
-
display: flex;
|
|
206
|
-
flex-direction: column;
|
|
207
|
-
padding: 0 32px 32px 32px;
|
|
208
|
-
box-sizing: border-box;
|
|
209
|
-
min-width: 0;
|
|
210
|
-
min-height: 0;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
.chat-header {
|
|
214
|
-
width: 100%;
|
|
215
|
-
padding: var(--spacing-l) 0 var(--spacing-l);
|
|
216
|
-
display: flex;
|
|
217
|
-
align-items: center;
|
|
218
|
-
justify-content: space-between;
|
|
219
|
-
gap: var(--spacing-m);
|
|
220
|
-
border-bottom: var(--border-light);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
.chat-header-title {
|
|
224
|
-
min-width: 0;
|
|
225
|
-
flex: 1 1 auto;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
.chat-header-title :global(p) {
|
|
229
|
-
overflow: hidden;
|
|
230
|
-
text-overflow: ellipsis;
|
|
231
|
-
white-space: nowrap;
|
|
232
|
-
font-size: 14px;
|
|
233
|
-
line-height: 17px;
|
|
234
|
-
letter-spacing: 0;
|
|
235
|
-
font-weight: 400;
|
|
236
|
-
color: var(--spectrum-alias-text-color);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.chat-empty {
|
|
240
|
-
flex: 1 1 auto;
|
|
241
|
-
display: flex;
|
|
242
|
-
flex-direction: column;
|
|
243
|
-
justify-content: center;
|
|
244
|
-
align-items: center;
|
|
245
|
-
gap: 32px;
|
|
246
|
-
padding: var(--spacing-xxl);
|
|
247
|
-
text-align: center;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
.chat-empty-greeting :global(p) {
|
|
251
|
-
color: var(--spectrum-alias-text-color);
|
|
252
|
-
font-size: 28px;
|
|
253
|
-
line-height: 34px;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
.chat-empty-input {
|
|
257
|
-
display: flex;
|
|
258
|
-
align-items: center;
|
|
259
|
-
gap: var(--spacing-m);
|
|
260
|
-
width: 600px;
|
|
261
|
-
padding: 10px;
|
|
262
|
-
padding-left: 20px;
|
|
263
|
-
border-radius: 999px;
|
|
264
|
-
background: var(--spectrum-alias-background-color-secondary);
|
|
265
|
-
color: var(--spectrum-alias-text-color);
|
|
266
|
-
border: 1px solid var(--spectrum-alias-border-color);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
.chat-empty-input-field {
|
|
270
|
-
flex: 1;
|
|
271
|
-
font-size: 16px;
|
|
272
|
-
color: var(--spectrum-alias-text-color);
|
|
273
|
-
background: transparent;
|
|
274
|
-
border: none;
|
|
275
|
-
outline: none;
|
|
276
|
-
font: inherit;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.chat-empty-input-field::placeholder {
|
|
280
|
-
color: var(--spectrum-alias-text-color-disabled);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
.chat-empty-input-action {
|
|
284
|
-
width: 32px;
|
|
285
|
-
height: 32px;
|
|
286
|
-
border-radius: 999px;
|
|
287
|
-
background: var(--spectrum-semantic-cta-color-background-default);
|
|
288
|
-
color: var(--spectrum-global-color-gray-50);
|
|
289
|
-
display: inline-flex;
|
|
290
|
-
align-items: center;
|
|
291
|
-
justify-content: center;
|
|
292
|
-
border: none;
|
|
293
|
-
cursor: pointer;
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
.chat-empty-input-action:disabled,
|
|
297
|
-
.chat-empty-input-field:disabled {
|
|
298
|
-
opacity: 0.5;
|
|
299
|
-
cursor: not-allowed;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
.chat-empty-input-action:hover {
|
|
303
|
-
background: var(--spectrum-semantic-cta-color-background-hover);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
.chat-empty-grid {
|
|
307
|
-
display: flex;
|
|
308
|
-
flex-direction: row;
|
|
309
|
-
gap: 16px;
|
|
310
|
-
width: min(720px, 100%);
|
|
311
|
-
align-items: center;
|
|
312
|
-
justify-content: center;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
.chat-empty-card {
|
|
316
|
-
border: 1px solid var(--spectrum-alias-border-color);
|
|
317
|
-
width: 240px;
|
|
318
|
-
border-radius: 16px;
|
|
319
|
-
padding: 0;
|
|
320
|
-
background: var(--spectrum-alias-background-color-primary);
|
|
321
|
-
color: var(--spectrum-alias-text-color);
|
|
322
|
-
font: inherit;
|
|
323
|
-
cursor: pointer;
|
|
324
|
-
text-align: left;
|
|
325
|
-
overflow: hidden;
|
|
326
|
-
transform: translateY(var(--card-offset, 0px))
|
|
327
|
-
rotate(var(--card-rotation, 0deg));
|
|
328
|
-
transition:
|
|
329
|
-
border-color 150ms ease,
|
|
330
|
-
transform 150ms ease;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
.chat-empty-card:hover {
|
|
334
|
-
border-color: var(--spectrum-alias-border-color-hover);
|
|
335
|
-
transform: translateY(calc(var(--card-offset, 0px) - 3px))
|
|
336
|
-
rotate(var(--card-rotation, 0deg));
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
.chat-empty-card:first-child {
|
|
340
|
-
--card-rotation: -6deg;
|
|
341
|
-
--card-offset: 12px;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
.chat-empty-card:last-child {
|
|
345
|
-
--card-rotation: 6deg;
|
|
346
|
-
--card-offset: 12px;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
.chat-empty-card.chat-empty-card-single {
|
|
350
|
-
--card-rotation: 0deg;
|
|
351
|
-
--card-offset: 0px;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
.chat-empty-card-head {
|
|
355
|
-
display: flex;
|
|
356
|
-
align-items: center;
|
|
357
|
-
gap: var(--spacing-s);
|
|
358
|
-
padding: var(--spacing-m);
|
|
359
|
-
background-color: var(--spectrum-alias-background-color-secondary);
|
|
360
|
-
color: var(--spectrum-alias-text-color);
|
|
361
|
-
border-bottom: 1px solid var(--spectrum-alias-border-color);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.chat-empty-card-icon {
|
|
365
|
-
width: 28px;
|
|
366
|
-
height: 28px;
|
|
367
|
-
border-radius: 8px;
|
|
368
|
-
display: inline-flex;
|
|
369
|
-
align-items: center;
|
|
370
|
-
justify-content: center;
|
|
371
|
-
background: transparent;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
.chat-empty-card-subtitle {
|
|
375
|
-
padding: var(--spacing-m);
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
@media (max-width: 1000px) {
|
|
379
|
-
.chat-wrapper {
|
|
380
|
-
padding: 0 var(--spacing-l) var(--spacing-l);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
.chat-empty-input {
|
|
384
|
-
width: min(600px, 100%);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
.chat-empty-grid {
|
|
388
|
-
flex-direction: column;
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
.chat-empty-card {
|
|
392
|
-
width: min(360px, 100%);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
.chat-empty-card:first-child,
|
|
396
|
-
.chat-empty-card:last-child {
|
|
397
|
-
--card-rotation: 0deg;
|
|
398
|
-
--card-offset: 0px;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
</style>
|