@forgeroute/ui 0.4.60 → 0.4.62

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.
@@ -35243,6 +35243,13 @@ function sanitizeRichTextHtml(html, options = {}) {
35243
35243
  walkChildren(parsed.body, out, ctx);
35244
35244
  return out.innerHTML;
35245
35245
  }
35246
+ function normalizeLinkUrl(raw) {
35247
+ const text = (raw ?? "").trim();
35248
+ if (!text || /\s/.test(text)) return null;
35249
+ if (/^(https?:\/\/|mailto:|tel:)\S+$/i.test(text)) return text;
35250
+ if (/^[a-z][a-z0-9+.-]*:/i.test(text) || /^[\/\\]{2}/.test(text)) return null;
35251
+ return /^[^\s/@]+\.[^\s/@]+/.test(text) ? `https://${text}` : null;
35252
+ }
35246
35253
  function plainTextToHtml(text) {
35247
35254
  return text.replace(/\r\n?/g, "\n").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\n/g, "<br>");
35248
35255
  }
@@ -35251,6 +35258,7 @@ const RICH_TEXT_OPTIONS = [
35251
35258
  "italic",
35252
35259
  "underline",
35253
35260
  "strikethrough",
35261
+ "link",
35254
35262
  "heading",
35255
35263
  "fontSize",
35256
35264
  "fontFamily",
@@ -35270,7 +35278,8 @@ const GROUPS = [
35270
35278
  "bold",
35271
35279
  "italic",
35272
35280
  "underline",
35273
- "strikethrough"
35281
+ "strikethrough",
35282
+ "link"
35274
35283
  ]
35275
35284
  },
