@n8n/chat 0.6.1 → 0.7.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 (209) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc.cjs +10 -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/build.config.js +21 -0
  9. package/env.d.ts +1 -0
  10. package/index.html +13 -0
  11. package/package.json +2 -34
  12. package/resources/images/fullscreen.png +0 -0
  13. package/resources/images/windowed.png +0 -0
  14. package/resources/workflow-manual.json +238 -0
  15. package/resources/workflow.json +119 -0
  16. package/scripts/pack.js +11 -0
  17. package/scripts/postbuild.js +36 -0
  18. package/src/__stories__/App.stories.ts +43 -0
  19. package/src/__tests__/index.spec.ts +218 -0
  20. package/src/__tests__/utils/create.ts +16 -0
  21. package/src/__tests__/utils/fetch.ts +18 -0
  22. package/src/__tests__/utils/selectors.ts +53 -0
  23. package/src/api/generic.ts +63 -0
  24. package/src/api/message.ts +37 -0
  25. package/src/components/Button.vue +41 -0
  26. package/src/components/ChatWindow.vue +125 -0
  27. package/{components → src/components}/GetStarted.vue +7 -7
  28. package/{components → src/components}/GetStartedFooter.vue +2 -2
  29. package/{components → src/components}/Input.vue +40 -35
  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/{components → src/components}/MessagesList.vue +4 -4
  34. package/{components → src/components}/PoweredBy.vue +7 -6
  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 +29 -0
  39. package/{constants/localStorage.mjs → src/constants/localStorage.ts} +1 -1
  40. package/src/constants/symbols.ts +8 -0
  41. package/src/css/_tokens.scss +36 -0
  42. package/src/css/index.scss +1 -0
  43. package/src/event-buses/chatEventBus.ts +3 -0
  44. package/src/index.ts +42 -0
  45. package/src/main.scss +5 -0
  46. package/src/plugins/chat.ts +105 -0
  47. package/src/types/chat.ts +12 -0
  48. package/src/types/messages.ts +6 -0
  49. package/src/types/options.ts +28 -0
  50. package/src/types/webhook.ts +17 -0
  51. package/src/utils/event-bus.ts +51 -0
  52. package/src/utils/mount.ts +16 -0
  53. package/tsconfig.json +27 -0
  54. package/vite.config.ts +53 -0
  55. package/vitest.config.ts +20 -0
  56. package/__stories__/App.stories.d.ts +0 -16
  57. package/__stories__/App.stories.js +0 -38
  58. package/__stories__/App.stories.mjs +0 -32
  59. package/__tests__/index.spec.d.ts +0 -1
  60. package/__tests__/index.spec.js +0 -146
  61. package/__tests__/index.spec.mjs +0 -172
  62. package/__tests__/setup.js +0 -3
  63. package/__tests__/setup.mjs +0 -1
  64. package/__tests__/utils/create.d.ts +0 -5
  65. package/__tests__/utils/create.js +0 -16
  66. package/__tests__/utils/create.mjs +0 -10
  67. package/__tests__/utils/fetch.d.ts +0 -3
  68. package/__tests__/utils/fetch.js +0 -20
  69. package/__tests__/utils/fetch.mjs +0 -9
  70. package/__tests__/utils/index.js +0 -38
  71. package/__tests__/utils/index.mjs +0 -3
  72. package/__tests__/utils/selectors.d.ts +0 -12
  73. package/__tests__/utils/selectors.js +0 -58
  74. package/__tests__/utils/selectors.mjs +0 -41
  75. package/api/generic.d.ts +0 -6
  76. package/api/generic.js +0 -68
  77. package/api/generic.mjs +0 -54
  78. package/api/index.js +0 -27
  79. package/api/index.mjs +0 -2
  80. package/api/message.d.ts +0 -3
  81. package/api/message.js +0 -33
  82. package/api/message.mjs +0 -30
  83. package/chat.bundle.es.js +0 -10753
  84. package/chat.bundle.umd.js +0 -18
  85. package/chat.es.js +0 -6864
  86. package/chat.umd.js +0 -18
  87. package/components/Button.vue +0 -34
  88. package/components/ChatWindow.vue +0 -104
  89. package/components/Layout.vue +0 -66
  90. package/components/Message.vue +0 -94
  91. package/components/MessageTyping.vue +0 -101
  92. package/components/index.js +0 -76
  93. package/components/index.mjs +0 -10
  94. package/composables/index.js +0 -38
  95. package/composables/index.mjs +0 -3
  96. package/composables/useChat.d.ts +0 -1
  97. package/composables/useChat.js +0 -11
  98. package/composables/useChat.mjs +0 -5
  99. package/composables/useI18n.d.ts +0 -4
  100. package/composables/useI18n.js +0 -23
  101. package/composables/useI18n.mjs +0 -12
  102. package/composables/useOptions.d.ts +0 -3
  103. package/composables/useOptions.js +0 -14
  104. package/composables/useOptions.mjs +0 -8
  105. package/constants/defaults.d.ts +0 -3
  106. package/constants/defaults.js +0 -32
  107. package/constants/defaults.mjs +0 -26
  108. package/constants/index.js +0 -38
  109. package/constants/index.mjs +0 -3
  110. package/constants/localStorage.d.ts +0 -2
  111. package/constants/localStorage.js +0 -8
  112. package/constants/symbols.d.ts +0 -3
  113. package/constants/symbols.js +0 -8
  114. package/constants/symbols.mjs +0 -2
  115. package/css/index.css +0 -31
  116. package/event-buses/chatEventBus.d.ts +0 -1
  117. package/event-buses/chatEventBus.js +0 -8
  118. package/event-buses/chatEventBus.mjs +0 -2
  119. package/event-buses/index.js +0 -16
  120. package/event-buses/index.mjs +0 -1
  121. package/index.d.ts +0 -3
  122. package/index.js +0 -43
  123. package/index.mjs +0 -36
  124. package/main.css +0 -151
  125. package/plugins/chat.d.ts +0 -3
  126. package/plugins/chat.js +0 -85
  127. package/plugins/chat.mjs +0 -83
  128. package/plugins/index.js +0 -16
  129. package/plugins/index.mjs +0 -1
  130. package/style.css +0 -1
  131. package/types/App.vue.d.ts +0 -8
  132. package/types/__stories__/App.stories.d.ts +0 -17
  133. package/types/__tests__/index.spec.d.ts +0 -1
  134. package/types/__tests__/setup.d.ts +0 -0
  135. package/types/__tests__/utils/create.d.ts +0 -5
  136. package/types/__tests__/utils/fetch.d.ts +0 -4
  137. package/types/__tests__/utils/index.d.ts +0 -3
  138. package/types/__tests__/utils/selectors.d.ts +0 -12
  139. package/types/api/generic.d.ts +0 -6
  140. package/types/api/index.d.ts +0 -2
  141. package/types/api/message.d.ts +0 -3
  142. package/types/chat.d.ts +0 -11
  143. package/types/chat.js +0 -1
  144. package/types/chat.mjs +0 -0
  145. package/types/components/Button.vue.d.ts +0 -9
  146. package/types/components/Chat.vue.d.ts +0 -2
  147. package/types/components/ChatWindow.vue.d.ts +0 -2
  148. package/types/components/GetStarted.vue.d.ts +0 -2
  149. package/types/components/GetStartedFooter.vue.d.ts +0 -2
  150. package/types/components/Input.vue.d.ts +0 -2
  151. package/types/components/Layout.vue.d.ts +0 -11
  152. package/types/components/Message.vue.d.ts +0 -21
  153. package/types/components/MessageTyping.vue.d.ts +0 -15
  154. package/types/components/MessagesList.vue.d.ts +0 -14
  155. package/types/components/PoweredBy.vue.d.ts +0 -2
  156. package/types/components/index.d.ts +0 -10
  157. package/types/composables/index.d.ts +0 -3
  158. package/types/composables/useChat.d.ts +0 -2
  159. package/types/composables/useI18n.d.ts +0 -4
  160. package/types/composables/useOptions.d.ts +0 -4
  161. package/types/constants/defaults.d.ts +0 -3
  162. package/types/constants/index.d.ts +0 -3
  163. package/types/constants/localStorage.d.ts +0 -2
  164. package/types/constants/symbols.d.ts +0 -4
  165. package/types/event-buses/chatEventBus.d.ts +0 -1
  166. package/types/event-buses/index.d.ts +0 -1
  167. package/types/index.js +0 -49
  168. package/types/index.mjs +0 -4
  169. package/types/messages.d.ts +0 -6
  170. package/types/messages.js +0 -1
  171. package/types/messages.mjs +0 -0
  172. package/types/options.d.ts +0 -25
  173. package/types/options.js +0 -1
  174. package/types/options.mjs +0 -0
  175. package/types/plugins/chat.d.ts +0 -3
  176. package/types/plugins/index.d.ts +0 -1
  177. package/types/types/chat.d.ts +0 -11
  178. package/types/types/index.d.ts +0 -4
  179. package/types/types/messages.d.ts +0 -6
  180. package/types/types/options.d.ts +0 -25
  181. package/types/types/webhook.d.ts +0 -15
  182. package/types/utils/event-bus.d.ts +0 -8
  183. package/types/utils/mount.d.ts +0 -1
  184. package/types/webhook.d.ts +0 -15
  185. package/types/webhook.js +0 -1
  186. package/types/webhook.mjs +0 -0
  187. package/utils/event-bus.d.ts +0 -8
  188. package/utils/event-bus.js +0 -38
  189. package/utils/event-bus.mjs +0 -32
  190. package/utils/index.d.ts +0 -2
  191. package/utils/index.js +0 -27
  192. package/utils/index.mjs +0 -2
  193. package/utils/mount.d.ts +0 -1
  194. package/utils/mount.js +0 -19
  195. package/utils/mount.mjs +0 -13
  196. package/{favicon.ico → public/favicon.ico} +0 -0
  197. package/{App.vue → src/App.vue} +1 -1
  198. package/{__tests__/setup.d.ts → src/__tests__/setup.ts} +0 -0
  199. package/{__tests__/utils/index.d.ts → src/__tests__/utils/index.ts} +0 -0
  200. package/{api/index.d.ts → src/api/index.ts} +0 -0
  201. package/{components → src/components}/Chat.vue +1 -1
  202. /package/{components/index.d.ts → src/components/index.ts} +0 -0
  203. /package/{composables/index.d.ts → src/composables/index.ts} +0 -0
  204. /package/{constants/index.d.ts → src/constants/index.ts} +0 -0
  205. /package/{event-buses/index.d.ts → src/event-buses/index.ts} +0 -0
  206. /package/{plugins/index.d.ts → src/plugins/index.ts} +0 -0
  207. /package/{shims.d.ts → src/shims.d.ts} +0 -0
  208. /package/{types/index.d.ts → src/types/index.ts} +0 -0
  209. /package/{types/utils/index.d.ts → src/utils/index.ts} +0 -0
