@quidgest/chatbot 0.1.0 → 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.
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .svg-icon[data-v-695796d5]{display:inline-flex;width:16px;height:14px}.svg-icon[data-v-695796d5] svg{width:100%;height:100%}.q-chatbot{width:100%;padding:1rem;display:flex;flex-direction:column;height:100%}.q-chatbot input{line-height:1.5rem}.q-chatbot .q-input-group .i-text__field{border-radius:0;flex:1}.q-chatbot__content{background-color:#fff;border:1px solid #eaebec;height:100%;width:100%;display:flex;gap:.75rem;flex-direction:column;overflow:hidden}.q-chatbot__footer-container{padding:.8rem}.q-chatbot__send-container{padding-bottom:.25rem;display:flex;justify-content:space-between;width:100%}.q-chatbot__send-container .q-chatbot__send,.q-chatbot__send-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__send-container .spacer{flex-grow:1}.q-chatbot__footer{position:sticky;padding:0 .5rem;border:1px solid #eaebec;border-radius:.25rem;bottom:0;width:100%;display:flex;flex-direction:column;gap:.25rem}.q-chatbot__footer-disabled{background-color:rgb(var(--q-theme-neutral-light-rgb)/.25);cursor:not-allowed}.q-chatbot__footer .q-chatbot__input{min-height:50px;max-height:100px;border-bottom:1px solid #eaebec;overflow-y:auto}.q-chatbot__footer .q-text-area{max-height:100%;overflow-y:auto}.q-chatbot__footer .q-text-area .q-field__control{border:none}.q-chatbot__upload-container{display:flex;justify-content:flex-start;padding:.25rem 0}.q-chatbot__upload-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__messages-container{display:flex;flex-direction:column;flex-grow:1;padding:0 1rem 2rem;gap:1.5rem;overflow-y:auto}.q-chatbot__messages-wrapper{display:flex;max-width:100%;gap:.2rem}.q-chatbot__tools{display:flex;flex-direction:row;justify-content:end;max-width:100%}.q-chatbot__message-wrapper{display:flex;flex-direction:column;gap:.2rem}.q-chatbot__message-container{display:flex;flex-direction:column;gap:.25rem}.q-chatbot__messages-wrapper_right{justify-content:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-container{align-items:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-wrapper{display:flex;align-items:flex-end}.q-chatbot__profile.q-icon__img{border-radius:50%;height:2rem;width:2rem}.q-chatbot__message{display:flex;align-items:center;padding:.3rem .5rem;background-color:#eaebec;width:fit-content;white-space:normal;min-height:2rem;word-wrap:break-word;word-break:break-word;border-radius:0 .5rem .5rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233;border-radius:.5rem 0 .5rem .5rem}.q-chatbot__sender{white-space:nowrap;color:#7c858d;font-size:.7rem}.q-chatbot__retry-button{align-items:center;display:flex}.q-chatbot__image-preview{position:relative;display:inline-block}.q-chatbot__image-preview img{max-height:100px;width:auto;border-radius:8px;margin:10px 0}.q-chatbot__remove-image{position:absolute;top:5px;right:5px;background-color:#00000080;color:#fff;border-radius:50%;padding:5px;cursor:pointer;font-size:12px;border:none}.hidden-input{display:none}.pulsing-dots{display:flex;align-items:center;justify-content:center;gap:.1rem}.dot{font-size:20px;line-height:1;animation:pulse 1s infinite;color:var(--q-theme-primary)}@keyframes pulse{0%,to{transform:scale(.8);opacity:.6}50%{transform:scale(1);opacity:1}}
1
+ .q-chatbot{width:100%;padding:1rem;display:flex;flex-direction:column;height:100%}.q-chatbot input{line-height:1.5rem}.q-chatbot .q-input-group .i-text__field{border-radius:0;flex:1}.q-chatbot__text p{margin:0}.q-chatbot__content{background-color:#fff;border:1px solid #eaebec;height:100%;width:100%;display:flex;gap:.75rem;flex-direction:column;overflow:hidden}.q-chatbot__footer-container{padding:.8rem}.q-chatbot__input-wrapper{display:flex;flex-direction:column;position:relative}.q-chatbot__image-preview{display:inline-flex;align-items:center;position:relative;margin-top:.5rem;width:fit-content}.q-chatbot__image-preview img{width:60px;height:60px;object-fit:cover;border-radius:4px;margin-right:.25rem;border:1px solid #eaebec;overflow:hidden}.q-chatbot__image-preview img:hover+.q-chatbot__remove-image,.q-chatbot__image-preview img:focus+.q-chatbot__remove-image{opacity:1;pointer-events:auto}.q-chatbot__image-preview img:focus{outline:solid rgb(var(--q-theme-info-rgb)/50%)}.q-chatbot .q-button.q-chatbot__remove-image{position:absolute;top:-5px;right:-5px;background-color:#00000080;color:#fff;border-radius:50%;padding:5px;font-size:12px;border:none;opacity:0;pointer-events:none;transition:opacity .2s ease-in-out}.q-chatbot .q-button.q-chatbot__remove-image:hover,.q-chatbot .q-button.q-chatbot__remove-image:focus{opacity:1;pointer-events:auto}.q-chatbot__send-container{padding-bottom:.25rem;display:flex;justify-content:space-between;width:100%}.q-chatbot__send-container .q-chatbot__send,.q-chatbot__send-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__send-container .spacer{flex-grow:1}.q-chatbot__footer{position:sticky;padding:0 .5rem;border:1px solid #eaebec;border-radius:.25rem;bottom:0;width:100%;display:flex;flex-direction:column;gap:.25rem}.q-chatbot__footer-disabled{background-color:rgb(var(--q-theme-neutral-light-rgb)/.25);cursor:not-allowed}.q-chatbot__footer.drag-over{border:2px dashed rgb(var(--q-theme-primary-rgb)/.25);background-color:#018bd20d}.q-chatbot__footer .q-chatbot__input{min-height:50px;max-height:100px;border-bottom:1px solid #eaebec;overflow-y:auto}.q-chatbot__footer .q-text-area{max-height:100%;overflow-y:auto}.q-chatbot__footer .q-text-area .q-field__control{border:none}.q-chatbot__upload-container{display:flex;justify-content:flex-start;padding:.25rem 0}.q-chatbot__upload-container .q-chatbot__upload{border-radius:1rem}.q-chatbot__messages-container{display:flex;flex-direction:column;flex-grow:1;padding:0 1rem 2rem;gap:1.5rem;overflow-y:auto}.q-chatbot__messages-wrapper{display:flex;max-width:100%;gap:.2rem}.q-chatbot__tools{display:flex;flex-direction:row;justify-content:end;max-width:100%}.q-chatbot__message-wrapper{display:flex;flex-direction:column;gap:.2rem}.q-chatbot__message-container{display:flex;flex-direction:column;gap:.25rem}.q-chatbot__messages-wrapper_right{justify-content:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-container{align-items:flex-end}.q-chatbot__messages-wrapper_right .q-chatbot__message-wrapper{display:flex;align-items:flex-end}.q-chatbot__profile.q-icon__img{border-radius:50%;height:2rem;width:2rem}.q-chatbot__message{display:flex;align-items:center;padding:.3rem .5rem;background-color:#eaebec;width:fit-content;white-space:normal;min-height:2rem;word-wrap:break-word;word-break:break-word;border-radius:0 .5rem .5rem}.q-chatbot__messages-wrapper_right .q-chatbot__message{background-color:#018bd233;border-radius:.5rem 0 .5rem .5rem}.q-chatbot__sender{white-space:nowrap;color:#7c858d;font-size:.7rem}.q-chatbot__retry-button{align-items:center;display:flex}.q-chatbot__dialog-title{margin:.5rem 0}#comment-dialog .q-dialog__header,.hidden-input{display:none}.pulsing-dots{display:flex;align-items:center;justify-content:center;gap:.1rem}.dot{font-size:20px;line-height:1;animation:pulse 1s infinite;color:var(--q-theme-primary)}@keyframes pulse{0%,to{transform:scale(.8);opacity:.6}50%{transform:scale(1);opacity:1}}
@@ -14,3 +14,21 @@ export type ChatBotMessageContent = {
14
14
  imageUrl?: string;
15
15
  };
16
16
  export type ChatBotMessageSender = 'bot' | 'user';
17
+ export interface CBMessageProps {
18
+ sender?: ChatBotMessageSender;
19
+ message?: string;
20
+ date?: Date;
21
+ loading?: boolean;
22
+ /**
23
+ * Project locale
24
+ */
25
+ dateFormat?: string;
26
+ /**
27
+ * User image
28
+ */
29
+ userImage: string;
30
+ /**
31
+ * Chatbot image
32
+ */
33
+ chatbotImage: string;
34
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quidgest/chatbot",
3
3
  "private": false,
4
- "version": "0.1.0",
4
+ "version": "0.3.0",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
7
7
  "main": "dist/index.cjs",
@@ -32,12 +32,14 @@
32
32
  "lint:fix": "eslint . --fix && prettier --write --list-different src"
33
33
  },
34
34
  "dependencies": {
35
- "axios": "^1.6.7",
36
- "uuid": "^11.0.5"
35
+ "axios": "^1.7.0",
36
+ "uuid": "^11.1.0",
37
+ "vue-markdown-render": "^2.2.1"
37
38
  },
38
39
  "devDependencies": {
39
- "@types/node": "^20.16.1",
40
- "@vitejs/plugin-vue": "^4.6.2",
40
+ "@types/markdown-it": "^14.1.2",
41
+ "@types/node": "^20.11.13",
42
+ "@vitejs/plugin-vue": "^4.5.2",
41
43
  "eslint": "^9.9.0",
42
44
  "eslint-plugin-prettier": "^5.2.1",
43
45
  "prettier": "^3.3.3",
@@ -49,7 +51,7 @@
49
51
  "vue-tsc": "^1.8.27"
50
52
  },
51
53
  "peerDependencies": {
52
- "@quidgest/ui": "^0.14.19",
53
- "vue": "3.5.13"
54
+ "@quidgest/ui": "^0.15.9",
55
+ "vue": "^3.5.13"
54
56
  }
55
57
  }
@@ -15,6 +15,12 @@
15
15
  flex: 1;
16
16
  }
