@n8n/chat 0.1.5 → 0.3.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.
Files changed (98) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +52 -0
  3. package/.np-config.json +5 -0
  4. package/.storybook/main.ts +27 -0
  5. package/.storybook/preview.scss +4 -0
  6. package/.storybook/preview.ts +16 -0
  7. package/.vscode/extensions.json +3 -0
  8. package/env.d.ts +1 -0
  9. package/index.html +13 -0
  10. package/package.json +2 -59
  11. package/resources/workflow.json +293 -0
  12. package/scripts/pack.js +11 -0
  13. package/scripts/postbuild.js +16 -0
  14. package/src/App.vue +23 -0
  15. package/src/__stories__/App.stories.ts +43 -0
  16. package/src/__tests__/index.spec.ts +223 -0
  17. package/src/__tests__/setup.ts +1 -0
  18. package/src/__tests__/utils/create.ts +16 -0
  19. package/src/__tests__/utils/fetch.ts +18 -0
  20. package/src/__tests__/utils/index.ts +3 -0
  21. package/src/__tests__/utils/selectors.ts +53 -0
  22. package/src/api/generic.ts +64 -0
  23. package/src/api/message.ts +31 -0
  24. package/src/components/Button.vue +41 -0
  25. package/src/components/Chat.vue +48 -0
  26. package/src/components/ChatWindow.vue +125 -0
  27. package/src/components/GetStarted.vue +24 -0
  28. package/src/components/GetStartedFooter.vue +20 -0
  29. package/src/components/Input.vue +93 -0
  30. package/src/components/Layout.vue +82 -0
  31. package/src/components/Message.vue +97 -0
  32. package/src/components/MessageTyping.vue +109 -0
  33. package/src/components/MessagesList.vue +37 -0
  34. package/src/components/PoweredBy.vue +17 -0
  35. package/src/composables/useChat.ts +7 -0
  36. package/src/composables/useI18n.ts +16 -0
  37. package/src/composables/useOptions.ts +11 -0
  38. package/src/constants/defaults.ts +25 -0
  39. package/src/constants/localStorage.ts +2 -0
  40. package/src/constants/symbols.ts +8 -0
  41. package/src/event-buses/chatEventBus.ts +3 -0
  42. package/src/index.ts +42 -0
  43. package/src/main.scss +40 -0
  44. package/src/plugins/chat.ts +101 -0
  45. package/src/shims.d.ts +6 -0
  46. package/src/types/chat.ts +12 -0
  47. package/src/types/messages.ts +6 -0
  48. package/src/types/options.ts +23 -0
  49. package/src/types/webhook.ts +17 -0
  50. package/src/utils/event-bus.ts +51 -0
  51. package/src/utils/mount.ts +16 -0
  52. package/tsconfig.json +27 -0
  53. package/vite.config.ts +51 -0
  54. package/vitest.config.ts +20 -0
  55. package/chat.bundle.es.js +0 -10773
  56. package/chat.bundle.umd.js +0 -18
  57. package/chat.es.js +0 -6869
  58. package/chat.umd.js +0 -18
  59. package/style.css +0 -1
  60. package/types/App.vue.d.ts +0 -8
  61. package/types/__stories__/App.stories.d.ts +0 -17
  62. package/types/api/generic.d.ts +0 -6
  63. package/types/api/message.d.ts +0 -3
  64. package/types/components/Button.vue.d.ts +0 -9
  65. package/types/components/Chat.vue.d.ts +0 -2
  66. package/types/components/ChatWindow.vue.d.ts +0 -2
  67. package/types/components/GetStarted.vue.d.ts +0 -2
  68. package/types/components/GetStartedFooter.vue.d.ts +0 -2
  69. package/types/components/Input.vue.d.ts +0 -2
  70. package/types/components/Layout.vue.d.ts +0 -11
  71. package/types/components/Message.vue.d.ts +0 -21
  72. package/types/components/MessageTyping.vue.d.ts +0 -15
  73. package/types/components/MessagesList.vue.d.ts +0 -14
  74. package/types/components/PoweredBy.vue.d.ts +0 -2
  75. package/types/composables/useChat.d.ts +0 -2
  76. package/types/composables/useI18n.d.ts +0 -4
  77. package/types/composables/useOptions.d.ts +0 -4
  78. package/types/constants/defaults.d.ts +0 -3
  79. package/types/constants/localStorage.d.ts +0 -2
  80. package/types/constants/symbols.d.ts +0 -4
  81. package/types/event-buses/chatEventBus.d.ts +0 -1
  82. package/types/index.d.ts +0 -2
  83. package/types/plugins/chat.d.ts +0 -3
  84. package/types/types/chat.d.ts +0 -11
  85. package/types/types/messages.d.ts +0 -6
  86. package/types/types/options.d.ts +0 -20
  87. package/types/types/webhook.d.ts +0 -15
  88. package/types/utils/event-bus.d.ts +0 -8
  89. package/types/utils/mount.d.ts +0 -1
  90. /package/{favicon.ico → public/favicon.ico} +0 -0
  91. /package/{types/api/index.d.ts → src/api/index.ts} +0 -0
  92. /package/{types/components/index.d.ts → src/components/index.ts} +0 -0
  93. /package/{types/composables/index.d.ts → src/composables/index.ts} +0 -0
  94. /package/{types/constants/index.d.ts → src/constants/index.ts} +0 -0
  95. /package/{types/event-buses/index.d.ts → src/event-buses/index.ts} +0 -0
  96. /package/{types/plugins/index.d.ts → src/plugins/index.ts} +0 -0
  97. /package/{types/types/index.d.ts → src/types/index.ts} +0 -0
  98. /package/{types/utils/index.d.ts → src/utils/index.ts} +0 -0
