vue-wiguet-chatweb 0.1.28 → 0.1.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. package/README.md +68 -68
  2. package/dist/components/Chat.vue.d.ts +2 -5
  3. package/dist/components/DangerIcon.vue.d.ts +1 -1
  4. package/dist/components/IconAttach.vue.d.ts +1 -1
  5. package/dist/components/IconChat.vue.d.ts +1 -1
  6. package/dist/components/IconClose.vue.d.ts +1 -1
  7. package/dist/components/IconSend.vue.d.ts +1 -1
  8. package/dist/components/IconTelegram.vue.d.ts +1 -1
  9. package/dist/components/IconWhatsApp.vue.d.ts +1 -1
  10. package/dist/components/Loader.vue.d.ts +1 -1
  11. package/dist/components/MessageList.vue.d.ts +2 -3
  12. package/dist/components/ODialog/IPropsDialog.d.ts +1 -0
  13. package/dist/components/ODialog/ODialog.vue.d.ts +15 -13
  14. package/dist/components/Widget.vue.d.ts +2 -1
  15. package/dist/dto/app.dto.d.ts +1 -0
  16. package/dist/index.d.ts +1 -0
  17. package/dist/main.d.ts +1 -0
  18. package/dist/store/config.d.ts +1 -0
  19. package/dist/store/index.d.ts +1 -0
  20. package/dist/style.css +1 -1
  21. package/dist/vue-wiguet-chatweb.js +1769 -1829
  22. package/dist/vue-wiguet-chatweb.umd.cjs +26 -26
  23. package/package.json +66 -66
  24. package/src/assets/emojis/AngryIcon.svg +4 -4
  25. package/src/assets/emojis/HappiestIcon.svg +4 -4
  26. package/src/assets/emojis/HappyIcon.svg +4 -4
  27. package/src/assets/emojis/NeutralIcon.svg +4 -4
  28. package/src/assets/emojis/SadIcon.svg +4 -4
  29. package/src/components/Chat.vue +691 -691
  30. package/src/components/ChatMessage.vue +102 -102
  31. package/src/components/DangerIcon.vue +12 -12
  32. package/src/components/IconAttach.vue +24 -24
  33. package/src/components/IconChat.vue +23 -23
  34. package/src/components/IconClose.vue +5 -5
  35. package/src/components/IconSend.vue +8 -8
  36. package/src/components/IconTelegram.vue +28 -28
  37. package/src/components/IconWhatsApp.vue +39 -39
  38. package/src/components/IconWidget.vue +45 -45
  39. package/src/components/Loader.vue +31 -31
  40. package/src/components/LoadingComponent.vue +111 -111
  41. package/src/components/MessageList.vue +357 -357
  42. package/src/components/ODialog/IPropsDialog.ts +4 -4
  43. package/src/components/ODialog/IPropsSidebar.ts +13 -13
  44. package/src/components/ODialog/ODialog.vue +106 -84
  45. package/src/components/Widget.vue +187 -205
  46. package/src/components/__tests__/Chat.spec.ts +5 -5
  47. package/src/components/__tests__/ChatMessage.spec.ts +5 -5
  48. package/src/components/__tests__/MessageList.spec.ts +47 -47
  49. package/dist/App.vue.d.ts +0 -2
  50. package/dist/components/ChatMessage.vue.d.ts +0 -12
