isomtrik-quickchat
Version:
isomtrik-quickchat is a lightweight, real-time chat component built with Stencil JS. It is designed to be seamlessly integrated into web applications, offering customizable and responsive chat functionalities. The module supports both CommonJS and ES modu
1,191 lines (1,102 loc) • 77.5 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
const index = require('./index-e1c67530.js');
const DocumentMessageBubble = require('./DocumentMessageBubble-a17c8aa2.js');
require('./ImageMessageBubble-1efdd496.js');
require('./VideoMessageBubble-db9efd68.js');
const ClockMark = require('./ClockMark-6b4b6198.js');
const index_m = require('./index.m-6869e521.js');
const Image = require('./Image-6ad8d97b.js');
const Text = ({
content = '',
color = '',
fontSize = '16px',
textAlign = 'center',
fontWeight = 'normal',
fontStyle = 'normal',
backgroundColor = 'transparent',
borderColor = 'transparent',
borderWidth = '1px',
borderStyle = 'solid',
borderRadius = '4px',
fontFamily = '',
width = "",
height = "auto",
}) => {
return ClockMark.ke`
<div
class="storybook-text"
style=${ClockMark.se({
color,
fontSize,
textAlign,
fontWeight,
fontStyle,
backgroundColor,
borderColor,
borderWidth,
borderStyle,
borderRadius,
fontFamily,
width,
height
})}
>
${content}
</div>
`;
};
class IncomingTextMessageBubble extends ClockMark.h {
static properties = {
bgColor: { type: String },
msgTextColor: { type: String },
msgTextTimeColor: { type: String },
borderWidth: { type: String },
borderColor: { type: String },
borderStyle: { type: String },
borderRadius: { type: String },
padding: { type: String },
height: { type: String },
width: { type: String },
time: { type: String },
textContent: { type: String },
alignSelf: {type: String},
fontFamily: {type: String}
};
static styles = ClockMark.i$1`
.message-container {
position: relative;
width:fit-content;
max-width:80% !important;
align-self: center;
overflow-wrap: break-word;
}
.image-container {
cursor: pointer;
}
.full-screen-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}
.full-screen-image {
max-width: 90%;
max-height: 90%;
object-fit: cover;
}
.close-button {
position: absolute;
top: 20px;
right: 20px;
font-size: 2rem;
color: white;
cursor: pointer;
background: transparent;
border: none;
}
`;
openFullScreen() {
this.isFullScreen = true;
}
closeFullScreen() {
this.isFullScreen = false;
}
render() {
return ClockMark.ke`
<div
class="message-container"
style="padding:${this.padding || "10px"};
border-width: ${this.borderWidth};
border-color: ${this.borderColor};
border-style:${this.borderStyle};
border-radius:${this.borderRadius || '7px'};
height:${this.height};
background-color:${this.bgColor || "#EFF1FA"};
align-self: ${this.alignSelf || 'left'}
font-family: ${this.fontFamily}
"
>
${Text({
content: this.textContent || 'some incoming message some somesomesomesome',
// width: '90%',
textAlign: 'left',
fontFamily: this.fontFamily,
color: this.msgTextColor
})}
<timestamp-element .time="${this.time || new Date().toISOString()}" .color="${this.msgTextTimeColor}"></timestamp-element>
</div>
`;
}
}
customElements.define('incoming-text-message-bubble', IncomingTextMessageBubble);
class OutgoingTextMessageBubble extends ClockMark.h {
static properties = {
bgColor: { type: String },
msgTextColor: { type: String },
msgTextTimeColor: { type: String },
borderWidth: { type: String },
borderColor: { type: String },
borderStyle: { type: String },
borderRadius: { type: String },
padding: { type: String },
height: { type: String },
width: { type: String },
time: { type: String },
textContent: { type: String },
alignSelf: { type: String },
isRead: { type: Boolean },
isPopupOpen: { type: Boolean },
fontFamily: { type: String },
isDelivered: { type: String },
};
constructor() {
super();
this.isPopupOpen = false;
}
static styles = ClockMark.i$1`
.message-container {
position: relative;
width: fit-content;
max-width: 80% !important;
align-self: center;
overflow-wrap: break-word;
}
.message-footer {
display: flex;
flex-direction: row;
align-items: center;
justify-content: end;
gap: 2px;
}
.actions {
position: absolute;
left: -15px;
cursor: pointer;
top: 5px;
}
.popup {
position: absolute;
top: 0px;
left: -100px;
background-color: white;
border: 1px solid #eef1fa;
border-radius: 5px;
padding: 10px;
box-shadow: 0 2px 10px #eef1fa;
z-index: 10;
display: flex;
flex-items: column;
align-items: center;
justify-content: center;
}
.popup div {
cursor: pointer;
}
`;
openPopup() {
this.isPopupOpen = !this.isPopupOpen;
}
openFullScreen() {
this.isFullScreen = true;
}
closeFullScreen() {
this.isFullScreen = false;
}
render() {
return ClockMark.ke`
<div
class="message-container"
style="padding:${this.padding || '10px'};
border-width: ${this.borderWidth};
border-color: ${this.borderColor }
border-style:${this.borderStyle || 'solid'};
border-radius:${this.borderRadius || '10px'};
height:${this.height};
background-color:${this.bgColor || '#FFF'};
align-self: ${this.alignSelf || 'right'}
font-family: ${this.fontFamily}
"
>
${Text({
content: this.textContent || 'some outgoing message sssj sj sj ssj ssj some some smosk ajabfa bfa bfhjab ome somesomesomesome',
textAlign: 'left',
fontFamily: this.fontFamily,
color: this.msgTextColor
})}
<div class="message-footer">
<div><timestamp-element .time="${this.time || new Date().toISOString()}" .color="${this.msgTextTimeColor}"></timestamp-element></div>
${this.isRead == true
? ClockMark.ke`<blue-read-mark></blue-read-mark>`
: this.isDelivered == 'true'
? ClockMark.ke`<double-mark></double-mark>`
: this.isDelivered == 'pending'
? ClockMark.ke`<clock-mark></clock-mark>`
: ClockMark.ke`<single-mark></single-mark>`}
</div>
</div>
`;
}
}
customElements.define('outgoing-text-message-bubble', OutgoingTextMessageBubble);
const formatMessageDateFromTimestamp = (timestamp) => {
if (!timestamp) {
return '';
}
const messageDate = new Date(timestamp);
const today = new Date();
today.setHours(0, 0, 0, 0);
const yesterday = new Date(today);
yesterday.setDate(today.getDate() - 1);
const day = messageDate.getDate();
const month = messageDate.toLocaleString(undefined, { month: 'long' });
// Function to determine the ordinal suffix (st, nd, rd, th)
const getOrdinalSuffix = (day) => {
if (day > 3 && day < 21)
return 'th';
switch (day % 10) {
case 1: return 'st';
case 2: return 'nd';
case 3: return 'rd';
default: return 'th';
}
};
const formattedDate = `${day}${getOrdinalSuffix(day)} ${month}`;
if (messageDate >= today) {
return 'Today';
}
else if (messageDate >= yesterday && messageDate < today) {
return 'Yesterday';
}
else {
return formattedDate;
}
};
class MessageDatePill extends ClockMark.h {
static properties = {
bgColor: { type: String },
textColor: { type: String },
width: { type: String },
padding: { type: String },
borderRadius: { type: String },
borderWidth: { type: String },
borderColor: { type: String },
fontSize: { type: String },
fontWeight: { type: String },
fontFamily: { type: String },
content: { type: String },
};
render() {
return ClockMark.ke`
<div
style="background-color: ${this.bgColor || '#F9E3FF'}; width: ${this.width};
border-radius: ${this.borderRadius}; border-width: ${this.borderWidth}; border-color: ${this.borderColor};
padding: ${this.padding}; color: ${this.textColor}; font-family: ${this.fontFamily};
font-size: ${this.fontSize}; font-weight: ${this.fontWeight};
"
>
${this.content}
</div>
`;
}
}
customElements.define('message-date-pill', MessageDatePill);
class SpinnerLoader extends ClockMark.h {
static properties = {
height: { type: String },
width: { type: String },
spinTime: { type: String },
spinnerPrimaryColor: { type: String },
spinnerSecondaryColor: { type: String },
spinnerBorderWidth: { type: String },
};
static styles = ClockMark.i$1`
.spinner {
border-radius: 50%;
z-index: 10;
}
.main-container {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`;
render() {
return ClockMark.ke`
<div class="main-container">
<div
class="spinner"
style="
border-color: ${this.spinnerSecondaryColor};
border-width: ${this.spinnerBorderWidth};
border-style: solid;
border-top-color: ${this.spinnerPrimaryColor};
height: ${this.height};
width: ${this.width};
animation: spin ${this.spinTime} linear infinite;
"
></div>
</div>
`;
}
}
customElements.define('spinner-loader', SpinnerLoader);
const ChatBody = class {
constructor(hostRef) {
index.registerInstance(this, hostRef);
this.openPopup = (event, messageId) => {
event.stopPropagation();
this.isPopupOpen = this.isPopupOpen === messageId ? null : messageId;
};
// Function to handle scroll event and trigger API call when scrolled near the bottom
this.handleScroll = () => {
const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body');
if (chatBodyDiv) {
const scrollTop = chatBodyDiv.scrollTop;
if (scrollTop === 0 && !this.isMessageLimitEnd) {
this.updateSkip();
}
// if (this.scrollTimeout) {
// clearTimeout(this.scrollTimeout);
// }
// this.scrollTimeout = setTimeout(() => {
// }, 300);
this.onScrollEnd();
}
};
this.onScrollEnd = () => {
const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body');
const scrollTop = chatBodyDiv.scrollTop;
this.previousTotalScrollHeight = chatBodyDiv.scrollHeight - scrollTop;
};
// Function to scroll the chat body to the bottom
this.scrollToBottom = () => {
const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body');
const scrollTop = chatBodyDiv.scrollTop;
if (chatBodyDiv) {
setTimeout(() => {
chatBodyDiv.scrollTop = chatBodyDiv.scrollHeight; // Scroll to the bottom
this.previousTotalScrollHeight = chatBodyDiv.scrollHeight - scrollTop;
}, 200);
}
};
this.scrollToTop = () => {
const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body');
if (chatBodyDiv) {
setTimeout(() => {
const toScroll = chatBodyDiv.scrollHeight - this.previousTotalScrollHeight;
chatBodyDiv.scrollTop = toScroll;
this.previousTotalScrollHeight = chatBodyDiv.scrollHeight;
}, 0);
}
};
this.putReadAll = async () => {
var _a;
const hasUnreadMessages = this.allMessages.some(message => { var _a, _b; return ((message === null || message === void 0 ? void 0 : message.senderId) || ((_a = message === null || message === void 0 ? void 0 : message.senderInfo) === null || _a === void 0 ? void 0 : _a.userId)) != ((_b = this.userMetaData) === null || _b === void 0 ? void 0 : _b.userId) && !message.readByAll; });
if (hasUnreadMessages) {
await index_m.w.getInstance().message.putRead({ conversationId: this.conversationId });
const newUpdatedAllMessages = (_a = this.allMessages) === null || _a === void 0 ? void 0 : _a.map(message => { var _a, _b; return (message === null || message === void 0 ? void 0 : message.readByAll) != true && ((message === null || message === void 0 ? void 0 : message.senderId) || ((_a = message === null || message === void 0 ? void 0 : message.senderInfo) === null || _a === void 0 ? void 0 : _a.userId)) != ((_b = this.userMetaData) === null || _b === void 0 ? void 0 : _b.userId) ? Object.assign(Object.assign({}, message), { readByAll: true }) : message; });
this.updateAllMessages(newUpdatedAllMessages);
}
};
this.handleVisibilityChange = async () => {
if (document.visibilityState === 'visible') {
this.isTabActive = true;
this.putReadAll();
}
else {
this.isTabActive = false;
}
};
// Add a new method to handle document clicks
this.handleDocumentClick = (event) => {
const target = event.target;
if (!target.closest('.popup') && !target.closest('.kebab-menu')) {
this.isPopupOpen = null;
}
};
this.isSelf = false;
this.conversationId = undefined;
this.skip = undefined;
this.isDark = undefined;
this.allMessages = undefined;
this.userMetaData = undefined;
this.isMessagesLoading = undefined;
this.isMessageSending = undefined;
this.isMessageLimitEnd = undefined;
this.updateSkip = undefined;
this.isScrollToBottom = undefined;
this.isScrollToTop = undefined;
this.deleteForAll = undefined;
this.deleteForSelf = undefined;
this.changeScrollToBottomState = undefined;
this.changeScrollToTopState = undefined;
this.updateAllMessages = undefined;
this.isChatClosed = undefined;
this.isChatMinimized = undefined;
this.previousTotalScrollHeight = 0;
this.deviceId = '';
this.scrollTimeout = null;
this.isPopupOpen = null;
this.deletedMessages = new Set();
this.isTabActive = true;
}
deleteMessageForSelf(messageId) {
this.deleteForSelf({ conversationId: this.conversationId, messageIds: messageId });
this.isPopupOpen = null;
}
deleteMessageForEveryone(messageId) {
this.deleteForAll({ conversationId: this.conversationId, messageIds: messageId });
this.isPopupOpen = null;
}
async componentWillLoad() {
const deviceId = await index_m.getDeviceID();
this.deviceId = deviceId;
}
// Attach the scroll listener after the component has loaded
async componentDidLoad() {
document.addEventListener('visibilitychange', this.handleVisibilityChange);
document.addEventListener('click', this.handleDocumentClick);
const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body');
if (chatBodyDiv) {
chatBodyDiv.addEventListener('scroll', this.handleScroll); // Listen to the scroll event
}
this.scrollToBottom();
this.putReadAll();
}
async handleDataChange() {
var _a, _b;
if (this.isScrollToBottom && this.allMessages.length > 0 && ((_a = this.userMetaData) === null || _a === void 0 ? void 0 : _a.userId)) {
this.scrollToBottom();
this.changeScrollToBottomState(false);
}
else if (this.allMessages.length > 0 && ((_b = this.userMetaData) === null || _b === void 0 ? void 0 : _b.userId) && !this.isScrollToBottom && this.isScrollToTop) {
this.scrollToTop();
this.changeScrollToTopState(false);
}
if (!this.isChatMinimized && !this.isChatClosed && this.isTabActive) {
this.putReadAll();
}
}
// Clean up the scroll listener when the component is removed
disconnectedCallback() {
document.removeEventListener('visibilitychange', this.handleVisibilityChange);
document.removeEventListener('click', this.handleDocumentClick);
const chatBodyDiv = this.chatBodyElement.shadowRoot.querySelector('.chat-body');
if (chatBodyDiv) {
chatBodyDiv.removeEventListener('scroll', this.handleScroll); // Remove the scroll listener
}
}
render() {
var _a;
const backgroundImage = index.getAssetPath('https://isometrik-website-bucket.s3.ap-south-1.amazonaws.com/chat_BG_8a53348931.png');
return (index.h(index.Host, { key: '3986d01d3b846ad517b2c61f6fe716bf7503b394' }, index.h("div", { key: '05072e8c6db5067a8176f1aaaed88fe4239326f7', id: 'lol', class: "chat-body chat-body-bg", style: {
backgroundColor: 'var(--chat-body-bg)',
backgroundImage: `url(${backgroundImage})`,
display: 'flex',
flexGrow: '1',
flexDirection: 'column',
gap: '20px',
padding: '10px 15px 35px 10px',
overflowY: 'scroll',
} }, this.isMessagesLoading && (index.h("spinner-loader", { key: '95f62ae1152616164dba87849942e87d4c16cc0a', height: "20px", width: "20px", spinTime: "1s", spinnerPrimaryColor: "#000", spinnerSecondaryColor: "#F9E3FF", spinnerBorderWidth: "3px" })), this.allMessages.length > 0 &&
((_a = this.userMetaData) === null || _a === void 0 ? void 0 : _a.userId) &&
this.allMessages.map((message, index$1) => {
var _a, _b, _c;
const currentMessageDate = formatMessageDateFromTimestamp(this.allMessages[index$1].sentAt);
const previousMessageDate = formatMessageDateFromTimestamp(((_a = this.allMessages[index$1 - 1]) === null || _a === void 0 ? void 0 : _a.sentAt) || '');
const showDatePill = currentMessageDate !== previousMessageDate;
if (message.attachments) {
return (index.h("div", { style: { display: 'flex', width: '100%', flexDirection: 'column', gap: '15px' } }, showDatePill && (index.h("div", { style: { display: 'flex', width: '100%', justifyContent: 'center' } }, index.h("message-date-pill", { borderRadius: '9px', textColor: 'var(--chat-date-pill-text)', bgColor: 'var(--chat-date-pill-bg)', padding: '5px 20px', content: currentMessageDate }))), message.attachments.map((attachment) => {
var _a, _b;
if (((message === null || message === void 0 ? void 0 : message.senderId) || ((_a = message === null || message === void 0 ? void 0 : message.senderInfo) === null || _a === void 0 ? void 0 : _a.userId)) == ((_b = this.userMetaData) === null || _b === void 0 ? void 0 : _b.userId)) {
return (index.h("div", { id: "outgoing-message", style: { position: 'relative', display: 'flex', width: '100%', justifyContent: 'right' } }, attachment.mimeType.startsWith('application/') ? (index.h("document-message", { docType: attachment.mimeType, fileName: attachment.name, href: attachment.mediaUrl, bgColor: 'var(--chat-outgoing-msg-bg)', width: "220px", padding: "10px 10px 30px 10px", borderRadius: "6px", time: message === null || message === void 0 ? void 0 : message.sentAt, docName: attachment.name, isRead: message.readByAll, isSelf: true, isDelivered: `${message === null || message === void 0 ? void 0 : message.deliveredToAll}` })) : attachment.mimeType.startsWith('video/') ? (index.h("video-message", { height: '180px', width: '200px', padding: "10px 10px 20px 10px", bgColor: 'var(--chat-outgoing-msg-bg)', isSelf: true, borderRadius: "6px", time: message === null || message === void 0 ? void 0 : message.sentAt, type: attachment.mimeType, videoSrc: attachment.mediaUrl, isRead: message.readByAll, isDelivered: `${message === null || message === void 0 ? void 0 : message.deliveredToAll}` })) : attachment.mimeType.startsWith('image/') ? (index.h("image-message", { bgColor: 'var(--chat-outgoing-msg-bg)', padding: "10px 10px 20px 10px", isSelf: true, borderRadius: "6px", time: message === null || message === void 0 ? void 0 : message.sentAt, imageSrc: attachment.mediaUrl, height: '150px', width: '150px', isRead: message.readByAll, borderWidth: '5px', borderColor: 'var(--chat-outgoing-msg-bg)', borderStyle: 'solid', isDelivered: `${message === null || message === void 0 ? void 0 : message.deliveredToAll}` })) : (''), index.h("span", { class: "kebab-menu", style: { cursor: 'pointer', position: 'absolute', right: '-12px ', top: '5px' }, onClick: e => this.openPopup(e, message === null || message === void 0 ? void 0 : message.messageId) }, index.h("svg", { width: "14px", height: "14px", viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg", fill: 'var(--chat-msg-info-icon)', class: "bi bi-three-dots-vertical" }, index.h("g", { id: "SVGRepo_bgCarrier", "stroke-width": "0" }), index.h("g", { id: "SVGRepo_tracerCarrier", "stroke-linecap": "round", "stroke-linejoin": "round" }), index.h("g", { id: "SVGRepo_iconCarrier" }, index.h("path", { d: "M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" })))), this.isPopupOpen === (message === null || message === void 0 ? void 0 : message.messageId) ? (index.h("div", { class: "popup" }, index.h("span", { class: "deleteText", onClick: () => this.deleteMessageForSelf(message === null || message === void 0 ? void 0 : message.messageId) }, "Delete For Me"), index.h("span", { class: "deleteText", onClick: () => this.deleteMessageForEveryone(message === null || message === void 0 ? void 0 : message.messageId) }, "Delete For All"))) : null));
}
else {
return (index.h("div", { style: { display: 'flex', width: '100%', justifyContent: 'left' } }, attachment.mimeType.startsWith('application/') ? (index.h("document-message", { docType: attachment.mimeType, fileName: attachment.name, href: attachment.mediaUrl, bgColor: 'var(--chat-incoming-msg-bg)', width: "220px", padding: "10px 10px 30px 10px", borderRadius: "6px", time: message === null || message === void 0 ? void 0 : message.sentAt, docName: attachment.name, isSelf: false })) : attachment.mimeType.startsWith('video/') ? (index.h("video-message", { height: '180px', width: '200px', bgColor: 'var(--chat-incoming-msg-bg)', padding: "10px 10px 20px 10px", borderRadius: "6px", isSelf: false, time: message === null || message === void 0 ? void 0 : message.sentAt, type: attachment.mimeType, videoSrc: attachment.mediaUrl })) : attachment.mimeType.startsWith('image/') ? (index.h("image-message", { bgColor: 'var(--chat-incoming-msg-bg)', padding: "10px 10px 20px 10px", borderRadius: "6px", isSelf: false, time: message === null || message === void 0 ? void 0 : message.sentAt, imageSrc: attachment.mediaUrl, height: '150px', width: '150px', borderWidth: '5px', borderColor: 'var(--chat-incoming-msg-bg)', borderStyle: 'solid' })) : ('')));
}
})));
}
else if (message.body) {
if (((message === null || message === void 0 ? void 0 : message.senderId) || ((_b = message === null || message === void 0 ? void 0 : message.senderInfo) === null || _b === void 0 ? void 0 : _b.userId)) == ((_c = this.userMetaData) === null || _c === void 0 ? void 0 : _c.userId)) {
return (index.h("div", { style: { display: 'flex', width: '100%', flexDirection: 'column', gap: '15px' } }, showDatePill && (index.h("div", { style: { display: 'flex', width: '100%', justifyContent: 'center' } }, index.h("message-date-pill", { borderRadius: '9px', textColor: 'var(--chat-date-pill-text)', bgColor: 'var(--chat-date-pill-bg)', padding: '5px 20px', content: currentMessageDate }))), index.h("div", { id: "outgoing-message", style: { position: 'relative', display: 'flex', width: '100%', justifyContent: 'end' } }, index.h("outgoing-text-message-bubble", { msgTextColor: 'var(--chat-outgoing-msg-text)', msgTextTimeColor: 'var(--chat-outgoing-msg-time-text)', isRead: message.readByAll, padding: "10px 10px 1px 10px", borderRadius: "10px 10px 0 10px", textContent: message === null || message === void 0 ? void 0 : message.body, time: message === null || message === void 0 ? void 0 : message.sentAt, bgColor: 'var(--chat-outgoing-msg-bg)', isDelivered: `${message === null || message === void 0 ? void 0 : message.deliveredToAll}` }), index.h("span", { class: "kebab-menu", style: { cursor: 'pointer', position: 'absolute', right: '-12px ', top: '5px' }, onClick: e => this.openPopup(e, message === null || message === void 0 ? void 0 : message.messageId) }, index.h("svg", { width: "14px", height: "14px", viewBox: "0 0 16 16", xmlns: "http://www.w3.org/2000/svg", fill: 'var(--chat-msg-info-icon, #000)', class: "bi bi-three-dots-vertical" }, index.h("g", { id: "SVGRepo_bgCarrier", "stroke-width": "0" }), index.h("g", { id: "SVGRepo_tracerCarrier", "stroke-linecap": "round", "stroke-linejoin": "round" }), index.h("g", { id: "SVGRepo_iconCarrier" }, index.h("path", { d: "M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z" })))), this.isPopupOpen === (message === null || message === void 0 ? void 0 : message.messageId) ? (index.h("div", { class: "popup" }, index.h("span", { class: "deleteText", onClick: () => this.deleteMessageForSelf(message === null || message === void 0 ? void 0 : message.messageId) }, "Delete For Me"), index.h("span", { class: "deleteText", onClick: () => this.deleteMessageForEveryone(message === null || message === void 0 ? void 0 : message.messageId) }, "Delete For All"))) : null)));
}
else {
return (index.h("div", { style: { display: 'flex', width: '100%', flexDirection: 'column', gap: '15px' } }, showDatePill && (index.h("div", { style: { display: 'flex', width: '100%', justifyContent: 'center' } }, index.h("message-date-pill", { borderRadius: '9px', textColor: 'var(--chat-date-pill-text)', bgColor: 'var(--chat-date-pill-bg)', padding: '5px 20px', content: currentMessageDate }))), index.h("incoming-text-message-bubble", { bgColor: 'var(--chat-incoming-msg-bg)', msgTextTimeColor: 'var(--chat-incoming-msg-time-text)', msgTextColor: 'var(--chat-incoming-msg-text)', borderRadius: "10px 10px 10px 0", time: message === null || message === void 0 ? void 0 : message.sentAt, textContent: message === null || message === void 0 ? void 0 : message.body })));
}
}
else if (message.action == 'conversationCreated') {
return (index.h("div", { style: { display: 'flex', width: '100%', justifyContent: 'center' } }, showDatePill && index.h("message-date-pill", { borderRadius: '9px', textColor: 'var(--chat-date-pill-text)', bgColor: 'var(--chat-date-pill-bg)', padding: '5px 20px', content: currentMessageDate })));
}
}))));
}
get chatBodyElement() { return index.getElement(this); }
static get watchers() { return {
"allMessages": ["handleDataChange"],
"userMetaData": ["handleDataChange"]
}; }
};
ChatBody.style = ":host {\n flex-grow: 1;\n overflow: hidden;\n display: flex;\n background-color: var(--chat-body-bg);\n}\n \n\n #outgoing-message > * {\n display: flex;\n width: 100%;\n justify-content: end;\n }\n\n ::-webkit-scrollbar {\n width: 5px;\n }\n\n ::-webkit-scrollbar-track {\n background: transparent;\n }\n ::-webkit-scrollbar-thumb {\n background-color: #F9E3FF !important;\n border-radius: 10px;\n }\n .popup {\n position: absolute;\n bottom: 100%;\n box-shadow: 0px 0px 10px 0px GRAY;\n z-index: 10;\n display: flex !important;\n flex-direction: column !important;\n align-items: center !important;\n justify-content: center !important;\n width: 30% !important;\n gap: 16px !important;\n background-color: #FFFFFF;\n font-family: 'Roboto';\n padding: 10px;\n font-weight:500;\n border-radius: 8px;\n }\n\n .popup span {\n cursor: pointer;\n }\n #outgoing-message .kebab-menu {\n opacity: 0;\n transition: opacity 0.2s ease;\n }\n\n #outgoing-message:hover .kebab-menu {\n opacity: 1;\n }\n\n .deleteText {\n font-size: 14px;\n font-weight: 700;\n }";
class Input extends ClockMark.h {
static properties = {
value: { type: String },
placeholder: { type: String },
width: { type: String },
height: { type: String },
borderColor: { type: String },
borderRadius: { type: String },
backgroundColor: { type: String },
fontSize: { type: String },
padding: { type: String },
color: { type: String },
placeholderColor: { type: String },
borderWidth: { type: String },
inputHeight: { type: String },
minHeight: { type: String },
maxHeight: { type: String },
};
static styles = ClockMark.i$1`
:host {
display: block;
}
textarea {
width: var(--input-width, 100%);
max-height: var(--input-max-height, 100px);
min-height: var(--input-min-height, 45px);
height: var(--input-height, 45px);
border: var(--input-border-width, 1px) solid var(--input-border-color, gray);
border-radius: var(--input-border-radius, 4px);
background-color: var(--input-background-color, white);
font-size: var(--input-font-size, 16px);
padding: var(--input-padding, 12px);
color: var(--input-color);
box-sizing: border-box;
resize: none;
overflow-y: auto;
outline: none;
border-width: none;
font-family: 'Roboto';
transition: height 0.2s ease;
}
textarea::-webkit-scrollbar {
width: 5px;
}
textarea::-webkit-scrollbar-track {
background: #eff1fa;
}
textarea::-webkit-scrollbar-thumb {
background-color: gray;
border-radius: 10px;
}
textarea::-webkit-scrollbar-thumb:hover {
background-color: #555;
}
textarea::placeholder {
color: var(--input-placeholder-color, #aaa);
font-family: sans-serif;
}
textarea:focus {
border-color: transparent;
outline: none;
}
`;
constructor() {
super();
this.value = '';
this.placeholder = 'Enter your text here...';
this.width = '100%';
this.minHeight = '45px';
this.maxHeight = '105px';
this.inputHeight = '45px';
this.borderColor = 'gray';
this.borderRadius = '4px';
this.backgroundColor = 'white';
this.fontSize = '16px';
this.padding = '12px';
this.placeholderColor = '#aaa';
this.borderWidth = '1px';
}
render() {
return ClockMark.ke`
<textarea
.value=${this.value}
placeholder=${this.placeholder}
style=${ClockMark.se({
'--input-width': this.width,
'--input-min-height': this.minHeight,
'--input-max-height': this.maxHeight,
'--input-height': this.inputHeight,
'--input-border-color': this.borderColor,
'--input-border-radius': this.borderRadius,
'--input-background-color': this.backgroundColor,
'--input-font-size': this.fontSize,
'--input-padding': this.padding,
'--input-color': this.color || '#202020',
'--input-placeholder-color': this.placeholderColor,
'--input-border-width': this.borderWidth,
})}
@input=${this.handleInputChange}
></textarea>
`;
}
handleInputChange(event) {
this.value = event.target.value;
this.adjustTextareaHeight(event.target);
this.dispatchEvent(
new CustomEvent('input', {
detail: { value: this.value },
bubbles: true,
composed: true,
}),
);
}
//
adjustTextareaHeight(textarea) {
if (textarea.value.length === 0) {
this.inputHeight = '45px';
} else {
textarea.style.height = '45px';
const scrollHeight = textarea.scrollHeight;
if (scrollHeight <= 45) {
this.inputHeight = '45px';
} else if (scrollHeight > 45 && scrollHeight <= 105) {
this.inputHeight = `${scrollHeight}px`;
} else {
this.inputHeight = '105px';
}
}
textarea.style.height = this.inputHeight;
}
resetHeight() {
const textarea = this.shadowRoot.querySelector('textarea');
if (textarea) {
this.inputHeight = '45px';
textarea.style.height = this.inputHeight;
}
}
//
}
customElements.define('my-input', Input);
class AttachmentBox extends ClockMark.h {
static properties = {
bgColor: { type: String },
textColor: { type: String },
documentIcon: { type: String },
mediaIcon: { type: String },
documentIconHeight: { type: String },
documentIconWidth: { type: String },
mediaIconHeight: { type: String },
mediaIconWidth: { type: String },
containerBorderWidth: { type: String },
containerBorderColor: { type: String },
containerBorderStyle: { type: String },
width: { type: String },
flexDirection: { type: String },
padding: { type: String },
iconGap: { type: String },
containerBorderRadius: { type: String },
onFileUploaded: {type: String}
};
static styles = ClockMark.i$1`
.attachment-box-container {
display: flex;
gap: 2px;
color: white;
align-items: center;
}
.document-container,
.media-container {
cursor: pointer !important;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
input[type="file"] {
opacity: 0;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
cursor: pointer;
}
`;
handleFileChange(event, fileType) {
const file = event.target.files[0];
if (file) {
console.log(`${fileType} uploaded:`, file);
this.dispatchEvent(new CustomEvent('file-uploaded', {
detail: {fileType, file},
bubbles: true,
composed: true
}));
}
}
render() {
return ClockMark.ke`
<div class='attachment-box-container' style='background-color: ${this.bgColor};
border-width: ${this.containerBorderWidth};
border-color: ${this.containerBorderColor};
border-style: ${this.containerBorderStyle};
border-radius: ${this.containerBorderRadius || '10px'};
width: ${this.width};
flex-direction: ${this.flexDirection};
padding: ${this.padding};
gap: ${this.iconGap};
'>
<div class='document-container'>
${this.documentIcon
? Image.Image({
src: this.documentIcon,
alt: 'document icon',
width: this.documentIconWidth,
height: this.documentIconHeight,
})
: ''}
<input
id="documentUpload"
type="file"
accept="application/"
@change="${(e) => this.handleFileChange(e, 'Document')}"
/>
</div>
<div class='media-container'>
${this.mediaIcon
? Image.Image({
src: this.mediaIcon,
alt: 'media icon',
width: this.mediaIconWidth,
height: this.mediaIconHeight,
})
: ''}
<!-- Hidden file input for media -->
<input
id="mediaUpload"
type="file"
accept="image/*,video/*"
@change="${(e) => this.handleFileChange(e, 'Media')}"
/>
</div>
</div>
`;
}
}
customElements.define('attachment-box', AttachmentBox);
class TestFooter extends ClockMark.h {
constructor() {
super();
(this.isAttachmentMenuVisible = false), (this.inputBorderColor = 'transparent'), (this.inputBorderWidth = '1px');
(this.inputBorderStyle = 'dashed'),
(this.inputPlaceholder = 'Type in your message here'),
(this.sendButtonIcon = 'https://flexcrew.s3.us-west-1.amazonaws.com/Group_1171280804_28e21ab22f.svg'),
(this.attachmentIcon = 'https://flexcrew.s3.us-west-1.amazonaws.com/gallery_add_4272954ac0.svg'),
(this.attachmentIconHeight = '34px'),
(this.attachmentIconWidth = '34px'),
(this.sendButtonIconHeight = '50px'),
(this.sendButtonIconWidth = '50px'),
(this.sendButtonIconRadius = '50%'),
(this.inputFontSize = '16px'),
(this.containerPadding = '10px'),
(this.inputBorderRadius = '20px'),
(this.inputContainerBorderWidth = '1px'),
(this.inputContainerBorderRadius = '10px'),
(this.inputContainerBorderStyle = 'solid'),
(this.inputPlaceholderColor = '#D4D8EB'),
(this.inputContainerPadding = '0 10px'),
(this.onSendClick = null);
}
static properties = {
bgColor: { type: String },
inputBorderColor: { type: String },
inputBorderWidth: { type: String },
inputBorderStyle: { type: String },
inputPlaceholder: { type: String },
inputBgColor: { type: String },
inputFontSize: { type: String },
inputFontColor: { type: String },
inputBorderRadius: { type: String },
attachmentIcon: { type: String },
attachmentIconColor: { type: String },
sendButtonIcon: { type: String },
sendButtonIconHeight: { type: String },
sendButtonIconWidth: { type: String },
attachmentIconHeight: { type: String },
attachmentIconWidth: { type: String },
sendButtonIconRadius: { type: String },
containerPadding: { type: String },
containerBoxShadow: { type: String },
inputContainerBorderColor: { type: String },
inputContainerBorderWidth: { type: String },
inputContainerBorderRadius: { type: String },
inputPlaceholderColor: { type: String },
inputContainerPadding: { type: String },
isAttachmentMenuVisible: { type: Boolean },
onSendClick: { type: Function },
inputValue: { type: String },
onMediaIconClick: { type: Function },
onDocumentClick: { type: Function },
onFileUploaded: { type: Function },
};
static styles = ClockMark.i$1`
.footer-container {
display: flex;
align-items: end;
gap: 10px;
position: relative;
box-shadow: 0 -4px 6px rgba(0, 0, 0, 0.1);
}
.input-container {
flex: 1;
display: flex;
align-items: end;
}
.attachment-container {
width: fit-content;
margin-right: 10px;
cursor: pointer;
}
.input-box-container {
width: 100%;
}
.send-container {
width: fit-content;
}
.focused-input {
border: none !important;
outline: none !important;
}
.attachment-menu {
position: absolute;
background-color: white;
border: 1px solid #d4d8eb;
bottom: 65px;
left: 12px;
padding: 10px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
gap: 10px;
border-radius: 10px;
}
`;
toggleAttachmentMenu() {
this.isAttachmentMenuVisible = !this.isAttachmentMenuVisible;
}
handleInputChange(event) {
this.inputValue = event.target.value;
this.dispatchEvent(
new CustomEvent('input-change', {
detail: { value: this.inputValue },
bubbles: true,
composed: true,
}),
);
}
handleMediaIconClick() {
console.log('inputclicked');
}
resetInputHeight() {
const inputElement = this.shadowRoot.querySelector('my-input');
if (inputElement) {
inputElement.resetHeight();
}
}
fileUploadHandler(event) {
this.onFileUploaded(event);
this.isAttachmentMenuVisible = !this.isAttachmentMenuVisible;
}
render() {
return ClockMark.ke`
<div class='footer-container'
style='padding: ${this.containerPadding};
box-shadow: ${this.containerBoxShadow};
background-color:${this.bgColor || '#000'}'
>
<div class='input-container'
style='border-color: ${this.inputContainerBorderColor || 'D4D8EB'};
border-width: ${this.inputContainerBorderWidth};
border-radius: ${this.inputContainerBorderRadius};
border-style: solid;
padding: ${this.inputContainerPadding}'
background-color: ${this.inputBgColor || '#ffffff'}
>
<div class='attachment-container' @click="${this.toggleAttachmentMenu}">
<svg width="36px" height="36px" viewBox="0 0 24.00 24.00" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M13 4H8.8C7.11984 4 6.27976 4 5.63803 4.32698C5.07354 4.6146 4.6146 5.07354 4.32698 5.63803C4 6.27976 4 7.11984 4 8.8V15.2C4 16.8802 4 17.7202 4.32698 18.362C4.6146 18.9265 5.07354 19.3854 5.63803 19.673C6.27976 20 7.11984 20 8.8 20H15.2C16.8802 20 17.7202 20 18.362 19.673C18.9265 19.3854 19.3854 18.9265 19.673 18.362C20 17.7202 20 16.8802 20 15.2V11" stroke=${this.attachmentIconColor || '#000'} stroke-width="1.536" stroke-linecap="round" stroke-linejoin="round"></path> <path d="M4 16L8.29289 11.7071C8.68342 11.3166 9.31658 11.3166 9.70711 11.7071L13 15M13 15L15.7929 12.2071C16.1834 11.8166 16.8166 11.8166 17.2071 12.2071L20 15M13 15L15.25 17.25" stroke=${this.attachmentIconColor || '#000'} stroke-width="1.536" stroke-linecap="round" stroke-linejoin="round"></path> <path d="M18.5 3V5.5M18.5 8V5.5M18.5 5.5H16M18.5 5.5H21" stroke=${this.attachmentIconColor || '#000'} stroke-width="1.536" stroke-linecap="round" stroke-linejoin="round"></path> </g></svg>
</div>
${
this.isAttachmentMenuVisible
? ClockMark.ke`
<div class="attachment-menu">
<attachment-box
.documentIcon=${'https://flexcrew.s3.us-west-1.amazonaws.com/document_text_svgrepo_com_1_2583e4b5fc.svg'}
.mediaIcon=${'https://flexcrew.s3.us-west-1.amazonaws.com/image_svgrepo_com_2f478c0a9b.svg'}
.mediaIconHeight=${'25px'}
.mediaIconWidth=${'25px'}
.documentIconHeight=${'25px'}
.documentIconWidth=${'25px'}
.flexDirection=${'column'}
.bgColor=${'white'}
.onMediaIconClick="${this.mediaIconHandler}"
.onDocumentIconClick="${this.onDocumentClick}"
.onFileUploaded="${this.onFileUploaded}"
@file-uploaded="${event => this.fileUploadHandler(event)}"
>
</attachment-box>
</div>
`
: ''
}
<div class='input-box-container som'>
<my-input
.value="${this.inputValue}"
.borderColor="${this.inputBorderColor || 'gray'}"
.borderWidth="${this.inputBorderWidth || '1px'}"
.borderRadius="${this.inputBorderRadius} || "10px"
.backgroundColor=${this.inputBgColor || '#ffffff'}
.fontSize="${this.inputFontSize || '14px'}"
.padding="10px"
.placeholder="${this.inputPlaceholder || 'Type your message'}"
.color=${this.inputFontColor}
.placeholderColor=${this.inputPlaceholderColor || '#000'}
@input="${this.handleInputChange}"
></my-input>
</div>
</div>
<div class='send-container' >
${
this.sendButtonIcon
? DocumentMessageBubble.Button({
backgroundImage: this.sendButtonIcon,
width: this.sendButtonIconWidth,
height: this.sendButtonIconHeight,
borderWidth: '0px',
borderColor: 'transparent',
borderRadius: this.sendButtonIconRadius,
onClick: () => {
this.onSendClick();
this.resetInputHeight();
},
})
: ''
}
</div>
</div>
`;
}
}
customElements.define('my-test-footer', TestFooter);
class AttachmentPreview extends ClockMark.h {
static properties = {
bgColor: { type: String },
textColor: { type: String },
width: { type: String },
padding: { type: String },
borderRadius: { type: String },
borderWidth: { type: String },
borderColor: { type: String },
onClose: { type: Function },
fontSize: { type: String },
fontWeight: { type: String },
fontFamily: { type: String },
content: { type: String }, // Can be a media URL or document name
height: { type: String },
contentType: { type: String }, // Type of content (e.g., 'image', 'video', 'document')
};
static styles = ClockMark.i$1`
.close-button {
cursor: pointer;
background: none;
border: none;
font-size: 20px;
position: absolute;
right: -5px;
top: -5px;
padding: 0px;
border-radius: 50%;
height: 14px;
width: 14px;
aspect-ratio: 1:1
}
.attachment-preview-container {
display: flex;
align-items: center;
position: absolute;
bottom:70px;
margin-left: 10px;
}
.document-preview {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
}
.document-name {
max-width: 90%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
`;
render() {
return ClockMark.ke`
<div
class="attachment-preview-container"
style="background-color: ${this.bgColor}; width: ${this.width};
border-radius: ${this.borderRadius}; border-width: ${this.borderWidth}; border-color: ${this.borderColor};
padding: ${this.padding}; height: ${this.height};"
>
<div class="attachment-details" style="height: ${this.height}; width: ${this.width}">
${
this.contentType === 'image'
? Image.Image({
src: this.content,
alt: 'attachment-preview',
height: '100%',
width: '100%',
objectFit: 'cover',
})
: this.contentType === 'video'
? ClockMark.ke`<video src="${this.content}" controls width="100%" height="100%" style="object-fit: cover;"></video>`
: ClockMark.ke`
<div class="document-preview">
<span class="document-icon">
<svg
width="64px"
height="64px"
viewBox="0 0 1024 1024"
class="icon"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
fill="#000000"
data-darkreader-inline-fill=""
style="--darkreader-inline-fill: #000000;"
>
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path
d="M719.8 651.8m-10 0a10 10 0 1 0 20 0 10 10 0 1 0-20 0Z"
fill="#EFF1FA"
style="--darkreader-inline-fill: #cddcef;"
data-darkreader-inline-fill=""
></path>
<path