@forgeroute/ui 0.4.57 → 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 */ []);
@@ -29749,7 +29749,7 @@ var ListComponent = class ListComponent {
29749
29749
  }
29750
29750
  `,
29751
29751
  isInline: true,
29752
- styles: ["ui-list{display:block;min-width:0}.ul-list{margin:0;padding:0;min-width:0}.ul-list--unordered{list-style:none}.ul-list--ordered{list-style:decimal;-webkit-padding-start:1.75rem;padding-inline-start:1.75rem}.ul-list--ordered>.ul-item::marker{color:var(--text-secondary, #64748b);font-size:.875rem}.ul-item{min-width:0;transition:background-color .4s ease}.ul-item.ul-item--moved{background-color:var(--surface-hover, #f1f5f9)}.ul-list:not(.ul-list--grid)>.ul-item+.ul-item{margin-top:var(--ul-gap, 0px)}.ul-list:not(.ul-list--grid)>.ul-item:not(:last-child)>.ul-row>.ul-content>ui-list-item:not(.li-bordered) .li-row{border-bottom:1px solid var(--border, #e2e8f0)}.ul-row{display:flex;align-items:center;gap:8px;min-width:0}.ul-content{flex:1 1 auto;min-width:0;word-break:break-word;overflow-wrap:anywhere}.ul-controls{display:flex;flex:0 0 auto;align-items:center;gap:2px}.ul-item--nav{cursor:pointer;border-radius:10px;transition:background-color .12s ease}.ul-item--nav:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.ul-item--nav:hover{background:var(--surface-hover, #f8fafc)}.ul-item--nav:hover:has(>.ul-row>.ul-content>ui-list-item.li-bordered){background:transparent}.ul-item--nav>.ul-row{padding-inline-end:8px}.ul-item--nav:hover .ul-chevron{color:#0f172a;transform:translate(2px)}.ul-chevron{flex:0 0 auto;color:#94a3b8;transition:color .15s ease,transform .15s ease}@media(prefers-reduced-motion:reduce){.ul-chevron{transition:none;transform:none!important}}.ul-list.ul-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ul-min, 130px),100%),1fr));gap:var(--ul-gap, 12px);list-style:none;-webkit-padding-start:0;padding-inline-start:0}.ul-list--grid>.ul-item>.ul-row{flex-direction:column;align-items:stretch;gap:6px}.ul-list--grid>.ul-item>.ul-row>.ul-controls{align-self:center}@media(pointer:coarse),(max-width:480px){.ul-controls{gap:16px}}.ul-item--draggable{-webkit-user-select:none;user-select:none;-webkit-user-drag:element}@media(hover:hover)and (pointer:fine){.ul-item--draggable{cursor:grab}.ul-item--draggable:active{cursor:grabbing}}.ul-item--draggable:focus{outline:2px solid #3b82f6;outline-offset:2px;border-radius:6px}.ul-item--draggable:focus:not(:focus-visible){outline:none}ui-list .ul-item--draggable img,ui-list .ul-item--draggable ui-image-preview{pointer-events:none;-webkit-user-drag:none}.ul-item--dragging{opacity:.5}.ul-item--over{outline:2px dashed #3b82f6;outline-offset:2px;border-radius:6px}@media(prefers-reduced-motion:reduce){.ul-item{transition:none}}@media(forced-colors:active){.ul-item.ul-item--moved{outline:2px solid Highlight;outline-offset:-2px}}@media(forced-colors:active){.ul-item.ul-item--dragging{outline:2px dotted Highlight;outline-offset:2px}.ul-item.ul-item--over{outline:2px dashed Highlight;outline-offset:2px}.ul-item--draggable:focus{outline:2px solid Highlight;outline-offset:2px}}.ul-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"],
29752
+ styles: ["ui-list{display:block;min-width:0}.ul-list{margin:0;padding:0;min-width:0}.ul-list--unordered{list-style:none}.ul-list--ordered{list-style:decimal;-webkit-padding-start:1.75rem;padding-inline-start:1.75rem}.ul-list--ordered>.ul-item::marker{color:var(--text-secondary, #64748b);font-size:.875rem}.ul-item{min-width:0;transition:background-color .4s ease}.ul-item.ul-item--moved{background-color:var(--surface-hover, #f1f5f9)}.ul-list:not(.ul-list--grid)>.ul-item+.ul-item{margin-top:var(--ul-gap, 0px)}.ul-list:not(.ul-list--grid)>.ul-item:not(:last-child)>.ul-row>.ul-content>ui-list-item:not(.li-bordered) .li-row{border-bottom:1px solid var(--border, #e2e8f0)}.ul-row{display:flex;align-items:center;gap:8px;min-width:0}.ul-content{flex:1 1 auto;min-width:0;word-break:break-word;overflow-wrap:anywhere}.ul-controls{display:flex;flex:0 0 auto;align-items:center;gap:2px}.ul-item--nav{cursor:pointer;border-radius:10px;transition:background-color .12s ease}.ul-item--nav:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.ul-item--nav:hover{background:var(--surface-hover, #f8fafc)}.ul-item--nav:hover:has(>.ul-row>.ul-content>ui-list-item.li-bordered){background:transparent}.ul-item--nav>.ul-row{padding-inline-end:8px}.ul-item--nav:hover .ul-chevron{color:#0f172a;transform:translate(2px)}.ul-chevron{flex:0 0 auto;color:#94a3b8;transition:color .15s ease,transform .15s ease}@media(prefers-reduced-motion:reduce){.ul-chevron{transition:none;transform:none!important}}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row{position:relative;padding-inline-end:0}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row>.ul-chevron{position:absolute;inset-inline-end:12px;top:50%;margin-top:-10px;pointer-events:none}.ul-item--nav>.ul-row>.ul-content>ui-list-item.li-bordered .li-row{padding-inline-end:40px}.ul-list.ul-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ul-min, 130px),100%),1fr));gap:var(--ul-gap, 12px);list-style:none;-webkit-padding-start:0;padding-inline-start:0}.ul-list--grid>.ul-item>.ul-row{flex-direction:column;align-items:stretch;gap:6px}.ul-list--grid>.ul-item>.ul-row>.ul-controls{align-self:center}@media(pointer:coarse),(max-width:480px){.ul-controls{gap:16px}}.ul-item--draggable{-webkit-user-select:none;user-select:none;-webkit-user-drag:element}@media(hover:hover)and (pointer:fine){.ul-item--draggable{cursor:grab}.ul-item--draggable:active{cursor:grabbing}}.ul-item--draggable:focus{outline:2px solid #3b82f6;outline-offset:2px;border-radius:6px}.ul-item--draggable:focus:not(:focus-visible){outline:none}ui-list .ul-item--draggable img,ui-list .ul-item--draggable ui-image-preview{pointer-events:none;-webkit-user-drag:none}.ul-item--dragging{opacity:.5}.ul-item--over{outline:2px dashed #3b82f6;outline-offset:2px;border-radius:6px}@media(prefers-reduced-motion:reduce){.ul-item{transition:none}}@media(forced-colors:active){.ul-item.ul-item--moved{outline:2px solid Highlight;outline-offset:-2px}}@media(forced-colors:active){.ul-item.ul-item--dragging{outline:2px dotted Highlight;outline-offset:2px}.ul-item.ul-item--over{outline:2px dashed Highlight;outline-offset:2px}.ul-item--draggable:focus{outline:2px solid Highlight;outline-offset:2px}}.ul-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"],
29753
29753
  dependencies: [{
29754
29754
  kind: "directive",
29755
29755
  type: NgTemplateOutlet,
@@ -29877,7 +29877,7 @@ i0.ɵɵngDeclareClassMetadata({
29877
29877
  <div class="ul-sr" role="status" aria-live="polite" aria-atomic="true">{{ announcement() }}</div>
29878
29878
  }
29879
29879
  `,
