@webitel/ui-chats 0.0.15 → 0.0.17

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webitel/ui-chats",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "Reusable Webitel Frontend Code for Chats UI",
5
5
  "workspaces": [
6
6
  "../../",
@@ -1,14 +1,15 @@
1
1
  <template>
2
- <wt-textarea
3
- ref="chatTextFieldInput"
4
- v-model="textModel"
5
- :size="size"
6
- autoresize
7
- />
2
+ <wt-textarea
3
+ ref="chatTextFieldInput"
4
+ :model-value="textModel"
5
+ :size="size"
6
+ autoresize
7
+ @update:model-value="send"
8
+ />
8
9
  </template>
9
10
 
10
11
  <script setup lang="ts">
11
- import type { WtTextarea } from "@webitel/ui-sdk/components";
12
+ import { WtTextarea } from "@webitel/ui-sdk/components";
12
13
  import { ComponentSize } from "@webitel/ui-sdk/enums";
13
14
  import insertTextAtCursor from "insert-text-at-cursor";
14
15
  import type { Emitter } from "mitt";
@@ -33,6 +34,10 @@ const textareaEl = computed(() =>
33
34
  chatTextFieldInputRef.value?.$el.querySelector("textarea"),
34
35
  );
35
36
 
37
+ function send(text: string) {
38
+ textModel.value = text;
39
+ }
40
+
36
41
  function focus() {
37
42
  textareaEl.value!.focus();
38
43
  }
@@ -42,3 +47,4 @@ function insertAtCursor(text: string) {
42
47
  insertTextAtCursor(textareaEl.value!, text);
43
48
  }
44
49
  </script>
50
+
@@ -26,7 +26,7 @@
26
26
  </div>
27
27
  <scroll-to-bottom-btn
28
28
  v-if="showScrollToBottomBtn"
29
- :new-message-count="newUnseenMessages"
29
+ :new-message-count="newUnseenMessagesCount"
30
30
  @scroll="scrollToBottom('smooth')"
31
31
  />
32
32
  </section>
@@ -34,7 +34,7 @@
34
34
 
35
35
  <script setup lang="ts">
36
36
  import type { Emitter } from "mitt";
37
- import { inject, useTemplateRef } from "vue";
37
+ import { computed, inject, nextTick, onMounted, useTemplateRef } from "vue";
38
38
 
39
39
  import type { UiChatsEmitterEvents } from "../../utils/emitter";
40
40
  import { useChatScroll } from "../composables/useChatScroll";
@@ -62,15 +62,24 @@ const { showAvatar, showChatDate } = useChatMessages(props.messages);
62
62
 
63
63
  const {
64
64
  showScrollToBottomBtn,
65
- newUnseenMessages,
65
+ newUnseenMessagesCount,
66
66
  scrollToBottom,
67
67
  handleChatScroll,
68
68
  handleChatResize,
69
- } = useChatScroll(messagesContainer, props.messages);
69
+ } = useChatScroll(
70
+ messagesContainer,
71
+ computed(() => props.messages),
72
+ );
70
73
 
71
74
  function focusOnInput() {
72
75
  uiChatsEmitter?.on("focusOnTextField", focus);
73
76
  }
77
+
78
+ onMounted(() => {
79
+ nextTick(() => {
80
+ scrollToBottom();
81
+ });
82
+ });
74
83
  </script>
75
84
 
76
85
  <style scoped lang="scss">
@@ -5,27 +5,23 @@ import type { ChatMessageType } from "../types/ChatMessage.types";
5
5
 
