@n8n/chat 0.5.2 → 0.6.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 (247) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +51 -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/README.md +4 -21
  9. package/env.d.ts +1 -0
  10. package/index.html +13 -0
  11. package/package.json +2 -69
  12. package/resources/workflow.json +293 -0
  13. package/scripts/pack.js +11 -0
  14. package/scripts/postbuild.js +16 -0
  15. package/{App.vue → src/App.vue} +2 -2
  16. package/src/__stories__/App.stories.ts +43 -0
  17. package/src/__tests__/index.spec.ts +223 -0
  18. package/src/__tests__/utils/create.ts +16 -0
  19. package/src/__tests__/utils/fetch.ts +18 -0
  20. package/src/__tests__/utils/selectors.ts +53 -0
  21. package/src/api/generic.ts +64 -0
  22. package/src/api/message.ts +31 -0
  23. package/src/components/Button.vue +41 -0
  24. package/{components → src/components}/Chat.vue +15 -19
  25. package/src/components/ChatWindow.vue +125 -0
  26. package/src/components/GetStarted.vue +24 -0
  27. package/{components → src/components}/GetStartedFooter.vue +4 -4
  28. package/{components → src/components}/Input.vue +40 -35
  29. package/src/components/Layout.vue +82 -0
  30. package/src/components/Message.vue +97 -0
  31. package/src/components/MessageTyping.vue +109 -0
  32. package/{components → src/components}/MessagesList.vue +8 -8
  33. package/{components → src/components}/PoweredBy.vue +7 -6
  34. package/src/composables/useChat.ts +7 -0
  35. package/src/composables/useI18n.ts +16 -0
  36. package/src/composables/useOptions.ts +11 -0
  37. package/src/constants/defaults.ts +25 -0
  38. package/{constants/localStorage.mjs → src/constants/localStorage.ts} +1 -1
  39. package/src/constants/symbols.ts +8 -0
  40. package/src/event-buses/chatEventBus.ts +3 -0
  41. package/src/index.ts +42 -0
  42. package/src/main.scss +40 -0
  43. package/src/plugins/chat.ts +101 -0
  44. package/src/types/chat.ts +12 -0
  45. package/src/types/messages.ts +6 -0
  46. package/src/types/options.ts +23 -0
  47. package/src/types/webhook.ts +17 -0
  48. package/src/utils/event-bus.ts +51 -0
  49. package/src/utils/mount.ts +16 -0
  50. package/tsconfig.json +27 -0
  51. package/vite.config.ts +51 -0
  52. package/vitest.config.ts +20 -0
  53. package/__stories__/App.stories.d.ts +0 -16
  54. package/__stories__/App.stories.js +0 -38
  55. package/__stories__/App.stories.mjs +0 -32
  56. package/__tests__/index.spec.d.ts +0 -1
  57. package/__tests__/index.spec.js +0 -146
  58. package/__tests__/index.spec.mjs +0 -172
  59. package/__tests__/setup.js +0 -3
  60. package/__tests__/setup.mjs +0 -1
  61. package/__tests__/utils/create.d.ts +0 -5
  62. package/__tests__/utils/create.js +0 -16
  63. package/__tests__/utils/create.mjs +0 -10
  64. package/__tests__/utils/fetch.d.ts +0 -3
  65. package/__tests__/utils/fetch.js +0 -20
  66. package/__tests__/utils/fetch.mjs +0 -9
  67. package/__tests__/utils/index.js +0 -38
  68. package/__tests__/utils/index.mjs +0 -3
  69. package/__tests__/utils/selectors.d.ts +0 -12
  70. package/__tests__/utils/selectors.js +0 -58
  71. package/__tests__/utils/selectors.mjs +0 -41
  72. package/api/generic.d.ts +0 -6
  73. package/api/generic.js +0 -68
  74. package/api/generic.mjs +0 -54
  75. package/api/index.js +0 -27
  76. package/api/index.mjs +0 -2
  77. package/api/message.d.ts +0 -3
  78. package/api/message.js +0 -33
  79. package/api/message.mjs +0 -30
  80. package/chat.bundle.es.js +0 -10760
  81. package/chat.bundle.umd.js +0 -18
  82. package/components/Button.vue +0 -34
  83. package/components/ChatWindow.vue +0 -104
  84. package/components/GetStarted.vue +0 -24
  85. package/components/Layout.vue +0 -66
  86. package/components/Message.vue +0 -94
  87. package/components/MessageTyping.vue +0 -101
  88. package/components/index.js +0 -76
  89. package/components/index.mjs +0 -10
  90. package/composables/index.js +0 -38
  91. package/composables/index.mjs +0 -3
  92. package/composables/useChat.d.ts +0 -1
  93. package/composables/useChat.js +0 -11
  94. package/composables/useChat.mjs +0 -5
  95. package/composables/useI18n.d.ts +0 -4
  96. package/composables/useI18n.js +0 -23
  97. package/composables/useI18n.mjs +0 -12
  98. package/composables/useOptions.d.ts +0 -3
  99. package/composables/useOptions.js +0 -14
  100. package/composables/useOptions.mjs +0 -8
  101. package/constants/defaults.d.ts +0 -3
  102. package/constants/defaults.js +0 -32
  103. package/constants/defaults.mjs +0 -26
  104. package/constants/index.js +0 -38
  105. package/constants/index.mjs +0 -3
  106. package/constants/localStorage.d.ts +0 -2
  107. package/constants/localStorage.js +0 -8
  108. package/constants/symbols.d.ts +0 -3
  109. package/constants/symbols.js +0 -8
  110. package/constants/symbols.mjs +0 -2
  111. package/css/index.css +0 -31
  112. package/event-buses/chatEventBus.d.ts +0 -1
  113. package/event-buses/chatEventBus.js +0 -8
  114. package/event-buses/chatEventBus.mjs +0 -2
  115. package/event-buses/index.js +0 -16
  116. package/event-buses/index.mjs +0 -1
  117. package/index.d.ts +0 -3
  118. package/index.js +0 -43
  119. package/index.mjs +0 -36
  120. package/main.css +0 -151
  121. package/plugins/chat.d.ts +0 -3
  122. package/plugins/chat.js +0 -85
  123. package/plugins/chat.mjs +0 -83
  124. package/plugins/index.js +0 -16
  125. package/plugins/index.mjs +0 -1
  126. package/style.css +0 -1
  127. package/types/App.vue.d.ts +0 -8
  128. package/types/__stories__/App.stories.d.ts +0 -17
  129. package/types/__tests__/index.spec.d.ts +0 -1
  130. package/types/__tests__/setup.d.ts +0 -0
  131. package/types/__tests__/utils/create.d.ts +0 -5
  132. package/types/__tests__/utils/fetch.d.ts +0 -4
  133. package/types/__tests__/utils/index.d.ts +0 -3
  134. package/types/__tests__/utils/selectors.d.ts +0 -12
  135. package/types/api/generic.d.ts +0 -6
  136. package/types/api/index.d.ts +0 -2
  137. package/types/api/message.d.ts +0 -3
  138. package/types/chat.d.ts +0 -11
  139. package/types/chat.js +0 -1
  140. package/types/chat.mjs +0 -0
  141. package/types/components/Button.vue.d.ts +0 -9
  142. package/types/components/Chat.vue.d.ts +0 -2
  143. package/types/components/ChatWindow.vue.d.ts +0 -2
  144. package/types/components/GetStarted.vue.d.ts +0 -2
  145. package/types/components/GetStartedFooter.vue.d.ts +0 -2
  146. package/types/components/Input.vue.d.ts +0 -2
  147. package/types/components/Layout.vue.d.ts +0 -11
  148. package/types/components/Message.vue.d.ts +0 -21
  149. package/types/components/MessageTyping.vue.d.ts +0 -15
  150. package/types/components/MessagesList.vue.d.ts +0 -14
  151. package/types/components/PoweredBy.vue.d.ts +0 -2
  152. package/types/components/index.d.ts +0 -10
  153. package/types/composables/index.d.ts +0 -3
  154. package/types/composables/useChat.d.ts +0 -2
  155. package/types/composables/useI18n.d.ts +0 -4
  156. package/types/composables/useOptions.d.ts +0 -4
  157. package/types/constants/defaults.d.ts +0 -3
  158. package/types/constants/index.d.ts +0 -3
  159. package/types/constants/localStorage.d.ts +0 -2
  160. package/types/constants/symbols.d.ts +0 -4
  161. package/types/event-buses/chatEventBus.d.ts +0 -1
  162. package/types/event-buses/index.d.ts +0 -1
  163. package/types/index.js +0 -49
  164. package/types/index.mjs +0 -4
  165. package/types/messages.d.ts +0 -6
  166. package/types/messages.js +0 -1
  167. package/types/messages.mjs +0 -0
  168. package/types/options.d.ts +0 -25
  169. package/types/options.js +0 -1
  170. package/types/options.mjs +0 -0
  171. package/types/plugins/chat.d.ts +0 -3
  172. package/types/plugins/index.d.ts +0 -1
  173. package/types/src/App.vue.d.ts +0 -8
  174. package/types/src/__stories__/App.stories.d.ts +0 -17
  175. package/types/src/__tests__/index.spec.d.ts +0 -1
  176. package/types/src/__tests__/setup.d.ts +0 -0
  177. package/types/src/__tests__/utils/create.d.ts +0 -5
  178. package/types/src/__tests__/utils/fetch.d.ts +0 -4
  179. package/types/src/__tests__/utils/index.d.ts +0 -3
  180. package/types/src/__tests__/utils/selectors.d.ts +0 -12
  181. package/types/src/api/generic.d.ts +0 -6
  182. package/types/src/api/index.d.ts +0 -2
  183. package/types/src/api/message.d.ts +0 -3
  184. package/types/src/components/Button.vue.d.ts +0 -9
  185. package/types/src/components/Chat.vue.d.ts +0 -2
  186. package/types/src/components/ChatWindow.vue.d.ts +0 -2
  187. package/types/src/components/GetStarted.vue.d.ts +0 -2
  188. package/types/src/components/GetStartedFooter.vue.d.ts +0 -2
  189. package/types/src/components/Input.vue.d.ts +0 -2
  190. package/types/src/components/Layout.vue.d.ts +0 -11
  191. package/types/src/components/Message.vue.d.ts +0 -21
  192. package/types/src/components/MessageTyping.vue.d.ts +0 -15
  193. package/types/src/components/MessagesList.vue.d.ts +0 -14
  194. package/types/src/components/PoweredBy.vue.d.ts +0 -2
  195. package/types/src/components/index.d.ts +0 -10
  196. package/types/src/composables/index.d.ts +0 -3
  197. package/types/src/composables/useChat.d.ts +0 -2
  198. package/types/src/composables/useI18n.d.ts +0 -4
  199. package/types/src/composables/useOptions.d.ts +0 -4
  200. package/types/src/constants/defaults.d.ts +0 -3
  201. package/types/src/constants/index.d.ts +0 -3
  202. package/types/src/constants/localStorage.d.ts +0 -2
  203. package/types/src/constants/symbols.d.ts +0 -4
  204. package/types/src/event-buses/chatEventBus.d.ts +0 -1
  205. package/types/src/event-buses/index.d.ts +0 -1
  206. package/types/src/index.d.ts +0 -2
  207. package/types/src/plugins/chat.d.ts +0 -3
  208. package/types/src/plugins/index.d.ts +0 -1
  209. package/types/src/types/chat.d.ts +0 -11
  210. package/types/src/types/index.d.ts +0 -4
  211. package/types/src/types/messages.d.ts +0 -6
  212. package/types/src/types/options.d.ts +0 -25
  213. package/types/src/types/webhook.d.ts +0 -15
  214. package/types/src/utils/event-bus.d.ts +0 -8
  215. package/types/src/utils/mount.d.ts +0 -1
  216. package/types/types/chat.d.ts +0 -11
  217. package/types/types/index.d.ts +0 -4
  218. package/types/types/messages.d.ts +0 -6
  219. package/types/types/options.d.ts +0 -25
  220. package/types/types/webhook.d.ts +0 -15
  221. package/types/utils/event-bus.d.ts +0 -8
  222. package/types/utils/index.d.ts +0 -2
  223. package/types/utils/mount.d.ts +0 -1
  224. package/types/webhook.d.ts +0 -15
  225. package/types/webhook.js +0 -1
  226. package/types/webhook.mjs +0 -0
  227. package/utils/event-bus.d.ts +0 -8
  228. package/utils/event-bus.js +0 -38
  229. package/utils/event-bus.mjs +0 -32
  230. package/utils/index.d.ts +0 -2
  231. package/utils/index.js +0 -27
  232. package/utils/index.mjs +0 -2
  233. package/utils/mount.d.ts +0 -1
  234. package/utils/mount.js +0 -19
  235. package/utils/mount.mjs +0 -13
  236. /package/{favicon.ico → public/favicon.ico} +0 -0
  237. /package/{__tests__/setup.d.ts → src/__tests__/setup.ts} +0 -0
  238. /package/{__tests__/utils/index.d.ts → src/__tests__/utils/index.ts} +0 -0
  239. /package/{api/index.d.ts → src/api/index.ts} +0 -0
  240. /package/{components/index.d.ts → src/components/index.ts} +0 -0
  241. /package/{composables/index.d.ts → src/composables/index.ts} +0 -0
  242. /package/{constants/index.d.ts → src/constants/index.ts} +0 -0
  243. /package/{event-buses/index.d.ts → src/event-buses/index.ts} +0 -0
  244. /package/{plugins/index.d.ts → src/plugins/index.ts} +0 -0
  245. /package/{shims.d.ts → src/shims.d.ts} +0 -0
  246. /package/{types/index.d.ts → src/types/index.ts} +0 -0
  247. /package/{types/src/utils/index.d.ts → src/utils/index.ts} +0 -0
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  // eslint-disable-next-line import/no-unresolved
3
3
  import IconSend from 'virtual:icons/mdi/send';
