valtech-components 4.0.1037 → 4.0.1039

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.
@@ -70,7 +70,7 @@ import fixWebmDuration from 'fix-webm-duration';
70
70
  * Current version of valtech-components.
71
71
  * This is automatically updated during the publish process.
72
72
  */
73
- const VERSION = '4.0.1037';
73
+ const VERSION = '4.0.1039';
74
74
 
75
75
  function evaluateValtechAccess(rule, context, features = {}, visitedFeatures = new Set()) {
76
76
  if (rule == null)
@@ -1876,13 +1876,18 @@ class I18nService {
1876
1876
  console.warn(`[i18n] Language '${lang}' not in supported languages`);
1877
1877
  return;
1878
1878
  }
1879
- if (lang === this._lang()) {
1880
- return;
1881
- }
1882
- // Persistir en localStorage (browser-only)
1879
+ // Aunque el signal ya tenga este valor, re-persistimos. Esto corrige
1880
+ // estados viejos donde la UI quedó en el idioma correcto por snapshot, pero
1881
+ // localStorage conservó otro valor y el siguiente bootstrap volvió al viejo.
1883
1882
  if (this.isBrowser) {
1884
1883
  localStorage.setItem(LANG_STORAGE_KEY$1, lang);
1885
1884
  }
1885
+ if (lang === this._lang()) {
1886
+ if (forceReload && this.isBrowser) {
1887
+ window.location.reload();
1888
+ }
1889
+ return;
1890
+ }
1886
1891
  // Actualizar signal
1887
1892
  this._lang.set(lang);
1888
1893
  // Fallback: recargar si se solicita
@@ -10651,7 +10656,11 @@ class AuthService {
10651
10656
  handle: profile.handle ?? null,
10652
10657
  avatarUrl: profile.avatarUrl ?? null,
10653
10658
  phone: profile.phone ?? null,
10654
- })), catchError(error => this.handleAuthError(error)));
10659
+ })), tap(profile => {
10660
+ if (this.i18nService && profile.language) {
10661
+ this.i18nService.setLanguage(profile.language);
10662
+ }
10663
+ }), catchError(error => this.handleAuthError(error)));
10655
10664
  }