17
17
 
18
+ &__text {
19
+ p {
20
+ margin: 0;
21
+ }
22
+ }
23
+
18
24
  &__content {
19
25
  background-color: white;
20
26
  border: 1px solid #eaebec;
@@ -27,13 +33,70 @@
27
33
  overflow: hidden;
28
34
  }
29
35
 
30
-
31
36
  &__footer-container {
32
37
  padding: 0.8rem;
33
38
  }
34
39
 
40
+ &__input-wrapper {
41
+ display: flex;
42
+ flex-direction: column;
43
+ position: relative;
44
+ }
45
+
46
+ &__image-preview {
47
+ display: inline-flex;
48
+ align-items: center;
49
+ position: relative;
50
+ margin-top: 0.5rem;
51
+ width: fit-content;
52
+
53
+ img {
54
+ width: 60px;
55
+ height: 60px;
56
+ object-fit: cover;
57
+ border-radius: 4px;
58
+ margin-right: 0.25rem;
59
+ border: 1px solid #eaebec;
60
+ overflow: hidden;
61
+
62
+ &:hover,
63
+ &:focus {
64
+
65
+ & + .q-chatbot__remove-image {
66
+ opacity: 1;
67
+ pointer-events: auto;
68
+ }
69
+ }
70
+
71
+ &:focus {
72
+ outline: solid rgb(var(--q-theme-info-rgb) / 50%);
73
+ }
74
+ }
75
+ }
76
+
77
+ .q-button.q-chatbot__remove-image {
78
+ position: absolute;
79
+ top: -5px;
80
+ right: -5px;
81
+ background-color: rgba(0, 0, 0, 0.5);
82
+ color: white;
83
+ border-radius: 50%;
84
+ padding: 5px;
85
+ font-size: 12px;
86
+ border: none;
87
+ opacity: 0;
88
+ pointer-events: none;
89
+ transition: opacity 0.2s ease-in-out;
90
+
91
+ &:hover,
92
+ &:focus {
93
+ opacity: 1;
94
+ pointer-events: auto;
95
+ }
96
+ }
97
+
35
98
  &__send-container {
36
- padding-bottom: .25rem;
99
+ padding-bottom: 0.25rem;
37
100
  display: flex;
38
101
  justify-content: space-between;
39
102
  width: 100%;
@@ -53,20 +116,25 @@
53
116
 
54
117
  &__footer {
55
118
  position: sticky;
56
- padding: 0 .5rem;
119
+ padding: 0 0.5rem;
57
120
  border: 1px solid #eaebec;
58
- border-radius: .25rem;
121
+ border-radius: 0.25rem;
59
122
  bottom: 0;
60
123
  width: 100%;
61
124
  display: flex;
62
125
  flex-direction: column;
63
- gap: .25rem;
126
+ gap: 0.25rem;
64
127
 
65
128
  &-disabled {
66
129
  background-color: rgb(var(--q-theme-neutral-light-rgb) / 0.25);
67
130
  cursor: not-allowed;
68
131
  }
69
132
 
133
+ &.drag-over {
134
+ border: 2px dashed rgb(var(--q-theme-primary-rgb) / 0.25);
135
+ background-color: rgba(1, 139, 210, 0.05);
136
+ }
137
+
70
138
  & .q-chatbot__input {
71
139
  min-height: 50px;
72
140
  max-height: 100px;
@@ -87,8 +155,8 @@
87
155
  &__upload-container {
88
156
  display: flex;
89
157
  justify-content: flex-start;
90
- padding: .25rem 0;
91
-
158
+ padding: 0.25rem 0;
159
+
92
160
  & .q-chatbot__upload {
93
161
  border-radius: 1rem;
94
162
  }
@@ -180,29 +248,14 @@
180
248
  display: flex;
181
249
  }
182
250
 
183
- &__image-preview {
184
- position: relative;
185
- display: inline-block;
186
-
187
- img {
188
- max-height: 100px;
189
- width: auto;
190
- border-radius: 8px;
191
- margin: 10px 0;
192
- }
251
+ &__dialog-title{
252
+ margin: 0.5rem 0;
193
253
  }
254
+ }
194
255
 
195
- &__remove-image {
196
- position: absolute;
197
- top: 5px;
198
- right: 5px;
199
- background-color: rgba(0, 0, 0, 0.5);
200
- color: white;
201
- border-radius: 50%;
202
- padding: 5px;
203
- cursor: pointer;
204
- font-size: 12px;
205
- border: none;
256
+ #comment-dialog {
257
+ .q-dialog__header {
258
+ display: none;
206
259
  }
207
260
  }
208
261
 
@@ -225,12 +278,13 @@
225
278
  }
226
279
 
227
280
  @keyframes pulse {
228
- 0%, 100% {
229
- transform: scale(0.8);
230
- opacity: 0.6;
281
+ 0%,
282
+ 100% {
283
+ transform: scale(0.8);
284
+ opacity: 0.6;
231
285
  }
232
286
  50% {
233
- transform: scale(1);
234
- opacity: 1;
287
+ transform: scale(1);
288
+ opacity: 1;
235
289
  }
236
- }
290
+ }
@@ -1,6 +1,5 @@
1
1
  <template>
2
2
  <div class="q-chatbot__message-container">
3
- <!-- Chatbot Image -->
4
3
  <q-icon
5
4
  type="img"
6
5
  :icon="messageImage"
@@ -20,22 +19,26 @@
20
19
  <!-- When loading is true, show bouncing dots animation -->
21
20
  <pulse-dots v-if="loading" />
22
21
  <template v-else>
23
- <div
24
- class="q-chatbot__text"
22
+ <vue-markdown-render
25
23
  v-if="props.sender === 'bot'"
26
- v-html="props.message"></div>
27
- <div
28
24
  class="q-chatbot__text"
29
- v-else>
25
+ :source="props.message || ''" />
26
+
27
+ <div
28
+ v-else
29
+ class="q-chatbot__text">
30
30
  {{ props.message }}
31
31
  </div>
32
32
  </template>
33
33
  </div>
34
34
  <q-dialog
35
+ id="comment-dialog"
35
36
  v-model="showDialog"
36
- :buttons="commentButtons"
37
- :text="props.texts.commentDialogTitle">
38
- <template #body.append>
37
+ :buttons="commentButtons">
38
+ <template #body.content>
39
+ <div class="q-chatbot__dialog-title">
40
+ {{ props.texts.commentDialogTitle }}
41
+ </div>
39
42
  <q-text-field
40
43
  v-model="feedbackComment"
41
44
  :maxLength="150"
@@ -53,25 +56,22 @@
53
56
  :title="props.texts.goodResponse"
54
57
  borderless
55
58
  :disabled="loading"
56
- b-style="secondary"
57
59
  @click="openFeedbackDialog(1)">
58
- <span v-html="thumbUpSvg" class="svg-icon"></span>
60
+ <q-icon icon="thumb-up" />
59
61
  </q-button>
60
62
  <q-button
61
63
  :title="props.texts.badResponse"
62
64
  borderless
63
65
  :disabled="loading"
64
- b-style="secondary"
65
66
  @click="openFeedbackDialog(0)">
66
- <span v-html="thumbDownSvg" class="svg-icon"></span>
67
+ <q-icon icon="thumb-down" />
67
68
  </q-button>
68
69
  <q-button
69
70
  :title="props.texts.copyResponse"
70
71
  borderless
71
72
  :disabled="loading"
72
- b-style="secondary"
73
73
  @click="copyResponse">
74
- <span v-html="copySvg" class="svg-icon"></span>
74
+ <q-icon icon="copy-content" />
75
75
  </q-button>
76
76
  </q-button-group>
77
77
  </div>
@@ -93,17 +93,8 @@
93
93
  import PulseDots from '@/components/PulseDots.vue'
94
94
  import type { ChatBotMessageSender } from '@/types/message.type'
95
95
  import { ResourceStrings } from '@/types/texts.type'
96
+ import VueMarkdownRender from 'vue-markdown-render'
96
97
  import Axios from 'axios'
97
-
98
- // Importando o conteúdo dos arquivos SVG como strings
99
- import thumbUpSvgFile from '@/assets/thumbUp.svg?raw'
100
- import thumbDownSvgFile from '@/assets/thumbDown.svg?raw'
101
- import copySvgFile from '@/assets/copy.svg?raw'
102
-
103
- // Armazenando o conteúdo SVG como strings
104
- const thumbUpSvg = thumbUpSvgFile;
105
- const thumbDownSvg = thumbDownSvgFile;
106
- const copySvg = copySvgFile;
107
98
 
108
99
  export interface CBMessageProps {
109
100
  /*
@@ -160,7 +151,7 @@
160
151
  * Chatbot image
161
152
  */
162
153
  chatbotImage: string
163
-
154
+
164
155
  /**
165
156
  * Flag to mark welcome messages
166
157
  */
@@ -193,36 +184,39 @@
193
184
  action: submitFeedback,
194
185
  props: {
195
186
  label: props.texts.submitButton,
196
- 'b-style': 'primary'
187
+ 'variant': 'bold',
188
+ },
189
+ icon: {
190
+ icon: 'submit'
197
191
  }
198
192
  },
199
193
  {
200
194
  id: 'cancel-btn',
201
195
  props: {
202
- label: props.texts.cancelButton,
203
- 'b-style': 'danger'
196
+ label: props.texts.cancelButton
197
+ },
198
+ icon: {
199
+ icon: 'cancel'
204
200
  }
205
201
  }
206
202
  ]
207
203
 
208
- const senderName = computed(() => {
209
- return props.sender === 'bot' ? 'GenioBot' : 'You'
210
- })
211
-
212
204
  const isBotMessageAndNotDefault = computed(() => {
213
- return props.sender === 'bot' &&
205
+ return (
206
+ props.sender === 'bot' &&
214
207
  !Object.values(props.texts || {}).includes(props.message || '') &&
215
208
  !props.isWelcomeMessage
209
+ )
216
210
  })
217
211
 
218
212
  const getLocaleDate = computed(() => {
219
213
  if (!props.dateFormat) return props.date.toLocaleString()
220
214
 
221
- return formatDate(props.date, props.dateFormat)
215
+ return formatDate(props.date, 'HH:mm')
222
216
  })
223
217
 
224
218
  const messageDate = computed(() => {
225
- return `${senderName.value} ${getLocaleDate.value}`
219
+ return `${getLocaleDate.value}`
226
220
  })
227
221
 
228
222
  const messageImage = computed(() =>
@@ -276,24 +270,7 @@
276
270
  console.log('Message copied to clipboard')
277
271
  })
278
272
  .catch((error) => {
279
- console.error(
280
- 'Failed to copy message to clipboard: ',
281
- error
282
- )
273
+ console.error('Failed to copy message to clipboard: ', error)
283
274
  })
284
275
  }
285
276
  </script>
286
-
287
- <style scoped>
288
-
289
- .svg-icon {
290
- display: inline-flex;
291
- width: 16px;
292
- height: 14px;
293
- }
294
-
295
- .svg-icon :deep(svg) {
296
- width: 100%;
297
- height: 100%;
298
- }
299
- </style>