@@ -1,8 +1,8 @@
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';
5
4
  import { computed, ref } from 'vue';
5
+ import { useI18n, useChat } from '@n8n/chat/composables';
6
6
 
7
7
  const chatStore = useChat();
8
8
  const { waitingForResponse } = chatStore;
@@ -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 '@n8n/chat/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" ref="chatBodyRef" class="chat-body">
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 { PropType } from 'vue';
4
+ import { computed, toRefs } from 'vue';
5
+ import VueMarkdown from 'vue-markdown-render';
6
+ import hljs from 'highlight.js/lib/core';
7
+ import type { ChatMessage } from '@n8n/chat/types';
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 messageText = computed(() => {
19
+ return message.value.text || '&lt;Empty response&gt;';
20
+ });
21
+
22
+ const classes = computed(() => {
23
+ return {
24
+ 'chat-message-from-user': message.value.sender === 'user',
25
+ 'chat-message-from-bot': message.value.sender === 'bot',
26
+ };
27
+ });
28
+
29
+ const markdownOptions = {
30
+ highlight(str: string, lang: string) {
31
+ if (lang && hljs.getLanguage(lang)) {
32
+ try {
33
+ return hljs.highlight(str, { language: lang }).value;
34
+ } catch {}
35
+ }
36
+
37
+ return ''; // use external default escaping
38
+ },
39
+ };
40
+ </script>
41
+ <template>
42
+ <div class="chat-message" :class="classes">
43
+ <slot>
44
+ <VueMarkdown class="chat-message-markdown" :source="messageText" :options="markdownOptions" />
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 { PropType } from 'vue';
3
+ import { computed } from 'vue';
4
+ import { Message } from './index';
5
+ import type { ChatMessage } from '@n8n/chat/types';
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>
@@ -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 '@n8n/chat/constants';
3
+ import type { Chat } from '@n8n/chat/types';
4
+
5
+ export function useChat() {
6
+ return inject(ChatSymbol) as Chat;
7
+ }
@@ -0,0 +1,16 @@
1
+ import { useOptions } from '@n8n/chat/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 '@n8n/chat/constants';
3
+ import type { ChatOptions } from '@n8n/chat/types';
4
+
5
+ export function useOptions() {
6
+ const options = inject(ChatOptionsSymbol) as ChatOptions;
7
+
8
+ return {
9
+ options,
10
+ };
11
+ }
@@ -0,0 +1,29 @@
1
+ import type { ChatOptions } from '@n8n/chat/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
+ loadPreviousSession: true,
12
+ chatInputKey: 'chatInput',
13
+ chatSessionKey: 'sessionId',
14
+ defaultLanguage: 'en',
15
+ showWelcomeScreen: false,
16
+ initialMessages: ['Hi there! 👋', 'My name is Nathan. How can I assist you today?'],
17
+ i18n: {
18
+ en: {
19
+ title: 'Hi there! 👋',
20
+ subtitle: "Start a chat. We're here to help you 24/7.",
21
+ footer: '',
22
+ getStarted: 'New Conversation',
23
+ inputPlaceholder: 'Type your question..',
24
+ },
25
+ },
26
+ theme: {},
27
+ };
28
+
29
+ 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 '@n8n/chat/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,36 @@
1
+ :root {
2
+ --chat--color-primary: #e74266;
3
+ --chat--color-primary-shade-50: #db4061;
4
+ --chat--color-primary-shade-100: #cf3c5c;
5
+ --chat--color-secondary: #20b69e;
6
+ --chat--color-secondary-shade-50: #1ca08a;
7
+ --chat--color-white: #ffffff;
8
+ --chat--color-light: #f2f4f8;
9
+ --chat--color-light-shade-50: #e6e9f1;
10
+ --chat--color-light-shade-100: #c2c5cc;
11
+ --chat--color-medium: #d2d4d9;
12
+ --chat--color-dark: #101330;
13
+ --chat--color-disabled: #777980;
14
+ --chat--color-typing: #404040;
15
+
16
+ --chat--spacing: 1rem;
17
+ --chat--border-radius: 0.25rem;
18
+ --chat--transition-duration: 0.15s;
19
+
20
+ --chat--window--width: 400px;
21
+ --chat--window--height: 600px;
22
+
23
+ --chat--textarea--height: 50px;
24
+
25
+ --chat--message--bot--background: var(--chat--color-white);
26
+ --chat--message--bot--color: var(--chat--color-dark);
27
+ --chat--message--user--background: var(--chat--color-secondary);
28
+ --chat--message--user--color: var(--chat--color-white);
29
+ --chat--message--pre--background: rgba(0, 0, 0, 0.05);
30
+
31
+ --chat--toggle--background: var(--chat--color-primary);
32
+ --chat--toggle--hover--background: var(--chat--color-primary-shade-50);
33
+ --chat--toggle--active--background: var(--chat--color-primary-shade-100);
34
+ --chat--toggle--color: var(--chat--color-white);
35
+ --chat--toggle--size: 64px;
36
+ }
@@ -0,0 +1 @@
1
+ @import 'tokens';
@@ -0,0 +1,3 @@
1
+ import { createEventBus } from '@n8n/chat/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 '@n8n/chat/types';
6
+ import { defaultMountingTarget, defaultOptions } from '@n8n/chat/constants';
7
+ import { createDefaultMountingTarget } from '@n8n/chat/utils';
8
+ import { ChatPlugin } from '@n8n/chat/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,5 @@
1
+ .n8n-chat {
2
+ @import 'highlight.js/styles/github';
3
+ }
4
+
5
+ @import 'css';