@softwareone/spi-sv5-library 1.10.2 → 1.10.4
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/Button/Button.svelte +95 -8
- package/dist/Button/Button.svelte.d.ts +1 -0
- package/dist/Table/Header.svelte +1 -1
- package/dist/Table/excel.d.ts +1 -1
- package/dist/Table/excel.js +1 -1
- package/dist/Table/index.d.ts +2 -1
- package/dist/Table/index.js +2 -1
- package/dist/Table/util.d.ts +2 -1
- package/dist/Table/util.js +11 -1
- package/package.json +15 -20
- package/dist/ChatBot/ChatBot.svelte +0 -210
- package/dist/ChatBot/ChatBot.svelte.d.ts +0 -8
- package/dist/ChatBot/ChatBotFooter.svelte +0 -53
- package/dist/ChatBot/ChatBotFooter.svelte.d.ts +0 -7
- package/dist/ChatBot/ChatBotHeader.svelte +0 -66
- package/dist/ChatBot/ChatBotHeader.svelte.d.ts +0 -8
- package/dist/ChatBot/ChatBotMessages.svelte +0 -278
- package/dist/ChatBot/ChatBotMessages.svelte.d.ts +0 -9
- package/dist/ChatBot/chatbotState.svelte.d.ts +0 -27
- package/dist/ChatBot/chatbotState.svelte.js +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { Attachment } from 'svelte/attachments';
|
|
3
4
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
4
5
|
|
|
5
6
|
type Variant = 'primary' | 'secondary' | 'outline' | 'outline-none';
|
|
@@ -8,14 +9,54 @@
|
|
|
8
9
|
interface ButtonProps extends HTMLButtonAttributes {
|
|
9
10
|
variant?: Variant;
|
|
10
11
|
variantColor?: VariantColor;
|
|
12
|
+
loading?: boolean;
|
|
11
13
|
children: Snippet;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
let {
|
|
16
|
+
let {
|
|
17
|
+
variant = 'primary',
|
|
18
|
+
variantColor = 'primary',
|
|
19
|
+
loading = false,
|
|
20
|
+
children,
|
|
21
|
+
...props
|
|
22
|
+
}: ButtonProps = $props();
|
|
23
|
+
|
|
24
|
+
const clearButtonFocus: Attachment<HTMLButtonElement> = (element: HTMLButtonElement) => {
|
|
25
|
+
if (loading) element.blur();
|
|
26
|
+
};
|
|
15
27
|
</script>
|
|
16
28
|
|
|
17
|
-
<button
|
|
18
|
-
{@
|
|
29
|
+
<button
|
|
30
|
+
{@attach clearButtonFocus}
|
|
31
|
+
class={['btn', `btn-${variant}-${variantColor}`, loading && 'loading']}
|
|
32
|
+
disabled={loading || props.disabled}
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
{#if loading}
|
|
36
|
+
<span class="spinner-wrapper">
|
|
37
|
+
<svg
|
|
38
|
+
class="spinner"
|
|
39
|
+
width="16"
|
|
40
|
+
height="16"
|
|
41
|
+
viewBox="0 0 16 16"
|
|
42
|
+
fill="none"
|
|
43
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
44
|
+
>
|
|
45
|
+
<path
|
|
46
|
+
d="M16 8C16 12.4183 12.4183 16 8 16C3.58172 16 0 12.4183 0 8C0 3.58172 3.58172 0 8 0C12.4183 0 16 3.58172 16 8ZM2.50919 8C2.50919 11.0325 4.96752 13.4908 8 13.4908C11.0325 13.4908 13.4908 11.0325 13.4908 8C13.4908 4.96752 11.0325 2.50919 8 2.50919C4.96752 2.50919 2.50919 4.96752 2.50919 8Z"
|
|
47
|
+
fill="currentColor"
|
|
48
|
+
opacity="0.3"
|
|
49
|
+
/>
|
|
50
|
+
<path
|
|
51
|
+
d="M8 1.2546C8 0.561698 8.56514 -0.0100693 9.24952 0.0981505C10.9084 0.360457 12.4543 1.14062 13.6569 2.34315C15.1571 3.84344 16 5.87827 16 8C16 10.1217 15.1571 12.1566 13.6569 13.6569C12.4543 14.8594 10.9084 15.6396 9.24952 15.9018C8.56514 16.0101 8 15.4383 8 14.7454C8 14.0525 8.56889 13.5051 9.24375 13.3481C10.235 13.1176 11.1513 12.6138 11.8826 11.8826C12.9123 10.8529 13.4908 9.45641 13.4908 8C13.4908 6.54359 12.9123 5.14709 11.8826 4.11742C11.1513 3.38615 10.235 2.88245 9.24375 2.65189C8.56889 2.49492 8 1.9475 8 1.2546Z"
|
|
52
|
+
fill="currentColor"
|
|
53
|
+
/>
|
|
54
|
+
</svg>
|
|
55
|
+
</span>
|
|
56
|
+
{/if}
|
|
57
|
+
<span class="content" class:hidden={loading}>
|
|
58
|
+
{@render children()}
|
|
59
|
+
</span>
|
|
19
60
|
</button>
|
|
20
61
|
|
|
21
62
|
<style>
|
|
@@ -27,6 +68,52 @@
|
|
|
27
68
|
font-style: normal;
|
|
28
69
|
font-weight: 400;
|
|
29
70
|
line-height: 20px;
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
position: relative;
|
|
73
|
+
transition: all 0.2s ease-in-out;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.content.hidden {
|
|
77
|
+
opacity: 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.spinner-wrapper {
|
|
81
|
+
position: absolute;
|
|
82
|
+
display: inline-flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
left: 50%;
|
|
85
|
+
top: 50%;
|
|
86
|
+
transform: translate(-50%, -50%);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.spinner {
|
|
90
|
+
animation: spin 0.8s linear infinite;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.btn-primary-primary .spinner,
|
|
94
|
+
.btn-primary-danger .spinner {
|
|
95
|
+
color: #fff;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.btn-secondary-primary .spinner,
|
|
99
|
+
.btn-outline-primary .spinner,
|
|
100
|
+
.btn-outline-none-primary .spinner {
|
|
101
|
+
color: #472aff;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.btn-secondary-danger .spinner,
|
|
105
|
+
.btn-outline-danger .spinner,
|
|
106
|
+
.btn-outline-none-danger .spinner {
|
|
107
|
+
color: #dc182c;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@keyframes spin {
|
|
111
|
+
from {
|
|
112
|
+
transform: rotate(0deg);
|
|
113
|
+
}
|
|
114
|
+
to {
|
|
115
|
+
transform: rotate(360deg);
|
|
116
|
+
}
|
|
30
117
|
}
|
|
31
118
|
|
|
32
119
|
.btn:hover:not(:disabled),
|
|
@@ -34,13 +121,13 @@
|
|
|
34
121
|
cursor: pointer;
|
|
35
122
|
}
|
|
36
123
|
|
|
37
|
-
.btn:focus:not(:disabled),
|
|
38
|
-
.btn:focus-visible:not(:disabled) {
|
|
124
|
+
.btn:focus:not(:disabled):not(.loading),
|
|
125
|
+
.btn:focus-visible:not(:disabled):not(.loading) {
|
|
39
126
|
box-shadow: 0px 0px 0px 3px #959bff;
|
|
40
127
|
outline: none;
|
|
41
128
|
}
|
|
42
129
|
|
|
43
|
-
.btn:disabled {
|
|
130
|
+
.btn:disabled:not(.loading) {
|
|
44
131
|
background: #e0e5e8;
|
|
45
132
|
border: none;
|
|
46
133
|
color: #6b7180;
|
|
@@ -132,8 +219,8 @@
|
|
|
132
219
|
background: #fce8ea;
|
|
133
220
|
}
|
|
134
221
|
|
|
135
|
-
.btn-outline-none-primary:disabled,
|
|
136
|
-
.btn-outline-none-danger:disabled {
|
|
222
|
+
.btn-outline-none-primary:disabled:not(.loading),
|
|
223
|
+
.btn-outline-none-danger:disabled:not(.loading) {
|
|
137
224
|
background: transparent;
|
|
138
225
|
color: #6b7180;
|
|
139
226
|
}
|
|
@@ -5,6 +5,7 @@ type VariantColor = 'primary' | 'danger';
|
|
|
5
5
|
interface ButtonProps extends HTMLButtonAttributes {
|
|
6
6
|
variant?: Variant;
|
|
7
7
|
variantColor?: VariantColor;
|
|
8
|
+
loading?: boolean;
|
|
8
9
|
children: Snippet;
|
|
9
10
|
}
|
|
10
11
|
declare const Button: import("svelte").Component<ButtonProps, {}, "">;
|
package/dist/Table/Header.svelte
CHANGED
package/dist/Table/excel.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Table } from './adapter/index.js';
|
|
2
2
|
import { type ExcelSetting } from './excel-setting.js';
|
|
3
|
-
declare const exportExcel: <T>(table: Table<T>, excelSetting: ExcelSetting) => Promise<void>;
|
|
3
|
+
export declare const exportExcel: <T>(table: Table<T>, excelSetting: ExcelSetting) => Promise<void>;
|
|
4
4
|
export default exportExcel;
|
package/dist/Table/excel.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import ExcelJS from 'exceljs';
|
|
3
3
|
import saveAs from 'file-saver';
|
|
4
4
|
import { ColumnFormat } from './excel-setting.js';
|
|
5
|
-
const exportExcel = async (table, excelSetting) => {
|
|
5
|
+
export const exportExcel = async (table, excelSetting) => {
|
|
6
6
|
const workbook = new ExcelJS.Workbook();
|
|
7
7
|
const worksheet = workbook.addWorksheet('Sheet 1');
|
|
8
8
|
worksheet.columns = getColumns(table, excelSetting);
|
package/dist/Table/index.d.ts
CHANGED
|
@@ -2,5 +2,6 @@ export * from './adapter/index.js';
|
|
|
2
2
|
export * from './consts.js';
|
|
3
3
|
export * from './context.js';
|
|
4
4
|
export { ColumnFormat, type ExcelSetting } from './excel-setting.js';
|
|
5
|
+
export * from './excel.js';
|
|
5
6
|
export { default as Table } from './Table.svelte';
|
|
6
|
-
export { createActionsColumn } from './util.js';
|
|
7
|
+
export { createActionsColumn, createStaticTable } from './util.js';
|
package/dist/Table/index.js
CHANGED
|
@@ -2,5 +2,6 @@ export * from './adapter/index.js';
|
|
|
2
2
|
export * from './consts.js';
|
|
3
3
|
export * from './context.js';
|
|
4
4
|
export { ColumnFormat } from './excel-setting.js';
|
|
5
|
+
export * from './excel.js';
|
|
5
6
|
export { default as Table } from './Table.svelte';
|
|
6
|
-
export { createActionsColumn } from './util.js';
|
|
7
|
+
export { createActionsColumn, createStaticTable } from './util.js';
|
package/dist/Table/util.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type Row } from './adapter/index.js';
|
|
1
|
+
import { type ColumnDef, type Row } from './adapter/index.js';
|
|
2
2
|
import type { Action } from './types.js';
|
|
3
3
|
export declare const createCheckedColumn: <T>() => import("./adapter/index.js").DisplayColumnDef<T, unknown>;
|
|
4
4
|
export declare const createActionsColumn: <T>(getActions: (row: Row<T>) => Action[]) => import("./adapter/index.js").DisplayColumnDef<T, unknown>;
|
|
5
|
+
export declare const createStaticTable: <TData>(columns: ColumnDef<TData, any>[], data: TData[]) => import("./adapter/index.js").Table<TData>;
|
package/dist/Table/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ActionsColumn from './ActionsColumn.svelte';
|
|
2
2
|
import RowCheckBox from './RowCheckBox.svelte';
|
|
3
|
-
import { createColumnHelper, renderComponent } from './adapter/index.js';
|
|
3
|
+
import { createColumnHelper, createTable, getCoreRowModel, renderComponent } from './adapter/index.js';
|
|
4
4
|
export const createCheckedColumn = () => {
|
|
5
5
|
const columnHelper = createColumnHelper();
|
|
6
6
|
return columnHelper.display({
|
|
@@ -44,3 +44,13 @@ export const createActionsColumn = (getActions) => {
|
|
|
44
44
|
})
|
|
45
45
|
});
|
|
46
46
|
};
|
|
47
|
+
export const createStaticTable = (columns, data) => {
|
|
48
|
+
return createTable({
|
|
49
|
+
columns,
|
|
50
|
+
data,
|
|
51
|
+
getCoreRowModel: getCoreRowModel(),
|
|
52
|
+
state: {},
|
|
53
|
+
onStateChange: () => { },
|
|
54
|
+
renderFallbackValue: null
|
|
55
|
+
});
|
|
56
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@softwareone/spi-sv5-library",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.4",
|
|
4
4
|
"description": "Svelte components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|
|
@@ -50,7 +50,6 @@
|
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"@tanstack/table-core": "^8.21.3",
|
|
53
|
-
"adaptivecards": "^3.0.5",
|
|
54
53
|
"exceljs": "^4.4.0",
|
|
55
54
|
"file-saver": "^2.0.5",
|
|
56
55
|
"svelte": "^5.0.0",
|
|
@@ -64,9 +63,6 @@
|
|
|
64
63
|
"zod": {
|
|
65
64
|
"optional": true
|
|
66
65
|
},
|
|
67
|
-
"adaptivecards": {
|
|
68
|
-
"optional": true
|
|
69
|
-
},
|
|
70
66
|
"@tanstack/table-core": {
|
|
71
67
|
"optional": true
|
|
72
68
|
},
|
|
@@ -78,27 +74,26 @@
|
|
|
78
74
|
}
|
|
79
75
|
},
|
|
80
76
|
"devDependencies": {
|
|
81
|
-
"@sveltejs/adapter-auto": "^7.0.
|
|
82
|
-
"@sveltejs/adapter-node": "^5.
|
|
83
|
-
"@sveltejs/kit": "^2.
|
|
84
|
-
"@sveltejs/package": "^2.5.
|
|
85
|
-
"@sveltejs/vite-plugin-svelte": "^6.2.
|
|
77
|
+
"@sveltejs/adapter-auto": "^7.0.1",
|
|
78
|
+
"@sveltejs/adapter-node": "^5.5.3",
|
|
79
|
+
"@sveltejs/kit": "^2.53.0",
|
|
80
|
+
"@sveltejs/package": "^2.5.7",
|
|
81
|
+
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
|
86
82
|
"@tanstack/table-core": "^8.21.3",
|
|
87
83
|
"@types/file-saver": "^2.0.7",
|
|
88
|
-
"adaptivecards": "^3.0.5",
|
|
89
84
|
"exceljs": "^4.4.0",
|
|
90
85
|
"file-saver": "^2.0.5",
|
|
91
|
-
"prettier": "^3.
|
|
92
|
-
"prettier-plugin-svelte": "^3.
|
|
93
|
-
"publint": "^0.3.
|
|
94
|
-
"svelte": "^5.
|
|
95
|
-
"svelte-check": "^4.
|
|
96
|
-
"sveltekit-superforms": "^2.
|
|
86
|
+
"prettier": "^3.8.1",
|
|
87
|
+
"prettier-plugin-svelte": "^3.5.0",
|
|
88
|
+
"publint": "^0.3.17",
|
|
89
|
+
"svelte": "^5.53.3",
|
|
90
|
+
"svelte-check": "^4.4.3",
|
|
91
|
+
"sveltekit-superforms": "^2.30.0",
|
|
97
92
|
"typescript": "^5.9.3",
|
|
98
|
-
"vite": "^
|
|
99
|
-
"zod": "^4.
|
|
93
|
+
"vite": "^7.3.1",
|
|
94
|
+
"zod": "^4.3.6"
|
|
100
95
|
},
|
|
101
96
|
"dependencies": {
|
|
102
|
-
"@sveltejs/kit": "^2.
|
|
97
|
+
"@sveltejs/kit": "^2.53.0"
|
|
103
98
|
}
|
|
104
99
|
}
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount } from 'svelte';
|
|
3
|
-
|
|
4
|
-
import ChatBotFooter from './ChatBotFooter.svelte';
|
|
5
|
-
import ChatBotHeader from './ChatBotHeader.svelte';
|
|
6
|
-
import ChatBotMessages from './ChatBotMessages.svelte';
|
|
7
|
-
import {
|
|
8
|
-
type ChatBotMessage,
|
|
9
|
-
type Chat,
|
|
10
|
-
type ChatMessage,
|
|
11
|
-
type ChatSessionStart,
|
|
12
|
-
type UserMessage,
|
|
13
|
-
type ChatBotReplyMessage
|
|
14
|
-
} from './chatbotState.svelte';
|
|
15
|
-
|
|
16
|
-
interface Props {
|
|
17
|
-
sendmessage: (chat: Chat) => Promise<ChatBotReplyMessage | undefined>;
|
|
18
|
-
title?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
let { sendmessage, title = 'Chat Bot' }: Props = $props();
|
|
22
|
-
|
|
23
|
-
const CHATBOT_MESSAGES_STORAGE_KEY = 'chatbot-messages';
|
|
24
|
-
|
|
25
|
-
let isOpen = $state(false);
|
|
26
|
-
let isLoading = $state(false);
|
|
27
|
-
let messages = $state<ChatBotMessage[]>([]);
|
|
28
|
-
|
|
29
|
-
const initializeChatBot = async () => {
|
|
30
|
-
const chat: ChatSessionStart = { type: 'session_init' };
|
|
31
|
-
await handleMessage(chat);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const onsend = async (text: string) => {
|
|
35
|
-
const chat: ChatMessage = { type: 'text', text };
|
|
36
|
-
const userMessage: UserMessage = {
|
|
37
|
-
type: 'user',
|
|
38
|
-
content: text
|
|
39
|
-
};
|
|
40
|
-
setMessages(userMessage);
|
|
41
|
-
await handleMessage(chat);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const handleMessage = async (chat: Chat) => {
|
|
45
|
-
isLoading = true;
|
|
46
|
-
const chatBotReplyMessage = await sendmessage(chat);
|
|
47
|
-
if (chatBotReplyMessage) setMessages(chatBotReplyMessage);
|
|
48
|
-
isLoading = false;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const setMessages = (message: ChatBotMessage) => {
|
|
52
|
-
messages = [...messages, message];
|
|
53
|
-
storeChatMessages(messages);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const handleClose = () => {
|
|
57
|
-
toggleModal();
|
|
58
|
-
messages = [];
|
|
59
|
-
clearChatMessages();
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const toggleModal = () => {
|
|
63
|
-
isOpen = !isOpen;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
function fetchChatMessages() {
|
|
67
|
-
const storedMessages = localStorage.getItem(CHATBOT_MESSAGES_STORAGE_KEY);
|
|
68
|
-
const messages: ChatBotMessage[] = storedMessages ? JSON.parse(storedMessages) : [];
|
|
69
|
-
return messages;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const storeChatMessages = (messages: ChatBotMessage[]) => {
|
|
73
|
-
localStorage.setItem(CHATBOT_MESSAGES_STORAGE_KEY, JSON.stringify(messages));
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const clearChatMessages = () => {
|
|
77
|
-
localStorage.removeItem(CHATBOT_MESSAGES_STORAGE_KEY);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
onMount(() => {
|
|
81
|
-
messages = fetchChatMessages();
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
$effect(() => {
|
|
85
|
-
if (isOpen && messages.length === 0) {
|
|
86
|
-
initializeChatBot();
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
</script>
|
|
90
|
-
|
|
91
|
-
<div class="container">
|
|
92
|
-
{#if isOpen}
|
|
93
|
-
<div class="chatbot-container">
|
|
94
|
-
<ChatBotHeader {title} onclose={handleClose} onminimize={toggleModal} />
|
|
95
|
-
<div class="chatbot-body">
|
|
96
|
-
<ChatBotMessages {messages} {isLoading} oncardaction={handleMessage} />
|
|
97
|
-
</div>
|
|
98
|
-
<ChatBotFooter {onsend} {isLoading} />
|
|
99
|
-
</div>
|
|
100
|
-
{:else}
|
|
101
|
-
<button class="chatbot-toggle" onclick={toggleModal} aria-label="Open chat">
|
|
102
|
-
<span class="material-icons">chat_bubble_outline</span>
|
|
103
|
-
</button>
|
|
104
|
-
{/if}
|
|
105
|
-
</div>
|
|
106
|
-
|
|
107
|
-
<style>
|
|
108
|
-
.container {
|
|
109
|
-
--chatbot-primary: #472aff;
|
|
110
|
-
--chatbot-primary-hover: #3520bf;
|
|
111
|
-
--chatbot-bg: #ffffff;
|
|
112
|
-
--chatbot-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
113
|
-
--chatbot-radius: 16px;
|
|
114
|
-
--chatbot-transition: all 0.3s ease;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.chatbot-container {
|
|
118
|
-
position: fixed;
|
|
119
|
-
bottom: 24px;
|
|
120
|
-
right: 24px;
|
|
121
|
-
width: 400px;
|
|
122
|
-
height: 600px;
|
|
123
|
-
display: flex;
|
|
124
|
-
flex-direction: column;
|
|
125
|
-
border-radius: var(--chatbot-radius);
|
|
126
|
-
box-shadow: var(--chatbot-shadow);
|
|
127
|
-
background: var(--chatbot-bg);
|
|
128
|
-
animation: slideUp 0.3s ease;
|
|
129
|
-
transition: var(--chatbot-transition);
|
|
130
|
-
z-index: 1000;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.chatbot-body {
|
|
134
|
-
flex: 1;
|
|
135
|
-
overflow-y: auto;
|
|
136
|
-
padding: 10px;
|
|
137
|
-
background-color: #f9fafb;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.chatbot-toggle {
|
|
141
|
-
position: fixed;
|
|
142
|
-
bottom: 24px;
|
|
143
|
-
right: 24px;
|
|
144
|
-
width: 60px;
|
|
145
|
-
height: 60px;
|
|
146
|
-
border-radius: 50%;
|
|
147
|
-
background: var(--chatbot-primary);
|
|
148
|
-
color: var(--chatbot-bg);
|
|
149
|
-
border: none;
|
|
150
|
-
cursor: pointer;
|
|
151
|
-
display: flex;
|
|
152
|
-
align-items: center;
|
|
153
|
-
justify-content: center;
|
|
154
|
-
box-shadow: var(--chatbot-shadow);
|
|
155
|
-
transition: var(--chatbot-transition);
|
|
156
|
-
z-index: 999;
|
|
157
|
-
animation: fadeIn 0.3s ease;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.chatbot-toggle:hover {
|
|
161
|
-
background: var(--chatbot-primary-hover);
|
|
162
|
-
transform: scale(1.1);
|
|
163
|
-
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.2);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
.chatbot-toggle:active {
|
|
167
|
-
transform: scale(0.95);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
.chatbot-toggle .material-icons {
|
|
171
|
-
font-size: 28px;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
@media (max-width: 480px) {
|
|
175
|
-
.chatbot-container {
|
|
176
|
-
width: 100vw;
|
|
177
|
-
height: 100vh;
|
|
178
|
-
bottom: 0;
|
|
179
|
-
right: 0;
|
|
180
|
-
border-radius: 0;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
.chatbot-toggle {
|
|
184
|
-
bottom: 16px;
|
|
185
|
-
right: 16px;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
@keyframes slideUp {
|
|
190
|
-
from {
|
|
191
|
-
transform: translateY(20px);
|
|
192
|
-
opacity: 0;
|
|
193
|
-
}
|
|
194
|
-
to {
|
|
195
|
-
transform: translateY(0);
|
|
196
|
-
opacity: 1;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
@keyframes fadeIn {
|
|
201
|
-
from {
|
|
202
|
-
opacity: 0;
|
|
203
|
-
transform: scale(0.8);
|
|
204
|
-
}
|
|
205
|
-
to {
|
|
206
|
-
opacity: 1;
|
|
207
|
-
transform: scale(1);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
</style>
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type Chat, type ChatBotReplyMessage } from './chatbotState.svelte';
|
|
2
|
-
interface Props {
|
|
3
|
-
sendmessage: (chat: Chat) => Promise<ChatBotReplyMessage | undefined>;
|
|
4
|
-
title?: string;
|
|
5
|
-
}
|
|
6
|
-
declare const ChatBot: import("svelte").Component<Props, {}, "">;
|
|
7
|
-
type ChatBot = ReturnType<typeof ChatBot>;
|
|
8
|
-
export default ChatBot;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { Input, Button } from '../index.js';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
onsend: (text: string) => Promise<void>;
|
|
6
|
-
isLoading: boolean;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
let { onsend, isLoading }: Props = $props();
|
|
10
|
-
|
|
11
|
-
let message = $state('');
|
|
12
|
-
|
|
13
|
-
const handleSend = async () => {
|
|
14
|
-
await onsend(message);
|
|
15
|
-
message = '';
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const handleKeyPress = (event: KeyboardEvent) => {
|
|
19
|
-
if (event.key === 'Enter' && !event.shiftKey) {
|
|
20
|
-
event.preventDefault();
|
|
21
|
-
handleSend();
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
</script>
|
|
25
|
-
|
|
26
|
-
<div class="chatbot-input">
|
|
27
|
-
<div class="input">
|
|
28
|
-
<Input
|
|
29
|
-
placeholder="Type a message"
|
|
30
|
-
bind:value={message}
|
|
31
|
-
disableValidationColor
|
|
32
|
-
onkeydown={handleKeyPress}
|
|
33
|
-
/>
|
|
34
|
-
</div>
|
|
35
|
-
<Button
|
|
36
|
-
variant="primary"
|
|
37
|
-
variantColor="primary"
|
|
38
|
-
disabled={!message || isLoading}
|
|
39
|
-
onclick={handleSend}>Send</Button
|
|
40
|
-
>
|
|
41
|
-
</div>
|
|
42
|
-
|
|
43
|
-
<style>
|
|
44
|
-
.input {
|
|
45
|
-
width: 100%;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.chatbot-input {
|
|
49
|
-
display: flex;
|
|
50
|
-
gap: 10px;
|
|
51
|
-
padding: 10px 14px;
|
|
52
|
-
}
|
|
53
|
-
</style>
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
type Props = {
|
|
3
|
-
title: string;
|
|
4
|
-
onclose: VoidFunction;
|
|
5
|
-
onminimize: VoidFunction;
|
|
6
|
-
};
|
|
7
|
-
let { title, onclose, onminimize }: Props = $props();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<div class="chatbot-header">
|
|
11
|
-
<h3 class="chatbot-title">{title}</h3>
|
|
12
|
-
<div class="header-actions">
|
|
13
|
-
<button type="button" class="icon-btn" onclick={onminimize} aria-label="Minimize chat">
|
|
14
|
-
<span class="material-icons">remove</span>
|
|
15
|
-
</button>
|
|
16
|
-
<button type="button" class="icon-btn" onclick={onclose} aria-label="Close chat">
|
|
17
|
-
<span class="material-icons">close</span>
|
|
18
|
-
</button>
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
|
|
22
|
-
<style>
|
|
23
|
-
.chatbot-header {
|
|
24
|
-
display: flex;
|
|
25
|
-
align-items: center;
|
|
26
|
-
justify-content: space-between;
|
|
27
|
-
padding: 12px 16px;
|
|
28
|
-
background: #472aff;
|
|
29
|
-
color: #fff;
|
|
30
|
-
border-top-left-radius: 16px;
|
|
31
|
-
border-top-right-radius: 16px;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.chatbot-title {
|
|
35
|
-
margin: 0;
|
|
36
|
-
font-size: 15px;
|
|
37
|
-
font-weight: 600;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.header-actions {
|
|
41
|
-
display: flex;
|
|
42
|
-
gap: 4px;
|
|
43
|
-
align-items: center;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.icon-btn {
|
|
47
|
-
background: transparent;
|
|
48
|
-
border: none;
|
|
49
|
-
color: #fff;
|
|
50
|
-
cursor: pointer;
|
|
51
|
-
padding: 4px;
|
|
52
|
-
border-radius: 6px;
|
|
53
|
-
display: flex;
|
|
54
|
-
align-items: center;
|
|
55
|
-
justify-content: center;
|
|
56
|
-
transition: background-color 0.2s ease;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.icon-btn:hover {
|
|
60
|
-
background-color: rgba(255, 255, 255, 0.2);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.icon-btn .material-icons {
|
|
64
|
-
font-size: 18px;
|
|
65
|
-
}
|
|
66
|
-
</style>
|
|
@@ -1,278 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Attachment } from 'svelte/attachments';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
Action,
|
|
6
|
-
AdaptiveCard,
|
|
7
|
-
HostConfig,
|
|
8
|
-
SubmitAction,
|
|
9
|
-
type IAdaptiveCard
|
|
10
|
-
} from 'adaptivecards';
|
|
11
|
-
|
|
12
|
-
import type { Chat, ChatBotMessage } from './chatbotState.svelte';
|
|
13
|
-
|
|
14
|
-
interface Props {
|
|
15
|
-
messages: ChatBotMessage[];
|
|
16
|
-
isLoading: boolean;
|
|
17
|
-
oncardaction: (chat: Chat) => void;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
let { messages, isLoading, oncardaction }: Props = $props();
|
|
21
|
-
|
|
22
|
-
const renderAdaptiveCard = (content: IAdaptiveCard): Attachment<HTMLElement> => {
|
|
23
|
-
return (element) => {
|
|
24
|
-
const adaptiveCard = new AdaptiveCard();
|
|
25
|
-
|
|
26
|
-
adaptiveCard.hostConfig = createHostConfig();
|
|
27
|
-
adaptiveCard.onExecuteAction = handleActionExecution;
|
|
28
|
-
adaptiveCard.parse(content);
|
|
29
|
-
|
|
30
|
-
const rendered = adaptiveCard.render();
|
|
31
|
-
if (rendered) {
|
|
32
|
-
rendered.classList.add('adaptive-card');
|
|
33
|
-
element.appendChild(rendered);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const createHostConfig = () => {
|
|
39
|
-
return new HostConfig({
|
|
40
|
-
fontFamily: 'Poppins, sans-serif'
|
|
41
|
-
});
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const handleActionExecution = (action: Action) => {
|
|
45
|
-
if (action instanceof SubmitAction) {
|
|
46
|
-
const chat = action.data as Chat;
|
|
47
|
-
oncardaction(chat);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const scrollIntoView: Attachment<HTMLDivElement> = (element: HTMLDivElement) => {
|
|
52
|
-
isLoading;
|
|
53
|
-
messages.length;
|
|
54
|
-
element.scrollIntoView({ behavior: 'smooth', block: 'end' });
|
|
55
|
-
};
|
|
56
|
-
</script>
|
|
57
|
-
|
|
58
|
-
<div {@attach scrollIntoView} class="messages">
|
|
59
|
-
{#each messages as message}
|
|
60
|
-
{@const isBot = message.type === 'bot'}
|
|
61
|
-
{@const isUser = message.type === 'user'}
|
|
62
|
-
|
|
63
|
-
<div class={['message', isBot && 'bot', isUser && 'user']}>
|
|
64
|
-
{#if isBot && typeof message.content !== 'string'}
|
|
65
|
-
<div {@attach renderAdaptiveCard(message.content)}></div>
|
|
66
|
-
{:else}
|
|
67
|
-
<p class="message-text">{message.content}</p>
|
|
68
|
-
{/if}
|
|
69
|
-
</div>
|
|
70
|
-
{/each}
|
|
71
|
-
|
|
72
|
-
{#if isLoading}
|
|
73
|
-
<div class="loading">
|
|
74
|
-
{#each Array(3) as _}
|
|
75
|
-
<span class="loading-dot"></span>
|
|
76
|
-
{/each}
|
|
77
|
-
</div>
|
|
78
|
-
{/if}
|
|
79
|
-
</div>
|
|
80
|
-
|
|
81
|
-
<style>
|
|
82
|
-
.messages {
|
|
83
|
-
--color-bg-messages: #f9fafb;
|
|
84
|
-
--color-bg-bot: #f8f8ff;
|
|
85
|
-
--color-bg-user: #472aff;
|
|
86
|
-
--color-text-primary: #1a1a1a;
|
|
87
|
-
--color-text-inverse: #ffffff;
|
|
88
|
-
--color-border-bot: #543bfa;
|
|
89
|
-
--color-scrollbar: #b5b6ff;
|
|
90
|
-
--color-scrollbar-hover: #8a8bff;
|
|
91
|
-
--color-button-primary: #472aff;
|
|
92
|
-
--color-button-hover: #3520bf;
|
|
93
|
-
--color-button-active: #2a1894;
|
|
94
|
-
--radius-sm: 8px;
|
|
95
|
-
--radius-md: 12px;
|
|
96
|
-
--spacing-xs: 6px;
|
|
97
|
-
--spacing-sm: 10px;
|
|
98
|
-
--spacing-md: 14px;
|
|
99
|
-
--spacing-lg: 16px;
|
|
100
|
-
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.06);
|
|
101
|
-
--shadow-md: 0 2px 10px rgba(0, 0, 0, 0.06);
|
|
102
|
-
--shadow-hover: 0 4px 10px rgba(0, 0, 0, 0.08);
|
|
103
|
-
|
|
104
|
-
padding: var(--spacing-lg);
|
|
105
|
-
display: flex;
|
|
106
|
-
flex-direction: column;
|
|
107
|
-
gap: var(--spacing-md);
|
|
108
|
-
background: var(--color-bg-messages);
|
|
109
|
-
border-radius: var(--radius-md);
|
|
110
|
-
box-shadow: var(--shadow-md);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.message {
|
|
114
|
-
padding: var(--spacing-md);
|
|
115
|
-
border-radius: var(--radius-md);
|
|
116
|
-
max-width: 95%;
|
|
117
|
-
word-break: break-word;
|
|
118
|
-
overflow-wrap: break-word;
|
|
119
|
-
line-height: 1.5;
|
|
120
|
-
animation: fadeIn 0.35s ease forwards;
|
|
121
|
-
transition: all 0.25s ease;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.message.user {
|
|
125
|
-
align-self: flex-end;
|
|
126
|
-
background-color: var(--color-bg-user);
|
|
127
|
-
color: var(--color-text-inverse);
|
|
128
|
-
border-radius: var(--radius-md) var(--radius-md) 0 var(--radius-md);
|
|
129
|
-
max-width: 80%;
|
|
130
|
-
box-shadow: var(--shadow-sm);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.message.bot {
|
|
134
|
-
align-self: flex-start;
|
|
135
|
-
background-color: var(--color-bg-bot);
|
|
136
|
-
color: var(--color-text-primary);
|
|
137
|
-
border-radius: var(--radius-md) var(--radius-md) var(--radius-md) 0;
|
|
138
|
-
box-shadow: var(--shadow-sm);
|
|
139
|
-
border-left: 4px solid var(--color-border-bot);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.message-text {
|
|
143
|
-
margin: 0;
|
|
144
|
-
line-height: 1.4;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.loading {
|
|
148
|
-
display: flex;
|
|
149
|
-
gap: var(--spacing-xs);
|
|
150
|
-
padding: var(--spacing-sm);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.loading-dot {
|
|
154
|
-
width: 8px;
|
|
155
|
-
height: 8px;
|
|
156
|
-
border-radius: 50%;
|
|
157
|
-
background-color: var(--color-border-bot);
|
|
158
|
-
animation: bounce 1.4s infinite ease-in-out both;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.loading-dot:nth-child(1) {
|
|
162
|
-
animation-delay: -0.32s;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.loading-dot:nth-child(2) {
|
|
166
|
-
animation-delay: -0.16s;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
:global(.adaptive-card),
|
|
170
|
-
:global(.adaptive-card .ac-container),
|
|
171
|
-
:global(.adaptive-card .ac-columnSet),
|
|
172
|
-
:global(.adaptive-card .ac-column),
|
|
173
|
-
:global(.adaptive-card .ac-actionSet) {
|
|
174
|
-
width: 100%;
|
|
175
|
-
max-width: 100%;
|
|
176
|
-
margin: 0;
|
|
177
|
-
padding: 0;
|
|
178
|
-
box-sizing: border-box;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
:global(.adaptive-card .ac-textBlock) {
|
|
182
|
-
margin-bottom: var(--spacing-xs);
|
|
183
|
-
line-height: 1.5;
|
|
184
|
-
word-break: break-word;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
:global(.adaptive-card .ac-pushButton),
|
|
188
|
-
:global(.adaptive-card button),
|
|
189
|
-
:global(.adaptive-card .ac-actionSet .ac-button) {
|
|
190
|
-
all: unset;
|
|
191
|
-
box-sizing: border-box;
|
|
192
|
-
display: inline-block;
|
|
193
|
-
text-align: center;
|
|
194
|
-
padding: 12px 16px;
|
|
195
|
-
border-radius: var(--radius-sm);
|
|
196
|
-
width: 100%;
|
|
197
|
-
cursor: pointer;
|
|
198
|
-
background: var(--color-button-primary);
|
|
199
|
-
color: var(--color-text-inverse);
|
|
200
|
-
font-size: 14px;
|
|
201
|
-
font-weight: 400;
|
|
202
|
-
line-height: 1.4;
|
|
203
|
-
min-height: 44px;
|
|
204
|
-
box-shadow: var(--shadow-sm);
|
|
205
|
-
transition:
|
|
206
|
-
transform 0.2s ease,
|
|
207
|
-
box-shadow 0.2s ease,
|
|
208
|
-
background-color 0.2s ease;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
:global(.adaptive-card .ac-pushButton:hover),
|
|
212
|
-
:global(.adaptive-card button:hover),
|
|
213
|
-
:global(.adaptive-card .ac-button:hover) {
|
|
214
|
-
background: var(--color-button-hover);
|
|
215
|
-
transform: translateY(-1px);
|
|
216
|
-
box-shadow: var(--shadow-hover);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
:global(.adaptive-card .ac-pushButton:active),
|
|
220
|
-
:global(.adaptive-card button:active),
|
|
221
|
-
:global(.adaptive-card .ac-button:active) {
|
|
222
|
-
background: var(--color-button-active);
|
|
223
|
-
transform: translateY(0);
|
|
224
|
-
box-shadow: none;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
:global(.adaptive-card .ac-actionSet) {
|
|
228
|
-
display: flex;
|
|
229
|
-
flex-wrap: wrap;
|
|
230
|
-
justify-content: center;
|
|
231
|
-
gap: var(--spacing-sm);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
:global(.adaptive-card .ac-actionSet .ac-pushButton),
|
|
235
|
-
:global(.adaptive-card .ac-actionSet button),
|
|
236
|
-
:global(.adaptive-card .ac-actionSet .ac-button) {
|
|
237
|
-
max-width: 280px;
|
|
238
|
-
text-align: center;
|
|
239
|
-
margin: 0 auto;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
:global(.adaptive-card .ac-actionSet.faq-buttons .ac-pushButton),
|
|
243
|
-
:global(.adaptive-card .ac-actionSet.faq-buttons button),
|
|
244
|
-
:global(.adaptive-card .ac-actionSet.faq-buttons .ac-button) {
|
|
245
|
-
width: 100%;
|
|
246
|
-
max-width: 100%;
|
|
247
|
-
text-align: left;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
@media (min-width: 640px) {
|
|
251
|
-
:global(.adaptive-card .ac-actionSet) {
|
|
252
|
-
flex-direction: column;
|
|
253
|
-
align-items: stretch;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
@keyframes fadeIn {
|
|
258
|
-
from {
|
|
259
|
-
opacity: 0;
|
|
260
|
-
transform: translateY(10px);
|
|
261
|
-
}
|
|
262
|
-
to {
|
|
263
|
-
opacity: 1;
|
|
264
|
-
transform: translateY(0);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
@keyframes bounce {
|
|
269
|
-
0%,
|
|
270
|
-
80%,
|
|
271
|
-
100% {
|
|
272
|
-
transform: scale(0);
|
|
273
|
-
}
|
|
274
|
-
40% {
|
|
275
|
-
transform: scale(1);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
</style>
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Chat, ChatBotMessage } from './chatbotState.svelte';
|
|
2
|
-
interface Props {
|
|
3
|
-
messages: ChatBotMessage[];
|
|
4
|
-
isLoading: boolean;
|
|
5
|
-
oncardaction: (chat: Chat) => void;
|
|
6
|
-
}
|
|
7
|
-
declare const ChatBotMessages: import("svelte").Component<Props, {}, "">;
|
|
8
|
-
type ChatBotMessages = ReturnType<typeof ChatBotMessages>;
|
|
9
|
-
export default ChatBotMessages;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { IAdaptiveCard } from 'adaptivecards';
|
|
2
|
-
export interface UserMessage {
|
|
3
|
-
type: 'user';
|
|
4
|
-
content: string;
|
|
5
|
-
}
|
|
6
|
-
export interface ChatBotReplyMessage {
|
|
7
|
-
type: 'bot';
|
|
8
|
-
content: IAdaptiveCard | string;
|
|
9
|
-
}
|
|
10
|
-
export type ChatBotMessage = UserMessage | ChatBotReplyMessage;
|
|
11
|
-
export interface ChatModuleSelector {
|
|
12
|
-
type: 'module_select';
|
|
13
|
-
module: string;
|
|
14
|
-
}
|
|
15
|
-
export interface ChatFAQSelector {
|
|
16
|
-
type: 'faq_select';
|
|
17
|
-
module: string;
|
|
18
|
-
question: string;
|
|
19
|
-
}
|
|
20
|
-
export interface ChatMessage {
|
|
21
|
-
type: 'text';
|
|
22
|
-
text: string;
|
|
23
|
-
}
|
|
24
|
-
export interface ChatSessionStart {
|
|
25
|
-
type: 'session_init';
|
|
26
|
-
}
|
|
27
|
-
export type Chat = ChatModuleSelector | ChatFAQSelector | ChatSessionStart | ChatMessage;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|