@@ -0,0 +1,93 @@
1
+ <script setup lang="ts">
2
+ // eslint-disable-next-line import/no-unresolved
3
+ import IconSend from 'virtual:icons/mdi/send';
4
+ import { useI18n, useChat } from '@/composables';
5
+ import { computed, ref } from 'vue';
6
+
7
+ const chatStore = useChat();
8
+ const { waitingForResponse } = chatStore;
9
+ const { t } = useI18n();
10
+
11
+ const input = ref('');
12
+
13
+ const isSubmitDisabled = computed(() => {
14
+ return input.value === '' || waitingForResponse.value;
15
+ });
16
+
17
+ async function onSubmit(event: MouseEvent | KeyboardEvent) {
18
+ event.preventDefault();
19
+
20
+ if (isSubmitDisabled.value) {
21
+ return;
22
+ }
23
+
24
+ const messageText = input.value;
25
+ input.value = '';
26
+ await chatStore.sendMessage(messageText);
27
+ }
28
+
29
+ async function onSubmitKeydown(event: KeyboardEvent) {
30
+ if (event.shiftKey) {
31
+ return;
32
+ }
33
+
34
+ await onSubmit(event);
35
+ }
36
+ </script>
37
+
38
+ <template>
39
+ <div class="chat-input">
40
+ <textarea
41
+ v-model="input"
42
+ rows="1"
43
+ :placeholder="t('inputPlaceholder')"
44
+ @keydown.enter="onSubmitKeydown"
45
+ />
46
+ <button :disabled="isSubmitDisabled" class="chat-input-send-button" @click="onSubmit">
47
+ <IconSend height="32" width="32" />
48
+ </button>
49
+ </div>
50
+ </template>
51
+
52
+ <style lang="scss">
53
+ .chat-input {
54
+ display: flex;
55
+ justify-content: center;
56
+ align-items: center;
57
+ width: 100%;
58
+
59
+ textarea {
60
+ font-family: inherit;
61
+ font-size: inherit;
62
+ width: 100%;
63
+ border: 0;
64
+ padding: var(--chat--spacing);
65
+ max-height: var(--chat--textarea--height);
66
+ resize: none;
67
+ }
68
+
69
+ .chat-input-send-button {
70
+ height: var(--chat--textarea--height);
71
+ width: var(--chat--textarea--height);
72
+ background: white;
73
+ cursor: pointer;
74
+ color: var(--chat--color-secondary);
75
+ border: 0;
76
+ font-size: 24px;
77
+ display: inline-flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ transition: color var(--chat--transition-duration) ease;
81
+
82
+ &:hover,
83
+ &:focus {
84
+ color: var(--chat--color-secondary-shade-50);
85
+ }
86
+
87
+ &[disabled] {
88
+ cursor: default;
89
+ color: var(--chat--color-disabled);
90
+ }
91
+ }
92
+ }
93
+ </style>
@@ -0,0 +1,82 @@
1
+ <script setup lang="ts">
2
+ import { onBeforeUnmount, onMounted, ref } from 'vue';
3
+ import { chatEventBus } from '@/event-buses';
4
+
5
+ const chatBodyRef = ref<HTMLElement | null>(null);
6
+
7
+ function scrollToBottom() {
8
+ const element = chatBodyRef.value as HTMLElement;
9
+ if (element) {
10
+ element.scrollTop = element.scrollHeight;
11
+ }
12
+ }
13
+
14
+ onMounted(() => {
15
+ chatEventBus.on('scrollToBottom', scrollToBottom);
16
+ window.addEventListener('resize', scrollToBottom);
17
+ });
18
+
19
+ onBeforeUnmount(() => {
20
+ chatEventBus.off('scrollToBottom', scrollToBottom);
21
+ window.removeEventListener('resize', scrollToBottom);
22
+ });
23
+ </script>
24
+ <template>
25
+ <main class="chat-layout">
26
+ <div v-if="$slots.header" class="chat-header">
27
+ <slot name="header" />
28
+ </div>
29
+ <div v-if="$slots.default" class="chat-body" ref="chatBodyRef">
30
+ <slot />
31
+ </div>
32
+ <div v-if="$slots.footer" class="chat-footer">
33
+ <slot name="footer" />
34
+ </div>
35
+ </main>
36
+ </template>
37
+
38
+ <style lang="scss">
39
+ .chat-layout {
40
+ width: 100%;
41
+ height: 100%;
42
+ display: flex;
43
+ overflow-y: auto;
44
+ flex-direction: column;
45
+ font-family: var(
46
+ --chat--font-family,
47
+ (
48
+ -apple-system,
49
+ BlinkMacSystemFont,
50
+ 'Segoe UI',
51
+ Roboto,
52
+ Oxygen-Sans,
53
+ Ubuntu,
54
+ Cantarell,
55
+ 'Helvetica Neue',
56
+ sans-serif
57
+ )
58
+ );
59
+
60
+ .chat-header {
61
+ padding: var(--chat--header--padding, var(--chat--spacing));
62
+ background: var(--chat--header--background, var(--chat--color-dark));
63
+ color: var(--chat--header--color, var(--chat--color-light));
64
+ }
65
+
66
+ .chat-body {
67
+ background: var(--chat--body--background, var(--chat--color-light));
68
+ flex: 1;
69
+ display: flex;
70
+ flex-direction: column;
71
+ overflow-y: auto;
72
+ position: relative;
73
+ min-height: 100px;
74
+ }
75
+
76
+ .chat-footer {
77
+ border-top: 1px solid var(--chat--color-light-shade-100);
78
+ background: var(--chat--footer--background, var(--chat--color-light));
79
+ color: var(--chat--footer--color, var(--chat--color-dark));
80
+ }
81
+ }
82
+ </style>
@@ -0,0 +1,97 @@
1
+ <script lang="ts" setup>
2
+ /* eslint-disable @typescript-eslint/naming-convention */
3
+ import type { ChatMessage } from '@/types';
4
+ import type { PropType } from 'vue';
5
+ import { computed, toRefs } from 'vue';
6
+ import VueMarkdown from 'vue-markdown-render';
7
+ import hljs from 'highlight.js/lib/core';
8
+
9
+ const props = defineProps({
10
+ message: {
11
+ type: Object as PropType<ChatMessage>,
12
+ required: true,
13
+ },
14
+ });
15
+
16
+ const { message } = toRefs(props);
17
+
18
+ const classes = computed(() => {
19
+ return {
20
+ 'chat-message-from-user': message.value.sender === 'user',
21
+ 'chat-message-from-bot': message.value.sender === 'bot',
22
+ };
23
+ });
24
+
25
+ const markdownOptions = {
26
+ highlight(str: string, lang: string) {
27
+ if (lang && hljs.getLanguage(lang)) {
28
+ try {
29
+ return hljs.highlight(str, { language: lang }).value;
30
+ } catch {}
31
+ }
32
+
33
+ return ''; // use external default escaping
34
+ },
35
+ };
36
+ </script>
37
+ <template>
38
+ <div class="chat-message" :class="classes">
39
+ <slot>
40
+ <vue-markdown
41
+ class="chat-message-markdown"
42
+ :source="message.text"
43
+ :options="markdownOptions"
44
+ />
45
+ </slot>
46
+ </div>
47
+ </template>
48
+
49
+ <style lang="scss">
50
+ .chat-message {
51
+ display: block;
52
+ max-width: 80%;
53
+ padding: var(--chat--message--padding, var(--chat--spacing));
54
+ border-radius: var(--chat--message--border-radius, var(--chat--border-radius));
55
+
56
+ + .chat-message {
57
+ margin-top: var(--chat--message--margin-bottom, calc(var(--chat--spacing) * 0.5));
58
+ }
59
+
60
+ &.chat-message-from-bot {
61
+ background-color: var(--chat--message--bot--background);
62
+ color: var(--chat--message--bot--color);
63
+ border-bottom-left-radius: 0;
64
+ }
65
+
66
+ &.chat-message-from-user {
67
+ background-color: var(--chat--message--user--background);
68
+ color: var(--chat--message--user--color);
69
+ margin-left: auto;
70
+ border-bottom-right-radius: 0;
71
+ }
72
+
73
+ > .chat-message-markdown {
74
+ display: block;
75
+ box-sizing: border-box;
76
+
77
+ > *:first-child {
78
+ margin-top: 0;
79
+ }
80
+
81
+ > *:last-child {
82
+ margin-bottom: 0;
83
+ }
84
+
85
+ pre {
86
+ font-family: inherit;
87
+ font-size: inherit;
88
+ margin: 0;
89
+ white-space: pre-wrap;
90
+ box-sizing: border-box;
91
+ padding: var(--chat--spacing);
92
+ background: var(--chat--message--pre--background);
93
+ border-radius: var(--chat--border-radius);
94
+ }
95
+ }
96
+ }
97
+ </style>
@@ -0,0 +1,109 @@
1
+ <script lang="ts" setup>
2
+ import type { ChatMessage } from '@/types';
3
+ import { Message } from './index';
4
+ import type { PropType } from 'vue';
5
+ import { computed } from 'vue';
6
+
7
+ const props = defineProps({
8
+ animation: {
9
+ type: String as PropType<'bouncing' | 'scaling'>,
10
+ default: 'bouncing',
11
+ },
12
+ });
13
+
14
+ const message: ChatMessage = {
15
+ id: 'typing',
16
+ text: '',
17
+ sender: 'bot',
18
+ createdAt: '',
19
+ };
20
+
21
+ const classes = computed(() => {
22
+ return {
23
+ // eslint-disable-next-line @typescript-eslint/naming-convention
24
+ 'chat-message-typing': true,
25
+ [`chat-message-typing-animation-${props.animation}`]: true,
26
+ };
27
+ });
28
+ </script>
29
+ <template>
30
+ <Message :class="classes" :message="message">
31
+ <div class="chat-message-typing-body">
32
+ <span class="chat-message-typing-circle"></span>
33
+ <span class="chat-message-typing-circle"></span>
34
+ <span class="chat-message-typing-circle"></span>
35
+ </div>
36
+ </Message>
37
+ </template>
38
+ <style lang="scss">
39
+ .chat-message-typing {
40
+ max-width: 80px;
41
+
42
+ &.chat-message-typing-animation-scaling .chat-message-typing-circle {
43
+ animation: chat-message-typing-animation-scaling 800ms ease-in-out infinite;
44
+ animation-delay: 3600ms;
45
+ }
46
+
47
+ &.chat-message-typing-animation-bouncing .chat-message-typing-circle {
48
+ animation: chat-message-typing-animation-bouncing 800ms ease-in-out infinite;
49
+ animation-delay: 3600ms;
50
+ }
51
+
52
+ .chat-message-typing-body {
53
+ display: flex;
54
+ justify-content: center;
55
+ align-items: center;
56
+ }
57
+
58
+ .chat-message-typing-circle {
59
+ display: block;
60
+ height: 10px;
61
+ width: 10px;
62
+ border-radius: 50%;
63
+ background-color: var(--chat--color-typing);
64
+ margin: 3px;
65
+
66
+ &:nth-child(1) {
67
+ animation-delay: 0ms;
68
+ }
69
+
70
+ &:nth-child(2) {
71
+ animation-delay: 333ms;
72
+ }
73
+
74
+ &:nth-child(3) {
75
+ animation-delay: 666ms;
76
+ }
77
+ }
78
+ }
79
+
80
+ @keyframes chat-message-typing-animation-scaling {
81
+ 0% {
82
+ transform: scale(1);
83
+ }
84
+ 33% {
85
+ transform: scale(1);
86
+ }
87
+ 50% {
88
+ transform: scale(1.4);
89
+ }
90
+ 100% {
91
+ transform: scale(1);
92
+ }
93
+ }
94
+
95
+ @keyframes chat-message-typing-animation-bouncing {
96
+ 0% {
97
+ transform: translateY(0);
98
+ }
99
+ 33% {
100
+ transform: translateY(0);
101
+ }
102
+ 50% {
103
+ transform: translateY(-10px);
104
+ }
105
+ 100% {
106
+ transform: translateY(0);
107
+ }
108
+ }
109
+ </style>
@@ -0,0 +1,37 @@
1
+ <script lang="ts" setup>
2
+ import type { PropType } from 'vue';
3
+ import Message from '@/components/Message.vue';
4
+ import type { ChatMessage } from '@/types';
5
+ import MessageTyping from '@/components/MessageTyping.vue';
6
+ import { useChat } from '@/composables';
7
+
8
+ defineProps({
9
+ messages: {
10
+ type: Array as PropType<ChatMessage[]>,
11
+ required: true,
12
+ },
13
+ });
14
+
15
+ const chatStore = useChat();
16
+
17
+ const { initialMessages, waitingForResponse } = chatStore;
18
+ </script>
19
+ <template>
20
+ <div class="chat-messages-list">
21
+ <Message
22
+ v-for="initialMessage in initialMessages"
23
+ :key="initialMessage.id"
24
+ :message="initialMessage"
25
+ />
26
+ <Message v-for="message in messages" :key="message.id" :message="message" />
27
+ <MessageTyping v-if="waitingForResponse" />
28
+ </div>
29
+ </template>
30
+
31
+ <style lang="scss">
32
+ .chat-messages-list {
33
+ margin-top: auto;
34
+ display: block;
35
+ padding: var(--chat--messages-list--padding, var(--chat--spacing));
36
+ }
37
+ </style>
@@ -0,0 +1,17 @@
1
+ <template>
2
+ <div class="chat-powered-by">
3
+ Powered by
4
+ <a href="https://n8n.io?utm_source=n8n-external&utm_medium=widget-powered-by">n8n</a>
5
+ </div>
6
+ </template>
7
+
8
+ <style lang="scss">
9
+ .chat-powered-by {
10
+ text-align: center;
11
+
12
+ a {
13
+ color: var(--chat--color-primary);
14
+ text-decoration: none;
15
+ }
16
+ }
17
+ </style>
@@ -0,0 +1,7 @@
1
+ import { inject } from 'vue';
2
+ import { ChatSymbol } from '@/constants';
3
+ import type { Chat } from '@/types';
4
+
5
+ export function useChat() {
6
+ return inject(ChatSymbol) as Chat;
7
+ }
@@ -0,0 +1,16 @@
1
+ import { useOptions } from '@/composables/useOptions';
2
+
3
+ export function useI18n() {
4
+ const { options } = useOptions();
5
+ const language = options?.defaultLanguage ?? 'en';
6
+
7
+ function t(key: string): string {
8
+ return options?.i18n?.[language]?.[key] ?? key;
9
+ }
10
+
11
+ function te(key: string): boolean {
12
+ return !!options?.i18n?.[language]?.[key];
13
+ }
14
+
15
+ return { t, te };
16
+ }
@@ -0,0 +1,11 @@
1
+ import { inject } from 'vue';
2
+ import { ChatOptionsSymbol } from '@/constants';
3
+ import type { ChatOptions } from '@/types';
4
+
5
+ export function useOptions() {
6
+ const options = inject(ChatOptionsSymbol) as ChatOptions;
7
+
8
+ return {
9
+ options,
10
+ };
11
+ }
@@ -0,0 +1,25 @@
1
+ import type { ChatOptions } from '@/types';
2
+
3
+ export const defaultOptions: ChatOptions = {
4
+ webhookUrl: 'http://localhost:5678',
5
+ webhookConfig: {
6
+ method: 'POST',
7
+ headers: {},
8
+ },
9
+ target: '#n8n-chat',
10
+ mode: 'window',
11
+ defaultLanguage: 'en',
12
+ initialMessages: ['Hi there! 👋', 'My name is Nathan. How can I assist you today?'],
13
+ i18n: {
14
+ en: {
15
+ title: 'Hi there! 👋',
16
+ subtitle: "Start a chat. We're here to help you 24/7.",
17
+ footer: '',
18
+ getStarted: 'New Conversation',
19
+ inputPlaceholder: 'Type your question..',
20
+ },
21
+ },
22
+ theme: {},
23
+ };
24
+
25
+ export const defaultMountingTarget = '#n8n-chat';
@@ -0,0 +1,2 @@
1
+ export const localStorageNamespace = 'n8n-chat';
2
+ export const localStorageSessionIdKey = `${localStorageNamespace}/sessionId`;
@@ -0,0 +1,8 @@
1
+ import type { InjectionKey } from 'vue';
2
+ import type { Chat, ChatOptions } from '@/types';
3
+
4
+ // eslint-disable-next-line @typescript-eslint/naming-convention
5
+ export const ChatSymbol = 'Chat' as unknown as InjectionKey<Chat>;
6
+
7
+ // eslint-disable-next-line @typescript-eslint/naming-convention
8
+ export const ChatOptionsSymbol = 'ChatOptions' as unknown as InjectionKey<ChatOptions>;
@@ -0,0 +1,3 @@
1
+ import { createEventBus } from '@/utils';
2
+
3
+ export const chatEventBus = createEventBus();
package/src/index.ts ADDED
@@ -0,0 +1,42 @@
1
+ import './main.scss';
2
+
3
+ import { createApp } from 'vue';
4
+ import App from './App.vue';
5
+ import type { ChatOptions } from '@/types';
6
+ import { defaultMountingTarget, defaultOptions } from '@/constants';
7
+ import { createDefaultMountingTarget } from '@/utils';
8
+ import { ChatPlugin } from '@/plugins';
9
+
10
+ export function createChat(options?: Partial<ChatOptions>) {
11
+ const resolvedOptions: ChatOptions = {
12
+ ...defaultOptions,
13
+ ...options,
14
+ webhookConfig: {
15
+ ...defaultOptions.webhookConfig,
16
+ ...options?.webhookConfig,
17
+ },
18
+ i18n: {
19
+ ...defaultOptions.i18n,
20
+ ...options?.i18n,
21
+ en: {
22
+ ...defaultOptions.i18n?.en,
23
+ ...options?.i18n?.en,
24
+ },
25
+ },
26
+ theme: {
27
+ ...defaultOptions.theme,
28
+ ...options?.theme,
29
+ },
30
+ };
31
+
32
+ const mountingTarget = resolvedOptions.target ?? defaultMountingTarget;
33
+ if (typeof mountingTarget === 'string') {
34
+ createDefaultMountingTarget(mountingTarget);
35
+ }
36
+
37
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
38
+ const app = createApp(App);
39
+ app.use(ChatPlugin, resolvedOptions);
40
+ app.mount(mountingTarget);
41
+ return app;
42
+ }
package/src/main.scss ADDED
@@ -0,0 +1,40 @@
1
+ .n8n-chat {
2
+ @import 'highlight.js/styles/github';
3
+ }
4
+
5
+ :root {
6
+ --chat--color-primary: #e74266;
7
+ --chat--color-primary-shade-50: #db4061;
8
+ --chat--color-primary-shade-100: #cf3c5c;
9
+ --chat--color-secondary: #20b69e;
10
+ --chat--color-secondary-shade-50: #1ca08a;
11
+ --chat--color-white: #ffffff;
12
+ --chat--color-light: #f2f4f8;
13
+ --chat--color-light-shade-50: #e6e9f1;
14
+ --chat--color-light-shade-100: #c2c5cc;
15
+ --chat--color-medium: #d2d4d9;
16
+ --chat--color-dark: #101330;
17
+ --chat--color-disabled: #777980;
18
+ --chat--color-typing: #404040;
19
+
20
+ --chat--spacing: 1rem;
21
+ --chat--border-radius: 0.25rem;
22
+ --chat--transition-duration: 0.15s;
23
+
24
+ --chat--window--width: 400px;
25
+ --chat--window--height: 600px;
26
+
27
+ --chat--textarea--height: 50px;
28
+
29
+ --chat--message--bot--background: var(--chat--color-white);
30
+ --chat--message--bot--color: var(--chat--color-dark);
31
+ --chat--message--user--background: var(--chat--color-secondary);
32
+ --chat--message--user--color: var(--chat--color-white);
33
+ --chat--message--pre--background: rgba(0, 0, 0, 0.05);
34
+
35
+ --chat--toggle--background: var(--chat--color-primary);
36
+ --chat--toggle--hover--background: var(--chat--color-primary-shade-50);
37
+ --chat--toggle--active--background: var(--chat--color-primary-shade-100);
38
+ --chat--toggle--color: var(--chat--color-white);
39
+ --chat--toggle--size: 64px;
40
+ }