29880
- styles: ["ui-list{display:block;min-width:0}.ul-list{margin:0;padding:0;min-width:0}.ul-list--unordered{list-style:none}.ul-list--ordered{list-style:decimal;-webkit-padding-start:1.75rem;padding-inline-start:1.75rem}.ul-list--ordered>.ul-item::marker{color:var(--text-secondary, #64748b);font-size:.875rem}.ul-item{min-width:0;transition:background-color .4s ease}.ul-item.ul-item--moved{background-color:var(--surface-hover, #f1f5f9)}.ul-list:not(.ul-list--grid)>.ul-item+.ul-item{margin-top:var(--ul-gap, 0px)}.ul-list:not(.ul-list--grid)>.ul-item:not(:last-child)>.ul-row>.ul-content>ui-list-item:not(.li-bordered) .li-row{border-bottom:1px solid var(--border, #e2e8f0)}.ul-row{display:flex;align-items:center;gap:8px;min-width:0}.ul-content{flex:1 1 auto;min-width:0;word-break:break-word;overflow-wrap:anywhere}.ul-controls{display:flex;flex:0 0 auto;align-items:center;gap:2px}.ul-item--nav{cursor:pointer;border-radius:10px;transition:background-color .12s ease}.ul-item--nav:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.ul-item--nav:hover{background:var(--surface-hover, #f8fafc)}.ul-item--nav:hover:has(>.ul-row>.ul-content>ui-list-item.li-bordered){background:transparent}.ul-item--nav>.ul-row{padding-inline-end:8px}.ul-item--nav:hover .ul-chevron{color:#0f172a;transform:translate(2px)}.ul-chevron{flex:0 0 auto;color:#94a3b8;transition:color .15s ease,transform .15s ease}@media(prefers-reduced-motion:reduce){.ul-chevron{transition:none;transform:none!important}}.ul-list.ul-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ul-min, 130px),100%),1fr));gap:var(--ul-gap, 12px);list-style:none;-webkit-padding-start:0;padding-inline-start:0}.ul-list--grid>.ul-item>.ul-row{flex-direction:column;align-items:stretch;gap:6px}.ul-list--grid>.ul-item>.ul-row>.ul-controls{align-self:center}@media(pointer:coarse),(max-width:480px){.ul-controls{gap:16px}}.ul-item--draggable{-webkit-user-select:none;user-select:none;-webkit-user-drag:element}@media(hover:hover)and (pointer:fine){.ul-item--draggable{cursor:grab}.ul-item--draggable:active{cursor:grabbing}}.ul-item--draggable:focus{outline:2px solid #3b82f6;outline-offset:2px;border-radius:6px}.ul-item--draggable:focus:not(:focus-visible){outline:none}ui-list .ul-item--draggable img,ui-list .ul-item--draggable ui-image-preview{pointer-events:none;-webkit-user-drag:none}.ul-item--dragging{opacity:.5}.ul-item--over{outline:2px dashed #3b82f6;outline-offset:2px;border-radius:6px}@media(prefers-reduced-motion:reduce){.ul-item{transition:none}}@media(forced-colors:active){.ul-item.ul-item--moved{outline:2px solid Highlight;outline-offset:-2px}}@media(forced-colors:active){.ul-item.ul-item--dragging{outline:2px dotted Highlight;outline-offset:2px}.ul-item.ul-item--over{outline:2px dashed Highlight;outline-offset:2px}.ul-item--draggable:focus{outline:2px solid Highlight;outline-offset:2px}}.ul-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"]
29880
+ styles: ["ui-list{display:block;min-width:0}.ul-list{margin:0;padding:0;min-width:0}.ul-list--unordered{list-style:none}.ul-list--ordered{list-style:decimal;-webkit-padding-start:1.75rem;padding-inline-start:1.75rem}.ul-list--ordered>.ul-item::marker{color:var(--text-secondary, #64748b);font-size:.875rem}.ul-item{min-width:0;transition:background-color .4s ease}.ul-item.ul-item--moved{background-color:var(--surface-hover, #f1f5f9)}.ul-list:not(.ul-list--grid)>.ul-item+.ul-item{margin-top:var(--ul-gap, 0px)}.ul-list:not(.ul-list--grid)>.ul-item:not(:last-child)>.ul-row>.ul-content>ui-list-item:not(.li-bordered) .li-row{border-bottom:1px solid var(--border, #e2e8f0)}.ul-row{display:flex;align-items:center;gap:8px;min-width:0}.ul-content{flex:1 1 auto;min-width:0;word-break:break-word;overflow-wrap:anywhere}.ul-controls{display:flex;flex:0 0 auto;align-items:center;gap:2px}.ul-item--nav{cursor:pointer;border-radius:10px;transition:background-color .12s ease}.ul-item--nav:focus-visible{outline:2px solid #2563eb;outline-offset:2px}.ul-item--nav:hover{background:var(--surface-hover, #f8fafc)}.ul-item--nav:hover:has(>.ul-row>.ul-content>ui-list-item.li-bordered){background:transparent}.ul-item--nav>.ul-row{padding-inline-end:8px}.ul-item--nav:hover .ul-chevron{color:#0f172a;transform:translate(2px)}.ul-chevron{flex:0 0 auto;color:#94a3b8;transition:color .15s ease,transform .15s ease}@media(prefers-reduced-motion:reduce){.ul-chevron{transition:none;transform:none!important}}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row{position:relative;padding-inline-end:0}.ul-item--nav:has(>.ul-row>.ul-content>ui-list-item.li-bordered)>.ul-row>.ul-chevron{position:absolute;inset-inline-end:12px;top:50%;margin-top:-10px;pointer-events:none}.ul-item--nav>.ul-row>.ul-content>ui-list-item.li-bordered .li-row{padding-inline-end:40px}.ul-list.ul-list--grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(min(var(--ul-min, 130px),100%),1fr));gap:var(--ul-gap, 12px);list-style:none;-webkit-padding-start:0;padding-inline-start:0}.ul-list--grid>.ul-item>.ul-row{flex-direction:column;align-items:stretch;gap:6px}.ul-list--grid>.ul-item>.ul-row>.ul-controls{align-self:center}@media(pointer:coarse),(max-width:480px){.ul-controls{gap:16px}}.ul-item--draggable{-webkit-user-select:none;user-select:none;-webkit-user-drag:element}@media(hover:hover)and (pointer:fine){.ul-item--draggable{cursor:grab}.ul-item--draggable:active{cursor:grabbing}}.ul-item--draggable:focus{outline:2px solid #3b82f6;outline-offset:2px;border-radius:6px}.ul-item--draggable:focus:not(:focus-visible){outline:none}ui-list .ul-item--draggable img,ui-list .ul-item--draggable ui-image-preview{pointer-events:none;-webkit-user-drag:none}.ul-item--dragging{opacity:.5}.ul-item--over{outline:2px dashed #3b82f6;outline-offset:2px;border-radius:6px}@media(prefers-reduced-motion:reduce){.ul-item{transition:none}}@media(forced-colors:active){.ul-item.ul-item--moved{outline:2px solid Highlight;outline-offset:-2px}}@media(forced-colors:active){.ul-item.ul-item--dragging{outline:2px dotted Highlight;outline-offset:2px}.ul-item.ul-item--over{outline:2px dashed Highlight;outline-offset:2px}.ul-item--draggable:focus{outline:2px solid Highlight;outline-offset:2px}}.ul-sr{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"]
29881
29881
  }]
29882
29882
  }],
29883
29883
  propDecorators: {
@@ -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 {
@@ -49166,6 +49166,3492 @@ i0.ɵɵngDeclareClassMetadata({
49166
49166
  }]
49167
49167
  }
49168
49168
  });