4
- import { useI18n, useChat } from '@n8n/chat/composables';
4
+ import { useI18n, useChat } from '@/composables';
5
5
  import { computed, ref } from 'vue';
6
6
 
7
7
  const chatStore = useChat();
@@ -49,40 +49,45 @@ async function onSubmitKeydown(event: KeyboardEvent) {
49
49
  </div>
50
50
  </template>
51
51
 
52
- <style>
52
+ <style lang="scss">
53
53
  .chat-input {
54
- display: flex;
55
- justify-content: center;
56
- align-items: center;
57
- width: 100%;
58
- }
59
- .chat-input 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
- .chat-input .chat-input-send-button {
69
- height: var(--chat--textarea--height);
70
- width: var(--chat--textarea--height);
71
- background: white;
72
- cursor: pointer;
73
- color: var(--chat--color-secondary);
74
- border: 0;
75
- font-size: 24px;
76
- display: inline-flex;
77
- align-items: center;
78
- justify-content: center;
79
- transition: color var(--chat--transition-duration) ease;
80
- }
81
- .chat-input .chat-input-send-button:hover, .chat-input .chat-input-send-button:focus {
82
- color: var(--chat--color-secondary-shade-50);
83
- }
84
- .chat-input .chat-input-send-button[disabled] {
85
- cursor: default;
86
- color: var(--chat--color-disabled);
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
+ }
87
92
  }
