UNPKG

@cometchat/chat-uikit-angular

Version:

Ready-to-use Chat UI Components for Angular (JavaScript/Web)

785 lines 121 kB
import { ChangeDetectionStrategy, Component, ElementRef, Input, ViewChildren, } from "@angular/core"; import { CometChat } from "@cometchat/chat-sdk-javascript"; import { AvatarStyle, ListItemStyle, } from "@cometchat/uikit-elements"; import { SelectionMode, localize, TitleAlignment, States, CometChatUserEvents, fontHelper, } from "@cometchat/uikit-resources"; import { UsersStyle, SelectedUserPreviewStyle } from "@cometchat/uikit-shared"; import { CometChatException } from "../../Shared/Utils/ComeChatException"; import { UserPresencePlacement } from "@cometchat/uikit-resources"; import { MessageUtils } from "../../Shared/Utils/MessageUtils"; import * as i0 from "@angular/core"; import * as i1 from "../../CometChatTheme.service"; import * as i2 from "../../CometChatList/cometchat-list.component"; import * as i3 from "@angular/common"; export class CometChatUsersComponent { constructor(ref, themeService) { this.ref = ref; this.themeService = themeService; this.disableUsersPresence = false; this.hideSeparator = false; this.searchPlaceholder = localize("SEARCH"); this.hideError = false; this.selectionMode = SelectionMode.none; this.searchIconURL = "assets/search.svg"; this.hideSearch = false; this.title = localize("USERS"); this.onError = (error) => { console.log(error); }; this.loadingIconURL = "assets/Spinner.svg"; this.showSectionHeader = true; this.sectionHeaderField = "name"; this.emptyStateText = localize("NO_USERS_FOUND"); this.errorStateText = localize("SOMETHING_WRONG"); this.titleAlignment = TitleAlignment.left; this.usersStyle = { width: "100%", height: "100%", separatorColor: "rgb(222 222 222 / 46%)", }; this.listItemStyle = { height: "100%", width: "100%", }; this.statusIndicatorStyle = { height: "10px", width: "10px", borderRadius: "16px", }; this.avatarStyle = { borderRadius: "16px", width: "28px", height: "28px", }; this.selectedUserPreviewStyle = {}; this.showSelectedUsersPreview = false; this.searchKeyword = ""; this.userPresencePlacement = UserPresencePlacement.bottom; this.disableLoadingState = false; this.fetchingUsers = false; this.userChecked = ""; this.listStyle = {}; this.state = States.loading; this.selectionmodeEnum = SelectionMode; this.usersList = []; this.limit = 30; this.userListenerId = "userlist_" + new Date().getTime(); this.firstReload = false; this.connectionListenerId = "connection_" + new Date().getTime(); this.previousSearchKeyword = ""; this.isWebsocketReconnected = false; this.selectedUsers = {}; this.checkboxStyle = { height: "24px", width: "24px", border: "none", borderRadius: "4px", checkedBackgroundColor: "#2196F3", uncheckedBackgroundColor: "#ccc" }; this.removeMemberButtonStyle = { height: "16px", width: "16px", iconHeight: "16px", iconWidth: "16px", border: "none", borderRadius: "50%", background: "transparent", buttonIconTint: "black" }; this.selectedUsersPreviewWrapper = {}; // Bulk selection properties this.lastSelectedIndex = -1; this.isShiftPressed = false; this.selectedUserPillStyle = {}; this.onScrolledToBottom = null; this.fetchUsersOnSearchKeyWordChange = () => { if (this.fetchingUsers) { clearTimeout(this.fetchTimeOut); this.fetchTimeOut = setTimeout(() => { this.searchForUser(); }, 800); } else { this.searchForUser(); } }; this.searchForUser = () => { this.setRequestBuilder(); if (!this.disableLoadingState) { this.usersList = []; } this.fetchNextUsersList(); }; /** * @param {CometChat.User} user */ this.onClick = (user) => { if (this.onItemClick) { this.onItemClick(user); } this.onRowClicked(user.getUid()); }; /** * @param {CometChat.User} user */ this.getActiveUser = (user) => { if (this.selectionMode == SelectionMode.none || !this.selectionMode) { if (user.getUid() == this.activeUser?.getUid()) { return true; } else { return false; } } else return false; }; /** * @param {CometChat.User} user */ this.getStatusIndicatorColor = (user) => { let userStatusVisibility = new MessageUtils().getUserStatusVisibility(user) || this.disableUsersPresence; if (!userStatusVisibility) { return (this.usersStyle?.onlineStatusColor ?? this.themeService?.theme.palette.getSuccess()); } return null; }; /** * @param {CometChat.User} user */ this.getStatusIndicatorStyle = (user) => { let userStatusVisibility = new MessageUtils().getUserStatusVisibility(user) || this.disableUsersPresence; if (!userStatusVisibility) { return (this.statusIndicatorStyle); } return null; }; /** * @param {CometChat.User} user */ this.updateUser = (user) => { let userlist = [...this.usersList]; //search for user let userKey = userlist.findIndex((u, k) => u.getUid() == user.getUid()); //if found in the list, update user object if (userKey > -1) { userlist.splice(userKey, 1, user); this.usersList = [...userlist]; this.ref.detectChanges(); } }; this.addMembersToList = (user, event) => { let selected = event?.detail?.checked; const currentIndex = this.usersList.findIndex(u => u.getUid() === user.getUid()); // Check if shift key was pressed for bulk selection if (this.isShiftPressed && this.lastSelectedIndex !== -1 && currentIndex !== -1) { this.handleBulkSelection(currentIndex, selected); } else { // Regular single selection if (this.selectionMode === this.selectionmodeEnum.single) { this.userChecked = user.getUid(); } if (this.onSelect) { this.onSelect(user, selected); } if (selected) { this.selectedUsers[user.getUid()] = user; } else { delete this.selectedUsers[user.getUid()]; } this.lastSelectedIndex = currentIndex; } this.ref.detectChanges(); }; /** * Handle checkbox click to detect shift key */ this.onCheckboxClick = (user, event) => { this.isShiftPressed = event.shiftKey; }; /** * Handle checkbox changed event */ this.onCheckboxChanged = (user, event) => { this.addMembersToList(user, event); // Reset shift flag after processing this.isShiftPressed = false; }; /** * Handle keyboard events for accessibility */ this.onKeyDown = (event) => { // Track shift key state for keyboard navigation if (event.key === 'Shift') { this.isShiftPressed = true; } }; /** * Handle keyboard events for accessibility */ this.onKeyUp = (event) => { if (event.key === 'Shift') { this.isShiftPressed = false; } }; this.fetchNextUsersList = (state = States.loading) => { this.onScrolledToBottom = null; if (!(this.disableLoadingState && state == States.loading)) { this.state = state; } if (this.requestBuilder && this.requestBuilder.pagination && (this.requestBuilder.pagination.current_page == 0 || this.requestBuilder.pagination.current_page != this.requestBuilder.pagination.total_pages)) { this.fetchingUsers = true; this.onScrolledToBottom = this.fetchNextUsersList; this.ref.detectChanges(); try { this.requestBuilder.fetchNext().then((userList) => { console.log(userList); if (userList.length <= 0) { if (this.onEmpty) { this.onEmpty(); this.previousSearchKeyword = ""; } } if (userList.length <= 0 && (this.usersList?.length <= 0 || this.disableLoadingState)) { this.state = States.empty; this.ref.detectChanges(); } else { if (!this.disableLoadingState) { if (this.isWebsocketReconnected) { this.usersList = userList; this.isWebsocketReconnected = false; } else { this.usersList = [...this.usersList, ...userList]; } } else { if (this.searchKeyword != this.previousSearchKeyword || [0, 1].includes(this.requestBuilder.pagination.current_page)) { this.usersList = userList; } else { this.usersList = [...this.usersList, ...userList]; } } this.state = States.loaded; this.ref.detectChanges(); } if (this.firstReload) { this.attachConnectionListeners(); this.firstReload = false; } this.fetchingUsers = false; this.previousSearchKeyword = this.searchKeyword; }, (error) => { if (this.onError) { this.onError(CometChatException(error)); } this.state = States.error; this.fetchingUsers = false; this.ref.detectChanges(); }); } catch (error) { if (this.onError) { this.onError(CometChatException(error)); } if (this.usersList?.length <= 0) { this.state = States.error; this.ref.detectChanges(); } this.fetchingUsers = false; } } }; /** * @param {string} key */ this.onSearch = (key) => { try { this.searchKeyword = key; clearTimeout(this.timeout); this.timeout = setTimeout(() => { this.setRequestBuilder(); if (!this.disableLoadingState) { this.usersList = []; this.ref.detectChanges(); } if (!this.fetchingUsers || (this.fetchingUsers && key == "")) { this.usersList = []; this.fetchNextUsersList(); } }, 500); } catch (error) { if (this.onError) { this.onError(CometChatException(error)); } } }; this.userStyle = () => { return { height: this.usersStyle.height, width: this.usersStyle.width, background: this.usersStyle.background, border: this.usersStyle.border, borderRadius: this.usersStyle.borderRadius, }; }; this.state = States.loading; } ngOnInit() { this.firstReload = true; this.state = States.loading; this.isWebsocketReconnected = false; this.setThemeStyle(); this.subscribeToEvents(); CometChat.getLoggedinUser() .then((user) => { this.setRequestBuilder(); if (!this.fetchingUsers) { this.fetchNextUsersList(); } this.attachListeners(); this.loggedInUser = user; this.onScrolledToBottom = this.fetchNextUsersList; }) .catch((error) => { if (this.onError) { this.onError(error); } }); } ngOnChanges(changes) { if (changes["searchKeyword"]) { this.fetchUsersOnSearchKeyWordChange(); } } onUserSelected(user, event) { let selected = event?.detail?.checked; if (this.onSelect) { this.onSelect(user, selected); } } fetchNewUsers() { this.setRequestBuilder(); let state = this.firstReload ? States.loading : States.loaded; this.fetchNextUsersList(state); } // subscribe to global events subscribeToEvents() { this.ccUserBlocked = CometChatUserEvents.ccUserBlocked.subscribe((user) => { if (this.activeUser && user.getUid() == this.activeUser.getUid()) { this.activeUser = user; this.updateUser(user); this.ref.detectChanges(); } }); this.ccUserUnBlocked = CometChatUserEvents.ccUserUnblocked.subscribe((user) => { if (this.activeUser && user.getUid() == this.activeUser.getUid()) { this.activeUser = user; this.updateUser(user); this.ref.detectChanges(); } }); } unsubscribeToEvents() { this.ccUserBlocked?.unsubscribe(); this.ccUserUnBlocked?.unsubscribe(); } ngOnDestroy() { this.usersRequest = null; this.ref.detach(); this.removeListener(); this.state = States.loaded; this.unsubscribeToEvents(); } isUserSelected(user) { return user.getUid() === this.userChecked || this.selectedUsers?.[user.getUid()]; } onRowClicked(uid) { const userCheckbox = this.checkboxes.find(checkboxRef => uid === checkboxRef.nativeElement.getAttribute('data-uid')); const userRadio = this.radios.find(radioRef => uid === radioRef.nativeElement.getAttribute('data-uid')); let input = null; if (userCheckbox && this.selectionMode === this.selectionmodeEnum.multiple) { const root = userCheckbox.nativeElement.shadowRoot || userCheckbox.nativeElement; input = root.querySelector('input[type="checkbox"]'); } else if (userRadio && this.selectionMode === this.selectionmodeEnum.single) { const root = userRadio.nativeElement.shadowRoot || userRadio.nativeElement; input = root.querySelector('input[type="radio"]'); } if (input) input.click(); } attachConnectionListeners() { CometChat.addConnectionListener(this.connectionListenerId, new CometChat.ConnectionListener({ onConnected: () => { this.isWebsocketReconnected = true; console.log("ConnectionListener =>connected"); this.fetchNewUsers(); }, inConnecting: () => { console.log("ConnectionListener => In connecting"); }, onDisconnected: () => { this.isWebsocketReconnected = false; console.log("ConnectionListener => On Disconnected"); }, })); } attachListeners() { this.state = States.loading; this.ref.detectChanges(); //Attaching User Listeners to dynamilcally update when a user comes online and goes offline CometChat.addUserListener(this.userListenerId, new CometChat.UserListener({ onUserOnline: (onlineUser) => { /* when someuser/friend comes online, user will be received here */ this.updateUser(onlineUser); }, onUserOffline: (offlineUser) => { /* when someuser/friend went offline, user will be received here */ this.updateUser(offlineUser); }, })); } removeListener() { CometChat.removeUserListener(this.userListenerId); this.userListenerId = ""; CometChat.removeConnectionListener(this.connectionListenerId); } getUserNameStyle() { return { font: this.selectedUserPreviewStyle.textFont || fontHelper(this.themeService.theme.typography.name), color: this.selectedUserPreviewStyle.textColor || this.themeService.theme.palette.getAccent(), }; } /** * Handle bulk selection when shift+click is used */ handleBulkSelection(currentIndex, selected) { const startIndex = Math.min(this.lastSelectedIndex, currentIndex); const endIndex = Math.max(this.lastSelectedIndex, currentIndex); const shouldSelect = selected; // Apply selection/deselection to all users in range for (let i = startIndex; i <= endIndex; i++) { const user = this.usersList[i]; if (user) { const wasSelected = !!this.selectedUsers[user.getUid()]; if (shouldSelect && !wasSelected) { this.selectedUsers[user.getUid()] = user; if (this.onSelect) { this.onSelect(user, true); } this.updateCheckboxState(user.getUid(), true); } else if (!shouldSelect && wasSelected) { delete this.selectedUsers[user.getUid()]; if (this.onSelect) { this.onSelect(user, false); } this.updateCheckboxState(user.getUid(), false); } } } this.lastSelectedIndex = currentIndex; } /** * Update checkbox state programmatically */ updateCheckboxState(userId, checked) { setTimeout(() => { if (this.checkboxes) { const userCheckbox = this.checkboxes.find(checkboxRef => userId === checkboxRef.nativeElement.getAttribute('data-uid')); if (userCheckbox) { const root = userCheckbox.nativeElement.shadowRoot || userCheckbox.nativeElement; const input = root.querySelector('input[type="checkbox"]'); if (input && input.checked !== checked) { input.checked = checked; const changeEvent = new Event('change', { bubbles: true }); input.dispatchEvent(changeEvent); } } } }, 0); } /** * Get array of selected users for preview */ getSelectedUsersArray() { return Object.values(this.selectedUsers); } /** * Get count of selected users */ getSelectedUsersCount() { return Object.keys(this.selectedUsers).length; } /** * Remove user from selection by triggering checkbox click */ removeSelectedUser(user) { const userCheckbox = this.checkboxes.find(checkboxRef => user.getUid() === checkboxRef.nativeElement.getAttribute('data-uid')); if (userCheckbox) { const root = userCheckbox.nativeElement.shadowRoot || userCheckbox.nativeElement; const input = root.querySelector('input[type="checkbox"]'); if (input) { input.click(); } } } /** * Track by function for ngFor performance */ trackByUserId(index, user) { return user.getUid(); } setRequestBuilder() { if (!this.searchKeyword) { this.previousSearchKeyword = ""; } if (this.searchRequestBuilder && this.searchKeyword) { this.requestBuilder = this.searchRequestBuilder .setSearchKeyword(this.searchKeyword) .build(); } else if (this.usersRequestBuilder) { this.requestBuilder = this.usersRequestBuilder .setSearchKeyword(this.searchKeyword) .build(); } else { this.requestBuilder = new CometChat.UsersRequestBuilder() .setLimit(this.limit) .setSearchKeyword(this.searchKeyword) .build(); } return this.requestBuilder; } setThemeStyle() { this.setUsersStyle(); this.setListItemStyle(); this.setAvatarStyle(); this.setStatusStyle(); this.setSelectedUserStyle(); this.listStyle = { titleTextFont: this.usersStyle.titleTextFont, titleTextColor: this.usersStyle.titleTextColor, emptyStateTextFont: this.usersStyle.emptyStateTextFont, emptyStateTextColor: this.usersStyle.emptyStateTextColor, errorStateTextFont: this.usersStyle.errorStateTextFont, errorStateTextColor: this.usersStyle.errorStateTextColor, loadingIconTint: this.usersStyle.loadingIconTint, separatorColor: this.usersStyle.separatorColor, searchIconTint: this.usersStyle.searchIconTint, searchBorder: this.usersStyle.searchBorder, searchBorderRadius: this.usersStyle.searchBorderRadius, searchBackground: this.usersStyle.searchBackground, searchPlaceholderTextFont: this.usersStyle.searchPlaceholderTextFont, searchPlaceholderTextColor: this.usersStyle.searchPlaceholderTextColor, searchTextFont: this.usersStyle.searchTextFont, searchTextColor: this.usersStyle.searchTextColor, sectionHeaderTextColor: this.usersStyle.sectionHeaderTextColor, sectionHeaderTextFont: this.usersStyle.sectionHeaderTextFont, }; this.ref.detectChanges(); } setListItemStyle() { let defaultStyle = new ListItemStyle({ height: "45px", width: "100%", background: this.themeService.theme.palette.getBackground(), activeBackground: this.themeService.theme.palette.getAccent100(), borderRadius: "0", titleFont: fontHelper(this.themeService.theme.typography.title2), titleColor: this.themeService.theme.palette.getAccent(), border: "none", separatorColor: this.themeService.theme.palette.getAccent200(), hoverBackground: this.themeService.theme.palette.getAccent50(), }); this.listItemStyle = { ...defaultStyle, ...this.listItemStyle }; } setAvatarStyle() { let defaultStyle = new AvatarStyle({ borderRadius: "24px", width: "28px", height: "28px", border: "none", backgroundColor: this.themeService.theme.palette.getAccent700(), nameTextColor: this.themeService.theme.palette.getAccent900(), backgroundSize: "cover", nameTextFont: fontHelper(this.themeService.theme.typography.subtitle1), outerViewBorderSpacing: "", }); this.avatarStyle = { ...defaultStyle, ...this.avatarStyle }; } setStatusStyle() { let defaultStyle = { height: "12px", width: "12px", border: "none", borderRadius: "24px", }; this.statusIndicatorStyle = { ...defaultStyle, ...this.statusIndicatorStyle, }; } setUsersStyle() { let defaultStyle = new UsersStyle({ background: this.themeService.theme.palette.getBackground(), border: `1px solid ${this.themeService.theme.palette.getAccent50()}`, titleTextFont: fontHelper(this.themeService.theme.typography.title1), titleTextColor: this.themeService.theme.palette.getAccent(), emptyStateTextFont: fontHelper(this.themeService.theme.typography.title1), emptyStateTextColor: this.themeService.theme.palette.getAccent600(), errorStateTextFont: fontHelper(this.themeService.theme.typography.title1), errorStateTextColor: this.themeService.theme.palette.getAccent600(), loadingIconTint: this.themeService.theme.palette.getAccent600(), separatorColor: this.themeService.theme.palette.getAccent400(), onlineStatusColor: this.themeService.theme.palette.getSuccess(), sectionHeaderTextColor: this.themeService.theme.palette.getAccent600(), sectionHeaderTextFont: fontHelper(this.themeService.theme.typography.subtitle2), searchIconTint: this.themeService.theme.palette.getAccent600(), searchPlaceholderTextColor: this.themeService.theme.palette.getAccent600(), searchBackground: this.themeService.theme.palette.getAccent100(), searchPlaceholderTextFont: fontHelper(this.themeService.theme.typography.text3), searchTextColor: this.themeService.theme.palette.getAccent600(), searchTextFont: fontHelper(this.themeService.theme.typography.text3), }); this.usersStyle = { ...defaultStyle, ...this.usersStyle }; this.checkboxStyle = { height: "24px", width: "24px", border: "none", borderRadius: "4px", checkedBackgroundColor: this.themeService.theme.palette.getPrimary(), uncheckedBackgroundColor: this.themeService.theme.palette.getAccent400() }; } setSelectedUserStyle() { let defaultStyle = new SelectedUserPreviewStyle({ borderRadius: "1000px", width: "140px", height: "fit-content", border: `1px solid ${this.themeService.theme.palette.getAccent50()}`, textColor: this.themeService.theme.palette.getAccent(), textFont: fontHelper(this.themeService.theme.typography.name), background: this.themeService.theme.palette.getBackground(), closeIconTint: this.themeService.theme.palette.getPrimary(), }); this.selectedUserPreviewStyle = { ...defaultStyle, ...this.selectedUserPreviewStyle }; this.removeMemberButtonStyle.buttonIconTint = this.selectedUserPreviewStyle.closeIconTint || this.themeService.theme.palette.getAccent600(); this.selectedUserPillStyle = { borderRadius: this.selectedUserPreviewStyle.borderRadius || "1000px", width: this.selectedUserPreviewStyle.width || "140px", height: this.selectedUserPreviewStyle.height || "fit-content", border: this.selectedUserPreviewStyle.border || `none`, color: this.selectedUserPreviewStyle.textColor || this.themeService.theme.palette.getAccent(), font: this.selectedUserPreviewStyle.textFont || fontHelper(this.themeService.theme.typography.name), background: this.selectedUserPreviewStyle.background || this.themeService.theme.palette.getBackground(), }; this.selectedUsersPreviewWrapper = { borderTop: `1px solid ${this.themeService.theme.palette.getAccent100()}`, borderBottom: `none`, background: this.usersStyle.background || "transparent" }; } } CometChatUsersComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CometChatUsersComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.CometChatThemeService }], target: i0.ɵɵFactoryTarget.Component }); CometChatUsersComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: CometChatUsersComponent, selector: "cometchat-users", inputs: { usersRequestBuilder: "usersRequestBuilder", searchRequestBuilder: "searchRequestBuilder", subtitleView: "subtitleView", disableUsersPresence: "disableUsersPresence", listItemView: "listItemView", menu: "menu", options: "options", activeUser: "activeUser", hideSeparator: "hideSeparator", searchPlaceholder: "searchPlaceholder", hideError: "hideError", selectionMode: "selectionMode", searchIconURL: "searchIconURL", hideSearch: "hideSearch", title: "title", onError: "onError", emptyStateView: "emptyStateView", onSelect: "onSelect", errorStateView: "errorStateView", loadingIconURL: "loadingIconURL", showSectionHeader: "showSectionHeader", sectionHeaderField: "sectionHeaderField", loadingStateView: "loadingStateView", emptyStateText: "emptyStateText", errorStateText: "errorStateText", titleAlignment: "titleAlignment", usersStyle: "usersStyle", listItemStyle: "listItemStyle", statusIndicatorStyle: "statusIndicatorStyle", avatarStyle: "avatarStyle", selectedUserPreviewStyle: "selectedUserPreviewStyle", showSelectedUsersPreview: "showSelectedUsersPreview", onItemClick: "onItemClick", searchKeyword: "searchKeyword", onEmpty: "onEmpty", userPresencePlacement: "userPresencePlacement", disableLoadingState: "disableLoadingState" }, viewQueries: [{ propertyName: "checkboxes", predicate: ["checkboxElement"], descendants: true, read: ElementRef }, { propertyName: "radios", predicate: ["radioElement"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cc-users\" [ngStyle]=\"userStyle()\" (keydown)=\"onKeyDown($event)\" (keyup)=\"onKeyUp($event)\" tabindex=\"0\">\n <div class=\"cc-menus\" *ngIf=\"menu\">\n <ng-container *ngTemplateOutlet=\"menu\">\n </ng-container>\n </div>\n\n <!-- Users List -->\n <div class=\"cc-users__list\" [class.cc-users__list--with-selection]=\"getSelectedUsersCount() > 0\">\n <cometchat-list [listItemView]=\"listItemView ? listItemView : listItem\" [onScrolledToBottom]=\"onScrolledToBottom\" [onSearch]=\"onSearch\"\n [list]=\"usersList\" [searchText]=\"searchKeyword\" [searchPlaceholderText]=\"searchPlaceholder\"\n [searchIconURL]=\"searchIconURL\" [hideSearch]=\"hideSearch\" [hideError]=\"hideError\" [title]=\"title\"\n [sectionHeaderField]=\"sectionHeaderField\" [showSectionHeader]=\"showSectionHeader\"\n [emptyStateText]=\"emptyStateText\" [loadingIconURL]=\"loadingIconURL\"\n [titleAlignment]=\"titleAlignment\" [loadingStateView]=\"loadingStateView\" [emptyStateView]=\"emptyStateView\"\n [errorStateText]=\"errorStateText\" [errorStateView]=\"errorStateView\" [listStyle]=\"listStyle\" [state]=\"state\">\n </cometchat-list>\n </div>\n\n <!-- Selected Users Preview Section -->\n <div class=\"cc-selected-users\" [style]=\"selectedUsersPreviewWrapper\" *ngIf=\"showSelectedUsersPreview && getSelectedUsersCount() > 0\">\n <div class=\"cc-selected-users__list\">\n <div class=\"cc-selected-user\" *ngFor=\"let user of getSelectedUsersArray(); trackBy: trackByUserId\" [style]=\"selectedUserPillStyle\">\n <div class=\"cc-selected-user__avatar\">\n <cometchat-avatar \n [image]=\"user?.getAvatar() || ''\" \n [name]=\"user?.getName()\" \n [avatarStyle]=\"avatarStyle\">\n </cometchat-avatar>\n </div>\n <div class=\"cc-selected-user__name\" [style]=\"getUserNameStyle()\">{{user?.getName()}}</div>\n <div class=\"cc-selected-user__remove\" (click)=\"removeSelectedUser(user)\">\n <cometchat-button \n [iconURL]=\"'assets/close2x.svg'\" \n [buttonStyle]=\"removeMemberButtonStyle\">\n </cometchat-button>\n </div>\n </div>\n </div>\n </div>\n <ng-template #listItem let-user>\n <cometchat-list-item [title]=\"user?.name\" [avatarURL]=\"user?.avatar\" [avatarName]=\"user?.name\"\n [listItemStyle]=\"listItemStyle\" [avatarStyle]=\"avatarStyle\" [statusIndicatorStyle]=\"getStatusIndicatorStyle(user)\"\n [statusIndicatorColor]=\"getStatusIndicatorColor(user)\" [hideSeparator]=\"hideSeparator\" (cc-listitem-clicked)=\"onClick(user)\" [isActive]=\"getActiveUser(user)\"\n [userPresencePlacement]=\"userPresencePlacement\">\n <div slot=\"subtitleView\" *ngIf=\"subtitleView\">\n <ng-container *ngTemplateOutlet=\"subtitleView;context:{ $implicit: user }\">\n </ng-container>\n </div>\n\n <div slot=\"menuView\" class=\"cc-users__options\" *ngIf=\"options\">\n <cometchat-menu-list [data]=\"options(user)\">\n\n </cometchat-menu-list>\n </div>\n <div slot=\"tailView\" *ngIf=\"selectionMode != selectionmodeEnum.none\" class=\"cc-users__tail-view\">\n <ng-container *ngTemplateOutlet=\"tailView\">\n </ng-container>\n </div>\n <ng-template #tailView>\n <div *ngIf=\"selectionMode == selectionmodeEnum.single\" class=\"cc-users__selection--single\">\n <cometchat-radio-button [attr.data-uid]=\"user?.uid\" #radioElement (cc-radio-button-changed)=\"addMembersToList(user,$event)\" [checked]=\"isUserSelected(user)\" ></cometchat-radio-button>\n\n </div>\n <div *ngIf=\"selectionMode == selectionmodeEnum.multiple\" class=\"cc-users__selection--multiple\">\n <cometchat-checkbox \n [attr.data-uid]=\"user?.uid\" \n #checkboxElement \n [checkboxStyle]=\"checkboxStyle\" \n (cc-checkbox-changed)=\"onCheckboxChanged(user, $event)\"\n (click)=\"onCheckboxClick(user, $event)\" \n [checked]=\"isUserSelected(user)\">\n </cometchat-checkbox>\n </div>\n </ng-template>\n </cometchat-list-item>\n\n </ng-template>\n</div>\n", styles: [".cc-users{height:100%;width:100%;box-sizing:border-box;display:flex;flex-direction:column;overflow:hidden}.cc-menus{position:absolute;right:12px;padding:12px;cursor:pointer}.cc-selected-users{padding:12px;background:transparent;max-height:150px;overflow-x:hidden;overflow-y:auto}.cc-selected-users__list{display:flex;flex-wrap:wrap;gap:8px}.cc-selected-user{display:flex;align-items:center;border-radius:20px;padding:4px 8px 4px 4px;width:140px;animation:slideInUp .3s ease-out}.cc-selected-user__avatar{flex-shrink:0}.cc-selected-user__name{flex:1;margin:0 8px;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cc-selected-user__remove{flex-shrink:0;cursor:pointer}.cc-selected-user__remove:hover{opacity:.7}.cc-users__list{flex:1;overflow:hidden}.cc-selected-users::-webkit-scrollbar{background:transparent;width:8px}.cc-selected-users::-webkit-scrollbar-thumb{background:#e8e5e5;border-radius:8px}.cc-users__list--with-selection .cc-users__selection--multiple{position:relative}@keyframes slideInUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}\n"], components: [{ type: i2.CometchatListComponent, selector: "cometchat-list", inputs: ["listItemView", "onScrolledToBottom", "onScrolledToTop", "list", "onSearch", "getSectionHeader", "searchText", "searchIconURL", "listStyle", "searchPlaceholderText", "hideSearch", "hideError", "title", "titleAlignment", "errorStateView", "loadingStateView", "emptyStateView", "state", "errorStateText", "emptyStateText", "loadingIconURL", "showSectionHeader", "sectionHeaderField", "DateSeparatorPattern", "dateSeparatorStyle"] }], directives: [{ type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: CometChatUsersComponent, decorators: [{ type: Component, args: [{ selector: "cometchat-users", changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cc-users\" [ngStyle]=\"userStyle()\" (keydown)=\"onKeyDown($event)\" (keyup)=\"onKeyUp($event)\" tabindex=\"0\">\n <div class=\"cc-menus\" *ngIf=\"menu\">\n <ng-container *ngTemplateOutlet=\"menu\">\n </ng-container>\n </div>\n\n <!-- Users List -->\n <div class=\"cc-users__list\" [class.cc-users__list--with-selection]=\"getSelectedUsersCount() > 0\">\n <cometchat-list [listItemView]=\"listItemView ? listItemView : listItem\" [onScrolledToBottom]=\"onScrolledToBottom\" [onSearch]=\"onSearch\"\n [list]=\"usersList\" [searchText]=\"searchKeyword\" [searchPlaceholderText]=\"searchPlaceholder\"\n [searchIconURL]=\"searchIconURL\" [hideSearch]=\"hideSearch\" [hideError]=\"hideError\" [title]=\"title\"\n [sectionHeaderField]=\"sectionHeaderField\" [showSectionHeader]=\"showSectionHeader\"\n [emptyStateText]=\"emptyStateText\" [loadingIconURL]=\"loadingIconURL\"\n [titleAlignment]=\"titleAlignment\" [loadingStateView]=\"loadingStateView\" [emptyStateView]=\"emptyStateView\"\n [errorStateText]=\"errorStateText\" [errorStateView]=\"errorStateView\" [listStyle]=\"listStyle\" [state]=\"state\">\n </cometchat-list>\n </div>\n\n <!-- Selected Users Preview Section -->\n <div class=\"cc-selected-users\" [style]=\"selectedUsersPreviewWrapper\" *ngIf=\"showSelectedUsersPreview && getSelectedUsersCount() > 0\">\n <div class=\"cc-selected-users__list\">\n <div class=\"cc-selected-user\" *ngFor=\"let user of getSelectedUsersArray(); trackBy: trackByUserId\" [style]=\"selectedUserPillStyle\">\n <div class=\"cc-selected-user__avatar\">\n <cometchat-avatar \n [image]=\"user?.getAvatar() || ''\" \n [name]=\"user?.getName()\" \n [avatarStyle]=\"avatarStyle\">\n </cometchat-avatar>\n </div>\n <div class=\"cc-selected-user__name\" [style]=\"getUserNameStyle()\">{{user?.getName()}}</div>\n <div class=\"cc-selected-user__remove\" (click)=\"removeSelectedUser(user)\">\n <cometchat-button \n [iconURL]=\"'assets/close2x.svg'\" \n [buttonStyle]=\"removeMemberButtonStyle\">\n </cometchat-button>\n </div>\n </div>\n </div>\n </div>\n <ng-template #listItem let-user>\n <cometchat-list-item [title]=\"user?.name\" [avatarURL]=\"user?.avatar\" [avatarName]=\"user?.name\"\n [listItemStyle]=\"listItemStyle\" [avatarStyle]=\"avatarStyle\" [statusIndicatorStyle]=\"getStatusIndicatorStyle(user)\"\n [statusIndicatorColor]=\"getStatusIndicatorColor(user)\" [hideSeparator]=\"hideSeparator\" (cc-listitem-clicked)=\"onClick(user)\" [isActive]=\"getActiveUser(user)\"\n [userPresencePlacement]=\"userPresencePlacement\">\n <div slot=\"subtitleView\" *ngIf=\"subtitleView\">\n <ng-container *ngTemplateOutlet=\"subtitleView;context:{ $implicit: user }\">\n </ng-container>\n </div>\n\n <div slot=\"menuView\" class=\"cc-users__options\" *ngIf=\"options\">\n <cometchat-menu-list [data]=\"options(user)\">\n\n </cometchat-menu-list>\n </div>\n <div slot=\"tailView\" *ngIf=\"selectionMode != selectionmodeEnum.none\" class=\"cc-users__tail-view\">\n <ng-container *ngTemplateOutlet=\"tailView\">\n </ng-container>\n </div>\n <ng-template #tailView>\n <div *ngIf=\"selectionMode == selectionmodeEnum.single\" class=\"cc-users__selection--single\">\n <cometchat-radio-button [attr.data-uid]=\"user?.uid\" #radioElement (cc-radio-button-changed)=\"addMembersToList(user,$event)\" [checked]=\"isUserSelected(user)\" ></cometchat-radio-button>\n\n </div>\n <div *ngIf=\"selectionMode == selectionmodeEnum.multiple\" class=\"cc-users__selection--multiple\">\n <cometchat-checkbox \n [attr.data-uid]=\"user?.uid\" \n #checkboxElement \n [checkboxStyle]=\"checkboxStyle\" \n (cc-checkbox-changed)=\"onCheckboxChanged(user, $event)\"\n (click)=\"onCheckboxClick(user, $event)\" \n [checked]=\"isUserSelected(user)\">\n </cometchat-checkbox>\n </div>\n </ng-template>\n </cometchat-list-item>\n\n </ng-template>\n</div>\n", styles: [".cc-users{height:100%;width:100%;box-sizing:border-box;display:flex;flex-direction:column;overflow:hidden}.cc-menus{position:absolute;right:12px;padding:12px;cursor:pointer}.cc-selected-users{padding:12px;background:transparent;max-height:150px;overflow-x:hidden;overflow-y:auto}.cc-selected-users__list{display:flex;flex-wrap:wrap;gap:8px}.cc-selected-user{display:flex;align-items:center;border-radius:20px;padding:4px 8px 4px 4px;width:140px;animation:slideInUp .3s ease-out}.cc-selected-user__avatar{flex-shrink:0}.cc-selected-user__name{flex:1;margin:0 8px;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cc-selected-user__remove{flex-shrink:0;cursor:pointer}.cc-selected-user__remove:hover{opacity:.7}.cc-users__list{flex:1;overflow:hidden}.cc-selected-users::-webkit-scrollbar{background:transparent;width:8px}.cc-selected-users::-webkit-scrollbar-thumb{background:#e8e5e5;border-radius:8px}.cc-users__list--with-selection .cc-users__selection--multiple{position:relative}@keyframes slideInUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}\n"] }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.CometChatThemeService }]; }, propDecorators: { usersRequestBuilder: [{ type: Input }], searchRequestBuilder: [{ type: Input }], subtitleView: [{ type: Input }], disableUsersPresence: [{ type: Input }], listItemView: [{ type: Input }], menu: [{ type: Input }], options: [{ type: Input }], activeUser: [{ type: Input }], hideSeparator: [{ type: Input }], searchPlaceholder: [{ type: Input }], hideError: [{ type: Input }], selectionMode: [{ type: Input }], searchIconURL: [{ type: Input }], hideSearch: [{ type: Input }], title: [{ type: Input }], onError: [{ type: Input }], emptyStateView: [{ type: Input }], onSelect: [{ type: Input }], errorStateView: [{ type: Input }], loadingIconURL: [{ type: Input }], showSectionHeader: [{ type: Input }], sectionHeaderField: [{ type: Input }], loadingStateView: [{ type: Input }], emptyStateText: [{ type: Input }], errorStateText: [{ type: Input }], titleAlignment: [{ type: Input }], usersStyle: [{ type: Input }], listItemStyle: [{ type: Input }], statusIndicatorStyle: [{ type: Input }], avatarStyle: [{ type: Input }], selectedUserPreviewStyle: [{ type: Input }], showSelectedUsersPreview: [{ type: Input }], onItemClick: [{ type: Input }], searchKeyword: [{ type: Input }], onEmpty: [{ type: Input }], userPresencePlacement: [{ type: Input }], disableLoadingState: [{ type: Input }], checkboxes: [{ type: ViewChildren, args: ['checkboxElement', { read: ElementRef }] }], radios: [{ type: ViewChildren, args: ['radioElement', { read: ElementRef }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tZXRjaGF0LXVzZXJzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NoYXQtdWlraXQtYW5ndWxhci9zcmMvQ29tZXRDaGF0VXNlcnMvY29tZXRjaGF0LXVzZXJzL2NvbWV0Y2hhdC11c2Vycy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jaGF0LXVpa2l0LWFuZ3VsYXIvc3JjL0NvbWV0Q2hhdFVzZXJzL2NvbWV0Y2hhdC11c2Vycy9jb21ldGNoYXQtdXNlcnMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUV2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLEtBQUssRUFNTCxZQUFZLEdBQ2IsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzNELE9BQU8sRUFDTCxXQUFXLEVBR1gsYUFBYSxHQUNkLE1BQU0sMkJBQTJCLENBQUM7QUFFbkMsT0FBTyxFQUVMLGFBQWEsRUFDYixRQUFRLEVBQ1IsY0FBYyxFQUNkLE1BQU0sRUFDTixtQkFBbUIsRUFFbkIsVUFBVSxHQUNYLE1BQU0sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxFQUFFLFVBQVUsRUFBYSx3QkFBd0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRTFGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ25FLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQzs7Ozs7QUFPL0QsTUFBTSxPQUFPLHVCQUF1QjtJQWdIbEMsWUFDVSxHQUFzQixFQUN0QixZQUFtQztRQURuQyxRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQUN0QixpQkFBWSxHQUFaLFlBQVksQ0FBdUI7UUE5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