@webitel/ui-chats 0.0.24 → 0.0.26
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/package.json +6 -2
- package/src/config/config.ts +22 -0
- package/src/index.ts +1 -0
- package/src/locale/en/en.ts +2 -1
- package/src/locale/es/es.ts +10 -0
- package/src/locale/index.ts +23 -0
- package/src/locale/kz/kz.ts +10 -0
- package/src/locale/pl/pl.ts +10 -0
- package/src/locale/ro/ro.ts +10 -0
- package/src/locale/ru/ru.ts +10 -0
- package/src/locale/uk/uk.ts +10 -0
- package/src/locale/uz/uz.ts +10 -0
- package/src/locale/vi/vi.ts +10 -0
- package/src/ui/chat-footer/modules/user-input/components/chat-text-field.vue +4 -5
- package/src/ui/messaging/components/the-messages-container.vue +3 -12
- package/src/ui/messaging/modules/message/components/details/chat-message-blocked-error.vue +1 -3
- package/src/ui/messaging/modules/message/components/details/chat-message-player.vue +5 -2
- package/src/ui/messaging/modules/message/composables/useChatMessage.ts +4 -4
- package/src/ui/the-chat-container.vue +40 -42
- package/types/config/config.d.ts +6 -0
- package/types/index.d.ts +1 -1
- package/types/locale/en/en.d.ts +1 -0
- package/types/locale/es/es.d.ts +11 -0
- package/types/locale/index.d.ts +102 -0
- package/types/locale/kz/kz.d.ts +11 -0
- package/types/locale/pl/pl.d.ts +11 -0
- package/types/locale/ro/ro.d.ts +11 -0
- package/types/locale/ru/ru.d.ts +11 -0
- package/types/locale/uk/uk.d.ts +11 -0
- package/types/locale/uz/uz.d.ts +11 -0
- package/types/locale/vi/vi.d.ts +11 -0
- package/types/ui/chat-footer/modules/user-input/components/chat-text-field.vue.d.ts +0 -2
- package/types/ui/messaging/modules/message/composables/useChatMessage.d.ts +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webitel/ui-chats",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"description": "Reusable Webitel Frontend Code for Chats UI",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"../../",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"build": "(npm run build:types || true)",
|
|
13
13
|
"build:types": "vue-tsc -p ./tsconfig.build.json",
|
|
14
14
|
"lint:biome": "biome check --write",
|
|
15
|
-
"utils:publish": "npm publish --access public"
|
|
15
|
+
"utils:publish": "npm publish --access public --tag ${NPM_TAG:-latest}"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"autolinker": "^4.1.5",
|
|
@@ -41,6 +41,10 @@
|
|
|
41
41
|
"CHANGELOG.md"
|
|
42
42
|
],
|
|
43
43
|
"exports": {
|
|
44
|
+
".": {
|
|
45
|
+
"types": "./types/index.d.ts",
|
|
46
|
+
"import": "./src/index.ts"
|
|
47
|
+
},
|
|
44
48
|
"./ui": {
|
|
45
49
|
"types": "./types/ui/index.d.ts",
|
|
46
50
|
"import": "./src/ui/index.ts"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { I18n } from "vue-i18n";
|
|
2
|
+
import { messages } from "../locale";
|
|
3
|
+
|
|
4
|
+
export type UiChatsConfig = {
|
|
5
|
+
i18n?: I18n;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const defaultConfig: UiChatsConfig = {
|
|
9
|
+
i18n: null,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const setConfig = (conf: UiChatsConfig) => {
|
|
13
|
+
Object.assign(defaultConfig, conf);
|
|
14
|
+
|
|
15
|
+
if (!conf.i18n?.global) {
|
|
16
|
+
throw new Error("i18n is required");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Object.entries(messages).forEach(([locale, localeMessages]) => {
|
|
20
|
+
conf.i18n.global.mergeLocaleMessage(locale, localeMessages);
|
|
21
|
+
});
|
|
22
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { setConfig } from "./config/config";
|
package/src/locale/en/en.ts
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import en from "./en/en";
|
|
2
|
+
import es from "./es/es";
|
|
3
|
+
import kz from "./kz/kz";
|
|
4
|
+
import pl from "./pl/pl";
|
|
5
|
+
import ro from "./ro/ro";
|
|
6
|
+
import ru from "./ru/ru";
|
|
7
|
+
import uk from "./uk/uk";
|
|
8
|
+
import uz from "./uz/uz";
|
|
9
|
+
import vi from "./vi/vi";
|
|
10
|
+
|
|
11
|
+
export const messages = {
|
|
12
|
+
en,
|
|
13
|
+
uk,
|
|
14
|
+
ru,
|
|
15
|
+
es,
|
|
16
|
+
kz,
|
|
17
|
+
pl,
|
|
18
|
+
ro,
|
|
19
|
+
uz,
|
|
20
|
+
vi,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { en, uk, ru, es, kz, pl, ro, uz, vi };
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
ref="chatTextFieldInput"
|
|
4
4
|
class="chat-text-field"
|
|
5
5
|
:model-value="textModel"
|
|
6
|
+
:placeholder="t('@webitel/ui-chats.ui.messaging.textAreaPlaceholder')"
|
|
6
7
|
:size="size"
|
|
7
8
|
autoresize
|
|
8
9
|
@update:model-value="send"
|
|
9
|
-
@enter="emit('enter')"
|
|
10
10
|
/>
|
|
11
11
|
</template>
|
|
12
12
|
|
|
@@ -16,9 +16,12 @@ import { ComponentSize } from "@webitel/ui-sdk/enums";
|
|
|
16
16
|
import insertTextAtCursor from "insert-text-at-cursor";
|
|
17
17
|
import type { Emitter } from "mitt";
|
|
18
18
|
import { computed, inject, type MaybeRef, useTemplateRef } from "vue";
|
|
19
|
+
import { useI18n } from "vue-i18n";
|
|
19
20
|
|
|
20
21
|
import type { UiChatsEmitterEvents } from "../../../../utils/emitter";
|
|
21
22
|
|
|
23
|
+
const { t } = useI18n();
|
|
24
|
+
|
|
22
25
|
const textModel = defineModel<MaybeRef<string>>("text", {
|
|
23
26
|
required: true,
|
|
24
27
|
});
|
|
@@ -29,10 +32,6 @@ const uiChatsEmitter = inject<Emitter<UiChatsEmitterEvents>>("uiChatsEmitter");
|
|
|
29
32
|
uiChatsEmitter!.on("insertAtCursor", ({ text }) => insertAtCursor(text));
|
|
30
33
|
uiChatsEmitter!.on("focusOnTextField", focus);
|
|
31
34
|
|
|
32
|
-
const emit = defineEmits<{
|
|
33
|
-
enter: [];
|
|
34
|
-
}>();
|
|
35
|
-
|
|
36
35
|
const chatTextFieldInputRef =
|
|
37
36
|
useTemplateRef<typeof WtTextarea>("chatTextFieldInput");
|
|
38
37
|
|
|
@@ -41,14 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
<script setup lang="ts">
|
|
43
43
|
import type { Emitter } from "mitt";
|
|
44
|
-
import {
|
|
45
|
-
computed,
|
|
46
|
-
defineProps,
|
|
47
|
-
inject,
|
|
48
|
-
nextTick,
|
|
49
|
-
onMounted,
|
|
50
|
-
useTemplateRef,
|
|
51
|
-
} from "vue";
|
|
44
|
+
import { computed, inject, nextTick, onMounted, useTemplateRef } from "vue";
|
|
52
45
|
|
|
53
46
|
import { ChatAction } from "../../chat-footer/modules/user-input/enums/ChatAction.enum";
|
|
54
47
|
import type { UiChatsEmitterEvents } from "../../utils/emitter";
|
|
@@ -81,9 +74,7 @@ const emit = defineEmits<(e: typeof ChatAction.LoadNextMessages) => void>();
|
|
|
81
74
|
|
|
82
75
|
const messagesContainer = useTemplateRef("messages-container");
|
|
83
76
|
|
|
84
|
-
const { showAvatar, showChatDate } = useChatMessages(
|
|
85
|
-
computed(() => props.messages),
|
|
86
|
-
); // props values reactivity https://stackoverflow.com/questions/72408463/use-props-in-composables-vue3 @author ye.pohranichna
|
|
77
|
+
const { showAvatar, showChatDate } = useChatMessages(props.messages);
|
|
87
78
|
|
|
88
79
|
const {
|
|
89
80
|
showScrollToBottomBtn,
|
|
@@ -93,7 +84,7 @@ const {
|
|
|
93
84
|
handleChatResize,
|
|
94
85
|
} = useChatScroll(
|
|
95
86
|
messagesContainer,
|
|
96
|
-
computed(() => props.messages),
|
|
87
|
+
computed(() => props.messages),
|
|
97
88
|
);
|
|
98
89
|
|
|
99
90
|
function focusOnInput() {
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="chat-message-blocked-error">
|
|
2
|
+
<div class="chat-message-blocked-error typo-body-1">
|
|
3
3
|
<wt-icon
|
|
4
4
|
icon="protection-error"
|
|
5
5
|
color="error"
|
|
6
6
|
/>
|
|
7
|
-
<!-- TODO: move chat locales from cc-workspaces to this pkg -->
|
|
8
7
|
<p>
|
|
9
|
-
<!-- {{ t('workspaceSec.chat.chatsFileBlocked') }} -->
|
|
10
8
|
{{ t('@webitel/ui-chats.ui.messaging.chatsFileBlocked') }}
|
|
11
9
|
</p>
|
|
12
10
|
</div>
|
|
@@ -41,6 +41,9 @@ function handlePlayerInitialize(player) {
|
|
|
41
41
|
</script>
|
|
42
42
|
|
|
43
43
|
<style lang="scss" scoped>
|
|
44
|
+
$chat-file-max-width: 280px;
|
|
45
|
+
$chat-file-max-height: 280px;
|
|
46
|
+
|
|
44
47
|
.chat-message-player {
|
|
45
48
|
.wt-player :deep(.plyr) {
|
|
46
49
|
.wt-player__close-icon,
|
|
@@ -49,8 +52,8 @@ function handlePlayerInitialize(player) {
|
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
&.plyr--video {
|
|
52
|
-
max-height:
|
|
53
|
-
max-width:
|
|
55
|
+
max-height: $chat-file-max-height;
|
|
56
|
+
max-width: $chat-file-max-width;
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
59
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FormatDateMode } from "@webitel/ui-sdk/enums";
|
|
2
2
|
import { formatDate } from "@webitel/ui-sdk/utils";
|
|
3
|
-
import { type
|
|
3
|
+
import { type Ref, ref } from "vue";
|
|
4
4
|
|
|
5
5
|
import type { ChatMessageType } from "../../../types/ChatMessage.types";
|
|
6
6
|
|
|
@@ -10,9 +10,9 @@ interface GetMessageResult {
|
|
|
10
10
|
nextMessage?: ChatMessageType;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export const useChatMessages = (
|
|
14
|
-
messages: Ref<ChatMessageType[]>
|
|
15
|
-
|
|
13
|
+
export const useChatMessages = (chatMessages: ChatMessageType[]) => {
|
|
14
|
+
const messages: Ref<ChatMessageType[]> = ref(chatMessages);
|
|
15
|
+
|
|
16
16
|
function showChatDate(index: number): boolean {
|
|
17
17
|
const { prevMessage, message } = getMessage(index);
|
|
18
18
|
const prevDate = +prevMessage?.createdAt || 0;
|
|
@@ -1,51 +1,47 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<section class="the-chat-container">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
<slot name="main">
|
|
4
|
+
<dropzone
|
|
5
|
+
v-if="!isDropzoneDisabled && isDropzoneVisible"
|
|
6
|
+
@dragenter.prevent
|
|
7
|
+
@dragleave.prevent="handleDragLeave"
|
|
8
|
+
@drop="sendFile"
|
|
9
|
+
/>
|
|
10
|
+
<messages-container
|
|
11
|
+
:messages="props.messages"
|
|
12
|
+
:next="props.canLoadNextMessages"
|
|
13
|
+
:is-loading="props.isNextMessagesLoading"
|
|
14
|
+
:without-avatars="props.withoutAvatars"
|
|
15
|
+
@[ChatAction.LoadNextMessages]="emit(ChatAction.LoadNextMessages)"
|
|
16
|
+
/>
|
|
17
|
+
</slot>
|
|
18
|
+
<slot name="footer">
|
|
19
|
+
<chat-footer-wrapper v-if="!props.readonly">
|
|
20
|
+
<template #default>
|
|
21
|
+
<chat-text-field
|
|
22
|
+
v-model:text="draft"
|
|
23
|
+
@enter="sendMessage"
|
|
12
24
|
/>
|
|
13
|
-
<
|
|
14
|
-
:
|
|
15
|
-
|
|
16
|
-
:is-loading="props.isNextMessagesLoading"
|
|
17
|
-
:without-avatars="props.withoutAvatars"
|
|
18
|
-
@[ChatAction.LoadNextMessages]="emit(ChatAction.LoadNextMessages)"
|
|
25
|
+
<chat-input-actions-bar
|
|
26
|
+
:actions="props.chatActions"
|
|
27
|
+
@[ChatAction.SendMessage]="sendMessage"
|
|
19
28
|
@[ChatAction.AttachFiles]="sendFile"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
>
|
|
30
|
+
<template
|
|
31
|
+
v-for="action in slottedChatActions"
|
|
32
|
+
:key="action"
|
|
33
|
+
#[action]="{ size }"
|
|
34
|
+
>
|
|
35
|
+
<slot
|
|
36
|
+
:name="`action:${action}`"
|
|
37
|
+
v-bind="{ size }"
|
|
28
38
|
/>
|
|
29
|
-
<chat-input-actions-bar
|
|
30
|
-
:actions="props.chatActions"
|
|
31
|
-
@[ChatAction.SendMessage]="sendMessage"
|
|
32
|
-
@[ChatAction.AttachFiles]="sendFile"
|
|
33
|
-
>
|
|
34
|
-
<template
|
|
35
|
-
v-for="action in slottedChatActions"
|
|
36
|
-
:key="action"
|
|
37
|
-
#[action]="{ size }"
|
|
38
|
-
>
|
|
39
|
-
<slot
|
|
40
|
-
:name="`action:${action}`"
|
|
41
|
-
v-bind="{ size }"
|
|
42
|
-
/>
|
|
43
|
-
</template>
|
|
44
|
-
</chat-input-actions-bar>
|
|
45
39
|
</template>
|
|
46
|
-
</chat-
|
|
47
|
-
</
|
|
48
|
-
|
|
40
|
+
</chat-input-actions-bar>
|
|
41
|
+
</template>
|
|
42
|
+
</chat-footer-wrapper>
|
|
43
|
+
</slot>
|
|
44
|
+
</section>
|
|
49
45
|
</template>
|
|
50
46
|
|
|
51
47
|
<script setup lang="ts">
|
|
@@ -75,6 +71,7 @@ const props = withDefaults(
|
|
|
75
71
|
canLoadNextMessages?: boolean; // 'next'
|
|
76
72
|
isNextMessagesLoading?: boolean;
|
|
77
73
|
withoutAvatars?: boolean;
|
|
74
|
+
readonly?: boolean; // hide chat footer with textarea and action-buttons
|
|
78
75
|
}>(),
|
|
79
76
|
{
|
|
80
77
|
size: ComponentSize.MD,
|
|
@@ -84,6 +81,7 @@ const props = withDefaults(
|
|
|
84
81
|
],
|
|
85
82
|
canLoadNextMessages: false,
|
|
86
83
|
isNextMessagesLoading: false,
|
|
84
|
+
readonly: false,
|
|
87
85
|
},
|
|
88
86
|
);
|
|
89
87
|
|
package/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export { setConfig } from "./config/config";
|
package/types/locale/en/en.d.ts
CHANGED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import en from "./en/en";
|
|
2
|
+
import es from "./es/es";
|
|
3
|
+
import kz from "./kz/kz";
|
|
4
|
+
import pl from "./pl/pl";
|
|
5
|
+
import ro from "./ro/ro";
|
|
6
|
+
import ru from "./ru/ru";
|
|
7
|
+
import uk from "./uk/uk";
|
|
8
|
+
import uz from "./uz/uz";
|
|
9
|
+
import vi from "./vi/vi";
|
|
10
|
+
export declare const messages: {
|
|
11
|
+
en: {
|
|
12
|
+
"@webitel/ui-chats": {
|
|
13
|
+
ui: {
|
|
14
|
+
messaging: {
|
|
15
|
+
chatsFileBlocked: string;
|
|
16
|
+
textAreaPlaceholder: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
uk: {
|
|
22
|
+
"@webitel/ui-chats": {
|
|
23
|
+
ui: {
|
|
24
|
+
messaging: {
|
|
25
|
+
chatsFileBlocked: string;
|
|
26
|
+
textAreaPlaceholder: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
ru: {
|
|
32
|
+
"@webitel/ui-chats": {
|
|
33
|
+
ui: {
|
|
34
|
+
messaging: {
|
|
35
|
+
chatsFileBlocked: string;
|
|
36
|
+
textAreaPlaceholder: string;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
es: {
|
|
42
|
+
"@webitel/ui-chats": {
|
|
43
|
+
ui: {
|
|
44
|
+
messaging: {
|
|
45
|
+
chatsFileBlocked: string;
|
|
46
|
+
textAreaPlaceholder: string;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
kz: {
|
|
52
|
+
"@webitel/ui-chats": {
|
|
53
|
+
ui: {
|
|
54
|
+
messaging: {
|
|
55
|
+
chatsFileBlocked: string;
|
|
56
|
+
textAreaPlaceholder: string;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
pl: {
|
|
62
|
+
"@webitel/ui-chats": {
|
|
63
|
+
ui: {
|
|
64
|
+
messaging: {
|
|
65
|
+
chatsFileBlocked: string;
|
|
66
|
+
textAreaPlaceholder: string;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
ro: {
|
|
72
|
+
"@webitel/ui-chats": {
|
|
73
|
+
ui: {
|
|
74
|
+
messaging: {
|
|
75
|
+
chatsFileBlocked: string;
|
|
76
|
+
textAreaPlaceholder: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
uz: {
|
|
82
|
+
"@webitel/ui-chats": {
|
|
83
|
+
ui: {
|
|
84
|
+
messaging: {
|
|
85
|
+
chatsFileBlocked: string;
|
|
86
|
+
textAreaPlaceholder: string;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
vi: {
|
|
92
|
+
"@webitel/ui-chats": {
|
|
93
|
+
ui: {
|
|
94
|
+
messaging: {
|
|
95
|
+
chatsFileBlocked: string;
|
|
96
|
+
textAreaPlaceholder: string;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
export { en, uk, ru, es, kz, pl, ro, uz, vi };
|
|
@@ -3,10 +3,8 @@ type __VLS_ModelProps = {
|
|
|
3
3
|
"text": MaybeRef<string>;
|
|
4
4
|
};
|
|
5
5
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
6
|
-
enter: () => any;
|
|
7
6
|
"update:text": (value: MaybeRef<string>) => any;
|
|
8
7
|
}, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
|
|
9
|
-
onEnter?: () => any;
|
|
10
8
|
"onUpdate:text"?: (value: MaybeRef<string>) => any;
|
|
11
9
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
10
|
declare const _default: typeof __VLS_export;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { type ComputedRef, type Ref } from "vue";
|
|
2
1
|
import type { ChatMessageType } from "../../../types/ChatMessage.types";
|
|
3
2
|
interface GetMessageResult {
|
|
4
3
|
prevMessage?: ChatMessageType;
|
|
5
4
|
message?: ChatMessageType;
|
|
6
5
|
nextMessage?: ChatMessageType;
|
|
7
6
|
}
|
|
8
|
-
export declare const useChatMessages: (
|
|
7
|
+
export declare const useChatMessages: (chatMessages: ChatMessageType[]) => {
|
|
9
8
|
showAvatar: (index: number) => boolean;
|
|
10
9
|
getMessage: (index: number) => GetMessageResult;
|
|
11
10
|
showChatDate: (index: number) => boolean;
|