@@ -1,4 +1,4 @@
1
- import { IPropsSidebar } from './IPropsSidebar';
2
-
3
-
4
- export interface IPropsDialog extends IPropsSidebar {}
1
+ import { IPropsSidebar } from './IPropsSidebar';
2
+
3
+
4
+ export interface IPropsDialog extends IPropsSidebar {}
@@ -1,13 +1,13 @@
1
- export interface IPropsSidebar {
2
- modelValue?: boolean;
3
- title?: string;
4
- // isLoading?: boolean;
5
- // hideActions?: boolean;
6
- // hideHeader?: boolean;
7
- // acceptFn?: () => Promise<boolean>;
8
- // beforeAcceptFn?: () => Promise<boolean>;
9
- // disable?: boolean;
10
-
11
- // solo para v-bind
12
- 'onUpdate:modelValue'?: (args: IPropsSidebar['modelValue'])=> void
13
- }
1
+ export interface IPropsSidebar {
2
+ modelValue?: boolean;
3
+ title?: string;
4
+ // isLoading?: boolean;
5
+ // hideActions?: boolean;
6
+ // hideHeader?: boolean;
7
+ // acceptFn?: () => Promise<boolean>;
8
+ // beforeAcceptFn?: () => Promise<boolean>;
9
+ // disable?: boolean;
10
+
11
+ // solo para v-bind
12
+ 'onUpdate:modelValue'?: (args: IPropsSidebar['modelValue'])=> void
13
+ }
@@ -1,85 +1,107 @@
1
- <template>
2
- <div v-if="props.modelValue" class="dialog-overlay" @click="closeDialog">
3
- <div class="dialog-content" @click.stop>
4
- <div class="header-widget">
5
- <h4 class="title-chat">{{ title }}</h4>
6
- <button @click="() => closeDialog()" class="btn-close">
7
- <IconClose class="pointer" />
8
- </button>
9
- </div>
10
-
11
- <div>
12
- <slot></slot>
13
- </div>
14
- </div>
15
- </div>
16
- </template>
17
-
18
- <script lang="ts" setup>
19
- import IconClose from '../IconClose.vue'
20
- import { IPropsDialog } from './IPropsDialog';
21
-
22
- const props = defineProps<IPropsDialog>()
23
-
24
- const emit = defineEmits(['update:modelValue']);
25
-
26
- const closeDialog = () => {
27
- emit("update:modelValue", false);
28
- };
29
- </script>
30
-
31
- <style scoped>
32
- .dialog-overlay {
33
- position: fixed;
34
- top: 0;
35
- left: 0;
36
- width: 100%;
37
- height: 100%;
38
- background-color: rgba(0, 0, 0, 0.5);
39
- display: flex;
40
- justify-content: center;
41
- align-items: center;
42
- opacity: 0;
43
- animation: fadeIn 0.3s forwards;
44
- }
45
-
46
- .dialog-content {
47
- background-color: white;
48
- padding: 15px;
49
- border-radius: 8px;
50
- text-align: center;
51
- animation: slideIn 0.3s ease-out forwards;
52
- }
53
-
54
- @keyframes fadeIn {
55
- to {
56
- opacity: 1;
57
- }
58
- }
59
-
60
- @keyframes slideIn {
61
- from {
62
- transform: translateY(-50px);
63
- }
64
- to {
65
- transform: translateY(0);
66
- }
67
- }
68
-
69
- .dialog-overlay.v-enter-active,
70
- .dialog-overlay.v-leave-active {
71
- transition: opacity 0.3s;
72
- }
73
-
74
- .btn-close {
75
- padding: 0;
76
- background-color: transparent;
77
- border: none;
78
- display: flex;
79
- align-items: center;
80
- border-radius: 50%;
81
- &:hover {
82
- background-color: rgba(202, 202, 202, 0.534);
83
- }
84
- }
1
+ <template>
2
+ <Teleport v-if="isReadyTeleport" to="#dialogs">
3
+ <div v-if="props.modelValue" class="dialog-overlay" @click="closeDialog">
4
+ <div class="dialog-content" @click.stop>
5
+ <div class="header-widget">
6
+ <h4 class="title-chat">{{ title }}</h4>
7
+ <button @click="() => closeDialog()" class="btn-close">
8
+ <IconClose class="pointer" />
9
+ </button>
10
+ </div>
11
+
12
+ <div>
13
+ <slot></slot>
14
+ </div>
15
+ </div>
16
+ </div>
17
+ </Teleport>
18
+ </template>
19
+
20
+ <script lang="ts" setup>
21
+ import { onMounted, ref } from 'vue';
22
+ import IconClose from '../IconClose.vue'
23
+ import { IPropsDialog } from './IPropsDialog';
24
+
25
+ const props = defineProps<IPropsDialog>()
26
+
27
+ const emit = defineEmits(['update:modelValue']);
28
+
29
+ const isReadyTeleport = ref(false);
30
+
31
+
32
+ const closeDialog = () => {
33
+ emit("update:modelValue", false);
34
+ };
35
+
36
+ onMounted(() => {
37
+ const app = document.getElementById("app")
38
+
39
+ if(!app) throw new Error('app is required')
40
+
41
+ let dialogContainer = document.getElementById("dialogs");
42
+
43
+ if (!dialogContainer) {
44
+ dialogContainer = document.createElement("div");
45
+ dialogContainer.id = "dialogs";
46
+ dialogContainer.classList.add('widget-component')
47
+ app.appendChild(dialogContainer);
48
+ isReadyTeleport.value = true
49
+ }
50
+ });
51
+ </script>
52
+
53
+ <style scoped>
54
+ .dialog-overlay {
55
+ position: fixed;
56
+ top: 0;
57
+ left: 0;
58
+ width: 100%;
59
+ height: 100%;
60
+ background-color: rgba(0, 0, 0, 0.5);
61
+ display: flex;
62
+ justify-content: center;
63
+ align-items: center;
64
+ opacity: 0;
65
+ animation: fadeIn 0.3s forwards;
66
+ }
67
+
68
+ .dialog-content {
69
+ background-color: white;
70
+ padding: 15px;
71
+ border-radius: 8px;
72
+ text-align: center;
73
+ animation: slideIn 0.3s ease-out forwards;
74
+ }
75
+
76
+ @keyframes fadeIn {
77
+ to {
78
+ opacity: 1;
79
+ }
80
+ }
81
+
82
+ @keyframes slideIn {
83
+ from {
84
+ transform: translateY(-50px);
85
+ }
86
+ to {
87
+ transform: translateY(0);
88
+ }
89
+ }
90
+
91
+ .dialog-overlay.v-enter-active,
92
+ .dialog-overlay.v-leave-active {
93
+ transition: opacity 0.3s;
94
+ }
95
+
96
+ .btn-close {
97
+ padding: 0;
98
+ background-color: transparent;
99
+ border: none;
100
+ display: flex;
101
+ align-items: center;
102
+ border-radius: 50%;
103
+ &:hover {
104
+ background-color: rgba(202, 202, 202, 0.534);
105
+ }
106
+ }
85
107
  </style>
