@forgeroute/ui 0.4.58 → 0.4.59

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.
@@ -29251,7 +29251,7 @@ function defaultLabel(item, index) {
29251
29251
  }
29252
29252
  const DEFAULT_GAP_LIST = "0px";
29253
29253
  const DEFAULT_GAP_GRID = "12px";
29254
- let nextId$2 = 0;
29254
+ let nextId$3 = 0;
29255
29255
  var ListComponent = class ListComponent {
29256
29256
  constructor() {
29257
29257
  this.host = inject(ElementRef);
@@ -29278,7 +29278,7 @@ var ListComponent = class ListComponent {
29278
29278
  this.itemsChange = output();
29279
29279
  this.reorder = output();
29280
29280
  this.rowTemplate = contentChild(TemplateRef, ...ngDevMode ? [{ debugName: "rowTemplate" }] : /* istanbul ignore next */ []);
29281
- this.helpId = `ul-help-${nextId$2++}`;
29281
+ this.helpId = `ul-help-${nextId$3++}`;
29282
29282
  this.announcement = signal("", ...ngDevMode ? [{ debugName: "announcement" }] : /* istanbul ignore next */ []);
29283
29283
  this.movedKey = signal(void 0, ...ngDevMode ? [{ debugName: "movedKey" }] : /* istanbul ignore next */ []);
29284
29284
  this.dragIndex = signal(null, ...ngDevMode ? [{ debugName: "dragIndex" }] : /* istanbul ignore next */ []);
@@ -35515,7 +35515,7 @@ const STATE_COMMANDS = [
35515
35515
  "justifyCenter",
35516
35516
  "justifyRight"
35517
35517
  ];
35518
- let nextId$1 = 0;
35518
+ let nextId$2 = 0;
35519
35519
  var RichTextEditorComponent = class RichTextEditorComponent {
35520
35520
  constructor() {
35521
35521
  this.label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
@@ -35536,7 +35536,7 @@ var RichTextEditorComponent = class RichTextEditorComponent {
35536
35536
  this.disabled = computed(() => this._disabledInput() || this._cvaDisabled(), ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
35537
35537
  this.inert = computed(() => this.disabled() || this.readonly(), ...ngDevMode ? [{ debugName: "inert" }] : /* istanbul ignore next */ []);
35538
35538
  this.editor = viewChild("editor", ...ngDevMode ? [{ debugName: "editor" }] : /* istanbul ignore next */ []);
35539
- this._id = ++nextId$1;
35539
+ this._id = ++nextId$2;
35540
35540
  this._editorId = `rte-${this._id}`;
35541
35541
  this._labelId = `rte-${this._id}-label`;
35542
35542
  this._errorId = `rte-${this._id}-error`;
@@ -38912,14 +38912,14 @@ i0.ɵɵngDeclareClassMetadata({
38912
38912
  }]
38913
38913
  }
38914
38914
  });
38915
- let nextId = 0;
38915
+ let nextId$1 = 0;
38916
38916
  var ReadonlyFieldsetComponent = class ReadonlyFieldsetComponent {
38917
38917
  constructor() {
38918
38918
  this.readOnly = input(false, ...ngDevMode ? [{ debugName: "readOnly" }] : /* istanbul ignore next */ []);
38919
38919
  this.gap = input("0", ...ngDevMode ? [{ debugName: "gap" }] : /* istanbul ignore next */ []);
38920
38920
  this.ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
38921
38921
  this.reason = input("", ...ngDevMode ? [{ debugName: "reason" }] : /* istanbul ignore next */ []);
38922
- this._reasonId = `rf-reason-${nextId++}`;
38922
+ this._reasonId = `rf-reason-${nextId$1++}`;
38923
38923
  this._showReason = computed(() => this.readOnly() && !!this.reason().trim(), ...ngDevMode ? [{ debugName: "_showReason" }] : /* istanbul ignore next */ []);
38924
38924
  }
38925
38925
  static {
@@ -50179,6 +50179,2479 @@ i0.ɵɵngDeclareClassMetadata({
50179
50179
  }]
50180
50180
  }
50181
50181
  });
50182
- export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BankAccountFormComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_BANK_ACCOUNT_TYPE_OPTIONS, DEFAULT_BANK_HOLDER_TYPE_OPTIONS, DEFAULT_BANK_MANDATE_TEXT, DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, DEFAULT_PASSWORD_RULES, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EMAIL_BLOCK_DRAG_TYPE, EMAIL_TEMPLATE_MAX_BODY, EMAIL_TEMPLATE_MAX_TEXT, EMAIL_TEMPLATE_START_TEXT, EmailTemplateEditorComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FixedFooterComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IDX_BEHAVIOR_SIGNALS, INTEGRATION_CATALOG, INTEGRATION_FIELD_DEFS, INTEGRATION_GROUP_ORDER, INTEGRATION_OPTION_DEFS, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, ImportSourceGridComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, LiveRegionComponent, MAX_EMAIL_ADDRESS_LENGTH, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, OfflineBannerComponent, OptionCardComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, ReminderAlertsComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, SetupWizardStepHeaderDirective, ShareMenuComponent, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, SnackbarComponent, SnackbarService, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextTemplatePickerComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, blockHasContent, buildDefaultSchedule, buildPreviewDocument, buildVideoBlockHtml, builtInActionIcon, businessTimeOptions, createFieldReveal, decodeFilterValues, digitsOnly, downloadBlob, emailShareUrl, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, facebookShareUrl, fileMatchesAccept, formatAddress, formatCategoryLabel, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, gmailShareUrl, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isValidEmailAddress, isWebUrl, isoKey, issueToErrors, linkedInShareUrl, maxLengthIssue, mergeDescribedBy, normalizeHexColor, outlookShareUrl, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, serializedTextLength, setupIntegrations, splitIntro, xShareUrl };
50182
+ function formatConversationPhone(phone) {
50183
+ if (!phone) return "";
50184
+ const digits = phone.replace(/\D/g, "");
50185
+ if (digits.length === 10) return `(${digits.slice(0, 3)}) ${digits.slice(3, 6)}-${digits.slice(6)}`;
50186
+ if (digits.length === 11 && digits.startsWith("1")) return `+1 (${digits.slice(1, 4)}) ${digits.slice(4, 7)}-${digits.slice(7)}`;
50187
+ return phone;
50188
+ }
50189
+ function truncateConversationText(text, len) {
50190
+ if (!text) return "";
50191
+ return text.length > len ? text.substring(0, len) + "..." : text;
50192
+ }
50193
+ function formatConversationTime(iso, now = /* @__PURE__ */ new Date()) {
50194
+ if (!iso) return "";
50195
+ const d = new Date(iso);
50196
+ if (Number.isNaN(d.getTime())) return "";
50197
+ const mins = Math.floor((now.getTime() - d.getTime()) / 6e4);
50198
+ if (mins < 1) return "now";
50199
+ if (mins < 60) return `${mins}m`;
50200
+ const hrs = Math.floor(mins / 60);
50201
+ if (hrs < 24) return `${hrs}h`;
50202
+ const days = Math.floor(hrs / 24);
50203
+ if (days < 7) return `${days}d`;
50204
+ return d.toLocaleDateString("en-US", {
50205
+ month: "short",
50206
+ day: "numeric"
50207
+ });
50208
+ }
50209
+ function formatMessageTime(iso) {
50210
+ const d = new Date(iso);
50211
+ return Number.isNaN(d.getTime()) ? "" : d.toLocaleTimeString("en-US", {
50212
+ hour: "numeric",
50213
+ minute: "2-digit"
50214
+ });
50215
+ }
50216
+ function conversationDateLabel(iso, now = /* @__PURE__ */ new Date()) {
50217
+ const d = new Date(iso);
50218
+ if (Number.isNaN(d.getTime())) return "";
50219
+ const yesterday = new Date(now);
50220
+ yesterday.setDate(yesterday.getDate() - 1);
50221
+ if (d.toDateString() === now.toDateString()) return "Today";
50222
+ if (d.toDateString() === yesterday.toDateString()) return "Yesterday";
50223
+ return d.toLocaleDateString("en-US", {
50224
+ month: "short",
50225
+ day: "numeric",
50226
+ year: "numeric"
50227
+ });
50228
+ }
50229
+ function conversationInitial(name) {
50230
+ return (name ?? "").trim().charAt(0).toUpperCase() || "?";
50231
+ }
50232
+ function groupMessagesByDay(messages, now = /* @__PURE__ */ new Date()) {
50233
+ return messages.map((message, i) => {
50234
+ const label = conversationDateLabel(message.sentAt, now);
50235
+ return {
50236
+ message,
50237
+ separator: i === 0 || conversationDateLabel(messages[i - 1].sentAt, now) !== label ? label : ""
50238
+ };
50239
+ });
50240
+ }
50241
+ function conversationMessageStatusLabel(status) {
50242
+ switch (status) {
50243
+ case "delivered": return "Delivered";
50244
+ case "sent": return "Sent";
50245
+ case "failed": return "Failed";
50246
+ case "scheduled": return "Scheduled";
50247
+ default: return "";
50248
+ }
50249
+ }
50250
+ function conversationMessageStatusMark(status) {
50251
+ if (status === "delivered") return "✓✓";
50252
+ if (status === "sent") return "✓";
50253
+ return conversationMessageStatusLabel(status);
50254
+ }
50255
+ const SINGLE_COLUMN_QUERY = "(max-width: 768px)";
50256
+ const NEAR_BOTTOM_PX = 120;
50257
+ const PREVIEW_LENGTH = 60;
50258
+ let nextId = 0;
50259
+ var ConversationsComponent = class ConversationsComponent {
50260
+ constructor() {
50261
+ this.conversations = input([], ...ngDevMode ? [{ debugName: "conversations" }] : /* istanbul ignore next */ []);
50262
+ this.selected = input(null, ...ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []);
50263
+ this.title = input("Messages", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
50264
+ this.loading = input(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
50265
+ this.error = input(null, ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
50266
+ this.searchText = model("", ...ngDevMode ? [{ debugName: "searchText" }] : /* istanbul ignore next */ []);
50267
+ this.searchPlaceholder = input("Search by name or phone...", ...ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []);
50268
+ this.searchAriaLabel = input("Search conversations", ...ngDevMode ? [{ debugName: "searchAriaLabel" }] : /* istanbul ignore next */ []);
50269
+ this.showFilters = input(true, ...ngDevMode ? [{ debugName: "showFilters" }] : /* istanbul ignore next */ []);
50270
+ this.filterTabs = input([], ...ngDevMode ? [{ debugName: "filterTabs" }] : /* istanbul ignore next */ []);
50271
+ this.filterCounts = input({}, ...ngDevMode ? [{ debugName: "filterCounts" }] : /* istanbul ignore next */ []);
50272
+ this.activeFilter = input("", ...ngDevMode ? [{ debugName: "activeFilter" }] : /* istanbul ignore next */ []);
50273
+ this.filterAriaLabel = input("Filter conversations", ...ngDevMode ? [{ debugName: "filterAriaLabel" }] : /* istanbul ignore next */ []);
50274
+ this.page = input(1, ...ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []);
50275
+ this.pageSize = input(25, ...ngDevMode ? [{ debugName: "pageSize" }] : /* istanbul ignore next */ []);
50276
+ this.totalItems = input(0, ...ngDevMode ? [{ debugName: "totalItems" }] : /* istanbul ignore next */ []);
50277
+ this.paginationAriaLabel = input("Conversation pages", ...ngDevMode ? [{ debugName: "paginationAriaLabel" }] : /* istanbul ignore next */ []);
50278
+ this.listAriaLabel = input("Conversations", ...ngDevMode ? [{ debugName: "listAriaLabel" }] : /* istanbul ignore next */ []);
50279
+ this.loadingLabel = input("Loading conversations", ...ngDevMode ? [{ debugName: "loadingLabel" }] : /* istanbul ignore next */ []);
50280
+ this.emptyTitle = input("No conversations yet", ...ngDevMode ? [{ debugName: "emptyTitle" }] : /* istanbul ignore next */ []);
50281
+ this.emptyMessage = input("Click the + button to start messaging", ...ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []);
50282
+ this.emptyReadOnlyMessage = input("Conversations will appear here once texting starts.", ...ngDevMode ? [{ debugName: "emptyReadOnlyMessage" }] : /* istanbul ignore next */ []);
50283
+ this.filteredEmptyTitle = input("No conversations found", ...ngDevMode ? [{ debugName: "filteredEmptyTitle" }] : /* istanbul ignore next */ []);
50284
+ this.filteredEmptyMessage = input("No conversation matches your search or filter.", ...ngDevMode ? [{ debugName: "filteredEmptyMessage" }] : /* istanbul ignore next */ []);
50285
+ this.noMessagesText = input("No messages", ...ngDevMode ? [{ debugName: "noMessagesText" }] : /* istanbul ignore next */ []);
50286
+ this.allowNew = input(true, ...ngDevMode ? [{ debugName: "allowNew" }] : /* istanbul ignore next */ []);
50287
+ this.allowDelete = input(true, ...ngDevMode ? [{ debugName: "allowDelete" }] : /* istanbul ignore next */ []);
50288
+ this.newLabel = input("Start new message", ...ngDevMode ? [{ debugName: "newLabel" }] : /* istanbul ignore next */ []);
50289
+ this.newTooltip = input("New message", ...ngDevMode ? [{ debugName: "newTooltip" }] : /* istanbul ignore next */ []);
50290
+ this.deleteRowLabel = input("Delete conversation with", ...ngDevMode ? [{ debugName: "deleteRowLabel" }] : /* istanbul ignore next */ []);
50291
+ this.messages = input([], ...ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []);
50292
+ this.messagesLoading = input(false, ...ngDevMode ? [{ debugName: "messagesLoading" }] : /* istanbul ignore next */ []);
50293
+ this.messagesError = input(null, ...ngDevMode ? [{ debugName: "messagesError" }] : /* istanbul ignore next */ []);
50294
+ this.hasEarlier = input(false, ...ngDevMode ? [{ debugName: "hasEarlier" }] : /* istanbul ignore next */ []);
50295
+ this.loadingEarlier = input(false, ...ngDevMode ? [{ debugName: "loadingEarlier" }] : /* istanbul ignore next */ []);
50296
+ this.loadEarlierLabel = input("Load earlier messages", ...ngDevMode ? [{ debugName: "loadEarlierLabel" }] : /* istanbul ignore next */ []);
50297
+ this.statusActionLabel = input(null, ...ngDevMode ? [{ debugName: "statusActionLabel" }] : /* istanbul ignore next */ []);
50298
+ this.statusActionIcon = input("close", ...ngDevMode ? [{ debugName: "statusActionIcon" }] : /* istanbul ignore next */ []);
50299
+ this.statusChanging = input(false, ...ngDevMode ? [{ debugName: "statusChanging" }] : /* istanbul ignore next */ []);
50300
+ this.templatesEnabled = input(false, ...ngDevMode ? [{ debugName: "templatesEnabled" }] : /* istanbul ignore next */ []);
50301
+ this.templateLabel = input("Use a template", ...ngDevMode ? [{ debugName: "templateLabel" }] : /* istanbul ignore next */ []);
50302
+ this.deleteThreadLabel = input("Delete conversation", ...ngDevMode ? [{ debugName: "deleteThreadLabel" }] : /* istanbul ignore next */ []);
50303
+ this.backLabel = input("Back to conversations", ...ngDevMode ? [{ debugName: "backLabel" }] : /* istanbul ignore next */ []);
50304
+ this.threadAriaLabel = input("Message thread", ...ngDevMode ? [{ debugName: "threadAriaLabel" }] : /* istanbul ignore next */ []);
50305
+ this.messagesAriaLabel = input("Messages with", ...ngDevMode ? [{ debugName: "messagesAriaLabel" }] : /* istanbul ignore next */ []);
50306
+ this.threadEmptyTitle = input("Select a conversation", ...ngDevMode ? [{ debugName: "threadEmptyTitle" }] : /* istanbul ignore next */ []);
50307
+ this.threadEmptyMessage = input("Choose a conversation from the list or start a new one", ...ngDevMode ? [{ debugName: "threadEmptyMessage" }] : /* istanbul ignore next */ []);
50308
+ this.noMessagesWriteText = input("No messages in this conversation yet. Send the first message below.", ...ngDevMode ? [{ debugName: "noMessagesWriteText" }] : /* istanbul ignore next */ []);
50309
+ this.noMessagesReadText = input("No messages in this conversation yet.", ...ngDevMode ? [{ debugName: "noMessagesReadText" }] : /* istanbul ignore next */ []);
50310
+ this.youLabel = input("You", ...ngDevMode ? [{ debugName: "youLabel" }] : /* istanbul ignore next */ []);
50311
+ this.openMediaLabel = input("Open", ...ngDevMode ? [{ debugName: "openMediaLabel" }] : /* istanbul ignore next */ []);
50312
+ this.imageFallbackName = input("image", ...ngDevMode ? [{ debugName: "imageFallbackName" }] : /* istanbul ignore next */ []);
50313
+ this.fileFallbackName = input("Attachment", ...ngDevMode ? [{ debugName: "fileFallbackName" }] : /* istanbul ignore next */ []);
50314
+ this.hasContext = input(false, ...ngDevMode ? [{ debugName: "hasContext" }] : /* istanbul ignore next */ []);
50315
+ this.contextOpen = model(false, ...ngDevMode ? [{ debugName: "contextOpen" }] : /* istanbul ignore next */ []);
50316
+ this.contextTitle = input("Contact Info", ...ngDevMode ? [{ debugName: "contextTitle" }] : /* istanbul ignore next */ []);
50317
+ this.showContextLabel = input("Show contact info", ...ngDevMode ? [{ debugName: "showContextLabel" }] : /* istanbul ignore next */ []);
50318
+ this.hideContextLabel = input("Hide contact info", ...ngDevMode ? [{ debugName: "hideContextLabel" }] : /* istanbul ignore next */ []);
50319
+ this.closeContextLabel = input("Close contact info", ...ngDevMode ? [{ debugName: "closeContextLabel" }] : /* istanbul ignore next */ []);
50320
+ this.canWrite = input(true, ...ngDevMode ? [{ debugName: "canWrite" }] : /* istanbul ignore next */ []);
50321
+ this.draft = model("", ...ngDevMode ? [{ debugName: "draft" }] : /* istanbul ignore next */ []);
50322
+ this.sending = input(false, ...ngDevMode ? [{ debugName: "sending" }] : /* istanbul ignore next */ []);
50323
+ this.composerDisabled = input(false, ...ngDevMode ? [{ debugName: "composerDisabled" }] : /* istanbul ignore next */ []);
50324
+ this.sendBlocked = input(false, ...ngDevMode ? [{ debugName: "sendBlocked" }] : /* istanbul ignore next */ []);
50325
+ this.composerNotice = input("", ...ngDevMode ? [{ debugName: "composerNotice" }] : /* istanbul ignore next */ []);
50326
+ this.composerStatus = input("", ...ngDevMode ? [{ debugName: "composerStatus" }] : /* istanbul ignore next */ []);
50327
+ this.composerError = input("", ...ngDevMode ? [{ debugName: "composerError" }] : /* istanbul ignore next */ []);
50328
+ this.maxLength = input(1600, ...ngDevMode ? [{ debugName: "maxLength" }] : /* istanbul ignore next */ []);
50329
+ this.attachment = input(null, ...ngDevMode ? [{ debugName: "attachment" }] : /* istanbul ignore next */ []);
50330
+ this.uploading = input(false, ...ngDevMode ? [{ debugName: "uploading" }] : /* istanbul ignore next */ []);
50331
+ this.attachEnabled = input(true, ...ngDevMode ? [{ debugName: "attachEnabled" }] : /* istanbul ignore next */ []);
50332
+ this.acceptedFiles = input("image/*,video/*", ...ngDevMode ? [{ debugName: "acceptedFiles" }] : /* istanbul ignore next */ []);
50333
+ this.maxFileSize = input(null, ...ngDevMode ? [{ debugName: "maxFileSize" }] : /* istanbul ignore next */ []);
50334
+ this.typeMessage = input("Only image and video files are supported.", ...ngDevMode ? [{ debugName: "typeMessage" }] : /* istanbul ignore next */ []);
50335
+ this.sizeMessage = input("That file is too large.", ...ngDevMode ? [{ debugName: "sizeMessage" }] : /* istanbul ignore next */ []);
50336
+ this.composeLabel = input("Type a message", ...ngDevMode ? [{ debugName: "composeLabel" }] : /* istanbul ignore next */ []);
50337
+ this.composePlaceholder = input("Type a message...", ...ngDevMode ? [{ debugName: "composePlaceholder" }] : /* istanbul ignore next */ []);
50338
+ this.sendLabel = input("Send message", ...ngDevMode ? [{ debugName: "sendLabel" }] : /* istanbul ignore next */ []);
50339
+ this.attachLabel = input("Attach image or video", ...ngDevMode ? [{ debugName: "attachLabel" }] : /* istanbul ignore next */ []);
50340
+ this.removeAttachmentLabel = input("Remove attachment", ...ngDevMode ? [{ debugName: "removeAttachmentLabel" }] : /* istanbul ignore next */ []);
50341
+ this.attachmentPreviewLabel = input("Attachment preview", ...ngDevMode ? [{ debugName: "attachmentPreviewLabel" }] : /* istanbul ignore next */ []);
50342
+ this.now = input(null, ...ngDevMode ? [{ debugName: "now" }] : /* istanbul ignore next */ []);
50343
+ this.searchChange = output();
50344
+ this.filterChange = output();
50345
+ this.pageChange = output();
50346
+ this.selectConversation = output();
50347
+ this.back = output();
50348
+ this.newConversation = output();
50349
+ this.retry = output();
50350
+ this.deleteConversation = output();
50351
+ this.statusChange = output();
50352
+ this.templateRequest = output();
50353
+ this.send = output();
50354
+ this.filesSelected = output();
50355
+ this.attachmentRemove = output();
50356
+ this.mediaOpen = output();
50357
+ this.messageAction = output();
50358
+ this.loadEarlier = output();
50359
+ this.messagesRetry = output();
50360
+ this.titleId = `cv-title-${nextId++}`;
50361
+ this.skeletonRows = [
50362
+ 1,
50363
+ 2,
50364
+ 3,
50365
+ 4,
50366
+ 5
50367
+ ];
50368
+ this.skeletonBubbles = [
50369
+ 0,
50370
+ 1,
50371
+ 2
50372
+ ];
50373
+ this.trackConversation = (c) => c.id;
50374
+ this.initial = conversationInitial;
50375
+ this.statusLabel = conversationMessageStatusLabel;
50376
+ this.statusMark = conversationMessageStatusMark;
50377
+ this.injector = inject(Injector);
50378
+ this.host = inject(ElementRef);
50379
+ this.threadHeading = viewChild("threadHeading", ...ngDevMode ? [{ debugName: "threadHeading" }] : /* istanbul ignore next */ []);
50380
+ this.messagesEl = viewChild("messagesEl", ...ngDevMode ? [{ debugName: "messagesEl" }] : /* istanbul ignore next */ []);
50381
+ this.contextPanel = viewChild("contextPanel", ...ngDevMode ? [{ debugName: "contextPanel" }] : /* istanbul ignore next */ []);
50382
+ this.fileInput = viewChild(FileInputComponent, ...ngDevMode ? [{ debugName: "fileInput" }] : /* istanbul ignore next */ []);
50383
+ this.atBottom = true;
50384
+ this.lastThreadId = null;
50385
+ this.filtering = computed(() => !!this.searchText().trim() || this.activeFilter() !== "", ...ngDevMode ? [{ debugName: "filtering" }] : /* istanbul ignore next */ []);
50386
+ this.emptyText = computed(() => this.filtering() ? this.filteredEmptyMessage() : this.canWrite() ? this.emptyMessage() : this.emptyReadOnlyMessage(), ...ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []);
50387
+ this.messageRows = computed(() => groupMessagesByDay(this.messages(), this.clock()), ...ngDevMode ? [{ debugName: "messageRows" }] : /* istanbul ignore next */ []);
50388
+ this.contextVisible = computed(() => this.hasContext() && this.contextOpen() && !!this.selected(), ...ngDevMode ? [{ debugName: "contextVisible" }] : /* istanbul ignore next */ []);
50389
+ this.canSend = computed(() => !this.composerDisabled() && !this.sendBlocked() && !this.sending() && (this.draft().trim().length > 0 || !!this.attachment()), ...ngDevMode ? [{ debugName: "canSend" }] : /* istanbul ignore next */ []);
50390
+ effect(() => {
50391
+ const id = this.selected()?.id ?? null;
50392
+ const count = this.messages().length;
50393
+ untracked(() => {
50394
+ const switched = id !== this.lastThreadId;
50395
+ this.lastThreadId = id;
50396
+ if (switched) this.atBottom = true;
50397
+ if (count > 0 && this.atBottom) this.scrollToBottom();
50398
+ });
50399
+ });
50400
+ effect(() => {
50401
+ if (!this.selected() && this.contextOpen()) untracked(() => this.contextOpen.set(false));
50402
+ });
50403
+ }
50404
+ relativeTime(iso) {
50405
+ return formatConversationTime(iso, this.clock());
50406
+ }
50407
+ preview(text) {
50408
+ return truncateConversationText(text, PREVIEW_LENGTH);
50409
+ }
50410
+ time(message) {
50411
+ return formatMessageTime(message.sentAt);
50412
+ }
50413
+ onRowOpen(conv) {
50414
+ this.selectConversation.emit(conv);
50415
+ if (this.singleColumn()) afterNextRender(() => this.threadHeading()?.nativeElement.focus(), { injector: this.injector });
50416
+ }
50417
+ onBack() {
50418
+ const id = this.selected()?.id;
50419
+ this.back.emit();
50420
+ afterNextRender(() => {
50421
+ const rows = Array.from(this.host.nativeElement.querySelectorAll("[data-testid=\"conv-item\"]"));
50422
+ (rows.find((r) => r.dataset["conversationId"] === id) ?? rows[0])?.closest("li")?.focus();
50423
+ }, { injector: this.injector });
50424
+ }
50425
+ onMessagesScroll() {
50426
+ const el = this.messagesEl()?.nativeElement;
50427
+ if (el) this.atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < NEAR_BOTTOM_PX;
50428
+ }
50429
+ toggleContext() {
50430
+ if (this.contextOpen()) {
50431
+ this.closeContext(true);
50432
+ return;
50433
+ }
50434
+ this.contextOpen.set(true);
50435
+ afterNextRender(() => this.contextPanel()?.nativeElement.focus(), { injector: this.injector });
50436
+ }
50437
+ closeContext(restoreFocus = false) {
50438
+ this.contextOpen.set(false);
50439
+ if (restoreFocus) afterNextRender(() => this.host.nativeElement.querySelector("[data-testid=\"context-toggle\"] button")?.focus(), { injector: this.injector });
50440
+ }
50441
+ openFilePicker() {
50442
+ this.fileInput()?.open();
50443
+ }
50444
+ onComposeKeydown(event) {
50445
+ if (event.key === "Enter" && !event.shiftKey && !event.isComposing) {
50446
+ event.preventDefault();
50447
+ this.sendMessage();
50448
+ }
50449
+ }
50450
+ sendMessage() {
50451
+ if (!this.canSend()) return;
50452
+ this.send.emit({ text: this.draft().trim() });
50453
+ }
50454
+ clock() {
50455
+ return this.now() ?? /* @__PURE__ */ new Date();
50456
+ }
50457
+ singleColumn() {
50458
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(SINGLE_COLUMN_QUERY).matches;
50459
+ }
50460
+ scrollToBottom() {
50461
+ afterNextRender(() => {
50462
+ const el = this.messagesEl()?.nativeElement;
50463
+ if (el) el.scrollTop = el.scrollHeight;
50464
+ }, { injector: this.injector });
50465
+ }
50466
+ static {
50467
+ this.ɵfac = i0.ɵɵngDeclareFactory({
50468
+ minVersion: "12.0.0",
50469
+ version: "22.2.2",
50470
+ ngImport: i0,
50471
+ type: ConversationsComponent,
50472
+ deps: [],
50473
+ target: i0.ɵɵFactoryTarget.Component
50474
+ });
50475
+ }
50476
+ static {
50477
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
50478
+ minVersion: "17.0.0",
50479
+ version: "22.2.2",
50480
+ type: ConversationsComponent,
50481
+ isStandalone: true,
50482
+ selector: "ui-conversations",
50483
+ inputs: {
50484
+ conversations: {
50485
+ classPropertyName: "conversations",
50486
+ publicName: "conversations",
50487
+ isSignal: true,
50488
+ isRequired: false,
50489
+ transformFunction: null
50490
+ },
50491
+ selected: {
50492
+ classPropertyName: "selected",
50493
+ publicName: "selected",
50494
+ isSignal: true,
50495
+ isRequired: false,
50496
+ transformFunction: null
50497
+ },
50498
+ title: {
50499
+ classPropertyName: "title",
50500
+ publicName: "title",
50501
+ isSignal: true,
50502
+ isRequired: false,
50503
+ transformFunction: null
50504
+ },
50505
+ loading: {
50506
+ classPropertyName: "loading",
50507
+ publicName: "loading",
50508
+ isSignal: true,
50509
+ isRequired: false,
50510
+ transformFunction: null
50511
+ },
50512
+ error: {
50513
+ classPropertyName: "error",
50514
+ publicName: "error",
50515
+ isSignal: true,
50516
+ isRequired: false,
50517
+ transformFunction: null
50518
+ },
50519
+ searchText: {
50520
+ classPropertyName: "searchText",
50521
+ publicName: "searchText",
50522
+ isSignal: true,
50523
+ isRequired: false,
50524
+ transformFunction: null
50525
+ },
50526
+ searchPlaceholder: {
50527
+ classPropertyName: "searchPlaceholder",
50528
+ publicName: "searchPlaceholder",
50529
+ isSignal: true,
50530
+ isRequired: false,
50531
+ transformFunction: null
50532
+ },
50533
+ searchAriaLabel: {
50534
+ classPropertyName: "searchAriaLabel",
50535
+ publicName: "searchAriaLabel",
50536
+ isSignal: true,
50537
+ isRequired: false,
50538
+ transformFunction: null
50539
+ },
50540
+ showFilters: {
50541
+ classPropertyName: "showFilters",
50542
+ publicName: "showFilters",
50543
+ isSignal: true,
50544
+ isRequired: false,
50545
+ transformFunction: null
50546
+ },
50547
+ filterTabs: {
50548
+ classPropertyName: "filterTabs",
50549
+ publicName: "filterTabs",
50550
+ isSignal: true,
50551
+ isRequired: false,
50552
+ transformFunction: null
50553
+ },
50554
+ filterCounts: {
50555
+ classPropertyName: "filterCounts",
50556
+ publicName: "filterCounts",
50557
+ isSignal: true,
50558
+ isRequired: false,
50559
+ transformFunction: null
50560
+ },
50561
+ activeFilter: {
50562
+ classPropertyName: "activeFilter",
50563
+ publicName: "activeFilter",
50564
+ isSignal: true,
50565
+ isRequired: false,
50566
+ transformFunction: null
50567
+ },
50568
+ filterAriaLabel: {
50569
+ classPropertyName: "filterAriaLabel",
50570
+ publicName: "filterAriaLabel",
50571
+ isSignal: true,
50572
+ isRequired: false,
50573
+ transformFunction: null
50574
+ },
50575
+ page: {
50576
+ classPropertyName: "page",
50577
+ publicName: "page",
50578
+ isSignal: true,
50579
+ isRequired: false,
50580
+ transformFunction: null
50581
+ },
50582
+ pageSize: {
50583
+ classPropertyName: "pageSize",
50584
+ publicName: "pageSize",
50585
+ isSignal: true,
50586
+ isRequired: false,
50587
+ transformFunction: null
50588
+ },
50589
+ totalItems: {
50590
+ classPropertyName: "totalItems",
50591
+ publicName: "totalItems",
50592
+ isSignal: true,
50593
+ isRequired: false,
50594
+ transformFunction: null
50595
+ },
50596
+ paginationAriaLabel: {
50597
+ classPropertyName: "paginationAriaLabel",
50598
+ publicName: "paginationAriaLabel",
50599
+ isSignal: true,
50600
+ isRequired: false,
50601
+ transformFunction: null
50602
+ },
50603
+ listAriaLabel: {
50604
+ classPropertyName: "listAriaLabel",
50605
+ publicName: "listAriaLabel",
50606
+ isSignal: true,
50607
+ isRequired: false,
50608
+ transformFunction: null
50609
+ },
50610
+ loadingLabel: {
50611
+ classPropertyName: "loadingLabel",
50612
+ publicName: "loadingLabel",
50613
+ isSignal: true,
50614
+ isRequired: false,
50615
+ transformFunction: null
50616
+ },
50617
+ emptyTitle: {
50618
+ classPropertyName: "emptyTitle",
50619
+ publicName: "emptyTitle",
50620
+ isSignal: true,
50621
+ isRequired: false,
50622
+ transformFunction: null
50623
+ },
50624
+ emptyMessage: {
50625
+ classPropertyName: "emptyMessage",
50626
+ publicName: "emptyMessage",
50627
+ isSignal: true,
50628
+ isRequired: false,
50629
+ transformFunction: null
50630
+ },
50631
+ emptyReadOnlyMessage: {
50632
+ classPropertyName: "emptyReadOnlyMessage",
50633
+ publicName: "emptyReadOnlyMessage",
50634
+ isSignal: true,
50635
+ isRequired: false,
50636
+ transformFunction: null
50637
+ },
50638
+ filteredEmptyTitle: {
50639
+ classPropertyName: "filteredEmptyTitle",
50640
+ publicName: "filteredEmptyTitle",
50641
+ isSignal: true,
50642
+ isRequired: false,
50643
+ transformFunction: null
50644
+ },
50645
+ filteredEmptyMessage: {
50646
+ classPropertyName: "filteredEmptyMessage",
50647
+ publicName: "filteredEmptyMessage",
50648
+ isSignal: true,
50649
+ isRequired: false,
50650
+ transformFunction: null
50651
+ },
50652
+ noMessagesText: {
50653
+ classPropertyName: "noMessagesText",
50654
+ publicName: "noMessagesText",
50655
+ isSignal: true,
50656
+ isRequired: false,
50657
+ transformFunction: null
50658
+ },
50659
+ allowNew: {
50660
+ classPropertyName: "allowNew",
50661
+ publicName: "allowNew",
50662
+ isSignal: true,
50663
+ isRequired: false,
50664
+ transformFunction: null
50665
+ },
50666
+ allowDelete: {
50667
+ classPropertyName: "allowDelete",
50668
+ publicName: "allowDelete",
50669
+ isSignal: true,
50670
+ isRequired: false,
50671
+ transformFunction: null
50672
+ },
50673
+ newLabel: {
50674
+ classPropertyName: "newLabel",
50675
+ publicName: "newLabel",
50676
+ isSignal: true,
50677
+ isRequired: false,
50678
+ transformFunction: null
50679
+ },
50680
+ newTooltip: {
50681
+ classPropertyName: "newTooltip",
50682
+ publicName: "newTooltip",
50683
+ isSignal: true,
50684
+ isRequired: false,
50685
+ transformFunction: null
50686
+ },
50687
+ deleteRowLabel: {
50688
+ classPropertyName: "deleteRowLabel",
50689
+ publicName: "deleteRowLabel",
50690
+ isSignal: true,
50691
+ isRequired: false,
50692
+ transformFunction: null
50693
+ },
50694
+ messages: {
50695
+ classPropertyName: "messages",
50696
+ publicName: "messages",
50697
+ isSignal: true,
50698
+ isRequired: false,
50699
+ transformFunction: null
50700
+ },
50701
+ messagesLoading: {
50702
+ classPropertyName: "messagesLoading",
50703
+ publicName: "messagesLoading",
50704
+ isSignal: true,
50705
+ isRequired: false,
50706
+ transformFunction: null
50707
+ },
50708
+ messagesError: {
50709
+ classPropertyName: "messagesError",
50710
+ publicName: "messagesError",
50711
+ isSignal: true,
50712
+ isRequired: false,
50713
+ transformFunction: null
50714
+ },
50715
+ hasEarlier: {
50716
+ classPropertyName: "hasEarlier",
50717
+ publicName: "hasEarlier",
50718
+ isSignal: true,
50719
+ isRequired: false,
50720
+ transformFunction: null
50721
+ },
50722
+ loadingEarlier: {
50723
+ classPropertyName: "loadingEarlier",
50724
+ publicName: "loadingEarlier",
50725
+ isSignal: true,
50726
+ isRequired: false,
50727
+ transformFunction: null
50728
+ },
50729
+ loadEarlierLabel: {
50730
+ classPropertyName: "loadEarlierLabel",
50731
+ publicName: "loadEarlierLabel",
50732
+ isSignal: true,
50733
+ isRequired: false,
50734
+ transformFunction: null
50735
+ },
50736
+ statusActionLabel: {
50737
+ classPropertyName: "statusActionLabel",
50738
+ publicName: "statusActionLabel",
50739
+ isSignal: true,
50740
+ isRequired: false,
50741
+ transformFunction: null
50742
+ },
50743
+ statusActionIcon: {
50744
+ classPropertyName: "statusActionIcon",
50745
+ publicName: "statusActionIcon",
50746
+ isSignal: true,
50747
+ isRequired: false,
50748
+ transformFunction: null
50749
+ },
50750
+ statusChanging: {
50751
+ classPropertyName: "statusChanging",
50752
+ publicName: "statusChanging",
50753
+ isSignal: true,
50754
+ isRequired: false,
50755
+ transformFunction: null
50756
+ },
50757
+ templatesEnabled: {
50758
+ classPropertyName: "templatesEnabled",
50759
+ publicName: "templatesEnabled",
50760
+ isSignal: true,
50761
+ isRequired: false,
50762
+ transformFunction: null
50763
+ },
50764
+ templateLabel: {
50765
+ classPropertyName: "templateLabel",
50766
+ publicName: "templateLabel",
50767
+ isSignal: true,
50768
+ isRequired: false,
50769
+ transformFunction: null
50770
+ },
50771
+ deleteThreadLabel: {
50772
+ classPropertyName: "deleteThreadLabel",
50773
+ publicName: "deleteThreadLabel",
50774
+ isSignal: true,
50775
+ isRequired: false,
50776
+ transformFunction: null
50777
+ },
50778
+ backLabel: {
50779
+ classPropertyName: "backLabel",
50780
+ publicName: "backLabel",
50781
+ isSignal: true,
50782
+ isRequired: false,
50783
+ transformFunction: null
50784
+ },
50785
+ threadAriaLabel: {
50786
+ classPropertyName: "threadAriaLabel",
50787
+ publicName: "threadAriaLabel",
50788
+ isSignal: true,
50789
+ isRequired: false,
50790
+ transformFunction: null
50791
+ },
50792
+ messagesAriaLabel: {
50793
+ classPropertyName: "messagesAriaLabel",
50794
+ publicName: "messagesAriaLabel",
50795
+ isSignal: true,
50796
+ isRequired: false,
50797
+ transformFunction: null
50798
+ },
50799
+ threadEmptyTitle: {
50800
+ classPropertyName: "threadEmptyTitle",
50801
+ publicName: "threadEmptyTitle",
50802
+ isSignal: true,
50803
+ isRequired: false,
50804
+ transformFunction: null
50805
+ },
50806
+ threadEmptyMessage: {
50807
+ classPropertyName: "threadEmptyMessage",
50808
+ publicName: "threadEmptyMessage",
50809
+ isSignal: true,
50810
+ isRequired: false,
50811
+ transformFunction: null
50812
+ },
50813
+ noMessagesWriteText: {
50814
+ classPropertyName: "noMessagesWriteText",
50815
+ publicName: "noMessagesWriteText",
50816
+ isSignal: true,
50817
+ isRequired: false,
50818
+ transformFunction: null
50819
+ },
50820
+ noMessagesReadText: {
50821
+ classPropertyName: "noMessagesReadText",
50822
+ publicName: "noMessagesReadText",
50823
+ isSignal: true,
50824
+ isRequired: false,
50825
+ transformFunction: null
50826
+ },
50827
+ youLabel: {
50828
+ classPropertyName: "youLabel",
50829
+ publicName: "youLabel",
50830
+ isSignal: true,
50831
+ isRequired: false,
50832
+ transformFunction: null
50833
+ },
50834
+ openMediaLabel: {
50835
+ classPropertyName: "openMediaLabel",
50836
+ publicName: "openMediaLabel",
50837
+ isSignal: true,
50838
+ isRequired: false,
50839
+ transformFunction: null
50840
+ },
50841
+ imageFallbackName: {
50842
+ classPropertyName: "imageFallbackName",
50843
+ publicName: "imageFallbackName",
50844
+ isSignal: true,
50845
+ isRequired: false,
50846
+ transformFunction: null
50847
+ },
50848
+ fileFallbackName: {
50849
+ classPropertyName: "fileFallbackName",
50850
+ publicName: "fileFallbackName",
50851
+ isSignal: true,
50852
+ isRequired: false,
50853
+ transformFunction: null
50854
+ },
50855
+ hasContext: {
50856
+ classPropertyName: "hasContext",
50857
+ publicName: "hasContext",
50858
+ isSignal: true,
50859
+ isRequired: false,
50860
+ transformFunction: null
50861
+ },
50862
+ contextOpen: {
50863
+ classPropertyName: "contextOpen",
50864
+ publicName: "contextOpen",
50865
+ isSignal: true,
50866
+ isRequired: false,
50867
+ transformFunction: null
50868
+ },
50869
+ contextTitle: {
50870
+ classPropertyName: "contextTitle",
50871
+ publicName: "contextTitle",
50872
+ isSignal: true,
50873
+ isRequired: false,
50874
+ transformFunction: null
50875
+ },
50876
+ showContextLabel: {
50877
+ classPropertyName: "showContextLabel",
50878
+ publicName: "showContextLabel",
50879
+ isSignal: true,
50880
+ isRequired: false,
50881
+ transformFunction: null
50882
+ },
50883
+ hideContextLabel: {
50884
+ classPropertyName: "hideContextLabel",
50885
+ publicName: "hideContextLabel",
50886
+ isSignal: true,
50887
+ isRequired: false,
50888
+ transformFunction: null
50889
+ },
50890
+ closeContextLabel: {
50891
+ classPropertyName: "closeContextLabel",
50892
+ publicName: "closeContextLabel",
50893
+ isSignal: true,
50894
+ isRequired: false,
50895
+ transformFunction: null
50896
+ },
50897
+ canWrite: {
50898
+ classPropertyName: "canWrite",
50899
+ publicName: "canWrite",
50900
+ isSignal: true,
50901
+ isRequired: false,
50902
+ transformFunction: null
50903
+ },
50904
+ draft: {
50905
+ classPropertyName: "draft",
50906
+ publicName: "draft",
50907
+ isSignal: true,
50908
+ isRequired: false,
50909
+ transformFunction: null
50910
+ },
50911
+ sending: {
50912
+ classPropertyName: "sending",
50913
+ publicName: "sending",
50914
+ isSignal: true,
50915
+ isRequired: false,
50916
+ transformFunction: null
50917
+ },
50918
+ composerDisabled: {
50919
+ classPropertyName: "composerDisabled",
50920
+ publicName: "composerDisabled",
50921
+ isSignal: true,
50922
+ isRequired: false,
50923
+ transformFunction: null
50924
+ },
50925
+ sendBlocked: {
50926
+ classPropertyName: "sendBlocked",
50927
+ publicName: "sendBlocked",
50928
+ isSignal: true,
50929
+ isRequired: false,
50930
+ transformFunction: null
50931
+ },
50932
+ composerNotice: {
50933
+ classPropertyName: "composerNotice",
50934
+ publicName: "composerNotice",
50935
+ isSignal: true,
50936
+ isRequired: false,
50937
+ transformFunction: null
50938
+ },
50939
+ composerStatus: {
50940
+ classPropertyName: "composerStatus",
50941
+ publicName: "composerStatus",
50942
+ isSignal: true,
50943
+ isRequired: false,
50944
+ transformFunction: null
50945
+ },
50946
+ composerError: {
50947
+ classPropertyName: "composerError",
50948
+ publicName: "composerError",
50949
+ isSignal: true,
50950
+ isRequired: false,
50951
+ transformFunction: null
50952
+ },
50953
+ maxLength: {
50954
+ classPropertyName: "maxLength",
50955
+ publicName: "maxLength",
50956
+ isSignal: true,
50957
+ isRequired: false,
50958
+ transformFunction: null
50959
+ },
50960
+ attachment: {
50961
+ classPropertyName: "attachment",
50962
+ publicName: "attachment",
50963
+ isSignal: true,
50964
+ isRequired: false,
50965
+ transformFunction: null
50966
+ },
50967
+ uploading: {
50968
+ classPropertyName: "uploading",
50969
+ publicName: "uploading",
50970
+ isSignal: true,
50971
+ isRequired: false,
50972
+ transformFunction: null
50973
+ },
50974
+ attachEnabled: {
50975
+ classPropertyName: "attachEnabled",
50976
+ publicName: "attachEnabled",
50977
+ isSignal: true,
50978
+ isRequired: false,
50979
+ transformFunction: null
50980
+ },
50981
+ acceptedFiles: {
50982
+ classPropertyName: "acceptedFiles",
50983
+ publicName: "acceptedFiles",
50984
+ isSignal: true,
50985
+ isRequired: false,
50986
+ transformFunction: null
50987
+ },
50988
+ maxFileSize: {
50989
+ classPropertyName: "maxFileSize",
50990
+ publicName: "maxFileSize",
50991
+ isSignal: true,
50992
+ isRequired: false,
50993
+ transformFunction: null
50994
+ },
50995
+ typeMessage: {
50996
+ classPropertyName: "typeMessage",
50997
+ publicName: "typeMessage",
50998
+ isSignal: true,
50999
+ isRequired: false,
51000
+ transformFunction: null
51001
+ },
51002
+ sizeMessage: {
51003
+ classPropertyName: "sizeMessage",
51004
+ publicName: "sizeMessage",
51005
+ isSignal: true,
51006
+ isRequired: false,
51007
+ transformFunction: null
51008
+ },
51009
+ composeLabel: {
51010
+ classPropertyName: "composeLabel",
51011
+ publicName: "composeLabel",
51012
+ isSignal: true,
51013
+ isRequired: false,
51014
+ transformFunction: null
51015
+ },
51016
+ composePlaceholder: {
51017
+ classPropertyName: "composePlaceholder",
51018
+ publicName: "composePlaceholder",
51019
+ isSignal: true,
51020
+ isRequired: false,
51021
+ transformFunction: null
51022
+ },
51023
+ sendLabel: {
51024
+ classPropertyName: "sendLabel",
51025
+ publicName: "sendLabel",
51026
+ isSignal: true,
51027
+ isRequired: false,
51028
+ transformFunction: null
51029
+ },
51030
+ attachLabel: {
51031
+ classPropertyName: "attachLabel",
51032
+ publicName: "attachLabel",
51033
+ isSignal: true,
51034
+ isRequired: false,
51035
+ transformFunction: null
51036
+ },
51037
+ removeAttachmentLabel: {
51038
+ classPropertyName: "removeAttachmentLabel",
51039
+ publicName: "removeAttachmentLabel",
51040
+ isSignal: true,
51041
+ isRequired: false,
51042
+ transformFunction: null
51043
+ },
51044
+ attachmentPreviewLabel: {
51045
+ classPropertyName: "attachmentPreviewLabel",
51046
+ publicName: "attachmentPreviewLabel",
51047
+ isSignal: true,
51048
+ isRequired: false,
51049
+ transformFunction: null
51050
+ },
51051
+ now: {
51052
+ classPropertyName: "now",
51053
+ publicName: "now",
51054
+ isSignal: true,
51055
+ isRequired: false,
51056
+ transformFunction: null
51057
+ }
51058
+ },
51059
+ outputs: {
51060
+ searchText: "searchTextChange",
51061
+ contextOpen: "contextOpenChange",
51062
+ draft: "draftChange",
51063
+ searchChange: "searchChange",
51064
+ filterChange: "filterChange",
51065
+ pageChange: "pageChange",
51066
+ selectConversation: "selectConversation",
51067
+ back: "back",
51068
+ newConversation: "newConversation",
51069
+ retry: "retry",
51070
+ deleteConversation: "deleteConversation",
51071
+ statusChange: "statusChange",
51072
+ templateRequest: "templateRequest",
51073
+ send: "send",
51074
+ filesSelected: "filesSelected",
51075
+ attachmentRemove: "attachmentRemove",
51076
+ mediaOpen: "mediaOpen",
51077
+ messageAction: "messageAction",
51078
+ loadEarlier: "loadEarlier",
51079
+ messagesRetry: "messagesRetry"
51080
+ },
51081
+ viewQueries: [
51082
+ {
51083
+ propertyName: "threadHeading",
51084
+ first: true,
51085
+ predicate: ["threadHeading"],
51086
+ descendants: true,
51087
+ isSignal: true
51088
+ },
51089
+ {
51090
+ propertyName: "messagesEl",
51091
+ first: true,
51092
+ predicate: ["messagesEl"],
51093
+ descendants: true,
51094
+ isSignal: true
51095
+ },
51096
+ {
51097
+ propertyName: "contextPanel",
51098
+ first: true,
51099
+ predicate: ["contextPanel"],
51100
+ descendants: true,
51101
+ isSignal: true
51102
+ },
51103
+ {
51104
+ propertyName: "fileInput",
51105
+ first: true,
51106
+ predicate: FileInputComponent,
51107
+ descendants: true,
51108
+ isSignal: true
51109
+ }
51110
+ ],
51111
+ ngImport: i0,
51112
+ template: `
51113
+ <div class="cv-layout" [class.has-context]="contextVisible()" data-testid="conversations">
51114
+ @if (contextVisible()) {
51115
+ <div class="cv-context-backdrop" (click)="closeContext()" aria-hidden="true"></div>
51116
+ }
51117
+
51118
+ <!-- LEFT: conversation list -->
51119
+ <section class="cv-list-panel" [class.cv-hidden-mobile]="!!selected()" [attr.aria-labelledby]="titleId">
51120
+ <div class="cv-list-header">
51121
+ <h2 class="cv-list-title" [id]="titleId">{{ title() }}</h2>
51122
+ @if (canWrite() && allowNew()) {
51123
+ <ui-button class="cv-new-btn" variant="primary" size="sm" [ariaLabel]="newLabel()" [uiTooltip]="newTooltip()" tooltipPosition="bottom" (click)="newConversation.emit()" data-testid="new-message-btn">
51124
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>
51125
+ </ui-button>
51126
+ }
51127
+ </div>
51128
+
51129
+ @if (showFilters()) {
51130
+ <div class="cv-search">
51131
+ <ui-search-input [placeholder]="searchPlaceholder()" [ariaLabel]="searchAriaLabel()" [(value)]="searchText" (searchChange)="searchChange.emit($event)" data-testid="conv-search" />
51132
+ </div>
51133
+ @if (filterTabs().length) {
51134
+ <div class="cv-filters">
51135
+ <ui-quick-filter-tabs [ariaLabel]="filterAriaLabel()" [tabs]="filterTabs()" [counts]="filterCounts()" [activeValue]="activeFilter()" (tabChange)="filterChange.emit($event)" data-testid="conv-filters" />
51136
+ </div>
51137
+ }
51138
+ }
51139
+
51140
+ @if (loading()) {
51141
+ <div class="cv-loading" aria-busy="true" [attr.aria-label]="loadingLabel()" data-testid="conv-loading">
51142
+ @for (i of skeletonRows; track i) {
51143
+ <div class="cv-skeleton">
51144
+ <ui-skeleton [height]="40" width="40px" [radius]="20" />
51145
+ <div class="cv-skel-content">
51146
+ <div class="cv-skel-row">
51147
+ <ui-skeleton width="55%" [height]="12" />
51148
+ <ui-skeleton width="48px" [height]="10" />
51149
+ </div>
51150
+ <ui-skeleton width="30%" [height]="10" [mb]="2" />
51151
+ <ui-skeleton width="85%" [height]="10" />
51152
+ </div>
51153
+ </div>
51154
+ }
51155
+ </div>
51156
+ } @else if (error()) {
51157
+ <div class="cv-error" data-testid="conv-error">
51158
+ <ui-alert variant="danger">{{ error() }}</ui-alert>
51159
+ <ui-button variant="secondary" size="sm" (click)="retry.emit()" data-testid="conv-retry">Retry</ui-button>
51160
+ </div>
51161
+ } @else if (conversations().length === 0) {
51162
+ <ui-empty-state iconType="message" data-testid="conv-empty" [title]="filtering() ? filteredEmptyTitle() : emptyTitle()" [message]="emptyText()" />
51163
+ } @else {
51164
+ <div class="cv-list">
51165
+ <ui-list [ariaLabel]="listAriaLabel()" [items]="conversations()" [trackBy]="trackConversation" [navigable]="true" (itemClick)="onRowOpen($event)">
51166
+ <ng-template let-conv>
51167
+ <div class="cv-item" data-testid="conv-item" [attr.data-conversation-id]="conv.id"
51168
+ [class.selected]="selected()?.id === conv.id" [class.unread]="(conv.unreadCount ?? 0) > 0">
51169
+ <ui-avatar [initials]="initial(conv.name)" [name]="conv.name" [size]="40" />
51170
+ <div class="cv-item-info">
51171
+ <div class="cv-item-top">
51172
+ <span class="cv-name">{{ conv.name }}</span>@if (selected()?.id === conv.id) {<span class="cv-sr-only">, open</span>}
51173
+ <span class="cv-time">{{ relativeTime(conv.lastMessageAt) }}</span>
51174
+ </div>
51175
+ @if (conv.subtitle) { <span class="cv-subtitle">{{ conv.subtitle }}</span> }
51176
+ <div class="cv-item-bottom">
51177
+ <p class="cv-preview">{{ preview(conv.preview) || noMessagesText() }}</p>
51178
+ <div class="cv-item-right">
51179
+ @if (conv.statusLabel) { <ui-badge [label]="conv.statusLabel" variant="gray" /> }
51180
+ @if ((conv.unreadCount ?? 0) > 0) {
51181
+ <ui-badge class="cv-unread-badge" [label]="'' + conv.unreadCount" variant="blue" data-testid="conv-unread" />
51182
+ <span class="cv-sr-only">unread</span>
51183
+ }
51184
+ @if (canWrite() && allowDelete()) {
51185
+ <ui-button class="cv-delete-btn" variant="icon-danger" [ariaLabel]="deleteRowLabel() + ' ' + conv.name" (click)="$event.stopPropagation(); deleteConversation.emit(conv)" data-testid="conv-delete-btn">
51186
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
51187
+ </ui-button>
51188
+ }
51189
+ </div>
51190
+ </div>
51191
+ </div>
51192
+ </div>
51193
+ </ng-template>
51194
+ </ui-list>
51195
+ <ui-pagination [ariaLabel]="paginationAriaLabel()" [page]="page()" [pageSize]="pageSize()" [totalItems]="totalItems()" (pageChange)="pageChange.emit($event)" />
51196
+ </div>
51197
+ }
51198
+ </section>
51199
+
51200
+ <!-- CENTER: message thread -->
51201
+ <section class="cv-thread-panel" [class.cv-hidden-mobile]="!selected()" [attr.aria-label]="threadAriaLabel()">
51202
+ @if (selected(); as conv) {
51203
+ <div class="cv-thread-header">
51204
+ <ui-button class="cv-back-btn" variant="secondary" size="sm" [ariaLabel]="backLabel()" (click)="onBack()" data-testid="back-to-list">
51205
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
51206
+ </ui-button>
51207
+ <div class="cv-thread-header-info">
51208
+ <ui-avatar [initials]="initial(conv.name)" [name]="conv.name" [size]="40" />
51209
+ <div class="cv-thread-header-text">
51210
+ <h3 class="cv-thread-name" #threadHeading tabindex="-1" data-testid="thread-name">{{ conv.name }}</h3>
51211
+ @if (conv.subtitle) { <span class="cv-thread-subtitle" data-testid="thread-phone">{{ conv.subtitle }}</span> }
51212
+ </div>
51213
+ </div>
51214
+ <div class="cv-thread-actions">
51215
+ @if (canWrite() && templatesEnabled()) {
51216
+ <ui-button class="cv-thread-action" variant="secondary" size="sm" [ariaLabel]="templateLabel()" [uiTooltip]="templateLabel()" tooltipPosition="bottom" [disabled]="composerDisabled()" (click)="templateRequest.emit()" data-testid="use-template-btn">
51217
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
51218
+ </ui-button>
51219
+ }
51220
+ @if (hasContext()) {
51221
+ <ui-button #contextToggle class="cv-thread-action" [variant]="contextOpen() ? 'primary' : 'secondary'" size="sm" [ariaLabel]="contextOpen() ? hideContextLabel() : showContextLabel()" [uiTooltip]="contextOpen() ? hideContextLabel() : contextTitle()" tooltipPosition="bottom" (click)="toggleContext()" data-testid="context-toggle">
51222
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
51223
+ </ui-button>
51224
+ }
51225
+ @if (canWrite() && statusActionLabel()) {
51226
+ <ui-button class="cv-thread-action" variant="secondary" size="sm" [ariaLabel]="statusActionLabel() ?? ''" [uiTooltip]="statusActionLabel()" tooltipPosition="bottom" [disabled]="statusChanging()" (click)="statusChange.emit(conv)" data-testid="status-btn">
51227
+ @if (statusActionIcon() === 'reopen') {
51228
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg>
51229
+ } @else {
51230
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
51231
+ }
51232
+ </ui-button>
51233
+ }
51234
+ @if (canWrite() && allowDelete()) {
51235
+ <ui-button class="cv-thread-action" variant="danger" size="sm" [ariaLabel]="deleteThreadLabel()" [uiTooltip]="deleteThreadLabel()" tooltipPosition="bottom" (click)="deleteConversation.emit(conv)" data-testid="thread-delete-btn">
51236
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
51237
+ </ui-button>
51238
+ }
51239
+ </div>
51240
+ </div>
51241
+
51242
+ <div class="cv-messages" #messagesEl role="log" aria-live="polite" aria-relevant="additions" tabindex="0"
51243
+ [attr.aria-label]="messagesAriaLabel() + ' ' + conv.name" [attr.aria-busy]="messagesLoading()" (scroll)="onMessagesScroll()" data-testid="messages">
51244
+ @if (messagesLoading()) {
51245
+ <div class="cv-messages-loading" data-testid="messages-loading">
51246
+ @for (i of skeletonBubbles; track i) {
51247
+ <div class="cv-msg-skeleton" [class.outbound]="i % 2 === 0">
51248
+ <ui-skeleton [height]="48" [width]="i % 2 === 0 ? '60%' : '55%'" [radius]="16" />
51249
+ </div>
51250
+ }
51251
+ </div>
51252
+ } @else if (messagesError()) {
51253
+ <div class="cv-messages-error" data-testid="thread-error">
51254
+ <ui-alert variant="danger">{{ messagesError() }}</ui-alert>
51255
+ <ui-button variant="secondary" size="sm" (click)="messagesRetry.emit()" data-testid="thread-retry">Retry</ui-button>
51256
+ </div>
51257
+ } @else if (messages().length === 0) {
51258
+ <div class="cv-messages-empty" data-testid="messages-empty">
51259
+ <p>{{ canWrite() ? noMessagesWriteText() : noMessagesReadText() }}</p>
51260
+ </div>
51261
+ } @else {
51262
+ @if (hasEarlier()) {
51263
+ <div class="cv-load-earlier">
51264
+ <ui-button variant="secondary" size="sm" [loading]="loadingEarlier()" (click)="loadEarlier.emit()" data-testid="load-earlier">{{ loadEarlierLabel() }}</ui-button>
51265
+ </div>
51266
+ }
51267
+ @for (row of messageRows(); track row.message.id) {
51268
+ @if (row.separator) { <div class="cv-date-separator"><span>{{ row.separator }}</span></div> }
51269
+ <div class="cv-bubble" data-testid="message" [class.outbound]="row.message.direction === 'outbound'" [class.inbound]="row.message.direction === 'inbound'">
51270
+ <span class="cv-sr-only">{{ row.message.direction === 'outbound' ? youLabel() : conv.name }}:</span>
51271
+ @if (row.message.media; as media) {
51272
+ <div class="cv-media">
51273
+ @if (media.type?.startsWith('image/')) {
51274
+ <button type="button" class="cv-image-btn" (click)="mediaOpen.emit(media.url)" [attr.aria-label]="openMediaLabel() + ' ' + (media.fileName || imageFallbackName())">
51275
+ <img [src]="media.url" [alt]="media.fileName || imageFallbackName()" class="cv-image" loading="lazy" />
51276
+ </button>
51277
+ } @else if (media.type?.startsWith('video/')) {
51278
+ <video [src]="media.url" class="cv-video" controls preload="metadata"></video>
51279
+ } @else {
51280
+ <a [href]="media.url" target="_blank" rel="noopener noreferrer" class="cv-file-link">{{ media.fileName || fileFallbackName() }}</a>
51281
+ }
51282
+ </div>
51283
+ }
51284
+ @if (row.message.body) { <p class="cv-body">{{ row.message.body }}</p> }
51285
+ <span class="cv-meta">
51286
+ @if (row.message.direction === 'outbound' && row.message.sender) { <span class="cv-sender" data-testid="msg-sender">{{ row.message.sender }}</span> }
51287
+ {{ time(row.message) }}
51288
+ @if (row.message.action; as action) {
51289
+ <button type="button" class="cv-msg-action" data-testid="msg-action" (click)="messageAction.emit(row.message)">{{ action.label }}</button>
51290
+ }
51291
+ @if (row.message.direction === 'outbound' && statusLabel(row.message.status)) {
51292
+ <span class="cv-status" [class.failed]="row.message.status === 'failed'" data-testid="msg-status">
51293
+ <span aria-hidden="true">{{ statusMark(row.message.status) }}</span>
51294
+ <span class="cv-sr-only">{{ statusLabel(row.message.status) }}</span>
51295
+ </span>
51296
+ }
51297
+ </span>
51298
+ </div>
51299
+ }
51300
+ }
51301
+ </div>
51302
+
51303
+ @if (canWrite()) {
51304
+ <div class="cv-compose">
51305
+ @if (attachment(); as file) {
51306
+ <div class="cv-attachment" data-testid="attachment-preview">
51307
+ @if (file.previewUrl) {
51308
+ <img [src]="file.previewUrl" [alt]="attachmentPreviewLabel()" class="cv-attachment-thumb" />
51309
+ } @else {
51310
+ <span class="cv-attachment-name">{{ file.fileName }}</span>
51311
+ }
51312
+ <ui-button class="cv-attachment-remove" variant="icon-danger" [ariaLabel]="removeAttachmentLabel()" (click)="attachmentRemove.emit()" data-testid="attachment-remove">
51313
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
51314
+ </ui-button>
51315
+ </div>
51316
+ }
51317
+ <div class="cv-compose-row">
51318
+ @if (attachEnabled()) {
51319
+ <ui-button class="cv-attach-btn" variant="icon" [ariaLabel]="attachLabel()" [disabled]="uploading() || composerDisabled()" [loading]="uploading()" (click)="openFilePicker()" data-testid="attach-btn">
51320
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>
51321
+ </ui-button>
51322
+ <ui-file-input [showField]="false" [accept]="acceptedFiles()" [maxSize]="maxFileSize()" [toastOnReject]="true"
51323
+ [typeMessage]="typeMessage()" [sizeMessage]="sizeMessage()" (filesSelected)="filesSelected.emit($event)" data-testid="attach-input" />
51324
+ }
51325
+ <ui-textarea-input class="cv-compose-input" [ariaLabel]="composeLabel()" [placeholder]="composePlaceholder()" [rows]="1" [maxlength]="maxLength()"
51326
+ [ngModel]="draft()" (ngModelChange)="draft.set($event)" [disabled]="composerDisabled()" [error]="composerError()"
51327
+ (keydown)="onComposeKeydown($event)" data-testid="compose-input" />
51328
+ <ui-button class="cv-send-btn" variant="primary" [ariaLabel]="sendLabel()" [disabled]="!canSend()" [loading]="sending()" (click)="sendMessage()" data-testid="send-btn">
51329
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
51330
+ </ui-button>
51331
+ </div>
51332
+ @if (composerNotice()) {
51333
+ <ui-alert variant="warning" data-testid="compose-opted-out">{{ composerNotice() }}</ui-alert>
51334
+ }
51335
+ <!-- Always in the page (a live region that appears together with its text is often not announced): only its text comes and goes. -->
51336
+ <p class="cv-compose-status" role="status" data-testid="compose-loading-contact">{{ composerStatus() }}</p>
51337
+ </div>
51338
+ }
51339
+ } @else {
51340
+ <ui-empty-state iconType="message" [title]="threadEmptyTitle()" [message]="threadEmptyMessage()" data-testid="thread-empty" />
51341
+ }
51342
+ </section>
51343
+
51344
+ <!-- RIGHT: contact panel (the host's content) -->
51345
+ @if (contextVisible()) {
51346
+ <aside class="cv-context" #contextPanel tabindex="-1" [attr.aria-label]="contextTitle()" (keydown.escape)="closeContext(true)" data-testid="context-panel">
51347
+ <div class="cv-context-header">
51348
+ <h3>{{ contextTitle() }}</h3>
51349
+ <ui-button variant="icon" [ariaLabel]="closeContextLabel()" (click)="closeContext(true)" data-testid="context-close">
51350
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
51351
+ </ui-button>
51352
+ </div>
51353
+ <div class="cv-context-body"><ng-content select="[uiConversationsContext]" /></div>
51354
+ </aside>
51355
+ }
51356
+ </div>
51357
+ `,
51358
+ isInline: true,
51359
+ styles: [":host{display:flex;flex:1;min-height:0;min-width:0}.cv-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.cv-layout{display:grid;grid-template-columns:340px 1fr;flex:1;min-height:0;min-width:0;background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 1px 3px #0000000f;border:1px solid #e2e8f0}.cv-layout.has-context{grid-template-columns:340px 1fr 280px}.cv-list-panel{display:flex;flex-direction:column;min-height:0;border-right:1px solid #e2e8f0;background:#f8fafc;overflow:hidden}.cv-list-header{display:flex;align-items:center;justify-content:space-between;padding:20px 20px 12px}.cv-list-title{margin:0;font-size:1.125rem;font-weight:700;color:#1e293b}.cv-search,.cv-filters{padding:0 16px 12px}.cv-list{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}.cv-item{display:flex;gap:12px;padding:14px 16px;border-bottom:1px solid #f1f5f9;transition:background .15s}.cv-item.unread{background:#fffbeb}.cv-item.selected{background:#eff6ff;box-shadow:inset 3px 0 #2563eb}.cv-item-info{flex:1;min-width:0}.cv-item-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px}.cv-name{font-size:.875rem;font-weight:600;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cv-time{font-size:.6875rem;color:#64748b;flex-shrink:0;margin-left:8px}.cv-subtitle{font-size:.6875rem;color:#64748b;display:block;margin-bottom:2px}.cv-item-bottom{display:flex;justify-content:space-between;align-items:center;gap:8px}.cv-preview{margin:0;font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.cv-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.cv-delete-btn{opacity:0;transition:opacity .15s}.cv-item:hover .cv-delete-btn,.cv-item:focus-within .cv-delete-btn,.cv-delete-btn:focus-within{opacity:1}@media(hover:none){.cv-delete-btn{opacity:1}}.cv-loading{padding:8px 0}.cv-skeleton{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border-bottom:1px solid #f1f5f9}.cv-skel-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px;padding-top:2px}.cv-skel-row{display:flex;justify-content:space-between;gap:8px}.cv-error{display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 16px;text-align:center}.cv-thread-panel{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden;background:#fff}.cv-thread-header{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid #e2e8f0;background:#fff}.cv-back-btn{display:none}.cv-thread-header-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}.cv-thread-header-text{min-width:0;display:flex;flex-direction:column}.cv-thread-name{margin:0;font-size:.9375rem;font-weight:600;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cv-thread-name:focus{outline:none}.cv-thread-name:focus-visible{outline:2px solid #2563eb;outline-offset:2px;border-radius:4px}.cv-thread-subtitle{font-size:.75rem;color:#64748b}.cv-thread-actions{display:flex;align-items:center;gap:8px}.cv-messages{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;padding:20px 24px;display:flex;flex-direction:column;gap:4px;background:#f8fafc}.cv-messages:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}.cv-messages-loading{display:flex;flex-direction:column;gap:12px;padding:20px 0}.cv-msg-skeleton{display:flex}.cv-msg-skeleton.outbound{justify-content:flex-end}.cv-messages-error{display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 16px;text-align:center}.cv-load-earlier{display:flex;justify-content:center;padding:4px 0 12px}.cv-sender{font-weight:600}.cv-msg-action{padding:0;border:0;background:none;color:inherit;font:inherit;text-decoration:underline;cursor:pointer}.cv-msg-action:focus-visible{outline:2px solid currentColor;outline-offset:2px;border-radius:2px}.cv-messages-empty{display:flex;align-items:center;justify-content:center;flex:1}.cv-messages-empty p{margin:0;font-size:.875rem;color:#64748b;text-align:center}.cv-date-separator{display:flex;align-items:center;justify-content:center;padding:16px 0 8px}.cv-date-separator span{padding:4px 14px;border-radius:12px;background:#e2e8f0;font-size:.6875rem;font-weight:600;color:#475569;text-transform:uppercase;letter-spacing:.3px}.cv-bubble{max-width:70%;padding:10px 14px;border-radius:16px;position:relative;word-break:break-word;overflow-wrap:break-word}.cv-bubble.inbound{align-self:flex-start;background:#fff;border:1px solid #e2e8f0;border-bottom-left-radius:4px}.cv-bubble.inbound .cv-body{color:#1e293b}.cv-bubble.inbound .cv-meta{color:#64748b}.cv-bubble.outbound{align-self:flex-end;background:#2563eb;border-bottom-right-radius:4px}.cv-bubble.outbound .cv-body,.cv-bubble.outbound .cv-meta{color:#fff}@media(prefers-reduced-motion:no-preference){.cv-bubble{animation:cv-appear .2s ease}.cv-context{animation:cv-slide-in .25s ease}}.cv-body{margin:0;font-size:.875rem;line-height:1.45;word-break:break-word;white-space:pre-wrap}.cv-media{margin-bottom:6px}.cv-image-btn{display:block;padding:0;border:0;background:none;cursor:pointer;border-radius:8px}.cv-image-btn:focus-visible{outline:2px solid #fff;outline-offset:2px;box-shadow:0 0 0 4px #2563eb}.cv-image{display:block;max-width:240px;max-height:240px;border-radius:8px;object-fit:cover}.cv-video{max-width:240px;max-height:200px;border-radius:8px}.cv-file-link{font-size:.8125rem;color:#fff;text-decoration:underline}.cv-bubble.inbound .cv-file-link{color:#2563eb}.cv-meta{display:flex;align-items:center;gap:6px;justify-content:flex-end;font-size:.6875rem;margin-top:4px}.cv-status{font-weight:500}.cv-status.failed{color:#fff;font-weight:700}.cv-bubble.inbound .cv-status.failed{color:#dc2626}.cv-compose{display:flex;flex-direction:column;padding:12px 20px 16px;padding-bottom:calc(16px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#fff}.cv-compose-row{display:flex;align-items:flex-end;gap:10px}.cv-compose-input{flex:1;min-width:0}.cv-attach-btn,.cv-send-btn{flex-shrink:0}.cv-attachment{display:flex;align-items:center;gap:8px;padding:8px 12px;margin-bottom:8px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px}.cv-attachment-thumb{width:48px;height:48px;object-fit:cover;border-radius:6px}.cv-attachment-name{font-size:.8125rem;color:#475569;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cv-attachment-remove{flex-shrink:0}.cv-compose-status{margin:4px 0 0;font-size:.8125rem;color:#64748b}.cv-compose-status:empty{margin:0}.cv-context-backdrop{display:none}.cv-context{width:100%;min-width:0;border-left:1px solid #e2e8f0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.cv-context-header{display:flex;justify-content:space-between;align-items:center;padding:20px;border-bottom:1px solid #e2e8f0}.cv-context-header h3{margin:0;font-size:.875rem;font-weight:700;color:#1e293b}.cv-context-body{padding:20px;display:flex;flex-direction:column;gap:16px}@keyframes cv-appear{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes cv-slide-in{0%{transform:translate(100%)}to{transform:translate(0)}}@media(max-width:1100px){.cv-layout.has-context{grid-template-columns:280px 1fr 240px}}@media(max-width:768px){.cv-layout,.cv-layout.has-context{grid-template-columns:1fr;height:100%}.cv-hidden-mobile{display:none!important}.cv-back-btn{display:inline-flex}.cv-context-backdrop{display:block;position:fixed;inset:0;background:#00000059;z-index:99}.cv-context{position:fixed;top:0;right:0;bottom:0;width:300px;max-width:85vw;z-index:100;box-shadow:-4px 0 20px #0000001a}.cv-bubble{max-width:85%}.cv-messages,.cv-thread-header{padding:12px 16px}}@media(max-width:480px){.cv-thread-subtitle{display:none}.cv-compose{padding:8px 12px 12px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px))}.cv-list-header{padding:12px 16px 10px}.cv-context{width:100%;max-width:100vw}}\n"],
51360
+ dependencies: [
51361
+ {
51362
+ kind: "ngmodule",
51363
+ type: FormsModule
51364
+ },
51365
+ {
51366
+ kind: "directive",
51367
+ type: i1.NgControlStatus,
51368
+ selector: "[formControlName],[ngModel],[formControl]"
51369
+ },
51370
+ {
51371
+ kind: "directive",
51372
+ type: i1.MaxLengthValidator,
51373
+ selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]",
51374
+ inputs: ["maxlength"]
51375
+ },
51376
+ {
51377
+ kind: "directive",
51378
+ type: i1.NgModel,
51379
+ selector: "[ngModel]:not([formControlName]):not([formControl])",
51380
+ inputs: [
51381
+ "name",
51382
+ "disabled",
51383
+ "ngModel",
51384
+ "ngModelOptions"
51385
+ ],
51386
+ outputs: ["ngModelChange"],
51387
+ exportAs: ["ngModel"]
51388
+ },
51389
+ {
51390
+ kind: "component",
51391
+ type: AlertComponent,
51392
+ selector: "ui-alert",
51393
+ inputs: [
51394
+ "variant",
51395
+ "title",
51396
+ "dismissible",
51397
+ "dismissAriaLabel",
51398
+ "quiet",
51399
+ "compact",
51400
+ "inline",
51401
+ "fill"
51402
+ ],
51403
+ outputs: ["dismissed"]
51404
+ },
51405
+ {
51406
+ kind: "component",
51407
+ type: AvatarComponent,
51408
+ selector: "ui-avatar",
51409
+ inputs: [
51410
+ "initials",
51411
+ "name",
51412
+ "size",
51413
+ "imageUrl",
51414
+ "editable",
51415
+ "editLabel",
51416
+ "busy"
51417
+ ],
51418
+ outputs: ["editClick", "imageError"]
51419
+ },
51420
+ {
51421
+ kind: "component",
51422
+ type: BadgeComponent,
51423
+ selector: "ui-badge",
51424
+ inputs: ["label", "variant"]
51425
+ },
51426
+ {
51427
+ kind: "component",
51428
+ type: ButtonComponent,
51429
+ selector: "ui-button",
51430
+ inputs: [
51431
+ "variant",
51432
+ "routerLink",
51433
+ "queryParams",
51434
+ "fragment",
51435
+ "state",
51436
+ "href",
51437
+ "target",
51438
+ "rel",
51439
+ "shortLabel",
51440
+ "shortBelow",
51441
+ "color",
51442
+ "active",
51443
+ "size",
51444
+ "type",
51445
+ "disabled",
51446
+ "loading",
51447
+ "fullWidth",
51448
+ "ariaLabel",
51449
+ "ariaExpanded",
51450
+ "ariaPressed",
51451
+ "ariaDescribedBy",
51452
+ "modal-footer-left",
51453
+ "modal-footer-right"
51454
+ ]
51455
+ },
51456
+ {
51457
+ kind: "component",
51458
+ type: EmptyStateComponent,
51459
+ selector: "ui-empty-state",
51460
+ inputs: [
51461
+ "message",
51462
+ "title",
51463
+ "iconType"
51464
+ ]
51465
+ },
51466
+ {
51467
+ kind: "component",
51468
+ type: FileInputComponent,
51469
+ selector: "ui-file-input",
51470
+ inputs: [
51471
+ "label",
51472
+ "ariaLabel",
51473
+ "placeholder",
51474
+ "buttonLabel",
51475
+ "accept",
51476
+ "multiple",
51477
+ "required",
51478
+ "hint",
51479
+ "error",
51480
+ "showField",
51481
+ "showErrors",
51482
+ "toastOnReject",
51483
+ "clearable",
51484
+ "removeLabel",
51485
+ "maxSize",
51486
+ "enforceAccept",
51487
+ "typeMessage",
51488
+ "sizeMessage",
51489
+ "rejectEmpty",
51490
+ "emptyMessage",
51491
+ "minSize",
51492
+ "minSizeMessage",
51493
+ "dropzone",
51494
+ "showDetails",
51495
+ "preview",
51496
+ "loading",
51497
+ "loadingText",
51498
+ "disabled"
51499
+ ],
51500
+ outputs: [
51501
+ "filesSelected",
51502
+ "fileRejected",
51503
+ "fileRemoved",
51504
+ "invalidChange"
51505
+ ]
51506
+ },
51507
+ {
51508
+ kind: "component",
51509
+ type: ListComponent,
51510
+ selector: "ui-list",
51511
+ inputs: [
51512
+ "items",
51513
+ "ordered",
51514
+ "layout",
51515
+ "gridMin",
51516
+ "gap",
51517
+ "reorderable",
51518
+ "disabled",
51519
+ "moveControls",
51520
+ "dragDrop",
51521
+ "ariaLabel",
51522
+ "ariaLabelledby",
51523
+ "itemLabelFn",
51524
+ "trackBy",
51525
+ "moveEarlierLabel",
51526
+ "moveLaterLabel",
51527
+ "helpText",
51528
+ "moveAnnouncement",
51529
+ "navigable"
51530
+ ],
51531
+ outputs: [
51532
+ "itemClick",
51533
+ "itemsChange",
51534
+ "reorder"
51535
+ ]
51536
+ },
51537
+ {
51538
+ kind: "component",
51539
+ type: PaginationComponent,
51540
+ selector: "ui-pagination",
51541
+ inputs: [
51542
+ "page",
51543
+ "pageSize",
51544
+ "totalItems",
51545
+ "detached",
51546
+ "embedded",
51547
+ "ariaLabel"
51548
+ ],
51549
+ outputs: ["pageChange"]
51550
+ },
51551
+ {
51552
+ kind: "component",
51553
+ type: QuickFilterTabsComponent,
51554
+ selector: "ui-quick-filter-tabs",
51555
+ inputs: [
51556
+ "tabs",
51557
+ "counts",
51558
+ "activeValue",
51559
+ "ariaLabel"
51560
+ ],
51561
+ outputs: ["tabChange"]
51562
+ },
51563
+ {
51564
+ kind: "component",
51565
+ type: SearchInputComponent,
51566
+ selector: "ui-search-input",
51567
+ inputs: [
51568
+ "placeholder",
51569
+ "ariaLabel",
51570
+ "value",
51571
+ "maxlength",
51572
+ "endpoint",
51573
+ "loading"
51574
+ ],
51575
+ outputs: [
51576
+ "valueChange",
51577
+ "searchChange",
51578
+ "filteredData"
51579
+ ]
51580
+ },
51581
+ {
51582
+ kind: "component",
51583
+ type: SkeletonComponent,
51584
+ selector: "ui-skeleton",
51585
+ inputs: [
51586
+ "height",
51587
+ "width",
51588
+ "radius",
51589
+ "mb",
51590
+ "ariaLabel"
51591
+ ]
51592
+ },
51593
+ {
51594
+ kind: "component",
51595
+ type: TextareaInputComponent,
51596
+ selector: "ui-textarea-input",
51597
+ inputs: [
51598
+ "label",
51599
+ "ariaLabel",
51600
+ "placeholder",
51601
+ "rows",
51602
+ "maxlength",
51603
+ "required",
51604
+ "readonly",
51605
+ "hint",
51606
+ "ariaDescribedBy",
51607
+ "hintAsDescription",
51608
+ "error",
51609
+ "monospace",
51610
+ "showErrors",
51611
+ "disabled"
51612
+ ],
51613
+ outputs: ["invalidChange"]
51614
+ },
51615
+ {
51616
+ kind: "directive",
51617
+ type: TooltipDirective,
51618
+ selector: "[uiTooltip]",
51619
+ inputs: ["uiTooltip", "tooltipPosition"]
51620
+ }
51621
+ ],
51622
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
51623
+ });
51624
+ }
51625
+ };
51626
+ i0.ɵɵngDeclareClassMetadata({
51627
+ minVersion: "12.0.0",
51628
+ version: "22.2.2",
51629
+ ngImport: i0,
51630
+ type: ConversationsComponent,
51631
+ decorators: [{
51632
+ type: Component,
51633
+ args: [{
51634
+ selector: "ui-conversations",
51635
+ standalone: true,
51636
+ changeDetection: ChangeDetectionStrategy.OnPush,
51637
+ imports: [
51638
+ FormsModule,
51639
+ AlertComponent,
51640
+ AvatarComponent,
51641
+ BadgeComponent,
51642
+ ButtonComponent,
51643
+ EmptyStateComponent,
51644
+ FileInputComponent,
51645
+ ListComponent,
51646
+ PaginationComponent,
51647
+ QuickFilterTabsComponent,
51648
+ SearchInputComponent,
51649
+ SkeletonComponent,
51650
+ TextareaInputComponent,
51651
+ TooltipDirective
51652
+ ],
51653
+ template: `
51654
+ <div class="cv-layout" [class.has-context]="contextVisible()" data-testid="conversations">
51655
+ @if (contextVisible()) {
51656
+ <div class="cv-context-backdrop" (click)="closeContext()" aria-hidden="true"></div>
51657
+ }
51658
+
51659
+ <!-- LEFT: conversation list -->
51660
+ <section class="cv-list-panel" [class.cv-hidden-mobile]="!!selected()" [attr.aria-labelledby]="titleId">
51661
+ <div class="cv-list-header">
51662
+ <h2 class="cv-list-title" [id]="titleId">{{ title() }}</h2>
51663
+ @if (canWrite() && allowNew()) {
51664
+ <ui-button class="cv-new-btn" variant="primary" size="sm" [ariaLabel]="newLabel()" [uiTooltip]="newTooltip()" tooltipPosition="bottom" (click)="newConversation.emit()" data-testid="new-message-btn">
51665
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>
51666
+ </ui-button>
51667
+ }
51668
+ </div>
51669
+
51670
+ @if (showFilters()) {
51671
+ <div class="cv-search">
51672
+ <ui-search-input [placeholder]="searchPlaceholder()" [ariaLabel]="searchAriaLabel()" [(value)]="searchText" (searchChange)="searchChange.emit($event)" data-testid="conv-search" />
51673
+ </div>
51674
+ @if (filterTabs().length) {
51675
+ <div class="cv-filters">
51676
+ <ui-quick-filter-tabs [ariaLabel]="filterAriaLabel()" [tabs]="filterTabs()" [counts]="filterCounts()" [activeValue]="activeFilter()" (tabChange)="filterChange.emit($event)" data-testid="conv-filters" />
51677
+ </div>
51678
+ }
51679
+ }
51680
+
51681
+ @if (loading()) {
51682
+ <div class="cv-loading" aria-busy="true" [attr.aria-label]="loadingLabel()" data-testid="conv-loading">
51683
+ @for (i of skeletonRows; track i) {
51684
+ <div class="cv-skeleton">
51685
+ <ui-skeleton [height]="40" width="40px" [radius]="20" />
51686
+ <div class="cv-skel-content">
51687
+ <div class="cv-skel-row">
51688
+ <ui-skeleton width="55%" [height]="12" />
51689
+ <ui-skeleton width="48px" [height]="10" />
51690
+ </div>
51691
+ <ui-skeleton width="30%" [height]="10" [mb]="2" />
51692
+ <ui-skeleton width="85%" [height]="10" />
51693
+ </div>
51694
+ </div>
51695
+ }
51696
+ </div>
51697
+ } @else if (error()) {
51698
+ <div class="cv-error" data-testid="conv-error">
51699
+ <ui-alert variant="danger">{{ error() }}</ui-alert>
51700
+ <ui-button variant="secondary" size="sm" (click)="retry.emit()" data-testid="conv-retry">Retry</ui-button>
51701
+ </div>
51702
+ } @else if (conversations().length === 0) {
51703
+ <ui-empty-state iconType="message" data-testid="conv-empty" [title]="filtering() ? filteredEmptyTitle() : emptyTitle()" [message]="emptyText()" />
51704
+ } @else {
51705
+ <div class="cv-list">
51706
+ <ui-list [ariaLabel]="listAriaLabel()" [items]="conversations()" [trackBy]="trackConversation" [navigable]="true" (itemClick)="onRowOpen($event)">
51707
+ <ng-template let-conv>
51708
+ <div class="cv-item" data-testid="conv-item" [attr.data-conversation-id]="conv.id"
51709
+ [class.selected]="selected()?.id === conv.id" [class.unread]="(conv.unreadCount ?? 0) > 0">
51710
+ <ui-avatar [initials]="initial(conv.name)" [name]="conv.name" [size]="40" />
51711
+ <div class="cv-item-info">
51712
+ <div class="cv-item-top">
51713
+ <span class="cv-name">{{ conv.name }}</span>@if (selected()?.id === conv.id) {<span class="cv-sr-only">, open</span>}
51714
+ <span class="cv-time">{{ relativeTime(conv.lastMessageAt) }}</span>
51715
+ </div>
51716
+ @if (conv.subtitle) { <span class="cv-subtitle">{{ conv.subtitle }}</span> }
51717
+ <div class="cv-item-bottom">
51718
+ <p class="cv-preview">{{ preview(conv.preview) || noMessagesText() }}</p>
51719
+ <div class="cv-item-right">
51720
+ @if (conv.statusLabel) { <ui-badge [label]="conv.statusLabel" variant="gray" /> }
51721
+ @if ((conv.unreadCount ?? 0) > 0) {
51722
+ <ui-badge class="cv-unread-badge" [label]="'' + conv.unreadCount" variant="blue" data-testid="conv-unread" />
51723
+ <span class="cv-sr-only">unread</span>
51724
+ }
51725
+ @if (canWrite() && allowDelete()) {
51726
+ <ui-button class="cv-delete-btn" variant="icon-danger" [ariaLabel]="deleteRowLabel() + ' ' + conv.name" (click)="$event.stopPropagation(); deleteConversation.emit(conv)" data-testid="conv-delete-btn">
51727
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
51728
+ </ui-button>
51729
+ }
51730
+ </div>
51731
+ </div>
51732
+ </div>
51733
+ </div>
51734
+ </ng-template>
51735
+ </ui-list>
51736
+ <ui-pagination [ariaLabel]="paginationAriaLabel()" [page]="page()" [pageSize]="pageSize()" [totalItems]="totalItems()" (pageChange)="pageChange.emit($event)" />
51737
+ </div>
51738
+ }
51739
+ </section>
51740
+
51741
+ <!-- CENTER: message thread -->
51742
+ <section class="cv-thread-panel" [class.cv-hidden-mobile]="!selected()" [attr.aria-label]="threadAriaLabel()">
51743
+ @if (selected(); as conv) {
51744
+ <div class="cv-thread-header">
51745
+ <ui-button class="cv-back-btn" variant="secondary" size="sm" [ariaLabel]="backLabel()" (click)="onBack()" data-testid="back-to-list">
51746
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>
51747
+ </ui-button>
51748
+ <div class="cv-thread-header-info">
51749
+ <ui-avatar [initials]="initial(conv.name)" [name]="conv.name" [size]="40" />
51750
+ <div class="cv-thread-header-text">
51751
+ <h3 class="cv-thread-name" #threadHeading tabindex="-1" data-testid="thread-name">{{ conv.name }}</h3>
51752
+ @if (conv.subtitle) { <span class="cv-thread-subtitle" data-testid="thread-phone">{{ conv.subtitle }}</span> }
51753
+ </div>
51754
+ </div>
51755
+ <div class="cv-thread-actions">
51756
+ @if (canWrite() && templatesEnabled()) {
51757
+ <ui-button class="cv-thread-action" variant="secondary" size="sm" [ariaLabel]="templateLabel()" [uiTooltip]="templateLabel()" tooltipPosition="bottom" [disabled]="composerDisabled()" (click)="templateRequest.emit()" data-testid="use-template-btn">
51758
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
51759
+ </ui-button>
51760
+ }
51761
+ @if (hasContext()) {
51762
+ <ui-button #contextToggle class="cv-thread-action" [variant]="contextOpen() ? 'primary' : 'secondary'" size="sm" [ariaLabel]="contextOpen() ? hideContextLabel() : showContextLabel()" [uiTooltip]="contextOpen() ? hideContextLabel() : contextTitle()" tooltipPosition="bottom" (click)="toggleContext()" data-testid="context-toggle">
51763
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
51764
+ </ui-button>
51765
+ }
51766
+ @if (canWrite() && statusActionLabel()) {
51767
+ <ui-button class="cv-thread-action" variant="secondary" size="sm" [ariaLabel]="statusActionLabel() ?? ''" [uiTooltip]="statusActionLabel()" tooltipPosition="bottom" [disabled]="statusChanging()" (click)="statusChange.emit(conv)" data-testid="status-btn">
51768
+ @if (statusActionIcon() === 'reopen') {
51769
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg>
51770
+ } @else {
51771
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
51772
+ }
51773
+ </ui-button>
51774
+ }
51775
+ @if (canWrite() && allowDelete()) {
51776
+ <ui-button class="cv-thread-action" variant="danger" size="sm" [ariaLabel]="deleteThreadLabel()" [uiTooltip]="deleteThreadLabel()" tooltipPosition="bottom" (click)="deleteConversation.emit(conv)" data-testid="thread-delete-btn">
51777
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
51778
+ </ui-button>
51779
+ }
51780
+ </div>
51781
+ </div>
51782
+
51783
+ <div class="cv-messages" #messagesEl role="log" aria-live="polite" aria-relevant="additions" tabindex="0"
51784
+ [attr.aria-label]="messagesAriaLabel() + ' ' + conv.name" [attr.aria-busy]="messagesLoading()" (scroll)="onMessagesScroll()" data-testid="messages">
51785
+ @if (messagesLoading()) {
51786
+ <div class="cv-messages-loading" data-testid="messages-loading">
51787
+ @for (i of skeletonBubbles; track i) {
51788
+ <div class="cv-msg-skeleton" [class.outbound]="i % 2 === 0">
51789
+ <ui-skeleton [height]="48" [width]="i % 2 === 0 ? '60%' : '55%'" [radius]="16" />
51790
+ </div>
51791
+ }
51792
+ </div>
51793
+ } @else if (messagesError()) {
51794
+ <div class="cv-messages-error" data-testid="thread-error">
51795
+ <ui-alert variant="danger">{{ messagesError() }}</ui-alert>
51796
+ <ui-button variant="secondary" size="sm" (click)="messagesRetry.emit()" data-testid="thread-retry">Retry</ui-button>
51797
+ </div>
51798
+ } @else if (messages().length === 0) {
51799
+ <div class="cv-messages-empty" data-testid="messages-empty">
51800
+ <p>{{ canWrite() ? noMessagesWriteText() : noMessagesReadText() }}</p>
51801
+ </div>
51802
+ } @else {
51803
+ @if (hasEarlier()) {
51804
+ <div class="cv-load-earlier">
51805
+ <ui-button variant="secondary" size="sm" [loading]="loadingEarlier()" (click)="loadEarlier.emit()" data-testid="load-earlier">{{ loadEarlierLabel() }}</ui-button>
51806
+ </div>
51807
+ }
51808
+ @for (row of messageRows(); track row.message.id) {
51809
+ @if (row.separator) { <div class="cv-date-separator"><span>{{ row.separator }}</span></div> }
51810
+ <div class="cv-bubble" data-testid="message" [class.outbound]="row.message.direction === 'outbound'" [class.inbound]="row.message.direction === 'inbound'">
51811
+ <span class="cv-sr-only">{{ row.message.direction === 'outbound' ? youLabel() : conv.name }}:</span>
51812
+ @if (row.message.media; as media) {
51813
+ <div class="cv-media">
51814
+ @if (media.type?.startsWith('image/')) {
51815
+ <button type="button" class="cv-image-btn" (click)="mediaOpen.emit(media.url)" [attr.aria-label]="openMediaLabel() + ' ' + (media.fileName || imageFallbackName())">
51816
+ <img [src]="media.url" [alt]="media.fileName || imageFallbackName()" class="cv-image" loading="lazy" />
51817
+ </button>
51818
+ } @else if (media.type?.startsWith('video/')) {
51819
+ <video [src]="media.url" class="cv-video" controls preload="metadata"></video>
51820
+ } @else {
51821
+ <a [href]="media.url" target="_blank" rel="noopener noreferrer" class="cv-file-link">{{ media.fileName || fileFallbackName() }}</a>
51822
+ }
51823
+ </div>
51824
+ }
51825
+ @if (row.message.body) { <p class="cv-body">{{ row.message.body }}</p> }
51826
+ <span class="cv-meta">
51827
+ @if (row.message.direction === 'outbound' && row.message.sender) { <span class="cv-sender" data-testid="msg-sender">{{ row.message.sender }}</span> }
51828
+ {{ time(row.message) }}
51829
+ @if (row.message.action; as action) {
51830
+ <button type="button" class="cv-msg-action" data-testid="msg-action" (click)="messageAction.emit(row.message)">{{ action.label }}</button>
51831
+ }
51832
+ @if (row.message.direction === 'outbound' && statusLabel(row.message.status)) {
51833
+ <span class="cv-status" [class.failed]="row.message.status === 'failed'" data-testid="msg-status">
51834
+ <span aria-hidden="true">{{ statusMark(row.message.status) }}</span>
51835
+ <span class="cv-sr-only">{{ statusLabel(row.message.status) }}</span>
51836
+ </span>
51837
+ }
51838
+ </span>
51839
+ </div>
51840
+ }
51841
+ }
51842
+ </div>
51843
+
51844
+ @if (canWrite()) {
51845
+ <div class="cv-compose">
51846
+ @if (attachment(); as file) {
51847
+ <div class="cv-attachment" data-testid="attachment-preview">
51848
+ @if (file.previewUrl) {
51849
+ <img [src]="file.previewUrl" [alt]="attachmentPreviewLabel()" class="cv-attachment-thumb" />
51850
+ } @else {
51851
+ <span class="cv-attachment-name">{{ file.fileName }}</span>
51852
+ }
51853
+ <ui-button class="cv-attachment-remove" variant="icon-danger" [ariaLabel]="removeAttachmentLabel()" (click)="attachmentRemove.emit()" data-testid="attachment-remove">
51854
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
51855
+ </ui-button>
51856
+ </div>
51857
+ }
51858
+ <div class="cv-compose-row">
51859
+ @if (attachEnabled()) {
51860
+ <ui-button class="cv-attach-btn" variant="icon" [ariaLabel]="attachLabel()" [disabled]="uploading() || composerDisabled()" [loading]="uploading()" (click)="openFilePicker()" data-testid="attach-btn">
51861
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>
51862
+ </ui-button>
51863
+ <ui-file-input [showField]="false" [accept]="acceptedFiles()" [maxSize]="maxFileSize()" [toastOnReject]="true"
51864
+ [typeMessage]="typeMessage()" [sizeMessage]="sizeMessage()" (filesSelected)="filesSelected.emit($event)" data-testid="attach-input" />
51865
+ }
51866
+ <ui-textarea-input class="cv-compose-input" [ariaLabel]="composeLabel()" [placeholder]="composePlaceholder()" [rows]="1" [maxlength]="maxLength()"
51867
+ [ngModel]="draft()" (ngModelChange)="draft.set($event)" [disabled]="composerDisabled()" [error]="composerError()"
51868
+ (keydown)="onComposeKeydown($event)" data-testid="compose-input" />
51869
+ <ui-button class="cv-send-btn" variant="primary" [ariaLabel]="sendLabel()" [disabled]="!canSend()" [loading]="sending()" (click)="sendMessage()" data-testid="send-btn">
51870
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
51871
+ </ui-button>
51872
+ </div>
51873
+ @if (composerNotice()) {
51874
+ <ui-alert variant="warning" data-testid="compose-opted-out">{{ composerNotice() }}</ui-alert>
51875
+ }
51876
+ <!-- Always in the page (a live region that appears together with its text is often not announced): only its text comes and goes. -->
51877
+ <p class="cv-compose-status" role="status" data-testid="compose-loading-contact">{{ composerStatus() }}</p>
51878
+ </div>
51879
+ }
51880
+ } @else {
51881
+ <ui-empty-state iconType="message" [title]="threadEmptyTitle()" [message]="threadEmptyMessage()" data-testid="thread-empty" />
51882
+ }
51883
+ </section>
51884
+
51885
+ <!-- RIGHT: contact panel (the host's content) -->
51886
+ @if (contextVisible()) {
51887
+ <aside class="cv-context" #contextPanel tabindex="-1" [attr.aria-label]="contextTitle()" (keydown.escape)="closeContext(true)" data-testid="context-panel">
51888
+ <div class="cv-context-header">
51889
+ <h3>{{ contextTitle() }}</h3>
51890
+ <ui-button variant="icon" [ariaLabel]="closeContextLabel()" (click)="closeContext(true)" data-testid="context-close">
51891
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
51892
+ </ui-button>
51893
+ </div>
51894
+ <div class="cv-context-body"><ng-content select="[uiConversationsContext]" /></div>
51895
+ </aside>
51896
+ }
51897
+ </div>
51898
+ `,
51899
+ styles: [":host{display:flex;flex:1;min-height:0;min-width:0}.cv-sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.cv-layout{display:grid;grid-template-columns:340px 1fr;flex:1;min-height:0;min-width:0;background:#fff;border-radius:12px;overflow:hidden;box-shadow:0 1px 3px #0000000f;border:1px solid #e2e8f0}.cv-layout.has-context{grid-template-columns:340px 1fr 280px}.cv-list-panel{display:flex;flex-direction:column;min-height:0;border-right:1px solid #e2e8f0;background:#f8fafc;overflow:hidden}.cv-list-header{display:flex;align-items:center;justify-content:space-between;padding:20px 20px 12px}.cv-list-title{margin:0;font-size:1.125rem;font-weight:700;color:#1e293b}.cv-search,.cv-filters{padding:0 16px 12px}.cv-list{flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain}.cv-item{display:flex;gap:12px;padding:14px 16px;border-bottom:1px solid #f1f5f9;transition:background .15s}.cv-item.unread{background:#fffbeb}.cv-item.selected{background:#eff6ff;box-shadow:inset 3px 0 #2563eb}.cv-item-info{flex:1;min-width:0}.cv-item-top{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px}.cv-name{font-size:.875rem;font-weight:600;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cv-time{font-size:.6875rem;color:#64748b;flex-shrink:0;margin-left:8px}.cv-subtitle{font-size:.6875rem;color:#64748b;display:block;margin-bottom:2px}.cv-item-bottom{display:flex;justify-content:space-between;align-items:center;gap:8px}.cv-preview{margin:0;font-size:.8125rem;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:1;min-width:0}.cv-item-right{display:flex;align-items:center;gap:6px;flex-shrink:0}.cv-delete-btn{opacity:0;transition:opacity .15s}.cv-item:hover .cv-delete-btn,.cv-item:focus-within .cv-delete-btn,.cv-delete-btn:focus-within{opacity:1}@media(hover:none){.cv-delete-btn{opacity:1}}.cv-loading{padding:8px 0}.cv-skeleton{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border-bottom:1px solid #f1f5f9}.cv-skel-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px;padding-top:2px}.cv-skel-row{display:flex;justify-content:space-between;gap:8px}.cv-error{display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 16px;text-align:center}.cv-thread-panel{display:flex;flex-direction:column;min-width:0;min-height:0;overflow:hidden;background:#fff}.cv-thread-header{display:flex;align-items:center;gap:12px;padding:16px 20px;border-bottom:1px solid #e2e8f0;background:#fff}.cv-back-btn{display:none}.cv-thread-header-info{display:flex;align-items:center;gap:12px;flex:1;min-width:0}.cv-thread-header-text{min-width:0;display:flex;flex-direction:column}.cv-thread-name{margin:0;font-size:.9375rem;font-weight:600;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cv-thread-name:focus{outline:none}.cv-thread-name:focus-visible{outline:2px solid #2563eb;outline-offset:2px;border-radius:4px}.cv-thread-subtitle{font-size:.75rem;color:#64748b}.cv-thread-actions{display:flex;align-items:center;gap:8px}.cv-messages{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;padding:20px 24px;display:flex;flex-direction:column;gap:4px;background:#f8fafc}.cv-messages:focus-visible{outline:2px solid #2563eb;outline-offset:-2px}.cv-messages-loading{display:flex;flex-direction:column;gap:12px;padding:20px 0}.cv-msg-skeleton{display:flex}.cv-msg-skeleton.outbound{justify-content:flex-end}.cv-messages-error{display:flex;flex-direction:column;align-items:center;gap:12px;padding:24px 16px;text-align:center}.cv-load-earlier{display:flex;justify-content:center;padding:4px 0 12px}.cv-sender{font-weight:600}.cv-msg-action{padding:0;border:0;background:none;color:inherit;font:inherit;text-decoration:underline;cursor:pointer}.cv-msg-action:focus-visible{outline:2px solid currentColor;outline-offset:2px;border-radius:2px}.cv-messages-empty{display:flex;align-items:center;justify-content:center;flex:1}.cv-messages-empty p{margin:0;font-size:.875rem;color:#64748b;text-align:center}.cv-date-separator{display:flex;align-items:center;justify-content:center;padding:16px 0 8px}.cv-date-separator span{padding:4px 14px;border-radius:12px;background:#e2e8f0;font-size:.6875rem;font-weight:600;color:#475569;text-transform:uppercase;letter-spacing:.3px}.cv-bubble{max-width:70%;padding:10px 14px;border-radius:16px;position:relative;word-break:break-word;overflow-wrap:break-word}.cv-bubble.inbound{align-self:flex-start;background:#fff;border:1px solid #e2e8f0;border-bottom-left-radius:4px}.cv-bubble.inbound .cv-body{color:#1e293b}.cv-bubble.inbound .cv-meta{color:#64748b}.cv-bubble.outbound{align-self:flex-end;background:#2563eb;border-bottom-right-radius:4px}.cv-bubble.outbound .cv-body,.cv-bubble.outbound .cv-meta{color:#fff}@media(prefers-reduced-motion:no-preference){.cv-bubble{animation:cv-appear .2s ease}.cv-context{animation:cv-slide-in .25s ease}}.cv-body{margin:0;font-size:.875rem;line-height:1.45;word-break:break-word;white-space:pre-wrap}.cv-media{margin-bottom:6px}.cv-image-btn{display:block;padding:0;border:0;background:none;cursor:pointer;border-radius:8px}.cv-image-btn:focus-visible{outline:2px solid #fff;outline-offset:2px;box-shadow:0 0 0 4px #2563eb}.cv-image{display:block;max-width:240px;max-height:240px;border-radius:8px;object-fit:cover}.cv-video{max-width:240px;max-height:200px;border-radius:8px}.cv-file-link{font-size:.8125rem;color:#fff;text-decoration:underline}.cv-bubble.inbound .cv-file-link{color:#2563eb}.cv-meta{display:flex;align-items:center;gap:6px;justify-content:flex-end;font-size:.6875rem;margin-top:4px}.cv-status{font-weight:500}.cv-status.failed{color:#fff;font-weight:700}.cv-bubble.inbound .cv-status.failed{color:#dc2626}.cv-compose{display:flex;flex-direction:column;padding:12px 20px 16px;padding-bottom:calc(16px + env(safe-area-inset-bottom,0px));border-top:1px solid #e2e8f0;background:#fff}.cv-compose-row{display:flex;align-items:flex-end;gap:10px}.cv-compose-input{flex:1;min-width:0}.cv-attach-btn,.cv-send-btn{flex-shrink:0}.cv-attachment{display:flex;align-items:center;gap:8px;padding:8px 12px;margin-bottom:8px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px}.cv-attachment-thumb{width:48px;height:48px;object-fit:cover;border-radius:6px}.cv-attachment-name{font-size:.8125rem;color:#475569;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cv-attachment-remove{flex-shrink:0}.cv-compose-status{margin:4px 0 0;font-size:.8125rem;color:#64748b}.cv-compose-status:empty{margin:0}.cv-context-backdrop{display:none}.cv-context{width:100%;min-width:0;border-left:1px solid #e2e8f0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.cv-context-header{display:flex;justify-content:space-between;align-items:center;padding:20px;border-bottom:1px solid #e2e8f0}.cv-context-header h3{margin:0;font-size:.875rem;font-weight:700;color:#1e293b}.cv-context-body{padding:20px;display:flex;flex-direction:column;gap:16px}@keyframes cv-appear{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@keyframes cv-slide-in{0%{transform:translate(100%)}to{transform:translate(0)}}@media(max-width:1100px){.cv-layout.has-context{grid-template-columns:280px 1fr 240px}}@media(max-width:768px){.cv-layout,.cv-layout.has-context{grid-template-columns:1fr;height:100%}.cv-hidden-mobile{display:none!important}.cv-back-btn{display:inline-flex}.cv-context-backdrop{display:block;position:fixed;inset:0;background:#00000059;z-index:99}.cv-context{position:fixed;top:0;right:0;bottom:0;width:300px;max-width:85vw;z-index:100;box-shadow:-4px 0 20px #0000001a}.cv-bubble{max-width:85%}.cv-messages,.cv-thread-header{padding:12px 16px}}@media(max-width:480px){.cv-thread-subtitle{display:none}.cv-compose{padding:8px 12px 12px;padding-bottom:calc(12px + env(safe-area-inset-bottom,0px))}.cv-list-header{padding:12px 16px 10px}.cv-context{width:100%;max-width:100vw}}\n"]
51900
+ }]
51901
+ }],
51902
+ ctorParameters: () => [],
51903
+ propDecorators: {
51904
+ conversations: [{
51905
+ type: i0.Input,
51906
+ args: [{
51907
+ isSignal: true,
51908
+ alias: "conversations",
51909
+ required: false
51910
+ }]
51911
+ }],
51912
+ selected: [{
51913
+ type: i0.Input,
51914
+ args: [{
51915
+ isSignal: true,
51916
+ alias: "selected",
51917
+ required: false
51918
+ }]
51919
+ }],
51920
+ title: [{
51921
+ type: i0.Input,
51922
+ args: [{
51923
+ isSignal: true,
51924
+ alias: "title",
51925
+ required: false
51926
+ }]
51927
+ }],
51928
+ loading: [{
51929
+ type: i0.Input,
51930
+ args: [{
51931
+ isSignal: true,
51932
+ alias: "loading",
51933
+ required: false
51934
+ }]
51935
+ }],
51936
+ error: [{
51937
+ type: i0.Input,
51938
+ args: [{
51939
+ isSignal: true,
51940
+ alias: "error",
51941
+ required: false
51942
+ }]
51943
+ }],
51944
+ searchText: [{
51945
+ type: i0.Input,
51946
+ args: [{
51947
+ isSignal: true,
51948
+ alias: "searchText",
51949
+ required: false
51950
+ }]
51951
+ }, {
51952
+ type: i0.Output,
51953
+ args: ["searchTextChange"]
51954
+ }],
51955
+ searchPlaceholder: [{
51956
+ type: i0.Input,
51957
+ args: [{
51958
+ isSignal: true,
51959
+ alias: "searchPlaceholder",
51960
+ required: false
51961
+ }]
51962
+ }],
51963
+ searchAriaLabel: [{
51964
+ type: i0.Input,
51965
+ args: [{
51966
+ isSignal: true,
51967
+ alias: "searchAriaLabel",
51968
+ required: false
51969
+ }]
51970
+ }],
51971
+ showFilters: [{
51972
+ type: i0.Input,
51973
+ args: [{
51974
+ isSignal: true,
51975
+ alias: "showFilters",
51976
+ required: false
51977
+ }]
51978
+ }],
51979
+ filterTabs: [{
51980
+ type: i0.Input,
51981
+ args: [{
51982
+ isSignal: true,
51983
+ alias: "filterTabs",
51984
+ required: false
51985
+ }]
51986
+ }],
51987
+ filterCounts: [{
51988
+ type: i0.Input,
51989
+ args: [{
51990
+ isSignal: true,
51991
+ alias: "filterCounts",
51992
+ required: false
51993
+ }]
51994
+ }],
51995
+ activeFilter: [{
51996
+ type: i0.Input,
51997
+ args: [{
51998
+ isSignal: true,
51999
+ alias: "activeFilter",
52000
+ required: false
52001
+ }]
52002
+ }],
52003
+ filterAriaLabel: [{
52004
+ type: i0.Input,
52005
+ args: [{
52006
+ isSignal: true,
52007
+ alias: "filterAriaLabel",
52008
+ required: false
52009
+ }]
52010
+ }],
52011
+ page: [{
52012
+ type: i0.Input,
52013
+ args: [{
52014
+ isSignal: true,
52015
+ alias: "page",
52016
+ required: false
52017
+ }]
52018
+ }],
52019
+ pageSize: [{
52020
+ type: i0.Input,
52021
+ args: [{
52022
+ isSignal: true,
52023
+ alias: "pageSize",
52024
+ required: false
52025
+ }]
52026
+ }],
52027
+ totalItems: [{
52028
+ type: i0.Input,
52029
+ args: [{
52030
+ isSignal: true,
52031
+ alias: "totalItems",
52032
+ required: false
52033
+ }]
52034
+ }],
52035
+ paginationAriaLabel: [{
52036
+ type: i0.Input,
52037
+ args: [{
52038
+ isSignal: true,
52039
+ alias: "paginationAriaLabel",
52040
+ required: false
52041
+ }]
52042
+ }],
52043
+ listAriaLabel: [{
52044
+ type: i0.Input,
52045
+ args: [{
52046
+ isSignal: true,
52047
+ alias: "listAriaLabel",
52048
+ required: false
52049
+ }]
52050
+ }],
52051
+ loadingLabel: [{
52052
+ type: i0.Input,
52053
+ args: [{
52054
+ isSignal: true,
52055
+ alias: "loadingLabel",
52056
+ required: false
52057
+ }]
52058
+ }],
52059
+ emptyTitle: [{
52060
+ type: i0.Input,
52061
+ args: [{
52062
+ isSignal: true,
52063
+ alias: "emptyTitle",
52064
+ required: false
52065
+ }]
52066
+ }],
52067
+ emptyMessage: [{
52068
+ type: i0.Input,
52069
+ args: [{
52070
+ isSignal: true,
52071
+ alias: "emptyMessage",
52072
+ required: false
52073
+ }]
52074
+ }],
52075
+ emptyReadOnlyMessage: [{
52076
+ type: i0.Input,
52077
+ args: [{
52078
+ isSignal: true,
52079
+ alias: "emptyReadOnlyMessage",
52080
+ required: false
52081
+ }]
52082
+ }],
52083
+ filteredEmptyTitle: [{
52084
+ type: i0.Input,
52085
+ args: [{
52086
+ isSignal: true,
52087
+ alias: "filteredEmptyTitle",
52088
+ required: false
52089
+ }]
52090
+ }],
52091
+ filteredEmptyMessage: [{
52092
+ type: i0.Input,
52093
+ args: [{
52094
+ isSignal: true,
52095
+ alias: "filteredEmptyMessage",
52096
+ required: false
52097
+ }]
52098
+ }],
52099
+ noMessagesText: [{
52100
+ type: i0.Input,
52101
+ args: [{
52102
+ isSignal: true,
52103
+ alias: "noMessagesText",
52104
+ required: false
52105
+ }]
52106
+ }],
52107
+ allowNew: [{
52108
+ type: i0.Input,
52109
+ args: [{
52110
+ isSignal: true,
52111
+ alias: "allowNew",
52112
+ required: false
52113
+ }]
52114
+ }],
52115
+ allowDelete: [{
52116
+ type: i0.Input,
52117
+ args: [{
52118
+ isSignal: true,
52119
+ alias: "allowDelete",
52120
+ required: false
52121
+ }]
52122
+ }],
52123
+ newLabel: [{
52124
+ type: i0.Input,
52125
+ args: [{
52126
+ isSignal: true,
52127
+ alias: "newLabel",
52128
+ required: false
52129
+ }]
52130
+ }],
52131
+ newTooltip: [{
52132
+ type: i0.Input,
52133
+ args: [{
52134
+ isSignal: true,
52135
+ alias: "newTooltip",
52136
+ required: false
52137
+ }]
52138
+ }],
52139
+ deleteRowLabel: [{
52140
+ type: i0.Input,
52141
+ args: [{
52142
+ isSignal: true,
52143
+ alias: "deleteRowLabel",
52144
+ required: false
52145
+ }]
52146
+ }],
52147
+ messages: [{
52148
+ type: i0.Input,
52149
+ args: [{
52150
+ isSignal: true,
52151
+ alias: "messages",
52152
+ required: false
52153
+ }]
52154
+ }],
52155
+ messagesLoading: [{
52156
+ type: i0.Input,
52157
+ args: [{
52158
+ isSignal: true,
52159
+ alias: "messagesLoading",
52160
+ required: false
52161
+ }]
52162
+ }],
52163
+ messagesError: [{
52164
+ type: i0.Input,
52165
+ args: [{
52166
+ isSignal: true,
52167
+ alias: "messagesError",
52168
+ required: false
52169
+ }]
52170
+ }],
52171
+ hasEarlier: [{
52172
+ type: i0.Input,
52173
+ args: [{
52174
+ isSignal: true,
52175
+ alias: "hasEarlier",
52176
+ required: false
52177
+ }]
52178
+ }],
52179
+ loadingEarlier: [{
52180
+ type: i0.Input,
52181
+ args: [{
52182
+ isSignal: true,
52183
+ alias: "loadingEarlier",
52184
+ required: false
52185
+ }]
52186
+ }],
52187
+ loadEarlierLabel: [{
52188
+ type: i0.Input,
52189
+ args: [{
52190
+ isSignal: true,
52191
+ alias: "loadEarlierLabel",
52192
+ required: false
52193
+ }]
52194
+ }],
52195
+ statusActionLabel: [{
52196
+ type: i0.Input,
52197
+ args: [{
52198
+ isSignal: true,
52199
+ alias: "statusActionLabel",
52200
+ required: false
52201
+ }]
52202
+ }],
52203
+ statusActionIcon: [{
52204
+ type: i0.Input,
52205
+ args: [{
52206
+ isSignal: true,
52207
+ alias: "statusActionIcon",
52208
+ required: false
52209
+ }]
52210
+ }],
52211
+ statusChanging: [{
52212
+ type: i0.Input,
52213
+ args: [{
52214
+ isSignal: true,
52215
+ alias: "statusChanging",
52216
+ required: false
52217
+ }]
52218
+ }],
52219
+ templatesEnabled: [{
52220
+ type: i0.Input,
52221
+ args: [{
52222
+ isSignal: true,
52223
+ alias: "templatesEnabled",
52224
+ required: false
52225
+ }]
52226
+ }],
52227
+ templateLabel: [{
52228
+ type: i0.Input,
52229
+ args: [{
52230
+ isSignal: true,
52231
+ alias: "templateLabel",
52232
+ required: false
52233
+ }]
52234
+ }],
52235
+ deleteThreadLabel: [{
52236
+ type: i0.Input,
52237
+ args: [{
52238
+ isSignal: true,
52239
+ alias: "deleteThreadLabel",
52240
+ required: false
52241
+ }]
52242
+ }],
52243
+ backLabel: [{
52244
+ type: i0.Input,
52245
+ args: [{
52246
+ isSignal: true,
52247
+ alias: "backLabel",
52248
+ required: false
52249
+ }]
52250
+ }],
52251
+ threadAriaLabel: [{
52252
+ type: i0.Input,
52253
+ args: [{
52254
+ isSignal: true,
52255
+ alias: "threadAriaLabel",
52256
+ required: false
52257
+ }]
52258
+ }],
52259
+ messagesAriaLabel: [{
52260
+ type: i0.Input,
52261
+ args: [{
52262
+ isSignal: true,
52263
+ alias: "messagesAriaLabel",
52264
+ required: false
52265
+ }]
52266
+ }],
52267
+ threadEmptyTitle: [{
52268
+ type: i0.Input,
52269
+ args: [{
52270
+ isSignal: true,
52271
+ alias: "threadEmptyTitle",
52272
+ required: false
52273
+ }]
52274
+ }],
52275
+ threadEmptyMessage: [{
52276
+ type: i0.Input,
52277
+ args: [{
52278
+ isSignal: true,
52279
+ alias: "threadEmptyMessage",
52280
+ required: false
52281
+ }]
52282
+ }],
52283
+ noMessagesWriteText: [{
52284
+ type: i0.Input,
52285
+ args: [{
52286
+ isSignal: true,
52287
+ alias: "noMessagesWriteText",
52288
+ required: false
52289
+ }]
52290
+ }],
52291
+ noMessagesReadText: [{
52292
+ type: i0.Input,
52293
+ args: [{
52294
+ isSignal: true,
52295
+ alias: "noMessagesReadText",
52296
+ required: false
52297
+ }]
52298
+ }],
52299
+ youLabel: [{
52300
+ type: i0.Input,
52301
+ args: [{
52302
+ isSignal: true,
52303
+ alias: "youLabel",
52304
+ required: false
52305
+ }]
52306
+ }],
52307
+ openMediaLabel: [{
52308
+ type: i0.Input,
52309
+ args: [{
52310
+ isSignal: true,
52311
+ alias: "openMediaLabel",
52312
+ required: false
52313
+ }]
52314
+ }],
52315
+ imageFallbackName: [{
52316
+ type: i0.Input,
52317
+ args: [{
52318
+ isSignal: true,
52319
+ alias: "imageFallbackName",
52320
+ required: false
52321
+ }]
52322
+ }],
52323
+ fileFallbackName: [{
52324
+ type: i0.Input,
52325
+ args: [{
52326
+ isSignal: true,
52327
+ alias: "fileFallbackName",
52328
+ required: false
52329
+ }]
52330
+ }],
52331
+ hasContext: [{
52332
+ type: i0.Input,
52333
+ args: [{
52334
+ isSignal: true,
52335
+ alias: "hasContext",
52336
+ required: false
52337
+ }]
52338
+ }],
52339
+ contextOpen: [{
52340
+ type: i0.Input,
52341
+ args: [{
52342
+ isSignal: true,
52343
+ alias: "contextOpen",
52344
+ required: false
52345
+ }]
52346
+ }, {
52347
+ type: i0.Output,
52348
+ args: ["contextOpenChange"]
52349
+ }],
52350
+ contextTitle: [{
52351
+ type: i0.Input,
52352
+ args: [{
52353
+ isSignal: true,
52354
+ alias: "contextTitle",
52355
+ required: false
52356
+ }]
52357
+ }],
52358
+ showContextLabel: [{
52359
+ type: i0.Input,
52360
+ args: [{
52361
+ isSignal: true,
52362
+ alias: "showContextLabel",
52363
+ required: false
52364
+ }]
52365
+ }],
52366
+ hideContextLabel: [{
52367
+ type: i0.Input,
52368
+ args: [{
52369
+ isSignal: true,
52370
+ alias: "hideContextLabel",
52371
+ required: false
52372
+ }]
52373
+ }],
52374
+ closeContextLabel: [{
52375
+ type: i0.Input,
52376
+ args: [{
52377
+ isSignal: true,
52378
+ alias: "closeContextLabel",
52379
+ required: false
52380
+ }]
52381
+ }],
52382
+ canWrite: [{
52383
+ type: i0.Input,
52384
+ args: [{
52385
+ isSignal: true,
52386
+ alias: "canWrite",
52387
+ required: false
52388
+ }]
52389
+ }],
52390
+ draft: [{
52391
+ type: i0.Input,
52392
+ args: [{
52393
+ isSignal: true,
52394
+ alias: "draft",
52395
+ required: false
52396
+ }]
52397
+ }, {
52398
+ type: i0.Output,
52399
+ args: ["draftChange"]
52400
+ }],
52401
+ sending: [{
52402
+ type: i0.Input,
52403
+ args: [{
52404
+ isSignal: true,
52405
+ alias: "sending",
52406
+ required: false
52407
+ }]
52408
+ }],
52409
+ composerDisabled: [{
52410
+ type: i0.Input,
52411
+ args: [{
52412
+ isSignal: true,
52413
+ alias: "composerDisabled",
52414
+ required: false
52415
+ }]
52416
+ }],
52417
+ sendBlocked: [{
52418
+ type: i0.Input,
52419
+ args: [{
52420
+ isSignal: true,
52421
+ alias: "sendBlocked",
52422
+ required: false
52423
+ }]
52424
+ }],
52425
+ composerNotice: [{
52426
+ type: i0.Input,
52427
+ args: [{
52428
+ isSignal: true,
52429
+ alias: "composerNotice",
52430
+ required: false
52431
+ }]
52432
+ }],
52433
+ composerStatus: [{
52434
+ type: i0.Input,
52435
+ args: [{
52436
+ isSignal: true,
52437
+ alias: "composerStatus",
52438
+ required: false
52439
+ }]
52440
+ }],
52441
+ composerError: [{
52442
+ type: i0.Input,
52443
+ args: [{
52444
+ isSignal: true,
52445
+ alias: "composerError",
52446
+ required: false
52447
+ }]
52448
+ }],
52449
+ maxLength: [{
52450
+ type: i0.Input,
52451
+ args: [{
52452
+ isSignal: true,
52453
+ alias: "maxLength",
52454
+ required: false
52455
+ }]
52456
+ }],
52457
+ attachment: [{
52458
+ type: i0.Input,
52459
+ args: [{
52460
+ isSignal: true,
52461
+ alias: "attachment",
52462
+ required: false
52463
+ }]
52464
+ }],
52465
+ uploading: [{
52466
+ type: i0.Input,
52467
+ args: [{
52468
+ isSignal: true,
52469
+ alias: "uploading",
52470
+ required: false
52471
+ }]
52472
+ }],
52473
+ attachEnabled: [{
52474
+ type: i0.Input,
52475
+ args: [{
52476
+ isSignal: true,
52477
+ alias: "attachEnabled",
52478
+ required: false
52479
+ }]
52480
+ }],
52481
+ acceptedFiles: [{
52482
+ type: i0.Input,
52483
+ args: [{
52484
+ isSignal: true,
52485
+ alias: "acceptedFiles",
52486
+ required: false
52487
+ }]
52488
+ }],
52489
+ maxFileSize: [{
52490
+ type: i0.Input,
52491
+ args: [{
52492
+ isSignal: true,
52493
+ alias: "maxFileSize",
52494
+ required: false
52495
+ }]
52496
+ }],
52497
+ typeMessage: [{
52498
+ type: i0.Input,
52499
+ args: [{
52500
+ isSignal: true,
52501
+ alias: "typeMessage",
52502
+ required: false
52503
+ }]
52504
+ }],
52505
+ sizeMessage: [{
52506
+ type: i0.Input,
52507
+ args: [{
52508
+ isSignal: true,
52509
+ alias: "sizeMessage",
52510
+ required: false
52511
+ }]
52512
+ }],
52513
+ composeLabel: [{
52514
+ type: i0.Input,
52515
+ args: [{
52516
+ isSignal: true,
52517
+ alias: "composeLabel",
52518
+ required: false
52519
+ }]
52520
+ }],
52521
+ composePlaceholder: [{
52522
+ type: i0.Input,
52523
+ args: [{
52524
+ isSignal: true,
52525
+ alias: "composePlaceholder",
52526
+ required: false
52527
+ }]
52528
+ }],
52529
+ sendLabel: [{
52530
+ type: i0.Input,
52531
+ args: [{
52532
+ isSignal: true,
52533
+ alias: "sendLabel",
52534
+ required: false
52535
+ }]
52536
+ }],
52537
+ attachLabel: [{
52538
+ type: i0.Input,
52539
+ args: [{
52540
+ isSignal: true,
52541
+ alias: "attachLabel",
52542
+ required: false
52543
+ }]
52544
+ }],
52545
+ removeAttachmentLabel: [{
52546
+ type: i0.Input,
52547
+ args: [{
52548
+ isSignal: true,
52549
+ alias: "removeAttachmentLabel",
52550
+ required: false
52551
+ }]
52552
+ }],
52553
+ attachmentPreviewLabel: [{
52554
+ type: i0.Input,
52555
+ args: [{
52556
+ isSignal: true,
52557
+ alias: "attachmentPreviewLabel",
52558
+ required: false
52559
+ }]
52560
+ }],
52561
+ now: [{
52562
+ type: i0.Input,
52563
+ args: [{
52564
+ isSignal: true,
52565
+ alias: "now",
52566
+ required: false
52567
+ }]
52568
+ }],
52569
+ searchChange: [{
52570
+ type: i0.Output,
52571
+ args: ["searchChange"]
52572
+ }],
52573
+ filterChange: [{
52574
+ type: i0.Output,
52575
+ args: ["filterChange"]
52576
+ }],
52577
+ pageChange: [{
52578
+ type: i0.Output,
52579
+ args: ["pageChange"]
52580
+ }],
52581
+ selectConversation: [{
52582
+ type: i0.Output,
52583
+ args: ["selectConversation"]
52584
+ }],
52585
+ back: [{
52586
+ type: i0.Output,
52587
+ args: ["back"]
52588
+ }],
52589
+ newConversation: [{
52590
+ type: i0.Output,
52591
+ args: ["newConversation"]
52592
+ }],
52593
+ retry: [{
52594
+ type: i0.Output,
52595
+ args: ["retry"]
52596
+ }],
52597
+ deleteConversation: [{
52598
+ type: i0.Output,
52599
+ args: ["deleteConversation"]
52600
+ }],
52601
+ statusChange: [{
52602
+ type: i0.Output,
52603
+ args: ["statusChange"]
52604
+ }],
52605
+ templateRequest: [{
52606
+ type: i0.Output,
52607
+ args: ["templateRequest"]
52608
+ }],
52609
+ send: [{
52610
+ type: i0.Output,
52611
+ args: ["send"]
52612
+ }],
52613
+ filesSelected: [{
52614
+ type: i0.Output,
52615
+ args: ["filesSelected"]
52616
+ }],
52617
+ attachmentRemove: [{
52618
+ type: i0.Output,
52619
+ args: ["attachmentRemove"]
52620
+ }],
52621
+ mediaOpen: [{
52622
+ type: i0.Output,
52623
+ args: ["mediaOpen"]
52624
+ }],
52625
+ messageAction: [{
52626
+ type: i0.Output,
52627
+ args: ["messageAction"]
52628
+ }],
52629
+ loadEarlier: [{
52630
+ type: i0.Output,
52631
+ args: ["loadEarlier"]
52632
+ }],
52633
+ messagesRetry: [{
52634
+ type: i0.Output,
52635
+ args: ["messagesRetry"]
52636
+ }],
52637
+ threadHeading: [{
52638
+ type: i0.ViewChild,
52639
+ args: ["threadHeading", { isSignal: true }]
52640
+ }],
52641
+ messagesEl: [{
52642
+ type: i0.ViewChild,
52643
+ args: ["messagesEl", { isSignal: true }]
52644
+ }],
52645
+ contextPanel: [{
52646
+ type: i0.ViewChild,
52647
+ args: ["contextPanel", { isSignal: true }]
52648
+ }],
52649
+ fileInput: [{
52650
+ type: i0.ViewChild,
52651
+ args: [i0.forwardRef(() => FileInputComponent), { isSignal: true }]
52652
+ }]
52653
+ }
52654
+ });
52655
+ export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BankAccountFormComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, ConversationsComponent, DEFAULT_BANK_ACCOUNT_TYPE_OPTIONS, DEFAULT_BANK_HOLDER_TYPE_OPTIONS, DEFAULT_BANK_MANDATE_TEXT, DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, DEFAULT_PASSWORD_RULES, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EMAIL_BLOCK_DRAG_TYPE, EMAIL_TEMPLATE_MAX_BODY, EMAIL_TEMPLATE_MAX_TEXT, EMAIL_TEMPLATE_START_TEXT, EmailTemplateEditorComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FixedFooterComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IDX_BEHAVIOR_SIGNALS, INTEGRATION_CATALOG, INTEGRATION_FIELD_DEFS, INTEGRATION_GROUP_ORDER, INTEGRATION_OPTION_DEFS, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, ImportSourceGridComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, LiveRegionComponent, MAX_EMAIL_ADDRESS_LENGTH, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, OfflineBannerComponent, OptionCardComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, ReminderAlertsComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, SetupWizardStepHeaderDirective, ShareMenuComponent, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, SnackbarComponent, SnackbarService, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextTemplatePickerComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, blockHasContent, buildDefaultSchedule, buildPreviewDocument, buildVideoBlockHtml, builtInActionIcon, businessTimeOptions, conversationDateLabel, conversationInitial, conversationMessageStatusLabel, conversationMessageStatusMark, createFieldReveal, decodeFilterValues, digitsOnly, downloadBlob, emailShareUrl, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, facebookShareUrl, fileMatchesAccept, formatAddress, formatCategoryLabel, formatConversationPhone, formatConversationTime, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatMessageTime, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, gmailShareUrl, groupMessagesByDay, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isValidEmailAddress, isWebUrl, isoKey, issueToErrors, linkedInShareUrl, maxLengthIssue, mergeDescribedBy, normalizeHexColor, outlookShareUrl, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, serializedTextLength, setupIntegrations, splitIntro, truncateConversationText, xShareUrl };
50183
52656
 
50184
52657
  //# sourceMappingURL=forgeroute-ui.mjs.map