10656
10665
  /**
10657
10666
  * Actualiza el perfil del usuario. Sincroniza state con los nuevos values
@@ -24127,11 +24136,32 @@ class AiMessageRendererComponent {
24127
24136
  @if (part.kind === 'code') {
24128
24137
  <pre class="code"><code>{{ part.code }}</code></pre>
24129
24138
  } @else {
24130
- <p class="text">{{ part.text }}</p>
24139
+ @switch (part.tag) {
24140
+ @case ('h3') {
24141
+ <h3 class="heading" [innerHTML]="part.html"></h3>
24142
+ }
24143
+ @case ('ul') {
24144
+ <ul class="list">
24145
+ @for (item of part.items ?? []; track item) {
24146
+ <li [innerHTML]="item"></li>
24147
+ }
24148
+ </ul>
24149
+ }
24150
+ @case ('ol') {
24151
+ <ol class="list">
24152
+ @for (item of part.items ?? []; track item) {
24153
+ <li [innerHTML]="item"></li>
24154
+ }
24155
+ </ol>
24156
+ }
24157
+ @default {
24158
+ <p class="text" [innerHTML]="part.html"></p>
24159
+ }
24160
+ }
24131
24161
  }
24132
24162
  }
24133
24163
  </div>
24134
- `, isInline: true, styles: [":host{display:block}.ai-message{display:flex;flex-direction:column;gap:.65rem}.text{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}.code{max-width:100%;margin:0;padding:.75rem;overflow-x:auto;border-radius:8px;background:var(--val-ai-message-code-background, rgba(15, 23, 42, .06));color:var(--val-ai-message-code-color, currentColor);font-size:.82rem;line-height:1.45}code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
24164
+ `, isInline: true, styles: [":host{display:block}.ai-message{display:flex;flex-direction:column;gap:.65rem}.text,.heading,.list{margin:0;overflow-wrap:anywhere}.heading{font-size:1rem;line-height:1.3;font-weight:750}.text{white-space:pre-wrap}.list{display:flex;flex-direction:column;gap:.28rem;padding-inline-start:1.15rem}.code{max-width:100%;margin:0;padding:.75rem;overflow-x:auto;border-radius:8px;background:var(--val-ai-message-code-background, rgba(15, 23, 42, .06));color:var(--val-ai-message-code-color, currentColor);font-size:.82rem;line-height:1.45}code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace}.text ::ng-deep code,.heading ::ng-deep code,.list ::ng-deep code{padding:.08rem .28rem;border-radius:5px;background:var(--val-ai-message-inline-code-background, rgba(15, 23, 42, .08));font-size:.9em}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] }); }
24135
24165
  }
24136
24166
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AiMessageRendererComponent, decorators: [{
24137
24167
  type: Component,
@@ -24141,11 +24171,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
24141
24171
  @if (part.kind === 'code') {
24142
24172
  <pre class="code"><code>{{ part.code }}</code></pre>
24143
24173
  } @else {
24144
- <p class="text">{{ part.text }}</p>
24174
+ @switch (part.tag) {
24175
+ @case ('h3') {
24176
+ <h3 class="heading" [innerHTML]="part.html"></h3>
24177
+ }
24178
+ @case ('ul') {
24179
+ <ul class="list">
24180
+ @for (item of part.items ?? []; track item) {
24181
+ <li [innerHTML]="item"></li>
24182
+ }
24183
+ </ul>
24184
+ }
24185
+ @case ('ol') {
24186
+ <ol class="list">
24187
+ @for (item of part.items ?? []; track item) {
24188
+ <li [innerHTML]="item"></li>
24189
+ }
24190
+ </ol>
24191
+ }
24192
+ @default {
24193
+ <p class="text" [innerHTML]="part.html"></p>
24194
+ }
24195
+ }
24145
24196
  }
24146
24197
  }
24147
24198
  </div>
24148
- `, styles: [":host{display:block}.ai-message{display:flex;flex-direction:column;gap:.65rem}.text{margin:0;white-space:pre-wrap;overflow-wrap:anywhere}.code{max-width:100%;margin:0;padding:.75rem;overflow-x:auto;border-radius:8px;background:var(--val-ai-message-code-background, rgba(15, 23, 42, .06));color:var(--val-ai-message-code-color, currentColor);font-size:.82rem;line-height:1.45}code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace}\n"] }]
24199
+ `, styles: [":host{display:block}.ai-message{display:flex;flex-direction:column;gap:.65rem}.text,.heading,.list{margin:0;overflow-wrap:anywhere}.heading{font-size:1rem;line-height:1.3;font-weight:750}.text{white-space:pre-wrap}.list{display:flex;flex-direction:column;gap:.28rem;padding-inline-start:1.15rem}.code{max-width:100%;margin:0;padding:.75rem;overflow-x:auto;border-radius:8px;background:var(--val-ai-message-code-background, rgba(15, 23, 42, .06));color:var(--val-ai-message-code-color, currentColor);font-size:.82rem;line-height:1.45}code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,monospace}.text ::ng-deep code,.heading ::ng-deep code,.list ::ng-deep code{padding:.08rem .28rem;border-radius:5px;background:var(--val-ai-message-inline-code-background, rgba(15, 23, 42, .08));font-size:.9em}\n"] }]
24149
24200
  }] });
24150
24201
  function parseAiMessage(text) {
24151
24202
  const parts = [];
@@ -24156,7 +24207,8 @@ function parseAiMessage(text) {
24156
24207
  while ((match = fence.exec(text)) !== null) {
24157
24208
  const before = text.slice(lastIndex, match.index).trim();
24158
24209
  if (before) {
24159
- parts.push({ kind: 'text', id: `text-${index++}`, text: before });
24210
+ parts.push(...parseMarkdownBlocks(before, index));
24211
+ index = parts.length;
24160
24212
  }
24161
24213
  parts.push({
24162
24214
  kind: 'code',
@@ -24168,9 +24220,81 @@ function parseAiMessage(text) {
24168
24220
  }
24169
24221
  const rest = text.slice(lastIndex).trim();
24170
24222
  if (rest) {
24171
- parts.push({ kind: 'text', id: `text-${index++}`, text: rest });
24223
+ parts.push(...parseMarkdownBlocks(rest, index));
24224
+ }
24225
+ return parts.length > 0 ? parts : [{ kind: 'block', id: 'text-0', tag: 'p', html: renderInline(text) }];
24226
+ }
24227
+ function parseMarkdownBlocks(text, offset) {
24228
+ const blocks = [];
24229
+ const lines = text.split('\n');
24230
+ let paragraph = [];
24231
+ let listItems = [];
24232
+ let orderedItems = [];
24233
+ let index = offset;
24234
+ const flushParagraph = () => {
24235
+ if (paragraph.length === 0)
24236
+ return;
24237
+ blocks.push({ kind: 'block', id: `text-${index++}`, tag: 'p', html: renderInline(paragraph.join('\n')) });
24238
+ paragraph = [];
24239
+ };
24240
+ const flushLists = () => {
24241
+ if (listItems.length > 0) {
24242
+ blocks.push({ kind: 'block', id: `list-${index++}`, tag: 'ul', items: listItems });
24243
+ listItems = [];
24244
+ }
24245
+ if (orderedItems.length > 0) {
24246
+ blocks.push({ kind: 'block', id: `list-${index++}`, tag: 'ol', items: orderedItems });
24247
+ orderedItems = [];
24248
+ }
24249
+ };
24250
+ for (const raw of lines) {
24251
+ const line = raw.trim();
24252
+ if (!line) {
24253
+ flushParagraph();
24254
+ flushLists();
24255
+ continue;
24256
+ }
24257
+ const heading = line.match(/^#{1,4}\s+(.+)$/);
24258
+ if (heading) {
24259
+ flushParagraph();
24260
+ flushLists();
24261
+ blocks.push({ kind: 'block', id: `heading-${index++}`, tag: 'h3', html: renderInline(heading[1]) });
24262
+ continue;
24263
+ }
24264
+ const bullet = line.match(/^[-*]\s+(.+)$/);
24265
+ if (bullet) {
24266
+ flushParagraph();
24267
+ orderedItems = [];
24268
+ listItems.push(renderInline(bullet[1]));
24269
+ continue;
24270
+ }
24271
+ const ordered = line.match(/^\d+\.\s+(.+)$/);
24272
+ if (ordered) {
24273
+ flushParagraph();
24274
+ listItems = [];
24275
+ orderedItems.push(renderInline(ordered[1]));
24276
+ continue;
24277
+ }
24278
+ flushLists();
24279
+ paragraph.push(raw);
24172
24280
  }
24173
- return parts.length > 0 ? parts : [{ kind: 'text', id: 'text-0', text }];
24281
+ flushParagraph();
24282
+ flushLists();
24283
+ return blocks;
24284
+ }
24285
+ function renderInline(text) {
24286
+ return escapeHtml(text)
24287
+ .replace(/`([^`]+)`/g, '<code>$1</code>')
24288
+ .replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
24289
+ .replace(/\*([^*]+)\*/g, '<em>$1</em>');
24290
+ }
24291
+ function escapeHtml(text) {
24292
+ return text
24293
+ .replace(/&/g, '&amp;')
24294
+ .replace(/</g, '&lt;')
24295
+ .replace(/>/g, '&gt;')
24296
+ .replace(/"/g, '&quot;')
24297
+ .replace(/'/g, '&#39;');
24174
24298
  }
24175
24299
 
24176
24300
  /**
@@ -59650,9 +59774,13 @@ class PreferencesService {
59650
59774
  .docChanges(`users/${userId}/preferences`, 'main')
59651
59775
  .subscribe(doc => {
59652
59776
  if (!doc) {
59653
- // Doc no existe aún (user nuevo, sin primer sync). Mantenemos
59654
- // defaults locales pero NO marcamos synced — los side-effects no
59655
- // pisan el theme/lang locales con valores arbitrarios.
59777
+ // Doc no existe aún para esta app. Antes dejábamos la app con
59778
+ // localStorage/navigator, aunque el usuario ya tuviera idioma
59779
+ // canónico en auth. Resultado: cuenta en español, app nueva en inglés
59780
+ // hasta cambiar manualmente a inglés y volver a español. Hidratar
59781
+ // desde perfil canónico corrige ese primer arranque y además crea el
59782
+ // mirror de esta app.
59783
+ this.hydrateMissingPreferencesFromProfile(userId);
59656
59784
  return;
59657
59785
  }
59658
59786
  // Ignorar emisiones del listener mientras hay un update() en vuelo: un
@@ -59677,8 +59805,25 @@ class PreferencesService {
59677
59805
  this.subscription?.unsubscribe();
59678
59806
  this.subscription = undefined;
59679
59807
  this.currentUserId = undefined;
59808
+ this.missingDocHydrationUserId = undefined;
59680
59809
  this._synced.set(false);
59681
59810
  }
59811
+ hydrateMissingPreferencesFromProfile(userId) {
59812
+ if (this.missingDocHydrationUserId === userId)
59813
+ return;
59814
+ this.missingDocHydrationUserId = userId;
59815
+ void firstValueFrom(this.auth.getProfile())
59816
+ .then(profile => {
59817
+ const language = profile.language;
59818
+ if (language === 'es' || language === 'en') {
59819
+ this._language.set(language);
59820
+ this.i18n?.setLanguage(language);
59821
+ this._synced.set(true);
59822
+ void this.update({ language }).catch(() => undefined);
59823
+ }
59824
+ })
59825
+ .catch(() => undefined);
59826
+ }
59682
59827
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PreferencesService, deps: [{ token: VALTECH_AUTH_CONFIG }, { token: FirestoreService }, { token: AuthService }, { token: i1$3.HttpClient }, { token: FirebaseService, optional: true }, { token: ThemeService, optional: true }, { token: FontSizeService, optional: true }, { token: I18nService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
59683
59828
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PreferencesService, providedIn: 'root' }); }
59684
59829
  }
@@ -93166,6 +93311,21 @@ class MessageBubbleComponent {
93166
93311
  this.showCopyAction() ||
93167
93312
  (this.showEditAction() && this.msg().isMine) ||
93168
93313
  (this.showDeleteAction() && (this.msg().isMine || this.canModerate())));
93314
+ this.copyOnlyActions = computed(() => this.showCopyAction() && this.hasActionsCount() === 1);
93315
+ this.hasActionsCount = computed(() => {
93316
+ let count = 0;
93317
+ if (this.showReactAction())
93318
+ count++;
93319
+ if (this.showReplyAction())
93320
+ count++;
93321
+ if (this.showCopyAction())
93322
+ count++;
93323
+ if (this.showEditAction() && this.msg().isMine)
93324
+ count++;
93325
+ if (this.showDeleteAction() && (this.msg().isMine || this.canModerate()))
93326
+ count++;
93327
+ return count;
93328
+ });
93169
93329
  this.time = computed(() => formatClockTime(this.msg().createdAt, this.locale()));
93170
93330
  this.initials = computed(() => {
93171
93331
  const name = this.msg().senderName?.trim() ?? '';
@@ -93348,7 +93508,7 @@ class MessageBubbleComponent {
93348
93508
  }
93349
93509
 
93350
93510
  @if (!msg().isDeleted && hasActions()) {
93351
- <div class="actions" [class.open]="actionsOpen()">
93511
+ <div class="actions" [class.open]="actionsOpen()" [class.copy-only]="copyOnlyActions()">
93352
93512
  @if (showReactAction()) {
93353
93513
  <button class="act" [attr.aria-label]="t('react')" (click)="emit('react', '👍')">
93354
93514
  <ion-icon name="happy-outline" aria-hidden="true" />
@@ -93378,7 +93538,7 @@ class MessageBubbleComponent {
93378
93538
  }
93379
93539
  </div>
93380
93540
  </div>
93381
- `, isInline: true, styles: [":host{display:block}.row{display:flex;align-items:flex-end;gap:8px;margin:0}.row.mine{flex-direction:row-reverse}.row.tail{margin-bottom:8px}.avatar{width:28px;height:28px;border-radius:50%;overflow:hidden;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--ion-color-primary);color:#fff;font-size:.6875rem;font-weight:700}.avatar.hidden{visibility:hidden}.avatar img{width:100%;height:100%;object-fit:cover}.bubble-wrap{position:relative;max-width:min(86%,680px);display:flex;flex-direction:column}.row.mine .bubble-wrap{align-items:flex-end}.bubble{position:relative;padding:9px 12px;border-radius:18px;background:var(--val-message-background, transparent);border:1px solid var(--val-message-border, transparent);color:var(--ion-text-color, #000);font-size:.95rem;line-height:1.45;cursor:pointer;outline:none;word-break:break-word}.row:not(.mine).tail .bubble{border-bottom-left-radius:18px}.mine .bubble{background:var(--val-message-mine-background, var(--ion-color-dark, #111));border-color:var(--val-message-mine-border, var(--val-message-mine-background, var(--ion-color-dark, #111)));color:var(--val-message-mine-color, #fff)}.mine.tail .bubble{border-bottom-right-radius:18px}.bubble.deleted{background:transparent;border-style:dashed;cursor:default}.name{display:block;font-size:.75rem;font-weight:700;color:var(--ion-color-primary);margin-bottom:2px}.reply-preview{display:flex;flex-direction:column;gap:1px;padding:4px 8px;margin-bottom:4px;border-left:3px solid currentColor;border-radius:6px;background:var(--ion-color-step-100, rgba(127, 127, 127, .12));font-size:.8125rem;opacity:.85}.reply-name{font-weight:700}.reply-body{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}.body{white-space:pre-wrap}.deleted-text{font-style:italic;opacity:.6}.attachments{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.att-image{max-width:100%;border-radius:10px;display:block;cursor:pointer}.audios{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.att-audio{width:240px;max-width:100%;height:40px}.files{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.file-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:8px;background:var(--ion-color-step-100, rgba(127, 127, 127, .12));color:inherit;text-decoration:none;font-size:.8125rem}.meta{display:inline-flex;align-items:center;gap:4px;float:right;margin:2px 0 -2px 8px;font-size:.6875rem;opacity:var(--val-message-meta-opacity, 0)}.edited{font-style:italic}.status{font-size:.875rem}.status.read{color:var(--ion-color-secondary, #4fc3f7);opacity:1}.status.failed{color:var(--ion-color-danger, #eb445a);opacity:1}.reactions{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}.reaction{display:inline-flex;align-items:center;gap:3px;padding:1px 7px;border-radius:999px;border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-card-background, var(--ion-background-color, #fff));font-size:.75rem;cursor:pointer;color:var(--ion-text-color, #000)}.reaction.active{border-color:var(--ion-color-primary);background:var(--ion-color-primary-tint, var(--ion-color-primary));color:var(--ion-color-primary-contrast, #fff)}.reaction .count{opacity:.75}.actions{position:absolute;top:-14px;display:flex;gap:2px;padding:2px;border-radius:999px;background:var(--ion-card-background, var(--ion-background-color, #fff));border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));box-shadow:0 2px 8px #0000001f;opacity:0;pointer-events:none;transition:opacity .12s ease;z-index:2}.row.mine .actions{right:0}.row:not(.mine) .actions{left:0}.bubble-wrap:hover .actions,.actions.open{opacity:1;pointer-events:auto}.act{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;border-radius:50%;background:transparent;color:var(--ion-color-dark, #92949c);cursor:pointer;font-size:1rem}.act:hover{background:var(--ion-color-step-100, rgba(127, 127, 127, .12));color:var(--ion-text-color, #000)}.act.danger:hover{color:var(--ion-color-danger, #eb445a)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: AiMessageRendererComponent, selector: "val-ai-message-renderer", inputs: ["text"] }] }); }
93541
+ `, isInline: true, styles: [":host{display:block}.row{display:flex;align-items:flex-end;gap:8px;margin:0}.row.mine{flex-direction:row-reverse}.row.tail{margin-bottom:8px}.avatar{width:28px;height:28px;border-radius:50%;overflow:hidden;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--ion-color-primary);color:#fff;font-size:.6875rem;font-weight:700}.avatar.hidden{visibility:hidden}.avatar img{width:100%;height:100%;object-fit:cover}.bubble-wrap{position:relative;max-width:min(86%,680px);display:flex;flex-direction:column}.row.mine .bubble-wrap{align-items:flex-end}.bubble{position:relative;padding:9px 12px;border-radius:18px;background:var(--val-message-background, transparent);border:1px solid var(--val-message-border, transparent);color:var(--ion-text-color, #000);font-size:.95rem;line-height:1.45;cursor:pointer;outline:none;word-break:break-word}.row:not(.mine).tail .bubble{border-bottom-left-radius:18px}.mine .bubble{background:var(--val-message-mine-background, var(--ion-color-dark, #111));border-color:var(--val-message-mine-border, var(--val-message-mine-background, var(--ion-color-dark, #111)));color:var(--val-message-mine-color, #fff)}.mine.tail .bubble{border-bottom-right-radius:18px}.bubble.deleted{background:transparent;border-style:dashed;cursor:default}.name{display:block;font-size:.75rem;font-weight:700;color:var(--ion-color-primary);margin-bottom:2px}.reply-preview{display:flex;flex-direction:column;gap:1px;padding:4px 8px;margin-bottom:4px;border-left:3px solid currentColor;border-radius:6px;background:var(--ion-color-step-100, rgba(127, 127, 127, .12));font-size:.8125rem;opacity:.85}.reply-name{font-weight:700}.reply-body{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}.body{white-space:pre-wrap}.deleted-text{font-style:italic;opacity:.6}.attachments{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.att-image{max-width:100%;border-radius:10px;display:block;cursor:pointer}.audios{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.att-audio{width:240px;max-width:100%;height:40px}.files{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.file-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:8px;background:var(--ion-color-step-100, rgba(127, 127, 127, .12));color:inherit;text-decoration:none;font-size:.8125rem}.meta{display:inline-flex;align-items:center;gap:4px;float:right;margin:2px 0 -2px 8px;font-size:.6875rem;opacity:var(--val-message-meta-opacity, 0)}.edited{font-style:italic}.status{font-size:.875rem}.status.read{color:var(--ion-color-secondary, #4fc3f7);opacity:1}.status.failed{color:var(--ion-color-danger, #eb445a);opacity:1}.reactions{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}.reaction{display:inline-flex;align-items:center;gap:3px;padding:1px 7px;border-radius:999px;border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-card-background, var(--ion-background-color, #fff));font-size:.75rem;cursor:pointer;color:var(--ion-text-color, #000)}.reaction.active{border-color:var(--ion-color-primary);background:var(--ion-color-primary-tint, var(--ion-color-primary));color:var(--ion-color-primary-contrast, #fff)}.reaction .count{opacity:.75}.actions{position:absolute;top:-14px;display:flex;gap:2px;padding:2px;border-radius:999px;background:var(--ion-card-background, var(--ion-background-color, #fff));border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));box-shadow:0 2px 8px #0000001f;opacity:0;pointer-events:none;transition:opacity .12s ease;z-index:2}.row.mine .actions{right:0}.row:not(.mine) .actions{left:0}.actions.copy-only{inset:auto auto -14px 0}.row.mine .actions.copy-only{left:0;right:auto}.bubble-wrap:hover .actions,.actions.open{opacity:1;pointer-events:auto}.act{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;border-radius:50%;background:transparent;color:var(--ion-color-dark, #92949c);cursor:pointer;font-size:1rem}.act:hover{background:var(--ion-color-step-100, rgba(127, 127, 127, .12));color:var(--ion-text-color, #000)}.act.danger:hover{color:var(--ion-color-danger, #eb445a)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: AiMessageRendererComponent, selector: "val-ai-message-renderer", inputs: ["text"] }] }); }
93382
93542
  }
93383
93543
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessageBubbleComponent, decorators: [{
93384
93544
  type: Component,
@@ -93484,7 +93644,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
93484
93644
  }
93485
93645
 
93486
93646
  @if (!msg().isDeleted && hasActions()) {
93487
- <div class="actions" [class.open]="actionsOpen()">
93647
+ <div class="actions" [class.open]="actionsOpen()" [class.copy-only]="copyOnlyActions()">
93488
93648
  @if (showReactAction()) {
93489
93649
  <button class="act" [attr.aria-label]="t('react')" (click)="emit('react', '👍')">
93490
93650
  <ion-icon name="happy-outline" aria-hidden="true" />
@@ -93514,7 +93674,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
93514
93674
  }
93515
93675
  </div>
93516
93676
  </div>
93517
- `, styles: [":host{display:block}.row{display:flex;align-items:flex-end;gap:8px;margin:0}.row.mine{flex-direction:row-reverse}.row.tail{margin-bottom:8px}.avatar{width:28px;height:28px;border-radius:50%;overflow:hidden;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--ion-color-primary);color:#fff;font-size:.6875rem;font-weight:700}.avatar.hidden{visibility:hidden}.avatar img{width:100%;height:100%;object-fit:cover}.bubble-wrap{position:relative;max-width:min(86%,680px);display:flex;flex-direction:column}.row.mine .bubble-wrap{align-items:flex-end}.bubble{position:relative;padding:9px 12px;border-radius:18px;background:var(--val-message-background, transparent);border:1px solid var(--val-message-border, transparent);color:var(--ion-text-color, #000);font-size:.95rem;line-height:1.45;cursor:pointer;outline:none;word-break:break-word}.row:not(.mine).tail .bubble{border-bottom-left-radius:18px}.mine .bubble{background:var(--val-message-mine-background, var(--ion-color-dark, #111));border-color:var(--val-message-mine-border, var(--val-message-mine-background, var(--ion-color-dark, #111)));color:var(--val-message-mine-color, #fff)}.mine.tail .bubble{border-bottom-right-radius:18px}.bubble.deleted{background:transparent;border-style:dashed;cursor:default}.name{display:block;font-size:.75rem;font-weight:700;color:var(--ion-color-primary);margin-bottom:2px}.reply-preview{display:flex;flex-direction:column;gap:1px;padding:4px 8px;margin-bottom:4px;border-left:3px solid currentColor;border-radius:6px;background:var(--ion-color-step-100, rgba(127, 127, 127, .12));font-size:.8125rem;opacity:.85}.reply-name{font-weight:700}.reply-body{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}.body{white-space:pre-wrap}.deleted-text{font-style:italic;opacity:.6}.attachments{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.att-image{max-width:100%;border-radius:10px;display:block;cursor:pointer}.audios{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.att-audio{width:240px;max-width:100%;height:40px}.files{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.file-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:8px;background:var(--ion-color-step-100, rgba(127, 127, 127, .12));color:inherit;text-decoration:none;font-size:.8125rem}.meta{display:inline-flex;align-items:center;gap:4px;float:right;margin:2px 0 -2px 8px;font-size:.6875rem;opacity:var(--val-message-meta-opacity, 0)}.edited{font-style:italic}.status{font-size:.875rem}.status.read{color:var(--ion-color-secondary, #4fc3f7);opacity:1}.status.failed{color:var(--ion-color-danger, #eb445a);opacity:1}.reactions{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}.reaction{display:inline-flex;align-items:center;gap:3px;padding:1px 7px;border-radius:999px;border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-card-background, var(--ion-background-color, #fff));font-size:.75rem;cursor:pointer;color:var(--ion-text-color, #000)}.reaction.active{border-color:var(--ion-color-primary);background:var(--ion-color-primary-tint, var(--ion-color-primary));color:var(--ion-color-primary-contrast, #fff)}.reaction .count{opacity:.75}.actions{position:absolute;top:-14px;display:flex;gap:2px;padding:2px;border-radius:999px;background:var(--ion-card-background, var(--ion-background-color, #fff));border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));box-shadow:0 2px 8px #0000001f;opacity:0;pointer-events:none;transition:opacity .12s ease;z-index:2}.row.mine .actions{right:0}.row:not(.mine) .actions{left:0}.bubble-wrap:hover .actions,.actions.open{opacity:1;pointer-events:auto}.act{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;border-radius:50%;background:transparent;color:var(--ion-color-dark, #92949c);cursor:pointer;font-size:1rem}.act:hover{background:var(--ion-color-step-100, rgba(127, 127, 127, .12));color:var(--ion-text-color, #000)}.act.danger:hover{color:var(--ion-color-danger, #eb445a)}\n"] }]
93677
+ `, styles: [":host{display:block}.row{display:flex;align-items:flex-end;gap:8px;margin:0}.row.mine{flex-direction:row-reverse}.row.tail{margin-bottom:8px}.avatar{width:28px;height:28px;border-radius:50%;overflow:hidden;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:var(--ion-color-primary);color:#fff;font-size:.6875rem;font-weight:700}.avatar.hidden{visibility:hidden}.avatar img{width:100%;height:100%;object-fit:cover}.bubble-wrap{position:relative;max-width:min(86%,680px);display:flex;flex-direction:column}.row.mine .bubble-wrap{align-items:flex-end}.bubble{position:relative;padding:9px 12px;border-radius:18px;background:var(--val-message-background, transparent);border:1px solid var(--val-message-border, transparent);color:var(--ion-text-color, #000);font-size:.95rem;line-height:1.45;cursor:pointer;outline:none;word-break:break-word}.row:not(.mine).tail .bubble{border-bottom-left-radius:18px}.mine .bubble{background:var(--val-message-mine-background, var(--ion-color-dark, #111));border-color:var(--val-message-mine-border, var(--val-message-mine-background, var(--ion-color-dark, #111)));color:var(--val-message-mine-color, #fff)}.mine.tail .bubble{border-bottom-right-radius:18px}.bubble.deleted{background:transparent;border-style:dashed;cursor:default}.name{display:block;font-size:.75rem;font-weight:700;color:var(--ion-color-primary);margin-bottom:2px}.reply-preview{display:flex;flex-direction:column;gap:1px;padding:4px 8px;margin-bottom:4px;border-left:3px solid currentColor;border-radius:6px;background:var(--ion-color-step-100, rgba(127, 127, 127, .12));font-size:.8125rem;opacity:.85}.reply-name{font-weight:700}.reply-body{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:240px}.body{white-space:pre-wrap}.deleted-text{font-style:italic;opacity:.6}.attachments{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.att-image{max-width:100%;border-radius:10px;display:block;cursor:pointer}.audios{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.att-audio{width:240px;max-width:100%;height:40px}.files{display:flex;flex-direction:column;gap:4px;margin-bottom:4px}.file-chip{display:inline-flex;align-items:center;gap:6px;padding:6px 10px;border-radius:8px;background:var(--ion-color-step-100, rgba(127, 127, 127, .12));color:inherit;text-decoration:none;font-size:.8125rem}.meta{display:inline-flex;align-items:center;gap:4px;float:right;margin:2px 0 -2px 8px;font-size:.6875rem;opacity:var(--val-message-meta-opacity, 0)}.edited{font-style:italic}.status{font-size:.875rem}.status.read{color:var(--ion-color-secondary, #4fc3f7);opacity:1}.status.failed{color:var(--ion-color-danger, #eb445a);opacity:1}.reactions{display:flex;flex-wrap:wrap;gap:4px;margin-top:3px}.reaction{display:inline-flex;align-items:center;gap:3px;padding:1px 7px;border-radius:999px;border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));background:var(--ion-card-background, var(--ion-background-color, #fff));font-size:.75rem;cursor:pointer;color:var(--ion-text-color, #000)}.reaction.active{border-color:var(--ion-color-primary);background:var(--ion-color-primary-tint, var(--ion-color-primary));color:var(--ion-color-primary-contrast, #fff)}.reaction .count{opacity:.75}.actions{position:absolute;top:-14px;display:flex;gap:2px;padding:2px;border-radius:999px;background:var(--ion-card-background, var(--ion-background-color, #fff));border:1px solid var(--ion-border-color, rgba(0, 0, 0, .1));box-shadow:0 2px 8px #0000001f;opacity:0;pointer-events:none;transition:opacity .12s ease;z-index:2}.row.mine .actions{right:0}.row:not(.mine) .actions{left:0}.actions.copy-only{inset:auto auto -14px 0}.row.mine .actions.copy-only{left:0;right:auto}.bubble-wrap:hover .actions,.actions.open{opacity:1;pointer-events:auto}.act{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:none;border-radius:50%;background:transparent;color:var(--ion-color-dark, #92949c);cursor:pointer;font-size:1rem}.act:hover{background:var(--ion-color-step-100, rgba(127, 127, 127, .12));color:var(--ion-text-color, #000)}.act.danger:hover{color:var(--ion-color-danger, #eb445a)}\n"] }]
93518
93678
  }], ctorParameters: () => [] });
93519
93679
 
93520
93680
  addIcons({ sendOutline });