6
6
  export const useChatScroll = (
7
7
  element: Ref<HTMLElement | null> = null,
8
- chatMessages: ChatMessageType[] = [],
8
+ messages: Ref<ChatMessageType[]> | ComputedRef<ChatMessageType[]>,
9
9
  ) => {
10
+ /* @author ye.pohranichna
11
+ why 136px? because: https://webitel.atlassian.net/browse/WTEL-7136 */
10
12
  const defaultThreshold = 136;
11
- const { arrivedState } = useScroll(element.value);
13
+ const { arrivedState } = useScroll(element);
12
14
 
13
- const newUnseenMessages = ref<number>(0);
15
+ const newUnseenMessagesCount = ref<number>(0);
14
16
  const showScrollToBottomBtn = ref<boolean>(false);
15
17
  /* @author ye.pohranichna
16
- the distance where the scrollToBottomBtn must be shown/hide.
17
- why defaultThreshold=136px? because: https://webitel.atlassian.net/browse/WTEL-7136 */
18
+ the distance where the scrollToBottomBtn must be shown/hide. */
18
19
  const threshold = ref<number>(defaultThreshold);
19
- const messages = ref<ChatMessageType[]>(chatMessages);
20
-
21
- const lastMessage = computed<ChatMessageType>(
22
- () => messages.value[messages.value?.length - 1],
23
- );
24
20
 
25
- const isLastMessageIsMy = computed<boolean>(() =>
26
- Boolean(lastMessage.value?.member?.self),
21
+ const isLastMessageIsMy = computed<boolean>(
22
+ () => lastMessage.value?.member?.self,
27
23
  );
28
-
24
+ const lastMessage = computed<ChatMessageType>(() => messages.value?.at(-1));
29
25
  const handleChatScroll = () => {
30
26
  const wrapper = element.value;
31
27
  if (!wrapper) return;
@@ -42,13 +38,23 @@ export const useChatScroll = (
42
38
  };
43
39
 
44
40
  const handleShowScrollToBottomBtn = (el: HTMLElement) => {
45
- resetScrollToBottomBtn();
41
+ if (arrivedState.bottom) {
42
+ resetScrollToBottomBtn();
43
+ return;
44
+ /* @author ye.pohranichna
45
+ quit the function because we are already at the bottom */
46
+ }
46
47
 
47
48
  const { scrollTop, scrollHeight, clientHeight } = el;
48
49
  const distanceFromBottom = scrollHeight - (scrollTop + clientHeight);
49
50
  showScrollToBottomBtn.value = distanceFromBottom > threshold.value;
50
51
  };
51
52
 
53
+ const resetScrollToBottomBtn = (): void => {
54
+ newUnseenMessagesCount.value = 0;
55
+ showScrollToBottomBtn.value = false;
56
+ };
57
+
52
58
  const updateThreshold = (el: HTMLElement) => {
53
59
  /* @author ye.pohranichna
54
60
  need to update if clientHeight was changed
@@ -56,23 +62,11 @@ export const useChatScroll = (
56
62
  threshold.value = Math.max(defaultThreshold, el.clientHeight * 0.3);
57
63
  };
58
64
 
59
- const resetScrollToBottomBtn = (): void => {
60
- if (arrivedState.bottom && newUnseenMessages.value) {
61
- /* @author ye.pohranichna
62
- hide the btn and reset new messages count, when we scroll to the bottom without btn */
63
- newUnseenMessages.value = 0;
64
- showScrollToBottomBtn.value = false;
65
- /* @author ye.pohranichna
66
- quit the function because we are already at the bottom */
67
- return;
68
- }
69
- };
70
-
71
- const scrollToBottomAfterNewMessage = () => {
65
+ const handleBtnAfterNewMessage = () => {
72
66
  if (arrivedState.bottom || isLastMessageIsMy.value) {
73
67
  scrollToBottom("smooth");
74
68
  } else {
75
- newUnseenMessages.value += 1;
69
+ newUnseenMessagesCount.value += 1;
76
70
  }
77
71
  };
78
72
 
@@ -82,7 +76,7 @@ export const useChatScroll = (
82
76
  behavior: behavior === "instant" ? "auto" : behavior,
83
77
  });
84
78
 
85
- newUnseenMessages.value = 0;
79
+ newUnseenMessagesCount.value = 0;
86
80
  showScrollToBottomBtn.value = false;
87
81
  };
88
82
 
@@ -90,7 +84,7 @@ export const useChatScroll = (
90
84
  () => messages.value?.length,
91
85
  (newValue, oldValue) => {
92
86
  const newMessageReceived = newValue - oldValue === 1; // when chat have just 1 new message @author ye.pohranichna
93
- if (newMessageReceived) scrollToBottomAfterNewMessage();
87
+ if (newMessageReceived) handleBtnAfterNewMessage();
94
88
  },
95
89
  {
96
90
  flush: "post",
@@ -99,7 +93,7 @@ export const useChatScroll = (
99
93
 
100
94
  return {
101
95
  showScrollToBottomBtn,
102
- newUnseenMessages,
96
+ newUnseenMessagesCount,
103
97
  scrollToBottom,
104
98
  handleChatScroll,
105
99
  handleChatResize,
@@ -132,5 +132,6 @@ function sendFile(files: File[]) {
132
132
  display: flex;
133
133
  flex-direction: column;
134
134
  height: 100%;
135
+ width: 100%;
135
136
  }
136
137
  </style>
@@ -1,8 +1,8 @@
1
- import { type Ref } from "vue";
1
+ import { type ComputedRef, type Ref } from "vue";
2
2
  import type { ChatMessageType } from "../types/ChatMessage.types";
3
- export declare const useChatScroll: (element?: Ref<HTMLElement | null>, chatMessages?: ChatMessageType[]) => {
3
+ export declare const useChatScroll: (element: Ref<HTMLElement | null>, messages: Ref<ChatMessageType[]> | ComputedRef<ChatMessageType[]>) => {
4
4
  showScrollToBottomBtn: Ref<boolean, boolean>;
5
- newUnseenMessages: Ref<number, number>;
5
+ newUnseenMessagesCount: Ref<number, number>;
6
6
  scrollToBottom: (behavior?: ScrollBehavior) => void;
7
7
  handleChatScroll: () => void;
8
8
  handleChatResize: () => void;