49169
- 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, 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, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, SetupWizardStepHeaderDirective, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, 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, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, fileMatchesAccept, formatAddress, formatCategoryLabel, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isValidEmailAddress, isWebUrl, isoKey, issueToErrors, maxLengthIssue, mergeDescribedBy, normalizeHexColor, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, serializedTextLength, setupIntegrations, splitIntro };
49169
+ const facebookShareUrl = (url) => `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`;
49170
+ const xShareUrl = (url, text) => `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`;
49171
+ const linkedInShareUrl = (url) => `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`;
49172
+ const gmailShareUrl = (url, title) => `https://mail.google.com/mail/?view=cm&fs=1&su=${encodeURIComponent(title)}&body=${encodeURIComponent(`${title}\n\n${url}`)}`;
49173
+ const outlookShareUrl = (url, title) => `https://outlook.live.com/mail/0/deeplink/compose?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(`${title}\n\n${url}`)}`;
49174
+ const emailShareUrl = (url, title) => `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(`${title}\n\n${url}`)}`;
49175
+ let nextShareMenuId = 0;
49176
+ var ShareMenuComponent = class ShareMenuComponent {
49177
+ constructor() {
49178
+ this.url = input.required(...ngDevMode ? [{ debugName: "url" }] : /* istanbul ignore next */ []);
49179
+ this.title = input.required(...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
49180
+ this.label = input("this page", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
49181
+ this.panelId = `ui-share-panel-${nextShareMenuId++}`;
49182
+ this.doc = inject(DOCUMENT);
49183
+ this.toast = inject(ToastService);
49184
+ this.injector = inject(Injector);
49185
+ this.host = inject(ElementRef);
49186
+ this.trigger = viewChild("trigger", ...ngDevMode ? [{ debugName: "trigger" }] : /* istanbul ignore next */ []);
49187
+ this.panel = viewChild("panel", ...ngDevMode ? [{ debugName: "panel" }] : /* istanbul ignore next */ []);
49188
+ this.open = signal(false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
49189
+ this.shiftX = signal(0, ...ngDevMode ? [{ debugName: "shiftX" }] : /* istanbul ignore next */ []);
49190
+ this.isTouchDevice = computed(() => this.doc.defaultView?.matchMedia?.("(pointer: coarse)").matches === true, ...ngDevMode ? [{ debugName: "isTouchDevice" }] : /* istanbul ignore next */ []);
49191
+ this.canNativeShare = computed(() => typeof this.doc.defaultView?.navigator?.share === "function" && this.isTouchDevice(), ...ngDevMode ? [{ debugName: "canNativeShare" }] : /* istanbul ignore next */ []);
49192
+ this.tiles = computed(() => [
49193
+ {
49194
+ value: "facebook",
49195
+ label: "Facebook",
49196
+ background: "#1877f2"
49197
+ },
49198
+ {
49199
+ value: "x",
49200
+ label: "X",
49201
+ background: "#000000"
49202
+ },
49203
+ {
49204
+ value: "linkedin",
49205
+ label: "LinkedIn",
49206
+ background: "#0a66c2"
49207
+ },
49208
+ ...this.isTouchDevice() ? [{
49209
+ value: "email",
49210
+ label: "Email",
49211
+ background: "#78716c"
49212
+ }] : [{
49213
+ value: "gmail",
49214
+ label: "Gmail",
49215
+ background: "#ea4335"
49216
+ }, {
49217
+ value: "outlook",
49218
+ label: "Outlook",
49219
+ background: "#0078d4"
49220
+ }],
49221
+ {
49222
+ value: "copy",
49223
+ label: "Copy link",
49224
+ background: "var(--ui-share-accent, var(--primary, #2563eb))"
49225
+ },
49226
+ ...this.canNativeShare() ? [{
49227
+ value: "native",
49228
+ label: "More",
49229
+ background: "#57534e"
49230
+ }] : []
49231
+ ], ...ngDevMode ? [{ debugName: "tiles" }] : /* istanbul ignore next */ []);
49232
+ this.links = computed(() => ({
49233
+ facebook: facebookShareUrl(this.url()),
49234
+ x: xShareUrl(this.url(), this.title()),
49235
+ linkedin: linkedInShareUrl(this.url()),
49236
+ email: emailShareUrl(this.url(), this.title()),
49237
+ gmail: gmailShareUrl(this.url(), this.title()),
49238
+ outlook: outlookShareUrl(this.url(), this.title())
49239
+ }), ...ngDevMode ? [{ debugName: "links" }] : /* istanbul ignore next */ []);
49240
+ }
49241
+ toggle(event) {
49242
+ event.stopPropagation();
49243
+ if (this.open()) this.close();
49244
+ else this.show();
49245
+ }
49246
+ show() {
49247
+ this.shiftX.set(0);
49248
+ this.open.set(true);
49249
+ afterNextRender(() => {
49250
+ const panel = this.panel()?.nativeElement;
49251
+ if (!panel) return;
49252
+ const view = this.doc.documentElement.clientWidth;
49253
+ const rect = panel.getBoundingClientRect();
49254
+ const margin = 8;
49255
+ if (rect.right > view - margin) this.shiftX.set(Math.round(view - margin - rect.right));
49256
+ else if (rect.left < margin) this.shiftX.set(Math.round(margin - rect.left));
49257
+ if (this.doc.activeElement === this.trigger()?.nativeElement) panel.querySelector("button")?.focus();
49258
+ }, { injector: this.injector });
49259
+ }
49260
+ close(returnFocus = false) {
49261
+ if (!this.open()) return;
49262
+ this.open.set(false);
49263
+ if (returnFocus) this.trigger()?.nativeElement.focus();
49264
+ }
49265
+ onEscape() {
49266
+ if (!this.open()) return;
49267
+ const focusInside = this.host.nativeElement.contains(this.doc.activeElement);
49268
+ this.close(focusInside);
49269
+ }
49270
+ onDocumentClick(event) {
49271
+ if (this.open() && !this.host.nativeElement.contains(event.target)) this.close();
49272
+ }
49273
+ onFocusOut(event) {
49274
+ const next = event.relatedTarget;
49275
+ if (this.open() && next && !this.host.nativeElement.contains(next)) this.close();
49276
+ }
49277
+ onPanelKeydown(event) {
49278
+ const options = Array.from(this.panel().nativeElement.querySelectorAll("button"));
49279
+ const i = options.indexOf(this.doc.activeElement);
49280
+ const to = event.key === "ArrowRight" ? (i + 1) % options.length : event.key === "ArrowLeft" ? (i - 1 + options.length) % options.length : event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : -1;
49281
+ if (to < 0) return;
49282
+ event.preventDefault();
49283
+ options[to].focus();
49284
+ }
49285
+ choose(option) {
49286
+ switch (option) {
49287
+ case "native":
49288
+ this.nativeShare();
49289
+ break;
49290
+ case "facebook":
49291
+ case "x":
49292
+ case "linkedin":
49293
+ case "gmail":
49294
+ case "outlook":
49295
+ this.doc.defaultView?.open(this.links()[option], "_blank", "noopener,noreferrer");
49296
+ break;
49297
+ case "email":
49298
+ this.email();
49299
+ break;
49300
+ case "copy": this.copy();
49301
+ }
49302
+ this.close(true);
49303
+ }
49304
+ async nativeShare() {
49305
+ try {
49306
+ await this.doc.defaultView.navigator.share({
49307
+ title: this.title(),
49308
+ url: this.url()
49309
+ });
49310
+ } catch (err) {
49311
+ if (err?.name !== "AbortError") this.toast.error("Sharing from this page isn't available here. Use one of the other options.");
49312
+ }
49313
+ }
49314
+ email() {
49315
+ const link = this.doc.createElement("a");
49316
+ link.href = this.links().email;
49317
+ link.rel = "noopener noreferrer";
49318
+ link.click();
49319
+ }
49320
+ async copy() {
49321
+ const url = this.url();
49322
+ try {
49323
+ await this.doc.defaultView.navigator.clipboard.writeText(url);
49324
+ this.toast.show("Link copied");
49325
+ return;
49326
+ } catch {}
49327
+ if (this.legacyCopy(url)) {
49328
+ this.toast.show("Link copied");
49329
+ return;
49330
+ }
49331
+ this.doc.defaultView?.prompt("Copy this link:", url);
49332
+ }
49333
+ legacyCopy(text) {
49334
+ const textarea = this.doc.createElement("textarea");
49335
+ textarea.value = text;
49336
+ textarea.setAttribute("readonly", "");
49337
+ textarea.style.position = "fixed";
49338
+ textarea.style.opacity = "0";
49339
+ this.doc.body.appendChild(textarea);
49340
+ try {
49341
+ textarea.select();
49342
+ textarea.setSelectionRange(0, text.length);
49343
+ return this.doc.execCommand("copy");
49344
+ } catch {
49345
+ return false;
49346
+ } finally {
49347
+ textarea.remove();
49348
+ }
49349
+ }
49350
+ static {
49351
+ this.ɵfac = i0.ɵɵngDeclareFactory({
49352
+ minVersion: "12.0.0",
49353
+ version: "22.2.2",
49354
+ ngImport: i0,
49355
+ type: ShareMenuComponent,
49356
+ deps: [],
49357
+ target: i0.ɵɵFactoryTarget.Component
49358
+ });
49359
+ }
49360
+ static {
49361
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
49362
+ minVersion: "17.0.0",
49363
+ version: "22.2.2",
49364
+ type: ShareMenuComponent,
49365
+ isStandalone: true,
49366
+ selector: "ui-share-menu",
49367
+ inputs: {
49368
+ url: {
49369
+ classPropertyName: "url",
49370
+ publicName: "url",
49371
+ isSignal: true,
49372
+ isRequired: true,
49373
+ transformFunction: null
49374
+ },
49375
+ title: {
49376
+ classPropertyName: "title",
49377
+ publicName: "title",
49378
+ isSignal: true,
49379
+ isRequired: true,
49380
+ transformFunction: null
49381
+ },
49382
+ label: {
49383
+ classPropertyName: "label",
49384
+ publicName: "label",
49385
+ isSignal: true,
49386
+ isRequired: false,
49387
+ transformFunction: null
49388
+ }
49389
+ },
49390
+ host: { listeners: {
49391
+ "document:keydown.escape": "onEscape()",
49392
+ "document:click": "onDocumentClick($event)",
49393
+ "focusout": "onFocusOut($event)"
49394
+ } },
49395
+ viewQueries: [{
49396
+ propertyName: "trigger",
49397
+ first: true,
49398
+ predicate: ["trigger"],
49399
+ descendants: true,
49400
+ isSignal: true
49401
+ }, {
49402
+ propertyName: "panel",
49403
+ first: true,
49404
+ predicate: ["panel"],
49405
+ descendants: true,
49406
+ isSignal: true
49407
+ }],
49408
+ ngImport: i0,
49409
+ template: `
49410
+ <div class="share-wrap">
49411
+ <button
49412
+ #trigger
49413
+ type="button"
49414
+ class="share-trigger"
49415
+ data-testid="share-trigger"
49416
+ [attr.aria-label]="'Share ' + label()"
49417
+ [attr.aria-expanded]="open()"
49418
+ [attr.aria-controls]="open() ? panelId : null"
49419
+ (click)="toggle($event)"
49420
+ >
49421
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
49422
+ <circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
49423
+ <line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/>
49424
+ </svg>
49425
+ Share
49426
+ </button>
49427
+
49428
+ @if (open()) {
49429
+ <div
49430
+ #panel
49431
+ [id]="panelId"
49432
+ class="share-panel"
49433
+ role="group"
49434
+ aria-label="Share options"
49435
+ data-testid="share-panel"
49436
+ [style.transform]="'translateX(' + shiftX() + 'px)'"
49437
+ (keydown)="onPanelKeydown($event)"
49438
+ >
49439
+ @for (tile of tiles(); track tile.value) {
49440
+ <button type="button" class="share-tile" [attr.data-testid]="'share-' + tile.value" (click)="choose(tile.value)">
49441
+ <span class="share-icon" [style.background]="tile.background" aria-hidden="true">
49442
+ @switch (tile.value) {
49443
+ @case ('facebook') {
49444
+ <svg width="26" height="26" viewBox="0 0 24 24" fill="currentColor"><path d="M13.5 21v-7.5h2.6l.4-3h-3V8.6c0-.9.3-1.5 1.6-1.5h1.5V4.4c-.3 0-1.2-.1-2.3-.1-2.3 0-3.8 1.4-3.8 3.9v2.3H8v3h2.5V21h3z"/></svg>
49445
+ }
49446
+ @case ('x') {
49447
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><path d="M17.8 3h3.1l-6.8 7.7L22 21h-6.2l-4.9-6.4L5.3 21H2.2l7.3-8.3L2 3h6.4l4.4 5.8L17.8 3zm-1.1 16.2h1.7L7.3 4.7H5.5l11.2 14.5z"/></svg>
49448
+ }
49449
+ @case ('linkedin') {
49450
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M6.9 8.9H3.6V20h3.3V8.9zM5.2 3.5a1.9 1.9 0 100 3.8 1.9 1.9 0 000-3.8zM20.4 13.4c0-3-1.6-4.7-4.1-4.7-1.2 0-2.2.6-2.7 1.4V8.9h-3.2V20h3.3v-6c0-1.4.7-2.4 1.9-2.4s1.5 1 1.5 2.4V20h3.3v-6.6z"/></svg>
49451
+ }
49452
+ @case ('email') {
49453
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>
49454
+ }
49455
+ @case ('gmail') {
49456
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>
49457
+ }
49458
+ @case ('outlook') {
49459
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>
49460
+ }
49461
+ @case ('copy') {
49462
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 007.1 0l3-3a5 5 0 00-7.1-7.1l-1.7 1.7"/><path d="M14 11a5 5 0 00-7.1 0l-3 3A5 5 0 0011 21l1.7-1.7"/></svg>
49463
+ }
49464
+ @case ('native') {
49465
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><circle cx="5" cy="12" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="19" cy="12" r="2"/></svg>
49466
+ }
49467
+ }
49468
+ </span>
49469
+ <span class="share-name">{{ tile.label }}</span>
49470
+ </button>
49471
+ }
49472
+ </div>
49473
+ }
49474
+ </div>
49475
+ <ui-toast />
49476
+ `,
49477
+ isInline: true,
49478
+ styles: [":host{display:inline-block}.share-wrap{position:relative}.share-trigger{display:inline-flex;align-items:center;gap:.4rem;min-height:2.25rem;padding:.35rem .95rem;border:1px solid #d6d3d1;border-radius:9999px;background:#fff;color:#44403c;font-size:.875rem;font-weight:600;font-family:inherit;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.share-trigger:hover{border-color:#a8a29e;background:#fafaf9}.share-trigger[aria-expanded=true]{border-color:#78716c;background:#f5f5f4}.share-trigger:focus-visible,.share-tile:focus-visible{outline:2px solid var(--ui-share-accent, var(--primary, #2563eb));outline-offset:2px}@media(pointer:coarse){.share-trigger{min-height:2.75rem}}.share-panel{position:absolute;top:calc(100% + 8px);left:0;z-index:50;display:flex;align-items:flex-start;gap:4px;padding:14px 12px 10px;width:max-content;max-width:calc(100vw - 16px);overflow-x:auto;-webkit-overflow-scrolling:touch;background:#fff;border:1px solid #e7e5e4;border-radius:16px;box-shadow:0 10px 30px #1c19172e}.share-tile{display:flex;flex-direction:column;align-items:center;gap:6px;flex:none;width:64px;padding:2px 0;border:0;background:none;border-radius:10px;font-family:inherit;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.share-icon{display:flex;align-items:center;justify-content:center;width:52px;height:52px;border-radius:9999px;color:#fff;transition:transform .12s ease,box-shadow .12s ease}.share-tile:hover .share-icon{transform:translateY(-2px);box-shadow:0 4px 10px #1c191740}.share-name{font-size:.75rem;line-height:1.1;font-weight:500;color:#57534e;text-align:center}@media(max-width:480px){.share-panel{padding:12px 8px 8px;gap:2px}.share-tile{width:auto;min-width:48px;padding:2px 1px}.share-icon{width:44px;height:44px}.share-name{white-space:nowrap;font-size:.8125rem}}@media(prefers-reduced-motion:reduce){.share-icon{transition:none}.share-tile:hover .share-icon{transform:none}}\n"],
49479
+ dependencies: [{
49480
+ kind: "component",
49481
+ type: ToastComponent,
49482
+ selector: "ui-toast",
49483
+ inputs: ["dismissible", "persistentLiveRegion"]
49484
+ }],
49485
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
49486
+ });
49487
+ }
49488
+ };
49489
+ i0.ɵɵngDeclareClassMetadata({
49490
+ minVersion: "12.0.0",
49491
+ version: "22.2.2",
49492
+ ngImport: i0,
49493
+ type: ShareMenuComponent,
49494
+ decorators: [{
49495
+ type: Component,
49496
+ args: [{
49497
+ selector: "ui-share-menu",
49498
+ standalone: true,
49499
+ changeDetection: ChangeDetectionStrategy.OnPush,
49500
+ imports: [ToastComponent],
49501
+ host: {
49502
+ "(document:keydown.escape)": "onEscape()",
49503
+ "(document:click)": "onDocumentClick($event)",
49504
+ "(focusout)": "onFocusOut($event)"
49505
+ },
49506
+ template: `
49507
+ <div class="share-wrap">
49508
+ <button
49509
+ #trigger
49510
+ type="button"
49511
+ class="share-trigger"
49512
+ data-testid="share-trigger"
49513
+ [attr.aria-label]="'Share ' + label()"
49514
+ [attr.aria-expanded]="open()"
49515
+ [attr.aria-controls]="open() ? panelId : null"
49516
+ (click)="toggle($event)"
49517
+ >
49518
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
49519
+ <circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
49520
+ <line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/>
49521
+ </svg>
49522
+ Share
49523
+ </button>
49524
+
49525
+ @if (open()) {
49526
+ <div
49527
+ #panel
49528
+ [id]="panelId"
49529
+ class="share-panel"
49530
+ role="group"
49531
+ aria-label="Share options"
49532
+ data-testid="share-panel"
49533
+ [style.transform]="'translateX(' + shiftX() + 'px)'"
49534
+ (keydown)="onPanelKeydown($event)"
49535
+ >
49536
+ @for (tile of tiles(); track tile.value) {
49537
+ <button type="button" class="share-tile" [attr.data-testid]="'share-' + tile.value" (click)="choose(tile.value)">
49538
+ <span class="share-icon" [style.background]="tile.background" aria-hidden="true">
49539
+ @switch (tile.value) {
49540
+ @case ('facebook') {
49541
+ <svg width="26" height="26" viewBox="0 0 24 24" fill="currentColor"><path d="M13.5 21v-7.5h2.6l.4-3h-3V8.6c0-.9.3-1.5 1.6-1.5h1.5V4.4c-.3 0-1.2-.1-2.3-.1-2.3 0-3.8 1.4-3.8 3.9v2.3H8v3h2.5V21h3z"/></svg>
49542
+ }
49543
+ @case ('x') {
49544
+ <svg width="22" height="22" viewBox="0 0 24 24" fill="currentColor"><path d="M17.8 3h3.1l-6.8 7.7L22 21h-6.2l-4.9-6.4L5.3 21H2.2l7.3-8.3L2 3h6.4l4.4 5.8L17.8 3zm-1.1 16.2h1.7L7.3 4.7H5.5l11.2 14.5z"/></svg>
49545
+ }
49546
+ @case ('linkedin') {
49547
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M6.9 8.9H3.6V20h3.3V8.9zM5.2 3.5a1.9 1.9 0 100 3.8 1.9 1.9 0 000-3.8zM20.4 13.4c0-3-1.6-4.7-4.1-4.7-1.2 0-2.2.6-2.7 1.4V8.9h-3.2V20h3.3v-6c0-1.4.7-2.4 1.9-2.4s1.5 1 1.5 2.4V20h3.3v-6.6z"/></svg>
49548
+ }
49549
+ @case ('email') {
49550
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>
49551
+ }
49552
+ @case ('gmail') {
49553
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>
49554
+ }
49555
+ @case ('outlook') {
49556
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>
49557
+ }
49558
+ @case ('copy') {
49559
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 007.1 0l3-3a5 5 0 00-7.1-7.1l-1.7 1.7"/><path d="M14 11a5 5 0 00-7.1 0l-3 3A5 5 0 0011 21l1.7-1.7"/></svg>
49560
+ }
49561
+ @case ('native') {
49562
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><circle cx="5" cy="12" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="19" cy="12" r="2"/></svg>
49563
+ }
49564
+ }
49565
+ </span>
49566
+ <span class="share-name">{{ tile.label }}</span>
49567
+ </button>
49568
+ }
49569
+ </div>
49570
+ }
49571
+ </div>
49572
+ <ui-toast />
49573
+ `,
49574
+ styles: [":host{display:inline-block}.share-wrap{position:relative}.share-trigger{display:inline-flex;align-items:center;gap:.4rem;min-height:2.25rem;padding:.35rem .95rem;border:1px solid #d6d3d1;border-radius:9999px;background:#fff;color:#44403c;font-size:.875rem;font-weight:600;font-family:inherit;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.share-trigger:hover{border-color:#a8a29e;background:#fafaf9}.share-trigger[aria-expanded=true]{border-color:#78716c;background:#f5f5f4}.share-trigger:focus-visible,.share-tile:focus-visible{outline:2px solid var(--ui-share-accent, var(--primary, #2563eb));outline-offset:2px}@media(pointer:coarse){.share-trigger{min-height:2.75rem}}.share-panel{position:absolute;top:calc(100% + 8px);left:0;z-index:50;display:flex;align-items:flex-start;gap:4px;padding:14px 12px 10px;width:max-content;max-width:calc(100vw - 16px);overflow-x:auto;-webkit-overflow-scrolling:touch;background:#fff;border:1px solid #e7e5e4;border-radius:16px;box-shadow:0 10px 30px #1c19172e}.share-tile{display:flex;flex-direction:column;align-items:center;gap:6px;flex:none;width:64px;padding:2px 0;border:0;background:none;border-radius:10px;font-family:inherit;cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}.share-icon{display:flex;align-items:center;justify-content:center;width:52px;height:52px;border-radius:9999px;color:#fff;transition:transform .12s ease,box-shadow .12s ease}.share-tile:hover .share-icon{transform:translateY(-2px);box-shadow:0 4px 10px #1c191740}.share-name{font-size:.75rem;line-height:1.1;font-weight:500;color:#57534e;text-align:center}@media(max-width:480px){.share-panel{padding:12px 8px 8px;gap:2px}.share-tile{width:auto;min-width:48px;padding:2px 1px}.share-icon{width:44px;height:44px}.share-name{white-space:nowrap;font-size:.8125rem}}@media(prefers-reduced-motion:reduce){.share-icon{transition:none}.share-tile:hover .share-icon{transform:none}}\n"]
49575
+ }]
49576
+ }],
49577
+ propDecorators: {
49578
+ url: [{
49579
+ type: i0.Input,
49580
+ args: [{
49581
+ isSignal: true,
49582
+ alias: "url",
49583
+ required: true
49584
+ }]
49585
+ }],
49586
+ title: [{
49587
+ type: i0.Input,
49588
+ args: [{
49589
+ isSignal: true,
49590
+ alias: "title",
49591
+ required: true
49592
+ }]
49593
+ }],
49594
+ label: [{
49595
+ type: i0.Input,
49596
+ args: [{
49597
+ isSignal: true,
49598
+ alias: "label",
49599
+ required: false
49600
+ }]
49601
+ }],
49602
+ trigger: [{
49603
+ type: i0.ViewChild,
49604
+ args: ["trigger", { isSignal: true }]
49605
+ }],
49606
+ panel: [{
49607
+ type: i0.ViewChild,
49608
+ args: ["panel", { isSignal: true }]
49609
+ }]
49610
+ }
49611
+ });
49612
+ var SnackbarService = class SnackbarService {
49613
+ constructor() {
49614
+ this._messages = signal([], ...ngDevMode ? [{ debugName: "_messages" }] : /* istanbul ignore next */ []);
49615
+ this.nextId = 0;
49616
+ this.timers = /* @__PURE__ */ new Map();
49617
+ }
49618
+ messages$() {
49619
+ return [...this._messages()];
49620
+ }
49621
+ showSuccess(message, duration = 5e3) {
49622
+ this.show(message, "success", duration);
49623
+ }
49624
+ showError(message, duration = 5e3) {
49625
+ this.show(message, "error", duration);
49626
+ }
49627
+ showInfo(message, duration = 5e3, action) {
49628
+ this.show(message, "info", duration, action);
49629
+ }
49630
+ show(message, type, duration, action) {
49631
+ const id = this.nextId++;
49632
+ this._messages.update((messages) => [...messages, {
49633
+ id,
49634
+ message,
49635
+ type,
49636
+ action
49637
+ }]);
49638
+ if (duration > 0) this.timers.set(id, setTimeout(() => this.dismiss(id), duration));
49639
+ }
49640
+ dismiss(id) {
49641
+ const timer = this.timers.get(id);
49642
+ if (timer) {
49643
+ clearTimeout(timer);
49644
+ this.timers.delete(id);
49645
+ }
49646
+ this._messages.update((messages) => messages.filter((m) => m.id !== id));
49647
+ }
49648
+ static {
49649
+ this.ɵfac = i0.ɵɵngDeclareFactory({
49650
+ minVersion: "12.0.0",
49651
+ version: "22.2.2",
49652
+ ngImport: i0,
49653
+ type: SnackbarService,
49654
+ deps: [],
49655
+ target: i0.ɵɵFactoryTarget.Injectable
49656
+ });
49657
+ }
49658
+ static {
49659
+ this.ɵprov = i0.ɵɵngDeclareInjectable({
49660
+ minVersion: "12.0.0",
49661
+ version: "22.2.2",
49662
+ ngImport: i0,
49663
+ type: SnackbarService,
49664
+ providedIn: "root"
49665
+ });
49666
+ }
49667
+ };
49668
+ i0.ɵɵngDeclareClassMetadata({
49669
+ minVersion: "12.0.0",
49670
+ version: "22.2.2",
49671
+ ngImport: i0,
49672
+ type: SnackbarService,
49673
+ decorators: [{
49674
+ type: Injectable,
49675
+ args: [{ providedIn: "root" }]
49676
+ }]
49677
+ });
49678
+ var SnackbarComponent = class SnackbarComponent {
49679
+ constructor() {
49680
+ this.service = inject(SnackbarService);
49681
+ this.messages = computed(() => this.service.messages$(), ...ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []);
49682
+ }
49683
+ variant(m) {
49684
+ return m.type === "error" ? "danger" : m.type;
49685
+ }
49686
+ dismiss(id) {
49687
+ this.service.dismiss(id);
49688
+ }
49689
+ runAction(m, callback) {
49690
+ callback();
49691
+ this.service.dismiss(m.id);
49692
+ }
49693
+ static {
49694
+ this.ɵfac = i0.ɵɵngDeclareFactory({
49695
+ minVersion: "12.0.0",
49696
+ version: "22.2.2",
49697
+ ngImport: i0,
49698
+ type: SnackbarComponent,
49699
+ deps: [],
49700
+ target: i0.ɵɵFactoryTarget.Component
49701
+ });
49702
+ }
49703
+ static {
49704
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
49705
+ minVersion: "17.0.0",
49706
+ version: "22.2.2",
49707
+ type: SnackbarComponent,
49708
+ isStandalone: true,
49709
+ selector: "ui-snackbar",
49710
+ ngImport: i0,
49711
+ template: `
49712
+ <div class="sb-stack" role="region" aria-label="Notifications" aria-live="polite">
49713
+ @for (m of messages(); track m.id) {
49714
+ <ui-alert class="sb-item" [variant]="variant(m)" [dismissible]="true" dismissAriaLabel="Dismiss notification"
49715
+ [attr.data-testid]="m.type + '-message'" (dismissed)="dismiss(m.id)">
49716
+ <span class="sb-text">{{ m.message }}</span>
49717
+ @if (m.action; as act) {
49718
+ <ui-button variant="link" size="sm" data-testid="snackbar-action" (click)="runAction(m, act.callback)">{{ act.label }}</ui-button>
49719
+ }
49720
+ </ui-alert>
49721
+ }
49722
+ </div>
49723
+ `,
49724
+ isInline: true,
49725
+ styles: [":host{display:contents}.sb-stack{position:fixed;top:16px;right:16px;z-index:9999;display:flex;flex-direction:column;gap:8px;width:20rem;max-width:calc(100vw - 32px);pointer-events:none}.sb-item{pointer-events:auto;box-shadow:0 8px 20px #0f172a2e;border-radius:8px;animation:sb-in .28s cubic-bezier(.16,1,.3,1)}.sb-text{min-width:0;overflow-wrap:anywhere}@keyframes sb-in{0%{opacity:0;transform:translate(24px)}to{opacity:1;transform:translate(0)}}@media(prefers-reduced-motion:reduce){.sb-item{animation:none}}\n"],
49726
+ dependencies: [{
49727
+ kind: "component",
49728
+ type: AlertComponent,
49729
+ selector: "ui-alert",
49730
+ inputs: [
49731
+ "variant",
49732
+ "title",
49733
+ "dismissible",
49734
+ "dismissAriaLabel",
49735
+ "quiet",
49736
+ "compact",
49737
+ "inline",
49738
+ "fill"
49739
+ ],
49740
+ outputs: ["dismissed"]
49741
+ }, {
49742
+ kind: "component",
49743
+ type: ButtonComponent,
49744
+ selector: "ui-button",
49745
+ inputs: [
49746
+ "variant",
49747
+ "routerLink",
49748
+ "queryParams",
49749
+ "fragment",
49750
+ "state",
49751
+ "href",
49752
+ "target",
49753
+ "rel",
49754
+ "shortLabel",
49755
+ "shortBelow",
49756
+ "color",
49757
+ "active",
49758
+ "size",
49759
+ "type",
49760
+ "disabled",
49761
+ "loading",
49762
+ "fullWidth",
49763
+ "ariaLabel",
49764
+ "ariaExpanded",
49765
+ "ariaPressed",
49766
+ "ariaDescribedBy",
49767
+ "modal-footer-left",
49768
+ "modal-footer-right"
49769
+ ]
49770
+ }],
49771
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
49772
+ });
49773
+ }
49774
+ };
49775
+ i0.ɵɵngDeclareClassMetadata({
49776
+ minVersion: "12.0.0",
49777
+ version: "22.2.2",
49778
+ ngImport: i0,
49779
+ type: SnackbarComponent,
49780
+ decorators: [{
49781
+ type: Component,
49782
+ args: [{
49783
+ selector: "ui-snackbar",
49784
+ standalone: true,
49785
+ changeDetection: ChangeDetectionStrategy.OnPush,
49786
+ imports: [AlertComponent, ButtonComponent],
49787
+ template: `
49788
+ <div class="sb-stack" role="region" aria-label="Notifications" aria-live="polite">
49789
+ @for (m of messages(); track m.id) {
49790
+ <ui-alert class="sb-item" [variant]="variant(m)" [dismissible]="true" dismissAriaLabel="Dismiss notification"
49791
+ [attr.data-testid]="m.type + '-message'" (dismissed)="dismiss(m.id)">
49792
+ <span class="sb-text">{{ m.message }}</span>
49793
+ @if (m.action; as act) {
49794
+ <ui-button variant="link" size="sm" data-testid="snackbar-action" (click)="runAction(m, act.callback)">{{ act.label }}</ui-button>
49795
+ }
49796
+ </ui-alert>
49797
+ }
49798
+ </div>
49799
+ `,
49800
+ styles: [":host{display:contents}.sb-stack{position:fixed;top:16px;right:16px;z-index:9999;display:flex;flex-direction:column;gap:8px;width:20rem;max-width:calc(100vw - 32px);pointer-events:none}.sb-item{pointer-events:auto;box-shadow:0 8px 20px #0f172a2e;border-radius:8px;animation:sb-in .28s cubic-bezier(.16,1,.3,1)}.sb-text{min-width:0;overflow-wrap:anywhere}@keyframes sb-in{0%{opacity:0;transform:translate(24px)}to{opacity:1;transform:translate(0)}}@media(prefers-reduced-motion:reduce){.sb-item{animation:none}}\n"]
49801
+ }]
49802
+ }]
49803
+ });
49804
+ var OfflineBannerComponent = class OfflineBannerComponent {
49805
+ constructor() {
49806
+ this.title = input("You are currently offline", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
49807
+ this.message = input("Some features may not work properly. Please check your internet connection.", ...ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []);
49808
+ this.offline = input(null, ...ngDevMode ? [{ debugName: "offline" }] : /* istanbul ignore next */ []);
49809
+ this.browserOffline = signal(false, ...ngDevMode ? [{ debugName: "browserOffline" }] : /* istanbul ignore next */ []);
49810
+ this.dismissed = signal(false, ...ngDevMode ? [{ debugName: "dismissed" }] : /* istanbul ignore next */ []);
49811
+ this.isOffline = computed(() => this.offline() ?? this.browserOffline(), ...ngDevMode ? [{ debugName: "isOffline" }] : /* istanbul ignore next */ []);
49812
+ this.visible = computed(() => this.isOffline() && !this.dismissed(), ...ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []);
49813
+ const win = inject(DOCUMENT).defaultView;
49814
+ if (!win) return;
49815
+ this.browserOffline.set(win.navigator.onLine === false);
49816
+ const goOffline = () => this.browserOffline.set(true);
49817
+ const goOnline = () => {
49818
+ this.browserOffline.set(false);
49819
+ this.dismissed.set(false);
49820
+ };
49821
+ win.addEventListener("offline", goOffline);
49822
+ win.addEventListener("online", goOnline);
49823
+ inject(DestroyRef).onDestroy(() => {
49824
+ win.removeEventListener("offline", goOffline);
49825
+ win.removeEventListener("online", goOnline);
49826
+ });
49827
+ }
49828
+ dismiss() {
49829
+ this.dismissed.set(true);
49830
+ }
49831
+ static {
49832
+ this.ɵfac = i0.ɵɵngDeclareFactory({
49833
+ minVersion: "12.0.0",
49834
+ version: "22.2.2",
49835
+ ngImport: i0,
49836
+ type: OfflineBannerComponent,
49837
+ deps: [],
49838
+ target: i0.ɵɵFactoryTarget.Component
49839
+ });
49840
+ }
49841
+ static {
49842
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
49843
+ minVersion: "17.0.0",
49844
+ version: "22.2.2",
49845
+ type: OfflineBannerComponent,
49846
+ isStandalone: true,
49847
+ selector: "ui-offline-banner",
49848
+ inputs: {
49849
+ title: {
49850
+ classPropertyName: "title",
49851
+ publicName: "title",
49852
+ isSignal: true,
49853
+ isRequired: false,
49854
+ transformFunction: null
49855
+ },
49856
+ message: {
49857
+ classPropertyName: "message",
49858
+ publicName: "message",
49859
+ isSignal: true,
49860
+ isRequired: false,
49861
+ transformFunction: null
49862
+ },
49863
+ offline: {
49864
+ classPropertyName: "offline",
49865
+ publicName: "offline",
49866
+ isSignal: true,
49867
+ isRequired: false,
49868
+ transformFunction: null
49869
+ }
49870
+ },
49871
+ ngImport: i0,
49872
+ template: `
49873
+ @if (visible()) {
49874
+ <div class="ob-bar" data-testid="offline-banner">
49875
+ <ui-alert variant="warning" [title]="title()" [dismissible]="true" dismissAriaLabel="Dismiss offline notification" (dismissed)="dismiss()">{{ message() }}</ui-alert>
49876
+ </div>
49877
+ }
49878
+ `,
49879
+ isInline: true,
49880
+ styles: [":host{display:contents}.ob-bar{position:fixed;top:0;left:0;right:0;z-index:9999;padding:8px 16px;pointer-events:none}.ob-bar ui-alert{pointer-events:auto;max-width:1200px;margin:0 auto;box-shadow:0 4px 12px #0f172a26;border-radius:8px}\n"],
49881
+ dependencies: [{
49882
+ kind: "component",
49883
+ type: AlertComponent,
49884
+ selector: "ui-alert",
49885
+ inputs: [
49886
+ "variant",
49887
+ "title",
49888
+ "dismissible",
49889
+ "dismissAriaLabel",
49890
+ "quiet",
49891
+ "compact",
49892
+ "inline",
49893
+ "fill"
49894
+ ],
49895
+ outputs: ["dismissed"]
49896
+ }],
49897
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
49898
+ });
49899
+ }
49900
+ };
49901
+ i0.ɵɵngDeclareClassMetadata({
49902
+ minVersion: "12.0.0",
49903
+ version: "22.2.2",
49904
+ ngImport: i0,
49905
+ type: OfflineBannerComponent,
49906
+ decorators: [{
49907
+ type: Component,
49908
+ args: [{
49909
+ selector: "ui-offline-banner",
49910
+ standalone: true,
49911
+ changeDetection: ChangeDetectionStrategy.OnPush,
49912
+ imports: [AlertComponent],
49913
+ template: `
49914
+ @if (visible()) {
49915
+ <div class="ob-bar" data-testid="offline-banner">
49916
+ <ui-alert variant="warning" [title]="title()" [dismissible]="true" dismissAriaLabel="Dismiss offline notification" (dismissed)="dismiss()">{{ message() }}</ui-alert>
49917
+ </div>
49918
+ }
49919
+ `,
49920
+ styles: [":host{display:contents}.ob-bar{position:fixed;top:0;left:0;right:0;z-index:9999;padding:8px 16px;pointer-events:none}.ob-bar ui-alert{pointer-events:auto;max-width:1200px;margin:0 auto;box-shadow:0 4px 12px #0f172a26;border-radius:8px}\n"]
49921
+ }]
49922
+ }],
49923
+ ctorParameters: () => [],
49924
+ propDecorators: {
49925
+ title: [{
49926
+ type: i0.Input,
49927
+ args: [{
49928
+ isSignal: true,
49929
+ alias: "title",
49930
+ required: false
49931
+ }]
49932
+ }],
49933
+ message: [{
49934
+ type: i0.Input,
49935
+ args: [{
49936
+ isSignal: true,
49937
+ alias: "message",
49938
+ required: false
49939
+ }]
49940
+ }],
49941
+ offline: [{
49942
+ type: i0.Input,
49943
+ args: [{
49944
+ isSignal: true,
49945
+ alias: "offline",
49946
+ required: false
49947
+ }]
49948
+ }]
49949
+ }
49950
+ });
49951
+ var ReminderAlertsComponent = class ReminderAlertsComponent {
49952
+ constructor() {
49953
+ this.items = input([], ...ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []);
49954
+ this.ariaLabel = input("Alerts", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
49955
+ this.action = output();
49956
+ this.hidden = output();
49957
+ }
49958
+ variant(item) {
49959
+ return item.tone;
49960
+ }
49961
+ static {
49962
+ this.ɵfac = i0.ɵɵngDeclareFactory({
49963
+ minVersion: "12.0.0",
49964
+ version: "22.2.2",
49965
+ ngImport: i0,
49966
+ type: ReminderAlertsComponent,
49967
+ deps: [],
49968
+ target: i0.ɵɵFactoryTarget.Component
49969
+ });
49970
+ }
49971
+ static {
49972
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
49973
+ minVersion: "17.0.0",
49974
+ version: "22.2.2",
49975
+ type: ReminderAlertsComponent,
49976
+ isStandalone: true,
49977
+ selector: "ui-reminder-alerts",
49978
+ inputs: {
49979
+ items: {
49980
+ classPropertyName: "items",
49981
+ publicName: "items",
49982
+ isSignal: true,
49983
+ isRequired: false,
49984
+ transformFunction: null
49985
+ },
49986
+ ariaLabel: {
49987
+ classPropertyName: "ariaLabel",
49988
+ publicName: "ariaLabel",
49989
+ isSignal: true,
49990
+ isRequired: false,
49991
+ transformFunction: null
49992
+ }
49993
+ },
49994
+ outputs: {
49995
+ action: "action",
49996
+ hidden: "hidden"
49997
+ },
49998
+ ngImport: i0,
49999
+ template: `
50000
+ @if (items().length) {
50001
+ <div class="ra-stack" role="region" [attr.aria-label]="ariaLabel()" aria-live="polite">
50002
+ @for (item of items(); track item.id) {
50003
+ <ui-alert class="ra-item" [variant]="variant(item)" [attr.data-testid]="'reminder-alert-' + item.id">
50004
+ <div class="ra-body">
50005
+ <ui-button class="ra-hide" variant="icon" size="xs" [ariaLabel]="item.hideLabel || 'Hide alert'" [attr.data-testid]="item.hideTestId || 'alert-hide'" (click)="hidden.emit(item)">
50006
+ <ui-icon name="close" [size]="14" [interactive]="false" />
50007
+ </ui-button>
50008
+ <span class="ra-label">{{ item.label }}</span>
50009
+ <p class="ra-title">{{ item.title }}</p>
50010
+ @if (item.badge; as b) {
50011
+ <ui-badge class="ra-badge" role="img" variant="purple" [label]="b.label" [attr.aria-label]="b.ariaLabel || b.label" [attr.title]="b.ariaLabel || b.label" [attr.data-testid]="b.testId || 'alert-badge'" />
50012
+ }
50013
+ @for (line of item.lines ?? []; track $index) {
50014
+ <p class="ra-line">{{ line }}</p>
50015
+ }
50016
+ @if (item.actions?.length) {
50017
+ <div class="ra-actions">
50018
+ @for (a of item.actions; track a.id) {
50019
+ <ui-button [variant]="a.variant || 'secondary'" size="xs" [attr.data-testid]="'alert-' + a.id" (click)="action.emit({ item, actionId: a.id })">{{ a.label }}</ui-button>
50020
+ }
50021
+ </div>
50022
+ }
50023
+ </div>
50024
+ </ui-alert>
50025
+ }
50026
+ </div>
50027
+ }
50028
+ `,
50029
+ isInline: true,
50030
+ styles: [":host{display:contents}.ra-stack{position:fixed;top:16px;right:16px;z-index:9990;display:flex;flex-direction:column;gap:8px;width:24rem;max-width:calc(100vw - 32px);pointer-events:none}.ra-item{pointer-events:auto;box-shadow:0 8px 20px #0f172a2e;border-radius:8px;animation:ra-in .3s ease-out}.ra-body{position:relative;display:flex;flex-direction:column;gap:2px;min-width:0;width:100%;padding-right:28px}.ra-hide{position:absolute;top:-4px;right:-4px}.ra-label{font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.02em}.ra-title{margin:0;font-size:.875rem;font-weight:600;overflow-wrap:anywhere}.ra-line{margin:0;font-size:.75rem;overflow-wrap:anywhere}.ra-badge{align-self:flex-start;max-width:100%;overflow:hidden}.ra-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}@keyframes ra-in{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@media(prefers-reduced-motion:reduce){.ra-item{animation:none}}\n"],
50031
+ dependencies: [
50032
+ {
50033
+ kind: "component",
50034
+ type: AlertComponent,
50035
+ selector: "ui-alert",
50036
+ inputs: [
50037
+ "variant",
50038
+ "title",
50039
+ "dismissible",
50040
+ "dismissAriaLabel",
50041
+ "quiet",
50042
+ "compact",
50043
+ "inline",
50044
+ "fill"
50045
+ ],
50046
+ outputs: ["dismissed"]
50047
+ },
50048
+ {
50049
+ kind: "component",
50050
+ type: BadgeComponent,
50051
+ selector: "ui-badge",
50052
+ inputs: ["label", "variant"]
50053
+ },
50054
+ {
50055
+ kind: "component",
50056
+ type: ButtonComponent,
50057
+ selector: "ui-button",
50058
+ inputs: [
50059
+ "variant",
50060
+ "routerLink",
50061
+ "queryParams",
50062
+ "fragment",
50063
+ "state",
50064
+ "href",
50065
+ "target",
50066
+ "rel",
50067
+ "shortLabel",
50068
+ "shortBelow",
50069
+ "color",
50070
+ "active",
50071
+ "size",
50072
+ "type",
50073
+ "disabled",
50074
+ "loading",
50075
+ "fullWidth",
50076
+ "ariaLabel",
50077
+ "ariaExpanded",
50078
+ "ariaPressed",
50079
+ "ariaDescribedBy",
50080
+ "modal-footer-left",
50081
+ "modal-footer-right"
50082
+ ]
50083
+ },
50084
+ {
50085
+ kind: "component",
50086
+ type: IconComponent,
50087
+ selector: "ui-icon",
50088
+ inputs: [
50089
+ "name",
50090
+ "tooltip",
50091
+ "ariaLabel",
50092
+ "size",
50093
+ "variant",
50094
+ "disabled",
50095
+ "loading",
50096
+ "interactive"
50097
+ ],
50098
+ outputs: ["iconClick"]
50099
+ }
50100
+ ],
50101
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
50102
+ });
50103
+ }
50104
+ };
50105
+ i0.ɵɵngDeclareClassMetadata({
50106
+ minVersion: "12.0.0",
50107
+ version: "22.2.2",
50108
+ ngImport: i0,
50109
+ type: ReminderAlertsComponent,
50110
+ decorators: [{
50111
+ type: Component,
50112
+ args: [{
50113
+ selector: "ui-reminder-alerts",
50114
+ standalone: true,
50115
+ changeDetection: ChangeDetectionStrategy.OnPush,
50116
+ imports: [
50117
+ AlertComponent,
50118
+ BadgeComponent,
50119
+ ButtonComponent,
50120
+ IconComponent
50121
+ ],
50122
+ template: `
50123
+ @if (items().length) {
50124
+ <div class="ra-stack" role="region" [attr.aria-label]="ariaLabel()" aria-live="polite">
50125
+ @for (item of items(); track item.id) {
50126
+ <ui-alert class="ra-item" [variant]="variant(item)" [attr.data-testid]="'reminder-alert-' + item.id">
50127
+ <div class="ra-body">
50128
+ <ui-button class="ra-hide" variant="icon" size="xs" [ariaLabel]="item.hideLabel || 'Hide alert'" [attr.data-testid]="item.hideTestId || 'alert-hide'" (click)="hidden.emit(item)">
50129
+ <ui-icon name="close" [size]="14" [interactive]="false" />
50130
+ </ui-button>
50131
+ <span class="ra-label">{{ item.label }}</span>
50132
+ <p class="ra-title">{{ item.title }}</p>
50133
+ @if (item.badge; as b) {
50134
+ <ui-badge class="ra-badge" role="img" variant="purple" [label]="b.label" [attr.aria-label]="b.ariaLabel || b.label" [attr.title]="b.ariaLabel || b.label" [attr.data-testid]="b.testId || 'alert-badge'" />
50135
+ }
50136
+ @for (line of item.lines ?? []; track $index) {
50137
+ <p class="ra-line">{{ line }}</p>
50138
+ }
50139
+ @if (item.actions?.length) {
50140
+ <div class="ra-actions">
50141
+ @for (a of item.actions; track a.id) {
50142
+ <ui-button [variant]="a.variant || 'secondary'" size="xs" [attr.data-testid]="'alert-' + a.id" (click)="action.emit({ item, actionId: a.id })">{{ a.label }}</ui-button>
50143
+ }
50144
+ </div>
50145
+ }
50146
+ </div>
50147
+ </ui-alert>
50148
+ }
50149
+ </div>
50150
+ }
50151
+ `,
50152
+ styles: [":host{display:contents}.ra-stack{position:fixed;top:16px;right:16px;z-index:9990;display:flex;flex-direction:column;gap:8px;width:24rem;max-width:calc(100vw - 32px);pointer-events:none}.ra-item{pointer-events:auto;box-shadow:0 8px 20px #0f172a2e;border-radius:8px;animation:ra-in .3s ease-out}.ra-body{position:relative;display:flex;flex-direction:column;gap:2px;min-width:0;width:100%;padding-right:28px}.ra-hide{position:absolute;top:-4px;right:-4px}.ra-label{font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.02em}.ra-title{margin:0;font-size:.875rem;font-weight:600;overflow-wrap:anywhere}.ra-line{margin:0;font-size:.75rem;overflow-wrap:anywhere}.ra-badge{align-self:flex-start;max-width:100%;overflow:hidden}.ra-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}@keyframes ra-in{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@media(prefers-reduced-motion:reduce){.ra-item{animation:none}}\n"]
50153
+ }]
50154
+ }],
50155
+ propDecorators: {
50156
+ items: [{
50157
+ type: i0.Input,
50158
+ args: [{
50159
+ isSignal: true,
50160
+ alias: "items",
50161
+ required: false
50162
+ }]
50163
+ }],
50164
+ ariaLabel: [{
50165
+ type: i0.Input,
50166
+ args: [{
50167
+ isSignal: true,
50168
+ alias: "ariaLabel",
50169
+ required: false
50170
+ }]
50171
+ }],
50172
+ action: [{
50173
+ type: i0.Output,
50174
+ args: ["action"]
50175
+ }],
50176
+ hidden: [{
50177
+ type: i0.Output,
50178
+ args: ["hidden"]
50179
+ }]
50180
+ }
50181
+ });
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 };
49170
52656
 
49171
52657
  //# sourceMappingURL=forgeroute-ui.mjs.map