35276
35285
  {
@@ -35312,6 +35321,7 @@ const OPTION_TAGS = {
35312
35321
  "STRIKE",
35313
35322
  "DEL"
35314
35323
  ],
35324
+ link: ["A"],
35315
35325
  heading: [
35316
35326
  "H1",
35317
35327
  "H2",
@@ -35571,6 +35581,10 @@ var RichTextEditorComponent = class RichTextEditorComponent {
35571
35581
  this.activeFont = signal("Default", ...ngDevMode ? [{ debugName: "activeFont" }] : /* istanbul ignore next */ []);
35572
35582
  this.active = signal(Object.fromEntries(STATE_COMMANDS.map((c) => [c, false])), ...ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []);
35573
35583
  this.empty = signal(true, ...ngDevMode ? [{ debugName: "empty" }] : /* istanbul ignore next */ []);
35584
+ this.linkUrl = signal("", ...ngDevMode ? [{ debugName: "linkUrl" }] : /* istanbul ignore next */ []);
35585
+ this.linkError = signal("", ...ngDevMode ? [{ debugName: "linkError" }] : /* istanbul ignore next */ []);
35586
+ this.hasLink = signal(false, ...ngDevMode ? [{ debugName: "hasLink" }] : /* istanbul ignore next */ []);
35587
+ this._linkId = `rte-${++nextId$2}-link`;
35574
35588
  this.hidden = computed(() => new Set(this.hide()), ...ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []);
35575
35589
  this.groupVisible = computed(() => {
35576
35590
  const hidden = this.hidden();
@@ -35752,6 +35766,62 @@ var RichTextEditorComponent = class RichTextEditorComponent {
35752
35766
  this.openMenu.set(null);
35753
35767
  this.execWithArg("fontName", value);
35754
35768
  }
35769
+ _anchorAtSelection() {
35770
+ const el = this.editor()?.nativeElement;
35771
+ const sel = window.getSelection();
35772
+ const node = sel && sel.rangeCount > 0 && el?.contains(sel.anchorNode) ? sel.anchorNode : this._savedRange?.startContainer ?? null;
35773
+ const a = (node && node.nodeType === Node.TEXT_NODE ? node.parentElement : node)?.closest("a") ?? null;
35774
+ return a && el?.contains(a) ? a : null;
35775
+ }
35776
+ toggleLink() {
35777
+ if (this.openMenu() === "link") {
35778
+ this.openMenu.set(null);
35779
+ return;
35780
+ }
35781
+ this._saveSelection();
35782
+ const a = this._anchorAtSelection();
35783
+ this.hasLink.set(!!a);
35784
+ this.linkUrl.set(a?.getAttribute("href") ?? "");
35785
+ this.linkError.set("");
35786
+ this.openMenu.set("link");
35787
+ }
35788
+ closeLink() {
35789
+ this.openMenu.set(null);
35790
+ this._restoreSelection();
35791
+ }
35792
+ applyLink() {
35793
+ if (this.inert()) return;
35794
+ const url = normalizeLinkUrl(this.linkUrl());
35795
+ if (!url) {
35796
+ this.linkError.set("Enter a web address like example.com.");
35797
+ return;
35798
+ }
35799
+ this.openMenu.set(null);
35800
+ this._restoreSelection();
35801
+ const sel = window.getSelection();
35802
+ const existing = this._anchorAtSelection();
35803
+ if (existing) existing.setAttribute("href", url);
35804
+ else if (!sel || sel.isCollapsed) {
35805
+ const text = url.replace(/^(mailto:|tel:|https?:\/\/)/i, "");
35806
+ document.execCommand("insertHTML", false, `<a href="${url.replace(/&/g, "&amp;").replace(/"/g, "&quot;")}">${plainTextToHtml(text)}</a>`);
35807
+ } else document.execCommand("createLink", false, url);
35808
+ this.onInput();
35809
+ }
35810
+ removeLink() {
35811
+ if (this.inert()) return;
35812
+ this.openMenu.set(null);
35813
+ this._restoreSelection();
35814
+ const a = this._anchorAtSelection();
35815
+ if (a) {
35816
+ const range = document.createRange();
35817
+ range.selectNodeContents(a);
35818
+ const sel = window.getSelection();
35819
+ sel?.removeAllRanges();
35820
+ sel?.addRange(range);
35821
+ }
35822
+ document.execCommand("unlink", false);
35823
+ this.onInput();
35824
+ }
35755
35825
  exec(command) {
35756
35826
  if (this.inert()) return;
35757
35827
  this._restoreSelection();
@@ -35892,7 +35962,7 @@ var RichTextEditorComponent = class RichTextEditorComponent {
35892
35962
  @if (toolbarVisible()) {
35893
35963
  <div class="rte-toolbar" role="toolbar" aria-label="Text formatting" [attr.aria-controls]="_editorId"
35894
35964
  (mousedown)="onToolbarMouseDown($event)">
35895
- @if (show('bold') || show('italic') || show('underline') || show('strikethrough')) {
35965
+ @if (show('bold') || show('italic') || show('underline') || show('strikethrough') || show('link')) {
35896
35966
  @if (show('bold')) {
35897
35967
  <button type="button" class="rte-btn" data-option="bold" [class.active]="active()['bold']"
35898
35968
  [attr.aria-pressed]="active()['bold']" [disabled]="inert()"
@@ -35921,6 +35991,29 @@ var RichTextEditorComponent = class RichTextEditorComponent {
35921
35991
  <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="12" x2="20" y2="12"/><path d="M6 4h8a4 4 0 010 8H6"/><path d="M10 12v8"/></svg>
35922
35992
  </button>
35923
35993
  }
35994
+ @if (show('link')) {
35995
+ <span class="rte-menu-wrap" (click)="$event.stopPropagation()">
35996
+ <button type="button" class="rte-btn rte-menu-btn" data-option="link" [class.active]="openMenu() === 'link'"
35997
+ [disabled]="inert()" aria-label="Link" title="Link"
35998
+ aria-haspopup="dialog" [attr.aria-expanded]="openMenu() === 'link'" (click)="toggleLink()">
35999
+ <svg aria-hidden="true" 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.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"/></svg>
36000
+ </button>
36001
+ @if (openMenu() === 'link') {
36002
+ <div class="rte-dropdown rte-link-panel" role="dialog" aria-label="Link" (keydown.escape)="closeLink()">
36003
+ <label class="rte-link-label" [for]="_linkId">Web address</label>
36004
+ <input class="rte-link-input" type="url" inputmode="url" autocomplete="off" spellcheck="false" placeholder="example.com"
36005
+ [id]="_linkId" [value]="linkUrl()" [attr.aria-invalid]="linkError() ? 'true' : null"
36006
+ [attr.aria-describedby]="linkError() ? _linkId + '-error' : null"
36007
+ (input)="linkUrl.set($any($event.target).value); linkError.set('')" (keydown.enter)="$event.preventDefault(); applyLink()" />
36008
+ @if (linkError()) { <p class="rte-link-error" role="alert" [id]="_linkId + '-error'">{{ linkError() }}</p> }
36009
+ <div class="rte-link-actions">
36010
+ <button type="button" class="rte-link-btn rte-link-apply" data-testid="rte-link-apply" (click)="applyLink()">Apply</button>
36011
+ @if (hasLink()) { <button type="button" class="rte-link-btn" data-testid="rte-link-remove" (click)="removeLink()">Remove link</button> }
36012
+ </div>
36013
+ </div>
36014
+ }
36015
+ </span>
36016
+ }
35924
36017
  }
35925
36018
 
35926
36019
  @if (divider()['text']) { <div class="rte-divider" role="separator" aria-orientation="vertical"></div> }
@@ -36091,7 +36184,7 @@ var RichTextEditorComponent = class RichTextEditorComponent {
36091
36184
  </div>
36092
36185
  `,
36093
36186
  isInline: true,
36094
- styles: [":host{display:block}.rte-field{display:flex;flex-direction:column;gap:6px}.rte-label{font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.rte-required{color:#dc2626;margin-left:2px}.rte-hint-inline{font-size:.75rem;color:#94a3b8;font-weight:400;margin-left:4px}.rte-box{border:1px solid #7c8ba1;border-radius:8px;background:#fff;transition:border-color .15s,box-shadow .15s}.rte-box:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.rte-error .rte-box{border-color:#ef4444}.rte-error .rte-box:focus-within{box-shadow:0 0 0 3px #ef44441f}.rte-disabled .rte-box{opacity:.5;cursor:not-allowed}.rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:6px 8px;background:#f8fafc;border-bottom:1px solid #e2e8f0;border-radius:8px 8px 0 0}.rte-divider{width:1px;height:20px;background:#cbd5e1;margin:0 4px}.rte-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:none;border-radius:4px;background:none;color:#64748b;cursor:pointer;transition:background .15s,color .15s}.rte-btn svg{width:16px;height:16px}.rte-btn:hover:not(:disabled){background:#e2e8f0;color:#1e293b}.rte-btn:focus-visible,.rte-btn:focus-within{outline:2px solid #3b82f6;outline-offset:1px}.rte-btn.active{background:#dbeafe;color:#2563eb}.rte-btn:disabled,.rte-btn-disabled{cursor:not-allowed;opacity:.5}.rte-menu-wrap{position:relative;display:inline-flex}.rte-menu-btn{width:auto;padding:0 6px;gap:3px}.rte-menu-btn .rte-chevron{width:10px;height:10px;color:#64748b;flex-shrink:0}.rte-dropdown{position:absolute;top:calc(100% + 4px);left:0;z-index:100;background:#fff;border:1px solid #e2e8f0;border-radius:6px;box-shadow:0 4px 12px #0000001f;padding:4px;overflow-y:auto;max-height:260px}.rte-font-panel{min-width:180px}.rte-item{display:block;width:100%;text-align:left;padding:5px 10px;font-size:12px;color:#374151;border:none;background:none;border-radius:4px;cursor:pointer;white-space:nowrap}.rte-item:hover{background:#f1f5f9}.rte-item.selected{background:#dbeafe;color:#2563eb;font-weight:600}.rte-group-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:#94a3b8;padding:6px 10px 2px}.di-h1{font-size:18px;font-weight:700}.di-h2{font-size:15px;font-weight:600}.di-h3{font-size:13px;font-weight:600}.rte-color{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}.rte-editor{padding:12px;outline:none;overflow-y:auto;box-sizing:border-box;font-size:.875rem;line-height:1.6;color:#1e293b;background:#fff;border-radius:0 0 8px 8px;word-break:break-word}.rte-editor[data-empty=true]:before{content:attr(data-placeholder);color:#64748b;pointer-events:none;float:left;height:0}.rte-editor ul,.rte-editor ol{padding-left:1.5em;margin:.25em 0}.rte-editor li{margin:.15em 0}.rte-editor h1{font-size:1.75em;font-weight:700;margin:.5em 0 .25em}.rte-editor h2{font-size:1.4em;font-weight:600;margin:.5em 0 .25em}.rte-editor h3{font-size:1.15em;font-weight:600;margin:.5em 0 .25em}.rte-editor a{color:#2563eb;text-decoration:underline}.rte-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b}.rte-desc-error{color:#dc2626}@media(max-width:480px){.rte-editor{font-size:1rem}}@media(pointer:coarse),(max-width:480px){.rte-btn{width:44px;height:44px}.rte-menu-btn{width:auto;min-width:44px}.rte-divider{height:28px}}\n"],
36187
+ styles: [":host{display:block}.rte-field{display:flex;flex-direction:column;gap:6px}.rte-label{font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.rte-required{color:#dc2626;margin-left:2px}.rte-hint-inline{font-size:.75rem;color:#94a3b8;font-weight:400;margin-left:4px}.rte-box{border:1px solid #7c8ba1;border-radius:8px;background:#fff;transition:border-color .15s,box-shadow .15s}.rte-box:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.rte-error .rte-box{border-color:#ef4444}.rte-error .rte-box:focus-within{box-shadow:0 0 0 3px #ef44441f}.rte-disabled .rte-box{opacity:.5;cursor:not-allowed}.rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:6px 8px;background:#f8fafc;border-bottom:1px solid #e2e8f0;border-radius:8px 8px 0 0}.rte-divider{width:1px;height:20px;background:#cbd5e1;margin:0 4px}.rte-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:none;border-radius:4px;background:none;color:#64748b;cursor:pointer;transition:background .15s,color .15s}.rte-btn svg{width:16px;height:16px}.rte-btn:hover:not(:disabled){background:#e2e8f0;color:#1e293b}.rte-btn:focus-visible,.rte-btn:focus-within{outline:2px solid #3b82f6;outline-offset:1px}.rte-btn.active{background:#dbeafe;color:#2563eb}.rte-btn:disabled,.rte-btn-disabled{cursor:not-allowed;opacity:.5}.rte-menu-wrap{position:relative;display:inline-flex}.rte-menu-btn{width:auto;padding:0 6px;gap:3px}.rte-menu-btn .rte-chevron{width:10px;height:10px;color:#64748b;flex-shrink:0}.rte-dropdown{position:absolute;top:calc(100% + 4px);left:0;z-index:100;background:#fff;border:1px solid #e2e8f0;border-radius:6px;box-shadow:0 4px 12px #0000001f;padding:4px;overflow-y:auto;max-height:260px}.rte-font-panel{min-width:180px}.rte-link-panel{display:flex;flex-direction:column;gap:6px;min-width:240px;padding:10px;overflow:visible}.rte-link-label{font-size:12px;font-weight:600;color:#374151}.rte-link-input{box-sizing:border-box;width:100%;padding:6px 8px;font:inherit;font-size:14px;border:1px solid #cbd5e1;border-radius:6px}.rte-link-input:focus-visible{outline:2px solid #2563eb;outline-offset:1px}.rte-link-error{margin:0;font-size:12px;color:#dc2626}.rte-link-actions{display:flex;gap:6px}.rte-link-btn{padding:5px 10px;font-size:12px;border:1px solid #cbd5e1;border-radius:6px;background:#fff;color:#374151;cursor:pointer}.rte-link-apply{background:#2563eb;border-color:#2563eb;color:#fff}.rte-item{display:block;width:100%;text-align:left;padding:5px 10px;font-size:12px;color:#374151;border:none;background:none;border-radius:4px;cursor:pointer;white-space:nowrap}.rte-item:hover{background:#f1f5f9}.rte-item.selected{background:#dbeafe;color:#2563eb;font-weight:600}.rte-group-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:#94a3b8;padding:6px 10px 2px}.di-h1{font-size:18px;font-weight:700}.di-h2{font-size:15px;font-weight:600}.di-h3{font-size:13px;font-weight:600}.rte-color{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}.rte-editor{padding:12px;outline:none;overflow-y:auto;box-sizing:border-box;font-size:.875rem;line-height:1.6;color:#1e293b;background:#fff;border-radius:0 0 8px 8px;word-break:break-word}.rte-editor[data-empty=true]:before{content:attr(data-placeholder);color:#64748b;pointer-events:none;float:left;height:0}.rte-editor ul,.rte-editor ol{padding-left:1.5em;margin:.25em 0}.rte-editor li{margin:.15em 0}.rte-editor h1{font-size:1.75em;font-weight:700;margin:.5em 0 .25em}.rte-editor h2{font-size:1.4em;font-weight:600;margin:.5em 0 .25em}.rte-editor h3{font-size:1.15em;font-weight:600;margin:.5em 0 .25em}.rte-editor a{color:#2563eb;text-decoration:underline}.rte-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b}.rte-desc-error{color:#dc2626}@media(max-width:480px){.rte-editor{font-size:1rem}}@media(pointer:coarse),(max-width:480px){.rte-btn{width:44px;height:44px}.rte-menu-btn{width:auto;min-width:44px}.rte-divider{height:28px}}\n"],
36095
36188
  changeDetection: i0.ChangeDetectionStrategy.OnPush
36096
36189
  });
36097
36190
  }
@@ -36130,7 +36223,7 @@ i0.ɵɵngDeclareClassMetadata({
36130
36223
  @if (toolbarVisible()) {
36131
36224
  <div class="rte-toolbar" role="toolbar" aria-label="Text formatting" [attr.aria-controls]="_editorId"
36132
36225
  (mousedown)="onToolbarMouseDown($event)">
36133
- @if (show('bold') || show('italic') || show('underline') || show('strikethrough')) {
36226
+ @if (show('bold') || show('italic') || show('underline') || show('strikethrough') || show('link')) {
36134
36227
  @if (show('bold')) {
36135
36228
  <button type="button" class="rte-btn" data-option="bold" [class.active]="active()['bold']"
36136
36229
  [attr.aria-pressed]="active()['bold']" [disabled]="inert()"
@@ -36159,6 +36252,29 @@ i0.ɵɵngDeclareClassMetadata({
36159
36252
  <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="12" x2="20" y2="12"/><path d="M6 4h8a4 4 0 010 8H6"/><path d="M10 12v8"/></svg>
36160
36253
  </button>
36161
36254
  }
36255
+ @if (show('link')) {
36256
+ <span class="rte-menu-wrap" (click)="$event.stopPropagation()">
36257
+ <button type="button" class="rte-btn rte-menu-btn" data-option="link" [class.active]="openMenu() === 'link'"
36258
+ [disabled]="inert()" aria-label="Link" title="Link"
36259
+ aria-haspopup="dialog" [attr.aria-expanded]="openMenu() === 'link'" (click)="toggleLink()">
36260
+ <svg aria-hidden="true" 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.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71"/></svg>
36261
+ </button>
36262
+ @if (openMenu() === 'link') {
36263
+ <div class="rte-dropdown rte-link-panel" role="dialog" aria-label="Link" (keydown.escape)="closeLink()">
36264
+ <label class="rte-link-label" [for]="_linkId">Web address</label>
36265
+ <input class="rte-link-input" type="url" inputmode="url" autocomplete="off" spellcheck="false" placeholder="example.com"
36266
+ [id]="_linkId" [value]="linkUrl()" [attr.aria-invalid]="linkError() ? 'true' : null"
36267
+ [attr.aria-describedby]="linkError() ? _linkId + '-error' : null"
36268
+ (input)="linkUrl.set($any($event.target).value); linkError.set('')" (keydown.enter)="$event.preventDefault(); applyLink()" />
36269
+ @if (linkError()) { <p class="rte-link-error" role="alert" [id]="_linkId + '-error'">{{ linkError() }}</p> }
36270
+ <div class="rte-link-actions">
36271
+ <button type="button" class="rte-link-btn rte-link-apply" data-testid="rte-link-apply" (click)="applyLink()">Apply</button>
36272
+ @if (hasLink()) { <button type="button" class="rte-link-btn" data-testid="rte-link-remove" (click)="removeLink()">Remove link</button> }
36273
+ </div>
36274
+ </div>
36275
+ }
36276
+ </span>
36277
+ }
36162
36278
  }
36163
36279
 
36164
36280
  @if (divider()['text']) { <div class="rte-divider" role="separator" aria-orientation="vertical"></div> }
@@ -36328,7 +36444,7 @@ i0.ɵɵngDeclareClassMetadata({
36328
36444
  }
36329
36445
  </div>
36330
36446
  `,
36331
- styles: [":host{display:block}.rte-field{display:flex;flex-direction:column;gap:6px}.rte-label{font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.rte-required{color:#dc2626;margin-left:2px}.rte-hint-inline{font-size:.75rem;color:#94a3b8;font-weight:400;margin-left:4px}.rte-box{border:1px solid #7c8ba1;border-radius:8px;background:#fff;transition:border-color .15s,box-shadow .15s}.rte-box:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.rte-error .rte-box{border-color:#ef4444}.rte-error .rte-box:focus-within{box-shadow:0 0 0 3px #ef44441f}.rte-disabled .rte-box{opacity:.5;cursor:not-allowed}.rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:6px 8px;background:#f8fafc;border-bottom:1px solid #e2e8f0;border-radius:8px 8px 0 0}.rte-divider{width:1px;height:20px;background:#cbd5e1;margin:0 4px}.rte-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:none;border-radius:4px;background:none;color:#64748b;cursor:pointer;transition:background .15s,color .15s}.rte-btn svg{width:16px;height:16px}.rte-btn:hover:not(:disabled){background:#e2e8f0;color:#1e293b}.rte-btn:focus-visible,.rte-btn:focus-within{outline:2px solid #3b82f6;outline-offset:1px}.rte-btn.active{background:#dbeafe;color:#2563eb}.rte-btn:disabled,.rte-btn-disabled{cursor:not-allowed;opacity:.5}.rte-menu-wrap{position:relative;display:inline-flex}.rte-menu-btn{width:auto;padding:0 6px;gap:3px}.rte-menu-btn .rte-chevron{width:10px;height:10px;color:#64748b;flex-shrink:0}.rte-dropdown{position:absolute;top:calc(100% + 4px);left:0;z-index:100;background:#fff;border:1px solid #e2e8f0;border-radius:6px;box-shadow:0 4px 12px #0000001f;padding:4px;overflow-y:auto;max-height:260px}.rte-font-panel{min-width:180px}.rte-item{display:block;width:100%;text-align:left;padding:5px 10px;font-size:12px;color:#374151;border:none;background:none;border-radius:4px;cursor:pointer;white-space:nowrap}.rte-item:hover{background:#f1f5f9}.rte-item.selected{background:#dbeafe;color:#2563eb;font-weight:600}.rte-group-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:#94a3b8;padding:6px 10px 2px}.di-h1{font-size:18px;font-weight:700}.di-h2{font-size:15px;font-weight:600}.di-h3{font-size:13px;font-weight:600}.rte-color{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}.rte-editor{padding:12px;outline:none;overflow-y:auto;box-sizing:border-box;font-size:.875rem;line-height:1.6;color:#1e293b;background:#fff;border-radius:0 0 8px 8px;word-break:break-word}.rte-editor[data-empty=true]:before{content:attr(data-placeholder);color:#64748b;pointer-events:none;float:left;height:0}.rte-editor ul,.rte-editor ol{padding-left:1.5em;margin:.25em 0}.rte-editor li{margin:.15em 0}.rte-editor h1{font-size:1.75em;font-weight:700;margin:.5em 0 .25em}.rte-editor h2{font-size:1.4em;font-weight:600;margin:.5em 0 .25em}.rte-editor h3{font-size:1.15em;font-weight:600;margin:.5em 0 .25em}.rte-editor a{color:#2563eb;text-decoration:underline}.rte-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b}.rte-desc-error{color:#dc2626}@media(max-width:480px){.rte-editor{font-size:1rem}}@media(pointer:coarse),(max-width:480px){.rte-btn{width:44px;height:44px}.rte-menu-btn{width:auto;min-width:44px}.rte-divider{height:28px}}\n"]
36447
+ styles: [":host{display:block}.rte-field{display:flex;flex-direction:column;gap:6px}.rte-label{font-size:.8125rem;font-weight:600;color:#374151;line-height:1}.rte-required{color:#dc2626;margin-left:2px}.rte-hint-inline{font-size:.75rem;color:#94a3b8;font-weight:400;margin-left:4px}.rte-box{border:1px solid #7c8ba1;border-radius:8px;background:#fff;transition:border-color .15s,box-shadow .15s}.rte-box:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61f}.rte-error .rte-box{border-color:#ef4444}.rte-error .rte-box:focus-within{box-shadow:0 0 0 3px #ef44441f}.rte-disabled .rte-box{opacity:.5;cursor:not-allowed}.rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:6px 8px;background:#f8fafc;border-bottom:1px solid #e2e8f0;border-radius:8px 8px 0 0}.rte-divider{width:1px;height:20px;background:#cbd5e1;margin:0 4px}.rte-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:none;border-radius:4px;background:none;color:#64748b;cursor:pointer;transition:background .15s,color .15s}.rte-btn svg{width:16px;height:16px}.rte-btn:hover:not(:disabled){background:#e2e8f0;color:#1e293b}.rte-btn:focus-visible,.rte-btn:focus-within{outline:2px solid #3b82f6;outline-offset:1px}.rte-btn.active{background:#dbeafe;color:#2563eb}.rte-btn:disabled,.rte-btn-disabled{cursor:not-allowed;opacity:.5}.rte-menu-wrap{position:relative;display:inline-flex}.rte-menu-btn{width:auto;padding:0 6px;gap:3px}.rte-menu-btn .rte-chevron{width:10px;height:10px;color:#64748b;flex-shrink:0}.rte-dropdown{position:absolute;top:calc(100% + 4px);left:0;z-index:100;background:#fff;border:1px solid #e2e8f0;border-radius:6px;box-shadow:0 4px 12px #0000001f;padding:4px;overflow-y:auto;max-height:260px}.rte-font-panel{min-width:180px}.rte-link-panel{display:flex;flex-direction:column;gap:6px;min-width:240px;padding:10px;overflow:visible}.rte-link-label{font-size:12px;font-weight:600;color:#374151}.rte-link-input{box-sizing:border-box;width:100%;padding:6px 8px;font:inherit;font-size:14px;border:1px solid #cbd5e1;border-radius:6px}.rte-link-input:focus-visible{outline:2px solid #2563eb;outline-offset:1px}.rte-link-error{margin:0;font-size:12px;color:#dc2626}.rte-link-actions{display:flex;gap:6px}.rte-link-btn{padding:5px 10px;font-size:12px;border:1px solid #cbd5e1;border-radius:6px;background:#fff;color:#374151;cursor:pointer}.rte-link-apply{background:#2563eb;border-color:#2563eb;color:#fff}.rte-item{display:block;width:100%;text-align:left;padding:5px 10px;font-size:12px;color:#374151;border:none;background:none;border-radius:4px;cursor:pointer;white-space:nowrap}.rte-item:hover{background:#f1f5f9}.rte-item.selected{background:#dbeafe;color:#2563eb;font-weight:600}.rte-group-label{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:#94a3b8;padding:6px 10px 2px}.di-h1{font-size:18px;font-weight:700}.di-h2{font-size:15px;font-weight:600}.di-h3{font-size:13px;font-weight:600}.rte-color{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none}.rte-editor{padding:12px;outline:none;overflow-y:auto;box-sizing:border-box;font-size:.875rem;line-height:1.6;color:#1e293b;background:#fff;border-radius:0 0 8px 8px;word-break:break-word}.rte-editor[data-empty=true]:before{content:attr(data-placeholder);color:#64748b;pointer-events:none;float:left;height:0}.rte-editor ul,.rte-editor ol{padding-left:1.5em;margin:.25em 0}.rte-editor li{margin:.15em 0}.rte-editor h1{font-size:1.75em;font-weight:700;margin:.5em 0 .25em}.rte-editor h2{font-size:1.4em;font-weight:600;margin:.5em 0 .25em}.rte-editor h3{font-size:1.15em;font-weight:600;margin:.5em 0 .25em}.rte-editor a{color:#2563eb;text-decoration:underline}.rte-desc{margin:0;font-size:.75rem;line-height:1.4;color:#64748b}.rte-desc-error{color:#dc2626}@media(max-width:480px){.rte-editor{font-size:1rem}}@media(pointer:coarse),(max-width:480px){.rte-btn{width:44px;height:44px}.rte-menu-btn{width:auto;min-width:44px}.rte-divider{height:28px}}\n"]
36332
36448
  }]
36333
36449
  }],
36334
36450
  ctorParameters: () => [],
@@ -50274,6 +50390,115 @@ function conversationMessageStatusMark(status) {
50274
50390
  if (status === "sent") return "✓";
50275
50391
  return conversationMessageStatusLabel(status);
50276
50392
  }
50393
+ function conversationHtmlToText(html) {
50394
+ if (!html) return "";
50395
+ const doc = new DOMParser().parseFromString(`<body>${html}</body>`, "text/html");
50396
+ const out = [];
50397
+ const walk = (node) => {
50398
+ node.childNodes.forEach((child) => {
50399
+ if (child.nodeType === Node.TEXT_NODE) {
50400
+ out.push(child.nodeValue ?? "");
50401
+ return;
50402
+ }
50403
+ if (child.nodeType !== Node.ELEMENT_NODE) return;
50404
+ const el = child;
50405
+ if (el.tagName === "BR") {
50406
+ out.push("\n");
50407
+ return;
50408
+ }
50409
+ if (/^(SCRIPT|STYLE|NOSCRIPT|TEMPLATE)$/.test(el.tagName)) return;
50410
+ const block = /^(P|DIV|LI|UL|OL|BLOCKQUOTE|H[1-6])$/.test(el.tagName);
50411
+ if (block && out.length && !/\n$/.test(out[out.length - 1])) out.push("\n");
50412
+ walk(el);
50413
+ if (block && !/\n$/.test(out[out.length - 1] ?? "")) out.push("\n");
50414
+ });
50415
+ };
50416
+ walk(doc.body);
50417
+ return out.join("").replace(/\u00a0/g, " ").replace(/\n{3,}/g, "\n\n").trim();
50418
+ }
50419
+ var ConversationRichBodyComponent = class ConversationRichBodyComponent {
50420
+ constructor() {
50421
+ this.html = input("", ...ngDevMode ? [{ debugName: "html" }] : /* istanbul ignore next */ []);
50422
+ this.safe = computed(() => sanitizeRichTextHtml(this.html(), { mode: "paste" }), ...ngDevMode ? [{ debugName: "safe" }] : /* istanbul ignore next */ []);
50423
+ }
50424
+ static {
50425
+ this.ɵfac = i0.ɵɵngDeclareFactory({
50426
+ minVersion: "12.0.0",
50427
+ version: "22.2.2",
50428
+ ngImport: i0,
50429
+ type: ConversationRichBodyComponent,
50430
+ deps: [],
50431
+ target: i0.ɵɵFactoryTarget.Component
50432
+ });
50433
+ }
50434
+ static {
50435
+ this.ɵcmp = i0.ɵɵngDeclareComponent({
50436
+ minVersion: "17.1.0",
50437
+ version: "22.2.2",
50438
+ type: ConversationRichBodyComponent,
50439
+ isStandalone: true,
50440
+ selector: "ui-conversation-rich-body",
50441
+ inputs: { html: {
50442
+ classPropertyName: "html",
50443
+ publicName: "html",
50444
+ isSignal: true,
50445
+ isRequired: false,
50446
+ transformFunction: null
50447
+ } },
50448
+ host: {
50449
+ properties: { "innerHTML": "safe()" },
50450
+ classAttribute: "cv-rich"
50451
+ },
50452
+ ngImport: i0,
50453
+ template: "",
50454
+ isInline: true,
50455
+ styles: [".cv-rich{display:block;font-size:.875rem;line-height:1.45;word-break:break-word}.cv-rich p,.cv-rich div{margin:0}.cv-rich ul,.cv-rich ol{margin:0;padding-inline-start:1.25rem}.cv-rich a{color:inherit;text-decoration:underline;text-underline-offset:2px}.cv-rich strong,.cv-rich b{font-weight:700}.cv-rich blockquote{margin:4px 0;padding-inline-start:10px;border-inline-start:3px solid currentColor;opacity:.9}.cv-rich h1,.cv-rich h2,.cv-rich h3,.cv-rich h4{margin:0;font-size:1rem;font-weight:700;line-height:1.35}.cv-rich hr{border:0;border-top:1px solid currentColor;opacity:.4;margin:6px 0}\n"],
50456
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
50457
+ encapsulation: i0.ViewEncapsulation.None
50458
+ });
50459
+ }
50460
+ };
50461
+ i0.ɵɵngDeclareClassMetadata({
50462
+ minVersion: "12.0.0",
50463
+ version: "22.2.2",
50464
+ ngImport: i0,
50465
+ type: ConversationRichBodyComponent,
50466
+ decorators: [{
50467
+ type: Component,
50468
+ args: [{
50469
+ selector: "ui-conversation-rich-body",
50470
+ standalone: true,
50471
+ changeDetection: ChangeDetectionStrategy.OnPush,
50472
+ encapsulation: ViewEncapsulation.None,
50473
+ host: {
50474
+ class: "cv-rich",
50475
+ "[innerHTML]": "safe()"
50476
+ },
50477
+ template: "",
50478
+ styles: [".cv-rich{display:block;font-size:.875rem;line-height:1.45;word-break:break-word}.cv-rich p,.cv-rich div{margin:0}.cv-rich ul,.cv-rich ol{margin:0;padding-inline-start:1.25rem}.cv-rich a{color:inherit;text-decoration:underline;text-underline-offset:2px}.cv-rich strong,.cv-rich b{font-weight:700}.cv-rich blockquote{margin:4px 0;padding-inline-start:10px;border-inline-start:3px solid currentColor;opacity:.9}.cv-rich h1,.cv-rich h2,.cv-rich h3,.cv-rich h4{margin:0;font-size:1rem;font-weight:700;line-height:1.35}.cv-rich hr{border:0;border-top:1px solid currentColor;opacity:.4;margin:6px 0}\n"]
50479
+ }]
50480
+ }],
50481
+ propDecorators: { html: [{
50482
+ type: i0.Input,
50483
+ args: [{
50484
+ isSignal: true,
50485
+ alias: "html",
50486
+ required: false
50487
+ }]
50488
+ }] }
50489
+ });
50490
+ const RICH_COMPOSER_HIDE = [
50491
+ "strikethrough",
50492
+ "heading",
50493
+ "fontSize",
50494
+ "fontFamily",
50495
+ "textColor",
50496
+ "highlight",
50497
+ "align",
50498
+ "indent",
50499
+ "outdent",
50500
+ "clearFormat"
50501
+ ];
50277
50502
  const SINGLE_COLUMN_QUERY = "(max-width: 768px)";
50278
50503
  const NEAR_BOTTOM_PX = 120;
50279
50504
  const PREVIEW_LENGTH = 60;
@@ -50308,6 +50533,7 @@ var ConversationsComponent = class ConversationsComponent {
50308
50533
  this.allowNew = input(true, ...ngDevMode ? [{ debugName: "allowNew" }] : /* istanbul ignore next */ []);
50309
50534
  this.allowDelete = input(true, ...ngDevMode ? [{ debugName: "allowDelete" }] : /* istanbul ignore next */ []);
50310
50535
  this.showRowArrow = input(false, ...ngDevMode ? [{ debugName: "showRowArrow" }] : /* istanbul ignore next */ []);
50536
+ this.selectable = input(true, ...ngDevMode ? [{ debugName: "selectable" }] : /* istanbul ignore next */ []);
50311
50537
  this.newLabel = input("Start new message", ...ngDevMode ? [{ debugName: "newLabel" }] : /* istanbul ignore next */ []);
50312
50538
  this.newTooltip = input("New message", ...ngDevMode ? [{ debugName: "newTooltip" }] : /* istanbul ignore next */ []);
50313
50539
  this.deleteRowLabel = input("Delete conversation with", ...ngDevMode ? [{ debugName: "deleteRowLabel" }] : /* istanbul ignore next */ []);
@@ -50349,6 +50575,7 @@ var ConversationsComponent = class ConversationsComponent {
50349
50575
  this.composerStatus = input("", ...ngDevMode ? [{ debugName: "composerStatus" }] : /* istanbul ignore next */ []);
50350
50576
  this.composerError = input("", ...ngDevMode ? [{ debugName: "composerError" }] : /* istanbul ignore next */ []);
50351
50577
  this.maxLength = input(1600, ...ngDevMode ? [{ debugName: "maxLength" }] : /* istanbul ignore next */ []);
50578
+ this.richText = input(false, ...ngDevMode ? [{ debugName: "richText" }] : /* istanbul ignore next */ []);
50352
50579
  this.attachment = input(null, ...ngDevMode ? [{ debugName: "attachment" }] : /* istanbul ignore next */ []);
50353
50580
  this.uploading = input(false, ...ngDevMode ? [{ debugName: "uploading" }] : /* istanbul ignore next */ []);
50354
50581
  this.attachEnabled = input(true, ...ngDevMode ? [{ debugName: "attachEnabled" }] : /* istanbul ignore next */ []);
@@ -50409,7 +50636,16 @@ var ConversationsComponent = class ConversationsComponent {
50409
50636
  this.emptyText = computed(() => this.filtering() ? this.filteredEmptyMessage() : this.canWrite() ? this.emptyMessage() : this.emptyReadOnlyMessage(), ...ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []);
50410
50637
  this.messageRows = computed(() => groupMessagesByDay(this.messages(), this.clock()), ...ngDevMode ? [{ debugName: "messageRows" }] : /* istanbul ignore next */ []);
50411
50638
  this.contextVisible = computed(() => this.hasContext() && this.contextOpen() && !!this.selected(), ...ngDevMode ? [{ debugName: "contextVisible" }] : /* istanbul ignore next */ []);
50412
- this.canSend = computed(() => !this.composerDisabled() && !this.sendBlocked() && !this.sending() && (this.draft().trim().length > 0 || !!this.attachment()), ...ngDevMode ? [{ debugName: "canSend" }] : /* istanbul ignore next */ []);
50639
+ this.canSend = computed(() => !this.composerDisabled() && !this.sendBlocked() && !this.sending() && (this.draft().trim().length > 0 || !!this.attachment()) && this.draft().trim().length <= this.maxLength(), ...ngDevMode ? [{ debugName: "canSend" }] : /* istanbul ignore next */ []);
50640
+ this.editorHtml = signal("", ...ngDevMode ? [{ debugName: "editorHtml" }] : /* istanbul ignore next */ []);
50641
+ this.richHide = RICH_COMPOSER_HIDE;
50642
+ effect(() => {
50643
+ const text = this.draft();
50644
+ if (!this.richText()) return;
50645
+ untracked(() => {
50646
+ if (text !== conversationHtmlToText(this.editorHtml())) this.editorHtml.set(plainTextToHtml(text));
50647
+ });
50648
+ });
50413
50649
  effect(() => {
50414
50650
  const id = this.selected()?.id ?? null;
50415
50651
  const count = this.messages().length;
@@ -50465,14 +50701,22 @@ var ConversationsComponent = class ConversationsComponent {
50465
50701
  this.fileInput()?.open();
50466
50702
  }
50467
50703
  onComposeKeydown(event) {
50468
- if (event.key === "Enter" && !event.shiftKey && !event.isComposing) {
50704
+ if (event.key !== "Enter" || event.isComposing) return;
50705
+ if (this.richText() ? event.ctrlKey || event.metaKey : !event.shiftKey) {
50469
50706
  event.preventDefault();
50470
50707
  this.sendMessage();
50471
50708
  }
50472
50709
  }
50710
+ onEditorChange(html) {
50711
+ this.editorHtml.set(html);
50712
+ this.draft.set(conversationHtmlToText(html));
50713
+ }
50473
50714
  sendMessage() {
50474
50715
  if (!this.canSend()) return;
50475
- this.send.emit({ text: this.draft().trim() });
50716
+ this.send.emit(this.richText() ? {
50717
+ text: this.draft().trim(),
50718
+ html: sanitizeRichTextHtml(this.editorHtml(), { mode: "paste" })
50719
+ } : { text: this.draft().trim() });
50476
50720
  }
50477
50721
  clock() {
50478
50722
  return this.now() ?? /* @__PURE__ */ new Date();
@@ -50700,6 +50944,13 @@ var ConversationsComponent = class ConversationsComponent {
50700
50944
  isRequired: false,
50701
50945
  transformFunction: null
50702
50946
  },
50947
+ selectable: {
50948
+ classPropertyName: "selectable",
50949
+ publicName: "selectable",
50950
+ isSignal: true,
50951
+ isRequired: false,
50952
+ transformFunction: null
50953
+ },
50703
50954
  newLabel: {
50704
50955
  classPropertyName: "newLabel",
50705
50956
  publicName: "newLabel",
@@ -50987,6 +51238,13 @@ var ConversationsComponent = class ConversationsComponent {
50987
51238
  isRequired: false,
50988
51239
  transformFunction: null
50989
51240
  },
51241
+ richText: {
51242
+ classPropertyName: "richText",
51243
+ publicName: "richText",
51244
+ isSignal: true,
51245
+ isRequired: false,
51246
+ transformFunction: null
51247
+ },
50990
51248
  attachment: {
50991
51249
  classPropertyName: "attachment",
50992
51250
  publicName: "attachment",
@@ -51192,7 +51450,7 @@ var ConversationsComponent = class ConversationsComponent {
51192
51450
  <ui-empty-state iconType="message" data-testid="conv-empty" [title]="filtering() ? filteredEmptyTitle() : emptyTitle()" [message]="emptyText()" />
51193
51451
  } @else {
51194
51452
  <div class="cv-list">
51195
- <ui-list [ariaLabel]="listAriaLabel()" [items]="conversations()" [trackBy]="trackConversation" [navigable]="true" [arrow]="false" (itemClick)="onRowOpen($event)">
51453
+ <ui-list [ariaLabel]="listAriaLabel()" [items]="conversations()" [trackBy]="trackConversation" [navigable]="selectable()" [arrow]="false" (itemClick)="onRowOpen($event)">
51196
51454
  <ng-template let-conv>
51197
51455
  <div class="cv-item" data-testid="conv-item" [attr.data-conversation-id]="conv.id"
51198
51456
  [class.selected]="selected()?.id === conv.id" [class.unread]="(conv.unreadCount ?? 0) > 0">
@@ -51234,9 +51492,11 @@ var ConversationsComponent = class ConversationsComponent {
51234
51492
  <section class="cv-thread-panel" [class.cv-hidden-mobile]="!selected()" [attr.aria-label]="threadAriaLabel()">
51235
51493
  @if (selected(); as conv) {
51236
51494
  <div class="cv-thread-header">
51237
- <ui-button class="cv-back-btn" variant="secondary" size="sm" [ariaLabel]="backLabel()" (click)="onBack()" data-testid="back-to-list">
51238
- <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>
51239
- </ui-button>
51495
+ @if (selectable()) {
51496
+ <ui-button class="cv-back-btn" variant="secondary" size="sm" [ariaLabel]="backLabel()" (click)="onBack()" data-testid="back-to-list">
51497
+ <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>
51498
+ </ui-button>
51499
+ }
51240
51500
  <div class="cv-thread-header-info">
51241
51501
  <ui-avatar [initials]="initial(conv.name)" [name]="conv.name" [size]="40" />
51242
51502
  <div class="cv-thread-header-text">
@@ -51314,7 +51574,8 @@ var ConversationsComponent = class ConversationsComponent {
51314
51574
  }
51315
51575
  </div>
51316
51576
  }
51317
- @if (row.message.body) { <p class="cv-body">{{ row.message.body }}</p> }
51577
+ @if (row.message.bodyHtml) { <ui-conversation-rich-body [html]="row.message.bodyHtml" data-testid="msg-rich-body" /> }
51578
+ @else if (row.message.body) { <p class="cv-body">{{ row.message.body }}</p> }
51318
51579
  <span class="cv-meta">
51319
51580
  @if (row.message.direction === 'outbound' && row.message.sender) { <span class="cv-sender" data-testid="msg-sender">{{ row.message.sender }}</span> }
51320
51581
  {{ time(row.message) }}
@@ -51355,9 +51616,15 @@ var ConversationsComponent = class ConversationsComponent {
51355
51616
  <ui-file-input [showField]="false" [accept]="acceptedFiles()" [maxSize]="maxFileSize()" [toastOnReject]="true"
51356
51617
  [typeMessage]="typeMessage()" [sizeMessage]="sizeMessage()" (filesSelected)="filesSelected.emit($event)" data-testid="attach-input" />
51357
51618
  }
51358
- <ui-textarea-input class="cv-compose-input" [ariaLabel]="composeLabel()" [placeholder]="composePlaceholder()" [rows]="1" [maxlength]="maxLength()"
51359
- [ngModel]="draft()" (ngModelChange)="draft.set($event)" [disabled]="composerDisabled()" [error]="composerError()"
51360
- (keydown)="onComposeKeydown($event)" data-testid="compose-input" />
51619
+ @if (richText()) {
51620
+ <ui-rich-text-editor class="cv-compose-input cv-compose-rich" [ariaLabel]="composeLabel()" [placeholder]="composePlaceholder()" [hide]="richHide"
51621
+ [minHeight]="44" [maxHeight]="160" [ngModel]="editorHtml()" (ngModelChange)="onEditorChange($event)" [disabled]="composerDisabled()" [error]="composerError()"
51622
+ (keydown)="onComposeKeydown($event)" data-testid="compose-input" />
51623
+ } @else {
51624
+ <ui-textarea-input class="cv-compose-input" [ariaLabel]="composeLabel()" [placeholder]="composePlaceholder()" [rows]="1" [maxlength]="maxLength()"
51625
+ [ngModel]="draft()" (ngModelChange)="draft.set($event)" [disabled]="composerDisabled()" [error]="composerError()"
51626
+ (keydown)="onComposeKeydown($event)" data-testid="compose-input" />
51627
+ }
51361
51628
  <ui-button class="cv-send-btn" variant="primary" [ariaLabel]="sendLabel()" [disabled]="!canSend()" [loading]="sending()" (click)="sendMessage()" data-testid="send-btn">
51362
51629
  <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>
51363
51630
  </ui-button>
@@ -51389,7 +51656,7 @@ var ConversationsComponent = class ConversationsComponent {
51389
51656
  </div>
51390
51657
  `,
51391
51658
  isInline: true,
51392
- 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-row-arrow{flex:0 0 auto;align-self:center;color:#94a3b8}.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"],
51659
+ 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-row-arrow{flex:0 0 auto;align-self:center;color:#94a3b8}.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,.cv-bubble.inbound .cv-rich{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-rich,.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"],
51393
51660
  dependencies: [
51394
51661
  {
51395
51662
  kind: "ngmodule",
@@ -51594,6 +51861,24 @@ var ConversationsComponent = class ConversationsComponent {
51594
51861
  ],
51595
51862
  outputs: ["tabChange"]
51596
51863
  },
51864
+ {
51865
+ kind: "component",
51866
+ type: RichTextEditorComponent,
51867
+ selector: "ui-rich-text-editor",
51868
+ inputs: [
51869
+ "label",
51870
+ "ariaLabel",
51871
+ "placeholder",
51872
+ "required",
51873
+ "readonly",
51874
+ "hint",
51875
+ "error",
51876
+ "minHeight",
51877
+ "maxHeight",
51878
+ "hide",
51879
+ "disabled"
51880
+ ]
51881
+ },
51597
51882
  {
51598
51883
  kind: "component",
51599
51884
  type: SearchInputComponent,
@@ -51651,6 +51936,12 @@ var ConversationsComponent = class ConversationsComponent {
51651
51936
  type: TooltipDirective,
51652
51937
  selector: "[uiTooltip]",
51653
51938
  inputs: ["uiTooltip", "tooltipPosition"]
51939
+ },
51940
+ {
51941
+ kind: "component",
51942
+ type: ConversationRichBodyComponent,
51943
+ selector: "ui-conversation-rich-body",
51944
+ inputs: ["html"]
51654
51945
  }
51655
51946
  ],
51656
51947
  changeDetection: i0.ChangeDetectionStrategy.OnPush
@@ -51679,10 +51970,12 @@ i0.ɵɵngDeclareClassMetadata({
51679
51970
  ListComponent,
51680
51971
  PaginationComponent,
51681
51972
  QuickFilterTabsComponent,
51973
+ RichTextEditorComponent,
51682
51974
  SearchInputComponent,
51683
51975
  SkeletonComponent,
51684
51976
  TextareaInputComponent,
51685
- TooltipDirective
51977
+ TooltipDirective,
51978
+ ConversationRichBodyComponent
51686
51979
  ],
51687
51980
  template: `
51688
51981
  <div class="cv-layout" [class.has-context]="contextVisible()" data-testid="conversations">
@@ -51737,7 +52030,7 @@ i0.ɵɵngDeclareClassMetadata({
51737
52030
  <ui-empty-state iconType="message" data-testid="conv-empty" [title]="filtering() ? filteredEmptyTitle() : emptyTitle()" [message]="emptyText()" />
51738
52031
  } @else {
51739
52032
  <div class="cv-list">
51740
- <ui-list [ariaLabel]="listAriaLabel()" [items]="conversations()" [trackBy]="trackConversation" [navigable]="true" [arrow]="false" (itemClick)="onRowOpen($event)">
52033
+ <ui-list [ariaLabel]="listAriaLabel()" [items]="conversations()" [trackBy]="trackConversation" [navigable]="selectable()" [arrow]="false" (itemClick)="onRowOpen($event)">
51741
52034
  <ng-template let-conv>
51742
52035
  <div class="cv-item" data-testid="conv-item" [attr.data-conversation-id]="conv.id"
51743
52036
  [class.selected]="selected()?.id === conv.id" [class.unread]="(conv.unreadCount ?? 0) > 0">
@@ -51779,9 +52072,11 @@ i0.ɵɵngDeclareClassMetadata({
51779
52072
  <section class="cv-thread-panel" [class.cv-hidden-mobile]="!selected()" [attr.aria-label]="threadAriaLabel()">
51780
52073
  @if (selected(); as conv) {
51781
52074
  <div class="cv-thread-header">
51782
- <ui-button class="cv-back-btn" variant="secondary" size="sm" [ariaLabel]="backLabel()" (click)="onBack()" data-testid="back-to-list">
51783
- <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>
51784
- </ui-button>
52075
+ @if (selectable()) {
52076
+ <ui-button class="cv-back-btn" variant="secondary" size="sm" [ariaLabel]="backLabel()" (click)="onBack()" data-testid="back-to-list">
52077
+ <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>
52078
+ </ui-button>
52079
+ }
51785
52080
  <div class="cv-thread-header-info">
51786
52081
  <ui-avatar [initials]="initial(conv.name)" [name]="conv.name" [size]="40" />
51787
52082
  <div class="cv-thread-header-text">
@@ -51859,7 +52154,8 @@ i0.ɵɵngDeclareClassMetadata({
51859
52154
  }
51860
52155
  </div>
51861
52156
  }
51862
- @if (row.message.body) { <p class="cv-body">{{ row.message.body }}</p> }
52157
+ @if (row.message.bodyHtml) { <ui-conversation-rich-body [html]="row.message.bodyHtml" data-testid="msg-rich-body" /> }
52158
+ @else if (row.message.body) { <p class="cv-body">{{ row.message.body }}</p> }
51863
52159
  <span class="cv-meta">
51864
52160
  @if (row.message.direction === 'outbound' && row.message.sender) { <span class="cv-sender" data-testid="msg-sender">{{ row.message.sender }}</span> }
51865
52161
  {{ time(row.message) }}
@@ -51900,9 +52196,15 @@ i0.ɵɵngDeclareClassMetadata({
51900
52196
  <ui-file-input [showField]="false" [accept]="acceptedFiles()" [maxSize]="maxFileSize()" [toastOnReject]="true"
51901
52197
  [typeMessage]="typeMessage()" [sizeMessage]="sizeMessage()" (filesSelected)="filesSelected.emit($event)" data-testid="attach-input" />
51902
52198
  }
51903
- <ui-textarea-input class="cv-compose-input" [ariaLabel]="composeLabel()" [placeholder]="composePlaceholder()" [rows]="1" [maxlength]="maxLength()"
51904
- [ngModel]="draft()" (ngModelChange)="draft.set($event)" [disabled]="composerDisabled()" [error]="composerError()"
51905
- (keydown)="onComposeKeydown($event)" data-testid="compose-input" />
52199
+ @if (richText()) {
52200
+ <ui-rich-text-editor class="cv-compose-input cv-compose-rich" [ariaLabel]="composeLabel()" [placeholder]="composePlaceholder()" [hide]="richHide"
52201
+ [minHeight]="44" [maxHeight]="160" [ngModel]="editorHtml()" (ngModelChange)="onEditorChange($event)" [disabled]="composerDisabled()" [error]="composerError()"
52202
+ (keydown)="onComposeKeydown($event)" data-testid="compose-input" />
52203
+ } @else {
52204
+ <ui-textarea-input class="cv-compose-input" [ariaLabel]="composeLabel()" [placeholder]="composePlaceholder()" [rows]="1" [maxlength]="maxLength()"
52205
+ [ngModel]="draft()" (ngModelChange)="draft.set($event)" [disabled]="composerDisabled()" [error]="composerError()"
52206
+ (keydown)="onComposeKeydown($event)" data-testid="compose-input" />
52207
+ }
51906
52208
  <ui-button class="cv-send-btn" variant="primary" [ariaLabel]="sendLabel()" [disabled]="!canSend()" [loading]="sending()" (click)="sendMessage()" data-testid="send-btn">
51907
52209
  <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>
51908
52210
  </ui-button>
@@ -51933,7 +52235,7 @@ i0.ɵɵngDeclareClassMetadata({
51933
52235
  }
51934
52236
  </div>
51935
52237
  `,
51936
- 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-row-arrow{flex:0 0 auto;align-self:center;color:#94a3b8}.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"]
52238
+ 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-row-arrow{flex:0 0 auto;align-self:center;color:#94a3b8}.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,.cv-bubble.inbound .cv-rich{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-rich,.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"]
51937
52239
  }]
51938
52240
  }],
51939
52241
  ctorParameters: () => [],
@@ -52165,6 +52467,14 @@ i0.ɵɵngDeclareClassMetadata({
52165
52467
  required: false
52166
52468
  }]
52167
52469
  }],
52470
+ selectable: [{
52471
+ type: i0.Input,
52472
+ args: [{
52473
+ isSignal: true,
52474
+ alias: "selectable",
52475
+ required: false
52476
+ }]
52477
+ }],
52168
52478
  newLabel: [{
52169
52479
  type: i0.Input,
52170
52480
  args: [{
@@ -52499,6 +52809,14 @@ i0.ɵɵngDeclareClassMetadata({
52499
52809
  required: false
52500
52810
  }]
52501
52811
  }],
52812
+ richText: [{
52813
+ type: i0.Input,
52814
+ args: [{
52815
+ isSignal: true,
52816
+ alias: "richText",
52817
+ required: false
52818
+ }]
52819
+ }],
52502
52820
  attachment: [{
52503
52821
  type: i0.Input,
52504
52822
  args: [{
@@ -52697,6 +53015,6 @@ i0.ɵɵngDeclareClassMetadata({
52697
53015
  }]
52698
53016
  }
52699
53017
  });
52700
- 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 };
53018
+ 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, ConversationRichBodyComponent, 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, conversationHtmlToText, 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 };
52701
53019
 
52702
53020
  //# sourceMappingURL=forgeroute-ui.mjs.map