88
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>
@@ -1,9 +1,9 @@
1
1
  <script lang="ts" setup>
2
2
  import type { PropType } from 'vue';
3
- import Message from '@n8n/chat/components/Message.vue';
4
- import type { ChatMessage } from '@n8n/chat/types';
5
- import MessageTyping from '@n8n/chat/components/MessageTyping.vue';
6
- import { useChat } from '@n8n/chat/composables';
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
7
 
8
8
  defineProps({
9
9
  messages: {
@@ -28,10 +28,10 @@ const { initialMessages, waitingForResponse } = chatStore;
28
28
  </div>
29
29
  </template>
30
30
 
31
- <style>
31
+ <style lang="scss">
32
32
  .chat-messages-list {
33
- margin-top: auto;
34
- display: block;
35
- padding: var(--chat--messages-list--padding, var(--chat--spacing));
33
+ margin-top: auto;
34
+ display: block;
35
+ padding: var(--chat--messages-list--padding, var(--chat--spacing));
36
36
  }
37
37
  </style>
@@ -5,12 +5,13 @@
5
5
  </div>
6
6
  </template>
7
7
 
8
- <style>
8
+ <style lang="scss">
9
9
  .chat-powered-by {
10
- text-align: center;
11
- }
12
- .chat-powered-by a {
13
- color: var(--chat--color-primary);
14
- text-decoration: none;
10
+ text-align: center;
11
+
12
+ a {
13
+ color: var(--chat--color-primary);
14
+ text-decoration: none;
15
+ }
15
16
  }
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';
@@ -1,2 +1,2 @@
1
- export const localStorageNamespace = "n8n-chat";
1
+ export const localStorageNamespace = 'n8n-chat';
2
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
+ }