@@ -1,205 +1,187 @@
1
- <template>
2
- <div
3
- class="widget-css-reset widget-container"
4
- :class="isDarkMode ? 'chat-dark-mode' : ''"
5
- >
6
- <div
7
- id="chat-circle"
8
- class="widget-container"
9
- v-if="props.tokenAuth.length > 10"
10
- v-show="!isChatBoxVisible"
11
- >
12
- <div class="container-buttons-chat" :class="{'active': toggleButtonsChats}">
13
- <a href="javascript:;" class="button whatsapp" @click="go(MeansCommunication.WHATSAPP)">
14
- <IconWhatsApp />
15
- </a>
16
-
17
- <a href="javascript:;" class="button telegram" @click="go(MeansCommunication.TELEGRAM)">
18
- <IconTelegram />
19
- </a>
20
-
21
- <a
22
- href="javascript:;"
23
- class="button webchat"
24
- title="Debe estar autenticado"
25
- :class="{'disabled': props.tokenAuth.length < 10 }"
26
- @click="toggleButtonsChats && props.tokenAuth.length > 10 && toggleChat()"
27
- >
28
- <IconChat />
29
- </a>
30
- </div>
31
-
32
- <div class="new-message-badge" v-if="newMessages" >
33
- {{ newMessages > 9 ? "9+" : newMessages }}
34
- </div>
35
- <a href="javascript:;" @click="props.tokenAuth.length > 10 && toggleChat()">
36
- <IconWidget />
37
- </a>
38
- </div>
39
-
40
- <div class="chat-box" v-show="isChatBoxVisible">
41
- <Chat
42
- v-if="tokenAuth"
43
- :visible="isChatBoxVisible"
44
- :titlePrincipal="titlePrincipal"
45
- :toggleChat="toggleChat"
46
- :tokenAuth="tokenAuth"
47
- :user="user"
48
- @show-toast="(data) => emit('show-toast', data)"
49
- @show-confirm="(data) => emit('show-confirm', data)"
50
- @clear-new-messages="newMessages = 0"
51
- @new-message="() => newMessages++"
52
- @not-viewed-total="(val) => (newMessages = val)"
53
- @on-qualifying="(args)=> emit('onQualifying', args)"
54
- />
55
- </div>
56
-
57
- <Button label="Show" @click="visible = true" />
58
-
59
- <Dialog v-model:visible="visible" modal header="Edit Profile" :style="{ width: '25rem' }">
60
- <span class="text-surface-500 dark:text-surface-400 block mb-8">Update your information.</span>
61
- <div class="flex items-center gap-4 mb-4">
62
- <label for="username" class="font-semibold w-24">Username</label>
63
- <InputText id="username" class="flex-auto" autocomplete="off" />
64
- </div>
65
- <div class="flex items-center gap-4 mb-8">
66
- <label for="email" class="font-semibold w-24">Email</label>
67
- <InputText id="email" class="flex-auto" autocomplete="off" />
68
- </div>
69
- <div class="flex justify-end gap-2">
70
- <Button type="button" label="Cancel" severity="secondary" @click="visible = false"></Button>
71
- <Button type="button" label="Save" @click="visible = false"></Button>
72
- </div>
73
- </Dialog>
74
- </div>
75
- </template>
76
-
77
- <script setup lang="ts">
78
- import { PropType, ref } from "vue";
79
- import Chat from "./Chat.vue";
80
- import IconWidget from "./IconWidget.vue";
81
- import IconTelegram from "./IconTelegram.vue";
82
- import IconWhatsApp from "./IconWhatsApp.vue";
83
- import IconChat from "./IconChat.vue";
84
-
85
- const emit = defineEmits(["show-toast", "show-confirm", "onQualifying"]);
86
- const visible = ref(true);
87
- const enum MeansCommunication{
88
- WHATSAPP,
89
- TELEGRAM
90
- }
91
-
92
- function go(means: MeansCommunication) {
93
- const cellphoneNumbers = window.VITE_CELLPHONE_NUMBERS?.split(',') ?? [];
94
-
95
- if (cellphoneNumbers.length === 0) {
96
- console.warn('not found cellphone numbers')
97
- return
98
- }
99
-
100
- toggleButtonsChats.value = false;
101
-
102
- const index = Math.floor(Math.random() * cellphoneNumbers.length)
103
-
104
- if(MeansCommunication['WHATSAPP'] === means) {
105
- window.open('https://wa.me/'+ cellphoneNumbers[index], 'WhatsApp', 'noopener')
106
- return;
107
- }
108
-
109
- window.open('https://t.me/+' + cellphoneNumbers[index], 'Telegram', 'noopener')
110
- }
111
-
112
- const isChatBoxVisible = ref(false);
113
- const newMessages = ref(0);
114
- const toggleButtonsChats = ref(false);
115
-
116
- const toggleChat = () => {
117
- isChatBoxVisible.value = !isChatBoxVisible.value;
118
- };
119
-
120
- const props = defineProps({
121
- tokenAuth: { type: String, required: true },
122
- titlePrincipal: { type: String },
123
- user: {
124
- type: Object as PropType<{
125
- nombreCompleto: string;
126
- ci: string;
127
- msPersonaId: number;
128
- }>,
129
- required: true,
130
- },
131
- isDarkMode: {
132
- type: Boolean,
133
- default: false,
134
- },
135
- });
136
- </script>
137
- <style>
138
- @import url(../style.css);
139
- </style>
140
-
141
- <style scoped>
142
-
143
- .disabled {
144
- color: currentColor;
145
- cursor: not-allowed !important;
146
- opacity: 0.4 !important;
147
- text-decoration: none;
148
- }
149
-
150
- .container-buttons-chat {
151
- position: relative;
152
- right: -1.8rem;
153
- }
154
- .button {
155
- position: absolute;
156
- width: 2.5rem;
157
- height: 2.5rem;
158
-
159
- opacity: 0;
160
- box-shadow: 0px 1px 3px 1px #c0c0c0;
161
- border-radius: 100%;
162
- border: 1px solid white;
163
- background-color: white;
164
- overflow: hidden;
165
- cursor: pointer;
166
- transition: transform 0.5s ease, opacity 0.3s ease;
167
- z-index: -1;
168
- }
169
-
170
- .container-buttons-chat.active > a {
171
- z-index: 1;
172
- opacity: 1;
173
- }
174
-
175
- .container-buttons-chat.active .whatsapp {
176
- transform: translateY(-150px); /* Subir más arriba */
177
- }
178
-
179
- .container-buttons-chat.active .telegram {
180
- transform: translateY(-100px); /* Subir más arriba */
181
- }
182
-
183
- .container-buttons-chat.active .webchat {
184
- transform: translateY(-50px); /* Subir más arriba */
185
- }
186
-
187
- .widget-container {
188
- position: relative;
189
- }
190
- .new-message-badge {
191
- position: absolute;
192
- background-color: red;
193
- width: 30px;
194
- height: 30px;
195
- display: flex;
196
- font-family: "Roboto", sans-serif;
197
- align-items: center;
198
- font-weight: 500;
199
- justify-content: center;
200
- border-radius: 50%;
201
- right: -2px;
202
- top: -4px;
203
- z-index: 2;
204
- }
205
- </style>
1
+ <template>
2
+ <div
3
+ class="widget-component widget-css-reset widget-container"
4
+ :class="isDarkMode ? 'chat-dark-mode' : ''"
5
+ >
6
+ <div
7
+ id="chat-circle"
8
+ class="widget-container"
9
+ v-if="props.tokenAuth.length > 10"
10
+ v-show="!isChatBoxVisible"
11
+ >
12
+ <div class="container-buttons-chat" :class="{'active': toggleButtonsChats}">
13
+ <a href="javascript:;" class="button whatsapp" @click="go(MeansCommunication.WHATSAPP)">
14
+ <IconWhatsApp />
15
+ </a>
16
+
17
+ <a href="javascript:;" class="button telegram" @click="go(MeansCommunication.TELEGRAM)">
18
+ <IconTelegram />
19
+ </a>
20
+
21
+ <a
22
+ href="javascript:;"
23
+ class="button webchat"
24
+ title="Debe estar autenticado"
25
+ :class="{'disabled': props.tokenAuth.length < 10 }"
26
+ @click="toggleButtonsChats && props.tokenAuth.length > 10 && toggleChat()"
27
+ >
28
+ <IconChat />
29
+ </a>
30
+ </div>
31
+
32
+ <div class="new-message-badge" v-if="newMessages" >
33
+ {{ newMessages > 9 ? "9+" : newMessages }}
34
+ </div>
35
+ <a href="javascript:;" @click="props.tokenAuth.length > 10 && toggleChat()">
36
+ <IconWidget />
37
+ </a>
38
+ </div>
39
+
40
+ <div class="chat-box" v-show="isChatBoxVisible">
41
+ <Chat
42
+ v-if="tokenAuth"
43
+ :visible="isChatBoxVisible"
44
+ :titlePrincipal="titlePrincipal"
45
+ :toggleChat="toggleChat"
46
+ :tokenAuth="tokenAuth"
47
+ :user="user"
48
+ @show-toast="(data) => emit('show-toast', data)"
49
+ @show-confirm="(data) => emit('show-confirm', data)"
50
+ @clear-new-messages="newMessages = 0"
51
+ @new-message="() => newMessages++"
52
+ @not-viewed-total="(val) => (newMessages = val)"
53
+ @on-qualifying="(args)=> emit('onQualifying', args)"
54
+ />
55
+ </div>
56
+ </div>
57
+ </template>
58
+
59
+ <script setup lang="ts">
60
+ import { PropType, ref } from "vue";
61
+ import Chat from "./Chat.vue";
62
+ import IconWidget from "./IconWidget.vue";
63
+ import IconTelegram from "./IconTelegram.vue";
64
+ import IconWhatsApp from "./IconWhatsApp.vue";
65
+ import IconChat from "./IconChat.vue";
66
+
67
+ const emit = defineEmits(["show-toast", "show-confirm", "onQualifying"]);
68
+ const visible = ref(true);
69
+ const enum MeansCommunication{
70
+ WHATSAPP,
71
+ TELEGRAM
72
+ }
73
+
74
+ function go(means: MeansCommunication) {
75
+ const cellphoneNumbers = window.VITE_CELLPHONE_NUMBERS?.split(',') ?? [];
76
+
77
+ if (cellphoneNumbers.length === 0) {
78
+ console.warn('not found cellphone numbers')
79
+ return
80
+ }
81
+
82
+ toggleButtonsChats.value = false;
83
+
84
+ const index = Math.floor(Math.random() * cellphoneNumbers.length)
85
+
86
+ if(MeansCommunication['WHATSAPP'] === means) {
87
+ window.open('https://wa.me/'+ cellphoneNumbers[index], 'WhatsApp', 'noopener')
88
+ return;
89
+ }
90
+
91
+ window.open('https://t.me/+' + cellphoneNumbers[index], 'Telegram', 'noopener')
92
+ }
93
+
94
+ const isChatBoxVisible = ref(false);
95
+ const newMessages = ref(0);
96
+ const toggleButtonsChats = ref(false);
97
+
98
+ const toggleChat = () => {
99
+ isChatBoxVisible.value = !isChatBoxVisible.value;
100
+ };
101
+
102
+ const props = defineProps({
103
+ tokenAuth: { type: String, required: true },
104
+ titlePrincipal: { type: String },
105
+ user: {
106
+ type: Object as PropType<{
107
+ nombreCompleto: string;
108
+ ci: string;
109
+ msPersonaId: number;
110
+ }>,
111
+ required: true,
112
+ },
113
+ isDarkMode: {
114
+ type: Boolean,
115
+ default: false,
116
+ },
117
+ });
118
+ </script>
119
+ <style>
120
+ @import url(../style.css);
121
+ </style>
122
+
123
+ <style scoped>
124
+
125
+ .disabled {
126
+ color: currentColor;
127
+ cursor: not-allowed !important;
128
+ opacity: 0.4 !important;
129
+ text-decoration: none;
130
+ }
131
+
132
+ .container-buttons-chat {
133
+ position: relative;
134
+ right: -1.8rem;
135
+ }
136
+ .button {
137
+ position: absolute;
138
+ width: 2.5rem;
139
+ height: 2.5rem;
140
+
141
+ opacity: 0;
142
+ box-shadow: 0px 1px 3px 1px #c0c0c0;
143
+ border-radius: 100%;
144
+ border: 1px solid white;
145
+ background-color: white;
146
+ overflow: hidden;
147
+ cursor: pointer;
148
+ transition: transform 0.5s ease, opacity 0.3s ease;
149
+ z-index: -1;
150
+ }
151
+
152
+ .container-buttons-chat.active > a {
153
+ z-index: 1;
154
+ opacity: 1;
155
+ }
156
+
157
+ .container-buttons-chat.active .whatsapp {
158
+ transform: translateY(-150px); /* Subir más arriba */
159
+ }
160
+
161
+ .container-buttons-chat.active .telegram {
162
+ transform: translateY(-100px); /* Subir más arriba */
163
+ }
164
+
165
+ .container-buttons-chat.active .webchat {
166
+ transform: translateY(-50px); /* Subir más arriba */
167
+ }
168
+
169
+ .widget-container {
170
+ position: relative;
171
+ }
172
+ .new-message-badge {
173
+ position: absolute;
174
+ background-color: red;
175
+ width: 30px;
176
+ height: 30px;
177
+ display: flex;
178
+ font-family: "Roboto", sans-serif;
179
+ align-items: center;
180
+ font-weight: 500;
181
+ justify-content: center;
182
+ border-radius: 50%;
183
+ right: -2px;
184
+ top: -4px;
185
+ z-index: 2;
186
+ }
187
+ </style>
@@ -1,6 +1,6 @@
1
- import { expect, it } from 'vitest'
2
- import Chat from '../Chat.vue'
3
-
4
- it('definido', () => {
5
- expect(Chat).toBeDefined()
1
+ import { expect, it } from 'vitest'
2
+ import Chat from '../Chat.vue'
3
+
4
+ it('definido', () => {
5
+ expect(Chat).toBeDefined()
6
6
  })
@@ -1,6 +1,6 @@
1
- import { expect, it } from 'vitest'
2
- import ChatMessage from '../ChatMessage.vue'
3
-
4
- it('definido', () => {
5
- expect(ChatMessage).toBeDefined()
1
+ import { expect, it } from 'vitest'
2
+ import ChatMessage from '../ChatMessage.vue'
3
+
4
+ it('definido', () => {
5
+ expect(ChatMessage).toBeDefined()
6
6
  })