@propbinder/mobile-design 0.3.2 → 0.3.32

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.
@@ -9729,6 +9729,14 @@ class DsMobileMessageBubbleComponent {
9729
9729
  * Sender's name (for display purposes)
9730
9730
  */
9731
9731
  senderName = input('', ...(ngDevMode ? [{ debugName: "senderName" }] : []));
9732
+ /**
9733
+ * Whether the message is an internal message
9734
+ */
9735
+ isInternal = input(false, ...(ngDevMode ? [{ debugName: "isInternal" }] : []));
9736
+ /**
9737
+ * Text for the internal message badge
9738
+ */
9739
+ internalMessageBadgeText = input('Intern besked', ...(ngDevMode ? [{ debugName: "internalMessageBadgeText" }] : []));
9732
9740
  /**
9733
9741
  * Timestamp text (e.g., "12:34", "08-12-2025 13:18")
9734
9742
  */
@@ -9900,7 +9908,7 @@ class DsMobileMessageBubbleComponent {
9900
9908
  this.longPress.emit();
9901
9909
  }
9902
9910
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileMessageBubbleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9903
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileMessageBubbleComponent, isStandalone: true, selector: "ds-mobile-message-bubble", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, isOwnMessage: { classPropertyName: "isOwnMessage", publicName: "isOwnMessage", isSignal: true, isRequired: false, transformFunction: null }, senderName: { classPropertyName: "senderName", publicName: "senderName", isSignal: true, isRequired: false, transformFunction: null }, timestamp: { classPropertyName: "timestamp", publicName: "timestamp", isSignal: true, isRequired: true, transformFunction: null }, showTimestamp: { classPropertyName: "showTimestamp", publicName: "showTimestamp", isSignal: true, isRequired: false, transformFunction: null }, avatarInitials: { classPropertyName: "avatarInitials", publicName: "avatarInitials", isSignal: true, isRequired: false, transformFunction: null }, avatarType: { classPropertyName: "avatarType", publicName: "avatarType", isSignal: true, isRequired: false, transformFunction: null }, avatarSrc: { classPropertyName: "avatarSrc", publicName: "avatarSrc", isSignal: true, isRequired: false, transformFunction: null }, showAvatar: { classPropertyName: "showAvatar", publicName: "showAvatar", isSignal: true, isRequired: false, transformFunction: null }, clusterPosition: { classPropertyName: "clusterPosition", publicName: "clusterPosition", isSignal: true, isRequired: false, transformFunction: null }, attachments: { classPropertyName: "attachments", publicName: "attachments", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, isNewMessage: { classPropertyName: "isNewMessage", publicName: "isNewMessage", isSignal: true, isRequired: false, transformFunction: null }, isDeleted: { classPropertyName: "isDeleted", publicName: "isDeleted", isSignal: true, isRequired: false, transformFunction: null }, showEditedHint: { classPropertyName: "showEditedHint", publicName: "showEditedHint", isSignal: true, isRequired: false, transformFunction: null }, editedHintText: { classPropertyName: "editedHintText", publicName: "editedHintText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { attachmentClick: "attachmentClick", longPress: "longPress", messageClick: "messageClick" }, host: { listeners: { "touchstart": "handleTouchStart($event)", "touchend": "handleTouchEnd($event)", "touchmove": "handleTouchMove($event)", "contextmenu": "handleContextMenu($event)" }, properties: { "class.is-own-message": "isOwnMessage()", "class.has-attachments": "attachments() && attachments()!.length > 0", "class.cluster-single": "clusterPosition() === \"single\"", "class.cluster-first": "clusterPosition() === \"first\"", "class.cluster-middle": "clusterPosition() === \"middle\"", "class.cluster-last": "clusterPosition() === \"last\"", "class.tapped": "isTapped", "class.is-new-message": "isNewMessage()", "class.is-deleted": "isDeleted()" } }, ngImport: i0, template: `
9911
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: DsMobileMessageBubbleComponent, isStandalone: true, selector: "ds-mobile-message-bubble", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: true, transformFunction: null }, isOwnMessage: { classPropertyName: "isOwnMessage", publicName: "isOwnMessage", isSignal: true, isRequired: false, transformFunction: null }, senderName: { classPropertyName: "senderName", publicName: "senderName", isSignal: true, isRequired: false, transformFunction: null }, isInternal: { classPropertyName: "isInternal", publicName: "isInternal", isSignal: true, isRequired: false, transformFunction: null }, internalMessageBadgeText: { classPropertyName: "internalMessageBadgeText", publicName: "internalMessageBadgeText", isSignal: true, isRequired: false, transformFunction: null }, timestamp: { classPropertyName: "timestamp", publicName: "timestamp", isSignal: true, isRequired: true, transformFunction: null }, showTimestamp: { classPropertyName: "showTimestamp", publicName: "showTimestamp", isSignal: true, isRequired: false, transformFunction: null }, avatarInitials: { classPropertyName: "avatarInitials", publicName: "avatarInitials", isSignal: true, isRequired: false, transformFunction: null }, avatarType: { classPropertyName: "avatarType", publicName: "avatarType", isSignal: true, isRequired: false, transformFunction: null }, avatarSrc: { classPropertyName: "avatarSrc", publicName: "avatarSrc", isSignal: true, isRequired: false, transformFunction: null }, showAvatar: { classPropertyName: "showAvatar", publicName: "showAvatar", isSignal: true, isRequired: false, transformFunction: null }, clusterPosition: { classPropertyName: "clusterPosition", publicName: "clusterPosition", isSignal: true, isRequired: false, transformFunction: null }, attachments: { classPropertyName: "attachments", publicName: "attachments", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, isNewMessage: { classPropertyName: "isNewMessage", publicName: "isNewMessage", isSignal: true, isRequired: false, transformFunction: null }, isDeleted: { classPropertyName: "isDeleted", publicName: "isDeleted", isSignal: true, isRequired: false, transformFunction: null }, showEditedHint: { classPropertyName: "showEditedHint", publicName: "showEditedHint", isSignal: true, isRequired: false, transformFunction: null }, editedHintText: { classPropertyName: "editedHintText", publicName: "editedHintText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { attachmentClick: "attachmentClick", longPress: "longPress", messageClick: "messageClick" }, host: { listeners: { "touchstart": "handleTouchStart($event)", "touchend": "handleTouchEnd($event)", "touchmove": "handleTouchMove($event)", "contextmenu": "handleContextMenu($event)" }, properties: { "class.is-own-message": "isOwnMessage()", "class.has-attachments": "attachments() && attachments()!.length > 0", "class.cluster-single": "clusterPosition() === \"single\"", "class.cluster-first": "clusterPosition() === \"first\"", "class.cluster-middle": "clusterPosition() === \"middle\"", "class.cluster-last": "clusterPosition() === \"last\"", "class.tapped": "isTapped", "class.is-new-message": "isNewMessage()", "class.is-deleted": "isDeleted()" } }, ngImport: i0, template: `
9904
9912
  @if (!isOwnMessage()) {
9905
9913
  <div class="avatar-wrapper" [class.hidden]="!showAvatar()">
9906
9914
  <ds-avatar
@@ -9912,7 +9920,13 @@ class DsMobileMessageBubbleComponent {
9912
9920
  }
9913
9921
 
9914
9922
  <div class="message-content-wrapper" (click)="handleClick($event)">
9915
- <div class="message-bubble">
9923
+ @if (isInternal()) {
9924
+ <div class="internal-message-badge">
9925
+ <ds-icon name="remixLockLine" size="12px"></ds-icon>
9926
+ <span>{{ internalMessageBadgeText() }}</span>
9927
+ </div>
9928
+ }
9929
+ <div class="message-bubble" [class.is-internal]="isInternal()">
9916
9930
  <!-- Only show text if content is not empty -->
9917
9931
  @if (content().trim()) {
9918
9932
  <p class="message-text">{{ content() }}</p>
@@ -9949,7 +9963,7 @@ class DsMobileMessageBubbleComponent {
9949
9963
  </div>
9950
9964
  </div>
9951
9965
  </div>
9952
- `, isInline: true, styles: [":host{display:flex;gap:8px;margin-bottom:4px;width:100%;align-items:flex-end;box-sizing:border-box}:host.cluster-single{margin-bottom:12px}:host.cluster-first{margin-bottom:2px}:host.cluster-middle{margin-bottom:2px}:host.cluster-last{margin-bottom:12px}:host:not(.is-own-message){justify-content:flex-start!important;flex-direction:row!important}:host.is-own-message{justify-content:flex-end!important;flex-direction:row-reverse!important;margin-left:auto!important;margin-right:0!important}.avatar-wrapper{flex-shrink:0;display:flex;align-items:flex-end;width:32px}.avatar-wrapper.hidden{visibility:hidden}.message-content-wrapper{display:flex;flex-direction:column;gap:0;max-width:75%;min-width:0}:host:not(.is-own-message) .message-content-wrapper{align-items:flex-start}:host.is-own-message .message-content-wrapper{align-items:flex-end!important;margin-left:auto!important;margin-right:0!important}.message-bubble{padding:8px 12px;border-radius:20px;position:relative;word-wrap:break-word;white-space:pre-wrap;max-width:100%;display:flex;flex-direction:column;transition:transform var(--spring-bouncy),border-radius var(--spring-bouncy);will-change:transform,border-radius}:host:active .message-bubble{transform:scale(.98);transition:transform .1s ease-out,border-radius .1s ease-out}:host.is-own-message.cluster-first .message-bubble{border-radius:20px 20px 4px}:host.is-own-message.cluster-middle .message-bubble{border-radius:20px 4px 4px 20px}:host.is-own-message.cluster-last .message-bubble{border-radius:20px 4px 20px 20px}:host:not(.is-own-message).cluster-first .message-bubble{border-radius:20px 20px 20px 4px}:host:not(.is-own-message).cluster-middle .message-bubble{border-radius:4px 20px 20px 4px}:host:not(.is-own-message).cluster-last .message-bubble{border-radius:4px 20px 20px}:host:not(.is-own-message) .message-bubble{background:var(--color-background-neutral-secondary, #f5f5f5)}:host.is-own-message .message-bubble{background:var(--color-accent, var(--color-accent, #6B5FF5));color:var(--color-on-accent, #ffffff)}.message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;margin:0}:host:not(.is-own-message) .message-text{color:var(--color-text-primary, #1a1a1a)}:host.is-own-message .message-text{color:var(--color-on-accent, #ffffff)}:host.is-deleted .message-bubble{background:var(--color-background-neutral-secondary, #f5f5f5)!important}:host.is-deleted.is-own-message .message-bubble{background:var(--color-background-neutral-tertiary, #e8e8e8)!important}:host.is-deleted .message-text{font-style:italic;color:var(--text-color-default-tertiary, #737373)!important}:host.is-deleted.is-own-message .message-text{color:var(--text-color-default-secondary, #545b66)!important}.edited-hint{font-family:Brockmann,sans-serif;font-size:10px;font-weight:400;opacity:.75;margin:4px 0 0;align-self:flex-end}:host:not(.is-own-message) .edited-hint{align-self:flex-start;color:var(--text-color-default-tertiary, #737373)}:host.is-own-message .edited-hint{color:var(--color-on-accent, #ffffff)}.attachments{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}:host:not(.is-own-message) .attachments{justify-content:flex-start}:host.is-own-message .attachments{justify-content:flex-end}.attachment-item{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:8px;border:1px solid var(--border-color-default, #e5e5e5);cursor:pointer;transition:background .2s ease}:host.is-own-message .attachment-item{background:#fff3;border-color:#ffffff4d}.attachment-item:active{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host.is-own-message .attachment-item:active{background:#ffffff4d}.attachment-icon{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:var(--color-background-neutral-primary, #ffffff)}:host.is-own-message .attachment-icon{background:#ffffff4d}.attachment-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:500;line-height:16px;color:var(--color-text-primary, #1a1a1a);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host.is-own-message .attachment-name{color:var(--color-text-on-brand, #ffffff)}.message-footer{display:flex;align-items:center;gap:4px;align-self:flex-end;height:0;margin-top:0;opacity:0;overflow:hidden;transform:scale(.95);transition:height var(--spring-bouncy),margin-top var(--spring-bouncy),opacity var(--spring-bouncy),transform var(--spring-bouncy)}.message-footer.visible{height:14px;margin-top:4px;opacity:1;transform:scale(1)}:host:not(.is-own-message) .message-footer{align-self:flex-end}.timestamp{font-family:Brockmann,sans-serif;font-size:11px;font-weight:400;line-height:14px;white-space:nowrap}:host:not(.is-own-message) .timestamp{color:var(--color-text-tertiary, #a0a0a0)}:host.is-own-message .timestamp{color:var(--color-on-accent, #ffffff);opacity:.7}:host{-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}:host.is-new-message{animation:message-appear var(--spring-bouncy) forwards}@keyframes message-appear{0%{opacity:0;transform:translateY(20px) scale(.92)}to{opacity:1;transform:translateY(0) scale(1)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
9966
+ `, isInline: true, styles: [":host{display:flex;gap:8px;margin-bottom:4px;width:100%;align-items:flex-end;box-sizing:border-box}:host.cluster-single{margin-bottom:12px}:host.cluster-first{margin-bottom:2px}:host.cluster-middle{margin-bottom:2px}:host.cluster-last{margin-bottom:12px}:host:not(.is-own-message){justify-content:flex-start!important;flex-direction:row!important}:host.is-own-message{justify-content:flex-end!important;flex-direction:row-reverse!important;margin-left:auto!important;margin-right:0!important}.avatar-wrapper{flex-shrink:0;display:flex;align-items:flex-end;width:32px}.avatar-wrapper.hidden{visibility:hidden}.message-content-wrapper{display:flex;flex-direction:column;gap:0;max-width:75%;min-width:0}:host:not(.is-own-message) .message-content-wrapper{align-items:flex-start}:host.is-own-message .message-content-wrapper{align-items:flex-end!important;margin-left:auto!important;margin-right:0!important}.message-bubble{padding:8px 12px;border-radius:20px;position:relative;word-wrap:break-word;white-space:pre-wrap;max-width:100%;display:flex;flex-direction:column;transition:transform var(--spring-bouncy),border-radius var(--spring-bouncy);will-change:transform,border-radius}:host:active .message-bubble{transform:scale(.98);transition:transform .1s ease-out,border-radius .1s ease-out}:host.is-own-message.cluster-first .message-bubble{border-radius:20px 20px 4px}:host.is-own-message.cluster-middle .message-bubble{border-radius:20px 4px 4px 20px}:host.is-own-message.cluster-last .message-bubble{border-radius:20px 4px 20px 20px}:host:not(.is-own-message).cluster-first .message-bubble{border-radius:20px 20px 20px 4px}:host:not(.is-own-message).cluster-middle .message-bubble{border-radius:4px 20px 20px 4px}:host:not(.is-own-message).cluster-last .message-bubble{border-radius:4px 20px 20px}:host:not(.is-own-message) .message-bubble{background:var(--color-background-neutral-secondary, #f5f5f5)}:host.is-own-message .message-bubble{background:var(--color-accent, var(--color-accent, #6B5FF5));color:var(--color-on-accent, #ffffff)}.message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;margin:0}:host:not(.is-own-message) .message-text{color:var(--color-text-primary, #1a1a1a)}:host.is-own-message .message-text{color:var(--color-on-accent, #ffffff)}:host.is-deleted .message-bubble{background:var(--color-background-neutral-secondary, #f5f5f5)!important}:host.is-deleted.is-own-message .message-bubble{background:var(--color-background-neutral-tertiary, #e8e8e8)!important}:host.is-deleted .message-text{font-style:italic;color:var(--text-color-default-tertiary, #737373)!important}:host.is-deleted.is-own-message .message-text{color:var(--text-color-default-secondary, #545b66)!important}.edited-hint{font-family:Brockmann,sans-serif;font-size:10px;font-weight:400;opacity:.75;margin:4px 0 0;align-self:flex-end}:host:not(.is-own-message) .edited-hint{align-self:flex-start;color:var(--text-color-default-tertiary, #737373)}:host.is-own-message .edited-hint{color:var(--color-on-accent, #ffffff)}.attachments{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}:host:not(.is-own-message) .attachments{justify-content:flex-start}:host.is-own-message .attachments{justify-content:flex-end}.attachment-item{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:8px;border:1px solid var(--border-color-default, #e5e5e5);cursor:pointer;transition:background .2s ease}:host.is-own-message .attachment-item{background:#fff3;border-color:#ffffff4d}.attachment-item:active{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host.is-own-message .attachment-item:active{background:#ffffff4d}.attachment-icon{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:var(--color-background-neutral-primary, #ffffff)}:host.is-own-message .attachment-icon{background:#ffffff4d}.attachment-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:500;line-height:16px;color:var(--color-text-primary, #1a1a1a);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host.is-own-message .attachment-name{color:var(--color-text-on-brand, #ffffff)}.message-footer{display:flex;align-items:center;gap:4px;align-self:flex-end;height:0;margin-top:0;opacity:0;overflow:hidden;transform:scale(.95);transition:height var(--spring-bouncy),margin-top var(--spring-bouncy),opacity var(--spring-bouncy),transform var(--spring-bouncy)}.message-footer.visible{height:14px;margin-top:4px;opacity:1;transform:scale(1)}:host:not(.is-own-message) .message-footer{align-self:flex-end}.timestamp{font-family:Brockmann,sans-serif;font-size:11px;font-weight:400;line-height:14px;white-space:nowrap}:host:not(.is-own-message) .timestamp{color:var(--color-text-tertiary, #a0a0a0)}:host.is-own-message .timestamp{color:var(--color-on-accent, #ffffff);opacity:.7}:host{-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}:host.is-new-message{animation:message-appear var(--spring-bouncy) forwards}@keyframes message-appear{0%{opacity:0;transform:translateY(20px) scale(.92)}to{opacity:1;transform:translateY(0) scale(1)}}.message-bubble.is-internal{background:var(--color-background-warning-subtle, #fefce8)!important;border:1px solid var(--color-border-warning-muted, #fde047)}:host.is-own-message .message-bubble.is-internal{background:var(--color-background-warning-subtle, #fefce8)!important;color:var(--color-text-primary, #1a1a1a)}:host.is-own-message .message-bubble.is-internal .message-text{color:var(--color-text-primary, #1a1a1a)}.internal-message-badge{display:flex;align-items:center;gap:4px;font-family:Brockmann,sans-serif;font-size:11px;font-weight:500;color:var(--color-text-warning, #eab308);margin-bottom:4px;padding-left:12px}:host.is-own-message .internal-message-badge{align-self:flex-end;padding-left:0;padding-right:12px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarComponent, selector: "ds-avatar", inputs: ["type", "size", "initials", "src", "alt", "iconName", "iconColor"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }] });
9953
9967
  }
9954
9968
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileMessageBubbleComponent, decorators: [{
9955
9969
  type: Component,
@@ -9979,7 +9993,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
9979
9993
  }
9980
9994
 
9981
9995
  <div class="message-content-wrapper" (click)="handleClick($event)">
9982
- <div class="message-bubble">
9996
+ @if (isInternal()) {
9997
+ <div class="internal-message-badge">
9998
+ <ds-icon name="remixLockLine" size="12px"></ds-icon>
9999
+ <span>{{ internalMessageBadgeText() }}</span>
10000
+ </div>
10001
+ }
10002
+ <div class="message-bubble" [class.is-internal]="isInternal()">
9983
10003
  <!-- Only show text if content is not empty -->
9984
10004
  @if (content().trim()) {
9985
10005
  <p class="message-text">{{ content() }}</p>
@@ -10016,8 +10036,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
10016
10036
  </div>
10017
10037
  </div>
10018
10038
  </div>
10019
- `, styles: [":host{display:flex;gap:8px;margin-bottom:4px;width:100%;align-items:flex-end;box-sizing:border-box}:host.cluster-single{margin-bottom:12px}:host.cluster-first{margin-bottom:2px}:host.cluster-middle{margin-bottom:2px}:host.cluster-last{margin-bottom:12px}:host:not(.is-own-message){justify-content:flex-start!important;flex-direction:row!important}:host.is-own-message{justify-content:flex-end!important;flex-direction:row-reverse!important;margin-left:auto!important;margin-right:0!important}.avatar-wrapper{flex-shrink:0;display:flex;align-items:flex-end;width:32px}.avatar-wrapper.hidden{visibility:hidden}.message-content-wrapper{display:flex;flex-direction:column;gap:0;max-width:75%;min-width:0}:host:not(.is-own-message) .message-content-wrapper{align-items:flex-start}:host.is-own-message .message-content-wrapper{align-items:flex-end!important;margin-left:auto!important;margin-right:0!important}.message-bubble{padding:8px 12px;border-radius:20px;position:relative;word-wrap:break-word;white-space:pre-wrap;max-width:100%;display:flex;flex-direction:column;transition:transform var(--spring-bouncy),border-radius var(--spring-bouncy);will-change:transform,border-radius}:host:active .message-bubble{transform:scale(.98);transition:transform .1s ease-out,border-radius .1s ease-out}:host.is-own-message.cluster-first .message-bubble{border-radius:20px 20px 4px}:host.is-own-message.cluster-middle .message-bubble{border-radius:20px 4px 4px 20px}:host.is-own-message.cluster-last .message-bubble{border-radius:20px 4px 20px 20px}:host:not(.is-own-message).cluster-first .message-bubble{border-radius:20px 20px 20px 4px}:host:not(.is-own-message).cluster-middle .message-bubble{border-radius:4px 20px 20px 4px}:host:not(.is-own-message).cluster-last .message-bubble{border-radius:4px 20px 20px}:host:not(.is-own-message) .message-bubble{background:var(--color-background-neutral-secondary, #f5f5f5)}:host.is-own-message .message-bubble{background:var(--color-accent, var(--color-accent, #6B5FF5));color:var(--color-on-accent, #ffffff)}.message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;margin:0}:host:not(.is-own-message) .message-text{color:var(--color-text-primary, #1a1a1a)}:host.is-own-message .message-text{color:var(--color-on-accent, #ffffff)}:host.is-deleted .message-bubble{background:var(--color-background-neutral-secondary, #f5f5f5)!important}:host.is-deleted.is-own-message .message-bubble{background:var(--color-background-neutral-tertiary, #e8e8e8)!important}:host.is-deleted .message-text{font-style:italic;color:var(--text-color-default-tertiary, #737373)!important}:host.is-deleted.is-own-message .message-text{color:var(--text-color-default-secondary, #545b66)!important}.edited-hint{font-family:Brockmann,sans-serif;font-size:10px;font-weight:400;opacity:.75;margin:4px 0 0;align-self:flex-end}:host:not(.is-own-message) .edited-hint{align-self:flex-start;color:var(--text-color-default-tertiary, #737373)}:host.is-own-message .edited-hint{color:var(--color-on-accent, #ffffff)}.attachments{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}:host:not(.is-own-message) .attachments{justify-content:flex-start}:host.is-own-message .attachments{justify-content:flex-end}.attachment-item{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:8px;border:1px solid var(--border-color-default, #e5e5e5);cursor:pointer;transition:background .2s ease}:host.is-own-message .attachment-item{background:#fff3;border-color:#ffffff4d}.attachment-item:active{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host.is-own-message .attachment-item:active{background:#ffffff4d}.attachment-icon{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:var(--color-background-neutral-primary, #ffffff)}:host.is-own-message .attachment-icon{background:#ffffff4d}.attachment-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:500;line-height:16px;color:var(--color-text-primary, #1a1a1a);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host.is-own-message .attachment-name{color:var(--color-text-on-brand, #ffffff)}.message-footer{display:flex;align-items:center;gap:4px;align-self:flex-end;height:0;margin-top:0;opacity:0;overflow:hidden;transform:scale(.95);transition:height var(--spring-bouncy),margin-top var(--spring-bouncy),opacity var(--spring-bouncy),transform var(--spring-bouncy)}.message-footer.visible{height:14px;margin-top:4px;opacity:1;transform:scale(1)}:host:not(.is-own-message) .message-footer{align-self:flex-end}.timestamp{font-family:Brockmann,sans-serif;font-size:11px;font-weight:400;line-height:14px;white-space:nowrap}:host:not(.is-own-message) .timestamp{color:var(--color-text-tertiary, #a0a0a0)}:host.is-own-message .timestamp{color:var(--color-on-accent, #ffffff);opacity:.7}:host{-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}:host.is-new-message{animation:message-appear var(--spring-bouncy) forwards}@keyframes message-appear{0%{opacity:0;transform:translateY(20px) scale(.92)}to{opacity:1;transform:translateY(0) scale(1)}}\n"] }]
10020
- }], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }], isOwnMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOwnMessage", required: false }] }], senderName: [{ type: i0.Input, args: [{ isSignal: true, alias: "senderName", required: false }] }], timestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "timestamp", required: true }] }], showTimestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTimestamp", required: false }] }], avatarInitials: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarInitials", required: false }] }], avatarType: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarType", required: false }] }], avatarSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarSrc", required: false }] }], showAvatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAvatar", required: false }] }], clusterPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "clusterPosition", required: false }] }], attachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachments", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], isNewMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isNewMessage", required: false }] }], isDeleted: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDeleted", required: false }] }], showEditedHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEditedHint", required: false }] }], editedHintText: [{ type: i0.Input, args: [{ isSignal: true, alias: "editedHintText", required: false }] }], attachmentClick: [{ type: i0.Output, args: ["attachmentClick"] }], longPress: [{ type: i0.Output, args: ["longPress"] }], messageClick: [{ type: i0.Output, args: ["messageClick"] }] } });
10039
+ `, styles: [":host{display:flex;gap:8px;margin-bottom:4px;width:100%;align-items:flex-end;box-sizing:border-box}:host.cluster-single{margin-bottom:12px}:host.cluster-first{margin-bottom:2px}:host.cluster-middle{margin-bottom:2px}:host.cluster-last{margin-bottom:12px}:host:not(.is-own-message){justify-content:flex-start!important;flex-direction:row!important}:host.is-own-message{justify-content:flex-end!important;flex-direction:row-reverse!important;margin-left:auto!important;margin-right:0!important}.avatar-wrapper{flex-shrink:0;display:flex;align-items:flex-end;width:32px}.avatar-wrapper.hidden{visibility:hidden}.message-content-wrapper{display:flex;flex-direction:column;gap:0;max-width:75%;min-width:0}:host:not(.is-own-message) .message-content-wrapper{align-items:flex-start}:host.is-own-message .message-content-wrapper{align-items:flex-end!important;margin-left:auto!important;margin-right:0!important}.message-bubble{padding:8px 12px;border-radius:20px;position:relative;word-wrap:break-word;white-space:pre-wrap;max-width:100%;display:flex;flex-direction:column;transition:transform var(--spring-bouncy),border-radius var(--spring-bouncy);will-change:transform,border-radius}:host:active .message-bubble{transform:scale(.98);transition:transform .1s ease-out,border-radius .1s ease-out}:host.is-own-message.cluster-first .message-bubble{border-radius:20px 20px 4px}:host.is-own-message.cluster-middle .message-bubble{border-radius:20px 4px 4px 20px}:host.is-own-message.cluster-last .message-bubble{border-radius:20px 4px 20px 20px}:host:not(.is-own-message).cluster-first .message-bubble{border-radius:20px 20px 20px 4px}:host:not(.is-own-message).cluster-middle .message-bubble{border-radius:4px 20px 20px 4px}:host:not(.is-own-message).cluster-last .message-bubble{border-radius:4px 20px 20px}:host:not(.is-own-message) .message-bubble{background:var(--color-background-neutral-secondary, #f5f5f5)}:host.is-own-message .message-bubble{background:var(--color-accent, var(--color-accent, #6B5FF5));color:var(--color-on-accent, #ffffff)}.message-text{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:20px;letter-spacing:-.3px;margin:0}:host:not(.is-own-message) .message-text{color:var(--color-text-primary, #1a1a1a)}:host.is-own-message .message-text{color:var(--color-on-accent, #ffffff)}:host.is-deleted .message-bubble{background:var(--color-background-neutral-secondary, #f5f5f5)!important}:host.is-deleted.is-own-message .message-bubble{background:var(--color-background-neutral-tertiary, #e8e8e8)!important}:host.is-deleted .message-text{font-style:italic;color:var(--text-color-default-tertiary, #737373)!important}:host.is-deleted.is-own-message .message-text{color:var(--text-color-default-secondary, #545b66)!important}.edited-hint{font-family:Brockmann,sans-serif;font-size:10px;font-weight:400;opacity:.75;margin:4px 0 0;align-self:flex-end}:host:not(.is-own-message) .edited-hint{align-self:flex-start;color:var(--text-color-default-tertiary, #737373)}:host.is-own-message .edited-hint{color:var(--color-on-accent, #ffffff)}.attachments{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}:host:not(.is-own-message) .attachments{justify-content:flex-start}:host.is-own-message .attachments{justify-content:flex-end}.attachment-item{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--color-background-neutral-secondary, #f5f5f5);border-radius:8px;border:1px solid var(--border-color-default, #e5e5e5);cursor:pointer;transition:background .2s ease}:host.is-own-message .attachment-item{background:#fff3;border-color:#ffffff4d}.attachment-item:active{background:var(--color-background-neutral-secondary-hover, #ebebeb)}:host.is-own-message .attachment-item:active{background:#ffffff4d}.attachment-icon{flex-shrink:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border-radius:4px;background:var(--color-background-neutral-primary, #ffffff)}:host.is-own-message .attachment-icon{background:#ffffff4d}.attachment-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:500;line-height:16px;color:var(--color-text-primary, #1a1a1a);max-width:150px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host.is-own-message .attachment-name{color:var(--color-text-on-brand, #ffffff)}.message-footer{display:flex;align-items:center;gap:4px;align-self:flex-end;height:0;margin-top:0;opacity:0;overflow:hidden;transform:scale(.95);transition:height var(--spring-bouncy),margin-top var(--spring-bouncy),opacity var(--spring-bouncy),transform var(--spring-bouncy)}.message-footer.visible{height:14px;margin-top:4px;opacity:1;transform:scale(1)}:host:not(.is-own-message) .message-footer{align-self:flex-end}.timestamp{font-family:Brockmann,sans-serif;font-size:11px;font-weight:400;line-height:14px;white-space:nowrap}:host:not(.is-own-message) .timestamp{color:var(--color-text-tertiary, #a0a0a0)}:host.is-own-message .timestamp{color:var(--color-on-accent, #ffffff);opacity:.7}:host{-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}:host.is-new-message{animation:message-appear var(--spring-bouncy) forwards}@keyframes message-appear{0%{opacity:0;transform:translateY(20px) scale(.92)}to{opacity:1;transform:translateY(0) scale(1)}}.message-bubble.is-internal{background:var(--color-background-warning-subtle, #fefce8)!important;border:1px solid var(--color-border-warning-muted, #fde047)}:host.is-own-message .message-bubble.is-internal{background:var(--color-background-warning-subtle, #fefce8)!important;color:var(--color-text-primary, #1a1a1a)}:host.is-own-message .message-bubble.is-internal .message-text{color:var(--color-text-primary, #1a1a1a)}.internal-message-badge{display:flex;align-items:center;gap:4px;font-family:Brockmann,sans-serif;font-size:11px;font-weight:500;color:var(--color-text-warning, #eab308);margin-bottom:4px;padding-left:12px}:host.is-own-message .internal-message-badge{align-self:flex-end;padding-left:0;padding-right:12px}\n"] }]
10040
+ }], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: true }] }], isOwnMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOwnMessage", required: false }] }], senderName: [{ type: i0.Input, args: [{ isSignal: true, alias: "senderName", required: false }] }], isInternal: [{ type: i0.Input, args: [{ isSignal: true, alias: "isInternal", required: false }] }], internalMessageBadgeText: [{ type: i0.Input, args: [{ isSignal: true, alias: "internalMessageBadgeText", required: false }] }], timestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "timestamp", required: true }] }], showTimestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTimestamp", required: false }] }], avatarInitials: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarInitials", required: false }] }], avatarType: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarType", required: false }] }], avatarSrc: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatarSrc", required: false }] }], showAvatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAvatar", required: false }] }], clusterPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "clusterPosition", required: false }] }], attachments: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachments", required: false }] }], clickable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clickable", required: false }] }], isNewMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isNewMessage", required: false }] }], isDeleted: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDeleted", required: false }] }], showEditedHint: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEditedHint", required: false }] }], editedHintText: [{ type: i0.Input, args: [{ isSignal: true, alias: "editedHintText", required: false }] }], attachmentClick: [{ type: i0.Output, args: ["attachmentClick"] }], longPress: [{ type: i0.Output, args: ["longPress"] }], messageClick: [{ type: i0.Output, args: ["messageClick"] }] } });
10021
10041
 
10022
10042
  /**
10023
10043
  * DsMobileListItemStaticComponent
@@ -16040,6 +16060,7 @@ const DEFAULT_CHAT_LABELS = {
16040
16060
  internalToggleLabel: 'Intern besked',
16041
16061
  replyLabel: 'Besvar',
16042
16062
  internalMessageDescription: 'Interne beskeder er kun synlige for interne brugere. Lejeren kan ikke se denne besked.',
16063
+ internalMessageBadge: 'Intern besked',
16043
16064
  addMembersTitle: 'Tilføj beboere',
16044
16065
  youSenderName: 'You',
16045
16066
  actionCopy: 'Kopiér',
@@ -16134,7 +16155,7 @@ class DsMobileChatModalComponent {
16134
16155
  const uid = this.chatData?.currentUserId;
16135
16156
  if (!uid)
16136
16157
  return members;
16137
- return members.filter(m => m.id !== uid);
16158
+ return members.filter((m) => m.id !== uid);
16138
16159
  }, ...(ngDevMode ? [{ debugName: "groupMembersForStack" }] : []));
16139
16160
  isGroupAdmin = computed(() => {
16140
16161
  const g = this.group();
@@ -16334,7 +16355,8 @@ class DsMobileChatModalComponent {
16334
16355
  avatarType: this.currentUserAvatarType(),
16335
16356
  avatarSrc: this.currentUserAvatarSrc(),
16336
16357
  fileAttachments: event.attachments || [],
16337
- isNewMessage: true, // Mark as new message to trigger animation
16358
+ isNewMessage: true,
16359
+ isInternal: event.isInternal,
16338
16360
  };
16339
16361
  // Add message to list
16340
16362
  const updatedMessages = [...this.messages(), newMessage];
@@ -16550,9 +16572,7 @@ class DsMobileChatModalComponent {
16550
16572
  ],
16551
16573
  },
16552
16574
  ];
16553
- const canEdit = message.isOwnMessage &&
16554
- !message.fileAttachments?.length &&
16555
- message.content.trim().length > 0;
16575
+ const canEdit = message.isOwnMessage && !message.fileAttachments?.length && message.content.trim().length > 0;
16556
16576
  const canDelete = message.isOwnMessage;
16557
16577
  if (canEdit) {
16558
16578
  groups[0].actions.push({
@@ -16633,13 +16653,13 @@ class DsMobileChatModalComponent {
16633
16653
  if (!this.chatData.onEditMessage)
16634
16654
  return;
16635
16655
  await this.chatData.onEditMessage(messageId, newContent);
16636
- this.messages.update(msgs => msgs.map(m => m.id === messageId ? { ...m, content: newContent, editedAt: new Date() } : m));
16656
+ this.messages.update((msgs) => msgs.map((m) => (m.id === messageId ? { ...m, content: newContent, editedAt: new Date() } : m)));
16637
16657
  }
16638
16658
  async applyMessageDelete(messageId) {
16639
16659
  if (!this.chatData.onDeleteMessage)
16640
16660
  return;
16641
16661
  await this.chatData.onDeleteMessage(messageId);
16642
- this.messages.update(msgs => msgs.map(m => m.id === messageId ? { ...m, deletedAt: new Date(), content: '' } : m));
16662
+ this.messages.update((msgs) => msgs.map((m) => (m.id === messageId ? { ...m, deletedAt: new Date(), content: '' } : m)));
16643
16663
  }
16644
16664
  deletePlaceholder(message) {
16645
16665
  return message.isOwnMessage ? this.lbl.deletePlaceholderOwn : this.lbl.deletePlaceholderOther;
@@ -16648,21 +16668,13 @@ class DsMobileChatModalComponent {
16648
16668
  const m = message.systemMeta;
16649
16669
  switch (message.systemKind) {
16650
16670
  case 'member_added':
16651
- return m?.actorName && m?.targetName
16652
- ? this.lbl.activityMemberAddedWithNames(m.actorName, m.targetName)
16653
- : this.lbl.activityMemberAdded;
16671
+ return m?.actorName && m?.targetName ? this.lbl.activityMemberAddedWithNames(m.actorName, m.targetName) : this.lbl.activityMemberAdded;
16654
16672
  case 'member_removed':
16655
- return m?.actorName && m?.targetName
16656
- ? this.lbl.activityMemberRemovedWithNames(m.actorName, m.targetName)
16657
- : this.lbl.activityMemberRemoved;
16673
+ return m?.actorName && m?.targetName ? this.lbl.activityMemberRemovedWithNames(m.actorName, m.targetName) : this.lbl.activityMemberRemoved;
16658
16674
  case 'renamed':
16659
- return m?.newTitle
16660
- ? this.lbl.activityRenamed(m.newTitle)
16661
- : this.lbl.activityRenamedFallback;
16675
+ return m?.newTitle ? this.lbl.activityRenamed(m.newTitle) : this.lbl.activityRenamedFallback;
16662
16676
  case 'left_group':
16663
- return m?.actorName
16664
- ? this.lbl.activityLeftGroup(m.actorName)
16665
- : this.lbl.activityLeftGroupFallback;
16677
+ return m?.actorName ? this.lbl.activityLeftGroup(m.actorName) : this.lbl.activityLeftGroupFallback;
16666
16678
  default:
16667
16679
  return '';
16668
16680
  }
@@ -16694,32 +16706,30 @@ class DsMobileChatModalComponent {
16694
16706
  if (!data?.onRenameGroup)
16695
16707
  return;
16696
16708
  await data.onRenameGroup(title);
16697
- this.participant.update(p => ({ ...p, name: title }));
16698
- this.group.update(gr => (gr ? { ...gr, title } : gr));
16709
+ this.participant.update((p) => ({ ...p, name: title }));
16710
+ this.group.update((gr) => (gr ? { ...gr, title } : gr));
16699
16711
  }
16700
16712
  async handleAvatarUrlFromPanel(url) {
16701
16713
  const data = this.chatData;
16702
16714
  if (!data?.onSetGroupCustomAvatarUrl)
16703
16715
  return;
16704
16716
  await data.onSetGroupCustomAvatarUrl(url);
16705
- this.group.update(gr => gr ? { ...gr, customAvatarUrl: url || undefined } : gr);
16717
+ this.group.update((gr) => (gr ? { ...gr, customAvatarUrl: url || undefined } : gr));
16706
16718
  }
16707
16719
  async handleAddMembersFromPanel(ids) {
16708
16720
  const data = this.chatData;
16709
16721
  if (!data?.onAddMembers)
16710
16722
  return;
16711
16723
  await data.onAddMembers(ids);
16712
- this.group.update(gr => {
16724
+ this.group.update((gr) => {
16713
16725
  if (!gr)
16714
16726
  return gr;
16715
- const existing = new Set(gr.members.map(m => m.id));
16727
+ const existing = new Set(gr.members.map((m) => m.id));
16716
16728
  const newMembers = ids
16717
- .filter(id => !existing.has(id))
16718
- .map(id => data.allTenantsForPicker.find(x => x.id === id))
16729
+ .filter((id) => !existing.has(id))
16730
+ .map((id) => data.allTenantsForPicker.find((x) => x.id === id))
16719
16731
  .filter((t) => !!t);
16720
- return newMembers.length > 0
16721
- ? { ...gr, members: [...gr.members, ...newMembers] }
16722
- : gr;
16732
+ return newMembers.length > 0 ? { ...gr, members: [...gr.members, ...newMembers] } : gr;
16723
16733
  });
16724
16734
  }
16725
16735
  async handleRemoveMemberFromPanel(userId) {
@@ -16727,7 +16737,7 @@ class DsMobileChatModalComponent {
16727
16737
  if (!data?.onRemoveMember)
16728
16738
  return;
16729
16739
  await data.onRemoveMember(userId);
16730
- this.group.update(g => g ? { ...g, members: g.members.filter(x => x.id !== userId) } : g);
16740
+ this.group.update((g) => (g ? { ...g, members: g.members.filter((x) => x.id !== userId) } : g));
16731
16741
  }
16732
16742
  async handleMessageMemberFromPanel(userId) {
16733
16743
  if (this.chatData?.onMessageMember) {
@@ -16953,10 +16963,7 @@ class DsMobileChatModalComponent {
16953
16963
  />
16954
16964
  }
16955
16965
  } @else if (participant().avatarShape === 'squircle') {
16956
- <ds-mobile-vendor-avatar
16957
- [name]="participant().name"
16958
- [logo]="participant().avatarSrc || ''"
16959
- size="md" />
16966
+ <ds-mobile-vendor-avatar [name]="participant().name" [logo]="participant().avatarSrc || ''" size="md" />
16960
16967
  } @else {
16961
16968
  <ds-avatar-with-badge
16962
16969
  [initials]="participant().avatarInitials || ''"
@@ -17006,155 +17013,153 @@ class DsMobileChatModalComponent {
17006
17013
  (leaveGroup)="handleLeaveGroupFromPanel()"
17007
17014
  />
17008
17015
  } @else {
17009
- <!-- Messages Section -->
17010
- <ds-mobile-section>
17011
- <div class="chat-messages-container" (click)="handleContentClick()">
17012
- <!-- Centered avatar section at top of messages -->
17013
- <div class="chat-avatar-section">
17014
- @if (threadKind() === 'group' && group()) {
17015
- <ds-mobile-group-avatar-stack
17016
- [members]="groupMembersForStack()"
17017
- [customAvatarUrl]="group()!.customAvatarUrl || ''"
17018
- layout="list"
17019
- size="xl"
17020
- style="cursor: pointer"
17021
- (click)="onGroupTitleClick(); $event.stopPropagation()"
17022
- />
17023
- } @else if (participant().avatarShape === 'squircle') {
17024
- <ds-mobile-vendor-avatar
17025
- [name]="participant().name"
17026
- [logo]="participant().avatarSrc || ''"
17027
- size="xl" />
17028
- } @else {
17029
- <ds-avatar-with-badge
17030
- [initials]="participant().avatarInitials || ''"
17031
- [type]="participant().avatarType || 'initials'"
17032
- [src]="participant().avatarSrc || ''"
17033
- [badge]="participant().badge"
17034
- [showBadge]="threadContext() === 'inquiry'"
17035
- size="xl"
17036
- />
17037
- }
17038
- <div class="chat-avatar-info">
17039
- <div class="chat-avatar-name">
17040
- {{ participant().name }}
17041
- @if (participant().verified) {
17042
- <ds-icon name="remixCheckboxCircleFill" size="24px" [style.color]="'var(--color-primary-base)'"></ds-icon>
17016
+ <!-- Messages Section -->
17017
+ <ds-mobile-section>
17018
+ <div class="chat-messages-container" (click)="handleContentClick()">
17019
+ <!-- Centered avatar section at top of messages -->
17020
+ <div class="chat-avatar-section">
17021
+ @if (threadKind() === 'group' && group()) {
17022
+ <ds-mobile-group-avatar-stack
17023
+ [members]="groupMembersForStack()"
17024
+ [customAvatarUrl]="group()!.customAvatarUrl || ''"
17025
+ layout="list"
17026
+ size="xl"
17027
+ style="cursor: pointer"
17028
+ (click)="onGroupTitleClick(); $event.stopPropagation()"
17029
+ />
17030
+ } @else if (participant().avatarShape === 'squircle') {
17031
+ <ds-mobile-vendor-avatar [name]="participant().name" [logo]="participant().avatarSrc || ''" size="xl" />
17032
+ } @else {
17033
+ <ds-avatar-with-badge
17034
+ [initials]="participant().avatarInitials || ''"
17035
+ [type]="participant().avatarType || 'initials'"
17036
+ [src]="participant().avatarSrc || ''"
17037
+ [badge]="participant().badge"
17038
+ [showBadge]="threadContext() === 'inquiry'"
17039
+ size="xl"
17040
+ />
17041
+ }
17042
+ <div class="chat-avatar-info">
17043
+ <div class="chat-avatar-name">
17044
+ {{ participant().name }}
17045
+ @if (participant().verified) {
17046
+ <ds-icon name="remixCheckboxCircleFill" size="24px" [style.color]="'var(--color-primary-base)'"></ds-icon>
17047
+ }
17048
+ </div>
17049
+ @if (participant().role) {
17050
+ <div class="chat-avatar-role">{{ participant().role }}</div>
17051
+ }
17052
+ @if (participant().lastActive) {
17053
+ <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
17043
17054
  }
17044
17055
  </div>
17045
- @if (participant().role) {
17046
- <div class="chat-avatar-role">{{ participant().role }}</div>
17047
- }
17048
- @if (participant().lastActive) {
17049
- <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
17050
- }
17051
17056
  </div>
17052
- </div>
17053
-
17054
- <div class="messages-list">
17055
- @if (messages().length === 0) {
17056
- <!-- Empty State - Timestamp and optional inquiry system message -->
17057
- <div class="timestamp-header">
17058
- <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
17059
- </div>
17060
17057
 
17061
- @if (threadContext() === 'inquiry') {
17062
- <ds-mobile-system-message-banner [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'" [afterTimestamp]="true">
17063
- </ds-mobile-system-message-banner>
17064
- }
17065
- } @else {
17066
- @for (group of messagesWithDisplay(); track group.timestamp) {
17067
- <!-- Timestamp Header -->
17058
+ <div class="messages-list">
17059
+ @if (messages().length === 0) {
17060
+ <!-- Empty State - Timestamp and optional inquiry system message -->
17068
17061
  <div class="timestamp-header">
17069
- <span class="timestamp-text">{{ group.displayTimestamp }}</span>
17062
+ <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
17070
17063
  </div>
17071
17064
 
17072
- @if ($first && threadContext() === 'inquiry') {
17065
+ @if (threadContext() === 'inquiry') {
17073
17066
  <ds-mobile-system-message-banner [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'" [afterTimestamp]="true">
17074
17067
  </ds-mobile-system-message-banner>
17075
17068
  }
17076
- @for (message of group.messages; track message.id) {
17077
- @if (message.systemKind) {
17078
- <p class="chat-system-line">{{ formatActivityLine(message) }}</p>
17079
- } @else if (message.senderId === 'system' && message.content.trim()) {
17080
- <p class="chat-system-line">{{ message.content }}</p>
17081
- } @else if (message.deletedAt) {
17082
- <ds-mobile-message-bubble
17083
- [content]="deletePlaceholder(message)"
17084
- [isOwnMessage]="message.isOwnMessage"
17085
- [timestamp]="formatMessageTimestamp(message.timestamp)"
17086
- [showTimestamp]="selectedMessageId() === message.id"
17087
- [avatarInitials]="message.avatarInitials || ''"
17088
- [avatarType]="message.avatarType || 'initials'"
17089
- [avatarSrc]="message.avatarSrc || ''"
17090
- [showAvatar]="message.showAvatar"
17091
- [clusterPosition]="message.clusterPosition"
17092
- [attachments]="message.attachments"
17093
- [clickable]="false"
17094
- [isDeleted]="true"
17095
- [isNewMessage]="false"
17096
- >
17097
- </ds-mobile-message-bubble>
17098
- } @else if (message.content.trim()) {
17099
- <ds-mobile-message-bubble
17100
- [content]="message.content"
17101
- [isOwnMessage]="message.isOwnMessage"
17102
- [timestamp]="formatMessageTimestamp(message.timestamp)"
17103
- [showTimestamp]="selectedMessageId() === message.id"
17104
- [avatarInitials]="message.avatarInitials || ''"
17105
- [avatarType]="message.avatarType || 'initials'"
17106
- [avatarSrc]="message.avatarSrc || ''"
17107
- [showAvatar]="message.showAvatar && !(message.fileAttachments && message.fileAttachments.length > 0)"
17108
- [clusterPosition]="(message.fileAttachments && message.fileAttachments.length > 0) ? 'first' : message.clusterPosition"
17109
- [attachments]="message.attachments"
17110
- [clickable]="true"
17111
- [isNewMessage]="message.isNewMessage || false"
17112
- [showEditedHint]="!!message.editedAt"
17113
- [editedHintText]="lbl.editedHint"
17114
- (messageClick)="handleMessageClick(message.id)"
17115
- (attachmentClick)="handleAttachmentClick($event)"
17116
- (longPress)="handleMessageLongPress(message)"
17117
- >
17118
- </ds-mobile-message-bubble>
17069
+ } @else {
17070
+ @for (group of messagesWithDisplay(); track group.timestamp) {
17071
+ <!-- Timestamp Header -->
17072
+ <div class="timestamp-header">
17073
+ <span class="timestamp-text">{{ group.displayTimestamp }}</span>
17074
+ </div>
17075
+
17076
+ @if ($first && threadContext() === 'inquiry') {
17077
+ <ds-mobile-system-message-banner [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'" [afterTimestamp]="true">
17078
+ </ds-mobile-system-message-banner>
17119
17079
  }
17080
+ @for (message of group.messages; track message.id) {
17081
+ @if (message.systemKind) {
17082
+ <p class="chat-system-line">{{ formatActivityLine(message) }}</p>
17083
+ } @else if (message.senderId === 'system' && message.content.trim()) {
17084
+ <p class="chat-system-line">{{ message.content }}</p>
17085
+ } @else if (message.deletedAt) {
17086
+ <ds-mobile-message-bubble
17087
+ [content]="deletePlaceholder(message)"
17088
+ [isOwnMessage]="message.isOwnMessage"
17089
+ [isInternal]="message.isInternal || false"
17090
+ [internalMessageBadgeText]="lbl.internalMessageBadge"
17091
+ [timestamp]="formatMessageTimestamp(message.timestamp)"
17092
+ [showTimestamp]="selectedMessageId() === message.id"
17093
+ [avatarInitials]="message.avatarInitials || ''"
17094
+ [avatarType]="message.avatarType || 'initials'"
17095
+ [avatarSrc]="message.avatarSrc || ''"
17096
+ [showAvatar]="message.showAvatar"
17097
+ [clusterPosition]="message.clusterPosition"
17098
+ [attachments]="message.attachments"
17099
+ [clickable]="false"
17100
+ [isDeleted]="true"
17101
+ [isNewMessage]="false"
17102
+ >
17103
+ </ds-mobile-message-bubble>
17104
+ } @else if (message.content.trim()) {
17105
+ <ds-mobile-message-bubble
17106
+ [content]="message.content"
17107
+ [isOwnMessage]="message.isOwnMessage"
17108
+ [isInternal]="message.isInternal || false"
17109
+ [internalMessageBadgeText]="lbl.internalMessageBadge"
17110
+ [timestamp]="formatMessageTimestamp(message.timestamp)"
17111
+ [showTimestamp]="selectedMessageId() === message.id"
17112
+ [avatarInitials]="message.avatarInitials || ''"
17113
+ [avatarType]="message.avatarType || 'initials'"
17114
+ [avatarSrc]="message.avatarSrc || ''"
17115
+ [showAvatar]="message.showAvatar && !(message.fileAttachments && message.fileAttachments.length > 0)"
17116
+ [clusterPosition]="message.fileAttachments && message.fileAttachments.length > 0 ? 'first' : message.clusterPosition"
17117
+ [attachments]="message.attachments"
17118
+ [clickable]="true"
17119
+ [isNewMessage]="message.isNewMessage || false"
17120
+ [showEditedHint]="!!message.editedAt"
17121
+ [editedHintText]="lbl.editedHint"
17122
+ (messageClick)="handleMessageClick(message.id)"
17123
+ (attachmentClick)="handleAttachmentClick($event)"
17124
+ (longPress)="handleMessageLongPress(message)"
17125
+ >
17126
+ </ds-mobile-message-bubble>
17127
+ }
17120
17128
 
17121
- @if (!message.deletedAt && message.fileAttachments && message.fileAttachments.length > 0) {
17122
- <div
17123
- class="message-file-attachments"
17124
- [class.own-message]="message.isOwnMessage"
17125
- [class.attachment-only]="!message.content.trim()"
17126
- (click)="handleMessageClick(message.id)"
17127
- (touchstart)="startAttachmentLongPress(message)"
17128
- (touchend)="cancelAttachmentLongPress()"
17129
- (touchcancel)="cancelAttachmentLongPress()"
17130
- >
17131
- @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {
17132
- @if (fileAttachment.type === 'image') {
17133
- <div
17134
- class="message-image-attachment"
17135
- (click)="handleImageClick(fileAttachment, message); $event.stopPropagation()"
17136
- >
17137
- <img [src]="fileAttachment.src" [alt]="fileAttachment.name || 'Image'" class="inline-image" />
17138
- </div>
17139
- } @else {
17140
- <ds-mobile-card-inline-file
17141
- [fileName]="fileAttachment.name || 'Unknown file'"
17142
- [fileSize]="fileAttachment.size || ''"
17143
- [variant]="getFileVariant(fileAttachment.type)"
17144
- [layout]="'compact'"
17145
- (fileClick)="handleFileAttachmentClick(fileAttachment)"
17146
- >
17147
- </ds-mobile-card-inline-file>
17129
+ @if (!message.deletedAt && message.fileAttachments && message.fileAttachments.length > 0) {
17130
+ <div
17131
+ class="message-file-attachments"
17132
+ [class.own-message]="message.isOwnMessage"
17133
+ [class.attachment-only]="!message.content.trim()"
17134
+ (click)="handleMessageClick(message.id)"
17135
+ (touchstart)="startAttachmentLongPress(message)"
17136
+ (touchend)="cancelAttachmentLongPress()"
17137
+ (touchcancel)="cancelAttachmentLongPress()"
17138
+ >
17139
+ @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {
17140
+ @if (fileAttachment.type === 'image') {
17141
+ <div class="message-image-attachment" (click)="handleImageClick(fileAttachment, message); $event.stopPropagation()">
17142
+ <img [src]="fileAttachment.src" [alt]="fileAttachment.name || 'Image'" class="inline-image" />
17143
+ </div>
17144
+ } @else {
17145
+ <ds-mobile-card-inline-file
17146
+ [fileName]="fileAttachment.name || 'Unknown file'"
17147
+ [fileSize]="fileAttachment.size || ''"
17148
+ [variant]="getFileVariant(fileAttachment.type)"
17149
+ [layout]="'compact'"
17150
+ (fileClick)="handleFileAttachmentClick(fileAttachment)"
17151
+ >
17152
+ </ds-mobile-card-inline-file>
17153
+ }
17148
17154
  }
17149
- }
17150
- </div>
17155
+ </div>
17156
+ }
17151
17157
  }
17152
17158
  }
17153
17159
  }
17154
- }
17160
+ </div>
17155
17161
  </div>
17156
- </div>
17157
- </ds-mobile-section>
17162
+ </ds-mobile-section>
17158
17163
  }
17159
17164
 
17160
17165
  <!-- Fixed message composer -->
@@ -17182,7 +17187,7 @@ class DsMobileChatModalComponent {
17182
17187
  </ds-mobile-message-composer>
17183
17188
  </div>
17184
17189
  </ds-mobile-modal-base>
17185
- `, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important;padding:0!important}:host ::ng-deep ds-textarea.ghost-input-clean .textarea-container{padding:0!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ":host ::ng-deep .modal-content-container{padding-top:0}:host-context(.chat-modal--settings) ::ng-deep .modal-header{border-bottom:none}:host-context(.chat-modal--add-members) ::ng-deep .modal-header{border-bottom:1px solid var(--border-color-default)}.chat-messages-container{display:flex;flex-direction:column;width:100%}.chat-system-line{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;line-height:1.35;color:var(--text-color-default-tertiary, #737373);text-align:center;margin:8px 24px}.chat-avatar-section{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px 0 0;background:var(--color-background-neutral-primary, #ffffff)}.chat-avatar-info{display:flex;flex-direction:column;align-items:center;gap:4px}.chat-avatar-name{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.chat-avatar-role{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-secondary, #666666)}.chat-avatar-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:4px}.messages-list{display:flex;flex-direction:column;width:100%;padding:16px 0 0;align-items:stretch}.messages-list ds-mobile-message-bubble{width:100%;display:flex}.timestamp-header{display:flex;justify-content:center;margin:16px 0 8px}.timestamp-text{font-family:Brockmann,sans-serif;font-size:12px;font-weight:400;color:var(--color-text-secondary);padding:4px 12px}.message-file-attachments{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;padding:0 20px 0 60px;max-width:100%}.message-file-attachments.own-message{padding:0 0 0 96px;align-items:flex-end}.message-file-attachments ds-mobile-card-inline-file{max-width:280px;width:100%}.message-image-attachment{width:96px;height:96px;cursor:pointer;border-radius:12px;overflow:hidden;position:relative;transition:transform .2s ease;border:1px solid var(--border-color-default, #e5e5e5)}.message-image-attachment:active{transform:scale(.98)}.message-image-attachment .inline-image{width:100%;height:100%;display:block;-o-object-fit:cover;object-fit:cover}.group-settings-back-btn{flex-shrink:0;border-radius:50%}.group-settings-back-btn::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsMobileVendorAvatarComponent, selector: "ds-mobile-vendor-avatar", inputs: ["name", "logo", "size"] }, { kind: "component", type: DsMobileMessageComposerComponent, selector: "ds-mobile-message-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "placeholder", "sendButtonLabel", "attachmentButtonLabel", "showAttachmentButton", "showAiButton", "editIndicatorText", "replyIndicatorText", "enableMentions", "mentionUsers", "showInternalToggle", "internalToggleLabel", "replyLabel", "internalMessageDescription", "autoFocus"], outputs: ["messageSent", "editCancelled", "replyCancelled", "mentionSelected", "attachmentClicked", "attachmentsChanged", "aiClick"] }, { kind: "component", type: DsMobileMessageBubbleComponent, selector: "ds-mobile-message-bubble", inputs: ["content", "isOwnMessage", "senderName", "timestamp", "showTimestamp", "avatarInitials", "avatarType", "avatarSrc", "showAvatar", "clusterPosition", "attachments", "clickable", "isNewMessage", "isDeleted", "showEditedHint", "editedHintText"], outputs: ["attachmentClick", "longPress", "messageClick"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "textLoading", "textErrorTitle", "showHeader"], outputs: ["titleClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileSystemMessageBannerComponent, selector: "ds-mobile-system-message-banner", inputs: ["message", "iconName", "afterTimestamp"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileGroupAvatarStackComponent, selector: "ds-mobile-group-avatar-stack", inputs: ["members", "customAvatarUrl", "size", "layout", "currentUserId"] }, { kind: "component", type: DsMobileListSearchComponent, selector: "ds-mobile-list-search", inputs: ["placeholder", "ariaLabel", "value", "showDivider"], outputs: ["valueChange"] }, { kind: "component", type: DsMobileChatGroupPanelsComponent, selector: "ds-mobile-chat-group-panels", inputs: ["panelView", "group", "membersForStack", "participantName", "currentUserId", "isAdmin", "canEditGroupDetails", "canAddGroupMembers", "canLeaveGroup", "canRemoveMember", "canMessageMember", "allTenantsForPicker", "searchQuery", "labels"], outputs: ["navigateTo", "renameGroup", "setGroupAvatarUrl", "addMembers", "removeMember", "messageMember", "leaveGroup"] }] });
17190
+ `, isInline: true, styles: [".author-details{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.author-name{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:600;line-height:20px;letter-spacing:-.3px;color:var(--color-text-primary, #1a1a1a);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.author-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;letter-spacing:-.26px;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:6px}.author-meta .separator{color:var(--color-text-tertiary, #a0a0a0)}.lightbox-context .author-name,.overlay-context .author-name{color:#fffffff2}.lightbox-context .author-meta,.overlay-context .author-meta{color:#ffffffb3}.lightbox-context .author-meta .separator,.overlay-context .author-meta .separator{color:#ffffff80}.section-headline{font-size:var(--font-size-base);font-weight:600;color:var(--text-color-default-primary);padding:16px 0;margin:0;letter-spacing:-.2px;display:flex;align-items:center;gap:6px}.empty-state-title{font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--text-color-default-primary, #202227);margin:0 0 8px}.empty-state-description{font-family:Brockmann,sans-serif;font-size:var(--font-size-sm);font-weight:400;line-height:1.4;color:var(--text-color-default-secondary, #545B66);margin:0}.ghost-input-clean ::ng-deep .ds-input,.ghost-input-clean ::ng-deep .ds-textarea,.ghost-input-clean ::ng-deep .textarea-container{outline:none!important;border:none!important;padding:0!important}:host ::ng-deep ds-textarea.ghost-input-clean .textarea-container{padding:0!important}.ghost-input-clean ::ng-deep .ds-input:hover,.ghost-input-clean ::ng-deep .ds-textarea:hover,.ghost-input-clean ::ng-deep .textarea-container:hover,.ghost-input-clean ::ng-deep .ds-input:focus,.ghost-input-clean ::ng-deep .ds-textarea:focus,.ghost-input-clean ::ng-deep .textarea-container:focus,.ghost-input-clean ::ng-deep .ds-input:focus-within,.ghost-input-clean ::ng-deep .ds-textarea:focus-within,.ghost-input-clean ::ng-deep .textarea-container:focus-within{outline:none!important;border:none!important;box-shadow:none!important}.ghost-input-clean ::ng-deep textarea{outline:none!important;border:none!important;box-shadow:none!important;resize:none!important}.ghost-input-clean ::ng-deep textarea:hover,.ghost-input-clean ::ng-deep textarea:focus{outline:none!important;border:none!important;box-shadow:none!important}\n", ":host ::ng-deep .modal-content-container{padding-top:0}:host-context(.chat-modal--settings) ::ng-deep .modal-header{border-bottom:none}:host-context(.chat-modal--add-members) ::ng-deep .modal-header{border-bottom:1px solid var(--border-color-default)}.chat-messages-container{display:flex;flex-direction:column;width:100%}.chat-system-line{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs, 12px);font-weight:400;line-height:1.35;color:var(--text-color-default-tertiary, #737373);text-align:center;margin:8px 24px}.chat-avatar-section{display:flex;flex-direction:column;align-items:center;gap:12px;padding:48px 0 0;background:var(--color-background-neutral-primary, #ffffff)}.chat-avatar-info{display:flex;flex-direction:column;align-items:center;gap:4px}.chat-avatar-name{display:flex;align-items:center;gap:6px;font-family:Brockmann,sans-serif;font-size:var(--font-size-base);font-weight:600;line-height:1.3;color:var(--color-text-primary, #1a1a1a)}.chat-avatar-role{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-secondary, #666666)}.chat-avatar-meta{font-family:Brockmann,sans-serif;font-size:var(--font-size-xs);font-weight:400;line-height:1.2;color:var(--color-text-tertiary, #737373);display:flex;align-items:center;gap:4px}.messages-list{display:flex;flex-direction:column;width:100%;padding:16px 0 0;align-items:stretch}.messages-list ds-mobile-message-bubble{width:100%;display:flex}.timestamp-header{display:flex;justify-content:center;margin:16px 0 8px}.timestamp-text{font-family:Brockmann,sans-serif;font-size:12px;font-weight:400;color:var(--color-text-secondary);padding:4px 12px}.message-file-attachments{display:flex;flex-direction:column;gap:8px;margin-bottom:12px;padding:0 20px 0 60px;max-width:100%}.message-file-attachments.own-message{padding:0 0 0 96px;align-items:flex-end}.message-file-attachments ds-mobile-card-inline-file{max-width:280px;width:100%}.message-image-attachment{width:96px;height:96px;cursor:pointer;border-radius:12px;overflow:hidden;position:relative;transition:transform .2s ease;border:1px solid var(--border-color-default, #e5e5e5)}.message-image-attachment:active{transform:scale(.98)}.message-image-attachment .inline-image{width:100%;height:100%;display:block;-o-object-fit:cover;object-fit:cover}.group-settings-back-btn{flex-shrink:0;border-radius:50%}.group-settings-back-btn::ng-deep button{border-radius:50%!important;width:36px!important;height:36px!important;min-width:36px!important;min-height:36px!important;padding:0!important;display:flex!important;align-items:center!important;justify-content:center!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DsAvatarWithBadgeComponent, selector: "ds-avatar-with-badge", inputs: ["type", "size", "initials", "src", "iconName", "showBadge", "badgePosition"] }, { kind: "component", type: DsMobileVendorAvatarComponent, selector: "ds-mobile-vendor-avatar", inputs: ["name", "logo", "size"] }, { kind: "component", type: DsMobileMessageComposerComponent, selector: "ds-mobile-message-composer", inputs: ["avatarInitials", "avatarType", "avatarSrc", "placeholder", "sendButtonLabel", "attachmentButtonLabel", "showAttachmentButton", "showAiButton", "editIndicatorText", "replyIndicatorText", "enableMentions", "mentionUsers", "showInternalToggle", "internalToggleLabel", "replyLabel", "internalMessageDescription", "autoFocus"], outputs: ["messageSent", "editCancelled", "replyCancelled", "mentionSelected", "attachmentClicked", "attachmentsChanged", "aiClick"] }, { kind: "component", type: DsMobileMessageBubbleComponent, selector: "ds-mobile-message-bubble", inputs: ["content", "isOwnMessage", "senderName", "isInternal", "internalMessageBadgeText", "timestamp", "showTimestamp", "avatarInitials", "avatarType", "avatarSrc", "showAvatar", "clusterPosition", "attachments", "clickable", "isNewMessage", "isDeleted", "showEditedHint", "editedHintText"], outputs: ["attachmentClick", "longPress", "messageClick"] }, { kind: "component", type: DsMobileModalBaseComponent, selector: "ds-mobile-modal-base", inputs: ["headerTitleInteractive", "textLoading", "textErrorTitle", "showHeader"], outputs: ["titleClick"] }, { kind: "component", type: DsMobileCardInlineFileComponent, selector: "ds-mobile-card-inline-file", inputs: ["fileName", "fileSize", "variant", "layout", "fileUrl"], outputs: ["fileClick"] }, { kind: "component", type: DsMobileSystemMessageBannerComponent, selector: "ds-mobile-system-message-banner", inputs: ["message", "iconName", "afterTimestamp"] }, { kind: "component", type: DsIconComponent, selector: "ds-icon", inputs: ["name", "size", "color", "interactive"] }, { kind: "component", type: DsIconButtonComponent, selector: "ds-icon-button", inputs: ["variant", "size", "icon", "disabled", "loading", "pressed", "expanded", "ariaLabel", "tooltip", "tooltipDisabled", "tooltipPlacement"], outputs: ["clicked", "focused", "blurred"] }, { kind: "component", type: DsMobileSectionComponent, selector: "ds-mobile-section", inputs: ["headline", "icon", "linkText", "padding", "paddingDesktop", "gap", "contentGap", "showBorder", "overflow"], outputs: ["linkClick"] }, { kind: "component", type: DsMobileGroupAvatarStackComponent, selector: "ds-mobile-group-avatar-stack", inputs: ["members", "customAvatarUrl", "size", "layout", "currentUserId"] }, { kind: "component", type: DsMobileListSearchComponent, selector: "ds-mobile-list-search", inputs: ["placeholder", "ariaLabel", "value", "showDivider"], outputs: ["valueChange"] }, { kind: "component", type: DsMobileChatGroupPanelsComponent, selector: "ds-mobile-chat-group-panels", inputs: ["panelView", "group", "membersForStack", "participantName", "currentUserId", "isAdmin", "canEditGroupDetails", "canAddGroupMembers", "canLeaveGroup", "canRemoveMember", "canMessageMember", "allTenantsForPicker", "searchQuery", "labels"], outputs: ["navigateTo", "renameGroup", "setGroupAvatarUrl", "addMembers", "removeMember", "messageMember", "leaveGroup"] }] });
17186
17191
  }
17187
17192
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: DsMobileChatModalComponent, decorators: [{
17188
17193
  type: Component,
@@ -17241,10 +17246,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
17241
17246
  />
17242
17247
  }
17243
17248
  } @else if (participant().avatarShape === 'squircle') {
17244
- <ds-mobile-vendor-avatar
17245
- [name]="participant().name"
17246
- [logo]="participant().avatarSrc || ''"
17247
- size="md" />
17249
+ <ds-mobile-vendor-avatar [name]="participant().name" [logo]="participant().avatarSrc || ''" size="md" />
17248
17250
  } @else {
17249
17251
  <ds-avatar-with-badge
17250
17252
  [initials]="participant().avatarInitials || ''"
@@ -17294,155 +17296,153 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
17294
17296
  (leaveGroup)="handleLeaveGroupFromPanel()"
17295
17297
  />
17296
17298
  } @else {
17297
- <!-- Messages Section -->
17298
- <ds-mobile-section>
17299
- <div class="chat-messages-container" (click)="handleContentClick()">
17300
- <!-- Centered avatar section at top of messages -->
17301
- <div class="chat-avatar-section">
17302
- @if (threadKind() === 'group' && group()) {
17303
- <ds-mobile-group-avatar-stack
17304
- [members]="groupMembersForStack()"
17305
- [customAvatarUrl]="group()!.customAvatarUrl || ''"
17306
- layout="list"
17307
- size="xl"
17308
- style="cursor: pointer"
17309
- (click)="onGroupTitleClick(); $event.stopPropagation()"
17310
- />
17311
- } @else if (participant().avatarShape === 'squircle') {
17312
- <ds-mobile-vendor-avatar
17313
- [name]="participant().name"
17314
- [logo]="participant().avatarSrc || ''"
17315
- size="xl" />
17316
- } @else {
17317
- <ds-avatar-with-badge
17318
- [initials]="participant().avatarInitials || ''"
17319
- [type]="participant().avatarType || 'initials'"
17320
- [src]="participant().avatarSrc || ''"
17321
- [badge]="participant().badge"
17322
- [showBadge]="threadContext() === 'inquiry'"
17323
- size="xl"
17324
- />
17325
- }
17326
- <div class="chat-avatar-info">
17327
- <div class="chat-avatar-name">
17328
- {{ participant().name }}
17329
- @if (participant().verified) {
17330
- <ds-icon name="remixCheckboxCircleFill" size="24px" [style.color]="'var(--color-primary-base)'"></ds-icon>
17299
+ <!-- Messages Section -->
17300
+ <ds-mobile-section>
17301
+ <div class="chat-messages-container" (click)="handleContentClick()">
17302
+ <!-- Centered avatar section at top of messages -->
17303
+ <div class="chat-avatar-section">
17304
+ @if (threadKind() === 'group' && group()) {
17305
+ <ds-mobile-group-avatar-stack
17306
+ [members]="groupMembersForStack()"
17307
+ [customAvatarUrl]="group()!.customAvatarUrl || ''"
17308
+ layout="list"
17309
+ size="xl"
17310
+ style="cursor: pointer"
17311
+ (click)="onGroupTitleClick(); $event.stopPropagation()"
17312
+ />
17313
+ } @else if (participant().avatarShape === 'squircle') {
17314
+ <ds-mobile-vendor-avatar [name]="participant().name" [logo]="participant().avatarSrc || ''" size="xl" />
17315
+ } @else {
17316
+ <ds-avatar-with-badge
17317
+ [initials]="participant().avatarInitials || ''"
17318
+ [type]="participant().avatarType || 'initials'"
17319
+ [src]="participant().avatarSrc || ''"
17320
+ [badge]="participant().badge"
17321
+ [showBadge]="threadContext() === 'inquiry'"
17322
+ size="xl"
17323
+ />
17324
+ }
17325
+ <div class="chat-avatar-info">
17326
+ <div class="chat-avatar-name">
17327
+ {{ participant().name }}
17328
+ @if (participant().verified) {
17329
+ <ds-icon name="remixCheckboxCircleFill" size="24px" [style.color]="'var(--color-primary-base)'"></ds-icon>
17330
+ }
17331
+ </div>
17332
+ @if (participant().role) {
17333
+ <div class="chat-avatar-role">{{ participant().role }}</div>
17334
+ }
17335
+ @if (participant().lastActive) {
17336
+ <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
17331
17337
  }
17332
17338
  </div>
17333
- @if (participant().role) {
17334
- <div class="chat-avatar-role">{{ participant().role }}</div>
17335
- }
17336
- @if (participant().lastActive) {
17337
- <div class="chat-avatar-meta">{{ participant().lastActive }}</div>
17338
- }
17339
17339
  </div>
17340
- </div>
17341
17340
 
17342
- <div class="messages-list">
17343
- @if (messages().length === 0) {
17344
- <!-- Empty State - Timestamp and optional inquiry system message -->
17345
- <div class="timestamp-header">
17346
- <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
17347
- </div>
17348
-
17349
- @if (threadContext() === 'inquiry') {
17350
- <ds-mobile-system-message-banner [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'" [afterTimestamp]="true">
17351
- </ds-mobile-system-message-banner>
17352
- }
17353
- } @else {
17354
- @for (group of messagesWithDisplay(); track group.timestamp) {
17355
- <!-- Timestamp Header -->
17341
+ <div class="messages-list">
17342
+ @if (messages().length === 0) {
17343
+ <!-- Empty State - Timestamp and optional inquiry system message -->
17356
17344
  <div class="timestamp-header">
17357
- <span class="timestamp-text">{{ group.displayTimestamp }}</span>
17345
+ <span class="timestamp-text">{{ getInitialTimestamp() }}</span>
17358
17346
  </div>
17359
17347
 
17360
- @if ($first && threadContext() === 'inquiry') {
17348
+ @if (threadContext() === 'inquiry') {
17361
17349
  <ds-mobile-system-message-banner [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'" [afterTimestamp]="true">
17362
17350
  </ds-mobile-system-message-banner>
17363
17351
  }
17364
- @for (message of group.messages; track message.id) {
17365
- @if (message.systemKind) {
17366
- <p class="chat-system-line">{{ formatActivityLine(message) }}</p>
17367
- } @else if (message.senderId === 'system' && message.content.trim()) {
17368
- <p class="chat-system-line">{{ message.content }}</p>
17369
- } @else if (message.deletedAt) {
17370
- <ds-mobile-message-bubble
17371
- [content]="deletePlaceholder(message)"
17372
- [isOwnMessage]="message.isOwnMessage"
17373
- [timestamp]="formatMessageTimestamp(message.timestamp)"
17374
- [showTimestamp]="selectedMessageId() === message.id"
17375
- [avatarInitials]="message.avatarInitials || ''"
17376
- [avatarType]="message.avatarType || 'initials'"
17377
- [avatarSrc]="message.avatarSrc || ''"
17378
- [showAvatar]="message.showAvatar"
17379
- [clusterPosition]="message.clusterPosition"
17380
- [attachments]="message.attachments"
17381
- [clickable]="false"
17382
- [isDeleted]="true"
17383
- [isNewMessage]="false"
17384
- >
17385
- </ds-mobile-message-bubble>
17386
- } @else if (message.content.trim()) {
17387
- <ds-mobile-message-bubble
17388
- [content]="message.content"
17389
- [isOwnMessage]="message.isOwnMessage"
17390
- [timestamp]="formatMessageTimestamp(message.timestamp)"
17391
- [showTimestamp]="selectedMessageId() === message.id"
17392
- [avatarInitials]="message.avatarInitials || ''"
17393
- [avatarType]="message.avatarType || 'initials'"
17394
- [avatarSrc]="message.avatarSrc || ''"
17395
- [showAvatar]="message.showAvatar && !(message.fileAttachments && message.fileAttachments.length > 0)"
17396
- [clusterPosition]="(message.fileAttachments && message.fileAttachments.length > 0) ? 'first' : message.clusterPosition"
17397
- [attachments]="message.attachments"
17398
- [clickable]="true"
17399
- [isNewMessage]="message.isNewMessage || false"
17400
- [showEditedHint]="!!message.editedAt"
17401
- [editedHintText]="lbl.editedHint"
17402
- (messageClick)="handleMessageClick(message.id)"
17403
- (attachmentClick)="handleAttachmentClick($event)"
17404
- (longPress)="handleMessageLongPress(message)"
17405
- >
17406
- </ds-mobile-message-bubble>
17352
+ } @else {
17353
+ @for (group of messagesWithDisplay(); track group.timestamp) {
17354
+ <!-- Timestamp Header -->
17355
+ <div class="timestamp-header">
17356
+ <span class="timestamp-text">{{ group.displayTimestamp }}</span>
17357
+ </div>
17358
+
17359
+ @if ($first && threadContext() === 'inquiry') {
17360
+ <ds-mobile-system-message-banner [message]="participant().name + ' har overtaget din henvendelse og vil kontakte dig snart.'" [afterTimestamp]="true">
17361
+ </ds-mobile-system-message-banner>
17407
17362
  }
17363
+ @for (message of group.messages; track message.id) {
17364
+ @if (message.systemKind) {
17365
+ <p class="chat-system-line">{{ formatActivityLine(message) }}</p>
17366
+ } @else if (message.senderId === 'system' && message.content.trim()) {
17367
+ <p class="chat-system-line">{{ message.content }}</p>
17368
+ } @else if (message.deletedAt) {
17369
+ <ds-mobile-message-bubble
17370
+ [content]="deletePlaceholder(message)"
17371
+ [isOwnMessage]="message.isOwnMessage"
17372
+ [isInternal]="message.isInternal || false"
17373
+ [internalMessageBadgeText]="lbl.internalMessageBadge"
17374
+ [timestamp]="formatMessageTimestamp(message.timestamp)"
17375
+ [showTimestamp]="selectedMessageId() === message.id"
17376
+ [avatarInitials]="message.avatarInitials || ''"
17377
+ [avatarType]="message.avatarType || 'initials'"
17378
+ [avatarSrc]="message.avatarSrc || ''"
17379
+ [showAvatar]="message.showAvatar"
17380
+ [clusterPosition]="message.clusterPosition"
17381
+ [attachments]="message.attachments"
17382
+ [clickable]="false"
17383
+ [isDeleted]="true"
17384
+ [isNewMessage]="false"
17385
+ >
17386
+ </ds-mobile-message-bubble>
17387
+ } @else if (message.content.trim()) {
17388
+ <ds-mobile-message-bubble
17389
+ [content]="message.content"
17390
+ [isOwnMessage]="message.isOwnMessage"
17391
+ [isInternal]="message.isInternal || false"
17392
+ [internalMessageBadgeText]="lbl.internalMessageBadge"
17393
+ [timestamp]="formatMessageTimestamp(message.timestamp)"
17394
+ [showTimestamp]="selectedMessageId() === message.id"
17395
+ [avatarInitials]="message.avatarInitials || ''"
17396
+ [avatarType]="message.avatarType || 'initials'"
17397
+ [avatarSrc]="message.avatarSrc || ''"
17398
+ [showAvatar]="message.showAvatar && !(message.fileAttachments && message.fileAttachments.length > 0)"
17399
+ [clusterPosition]="message.fileAttachments && message.fileAttachments.length > 0 ? 'first' : message.clusterPosition"
17400
+ [attachments]="message.attachments"
17401
+ [clickable]="true"
17402
+ [isNewMessage]="message.isNewMessage || false"
17403
+ [showEditedHint]="!!message.editedAt"
17404
+ [editedHintText]="lbl.editedHint"
17405
+ (messageClick)="handleMessageClick(message.id)"
17406
+ (attachmentClick)="handleAttachmentClick($event)"
17407
+ (longPress)="handleMessageLongPress(message)"
17408
+ >
17409
+ </ds-mobile-message-bubble>
17410
+ }
17408
17411
 
17409
- @if (!message.deletedAt && message.fileAttachments && message.fileAttachments.length > 0) {
17410
- <div
17411
- class="message-file-attachments"
17412
- [class.own-message]="message.isOwnMessage"
17413
- [class.attachment-only]="!message.content.trim()"
17414
- (click)="handleMessageClick(message.id)"
17415
- (touchstart)="startAttachmentLongPress(message)"
17416
- (touchend)="cancelAttachmentLongPress()"
17417
- (touchcancel)="cancelAttachmentLongPress()"
17418
- >
17419
- @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {
17420
- @if (fileAttachment.type === 'image') {
17421
- <div
17422
- class="message-image-attachment"
17423
- (click)="handleImageClick(fileAttachment, message); $event.stopPropagation()"
17424
- >
17425
- <img [src]="fileAttachment.src" [alt]="fileAttachment.name || 'Image'" class="inline-image" />
17426
- </div>
17427
- } @else {
17428
- <ds-mobile-card-inline-file
17429
- [fileName]="fileAttachment.name || 'Unknown file'"
17430
- [fileSize]="fileAttachment.size || ''"
17431
- [variant]="getFileVariant(fileAttachment.type)"
17432
- [layout]="'compact'"
17433
- (fileClick)="handleFileAttachmentClick(fileAttachment)"
17434
- >
17435
- </ds-mobile-card-inline-file>
17412
+ @if (!message.deletedAt && message.fileAttachments && message.fileAttachments.length > 0) {
17413
+ <div
17414
+ class="message-file-attachments"
17415
+ [class.own-message]="message.isOwnMessage"
17416
+ [class.attachment-only]="!message.content.trim()"
17417
+ (click)="handleMessageClick(message.id)"
17418
+ (touchstart)="startAttachmentLongPress(message)"
17419
+ (touchend)="cancelAttachmentLongPress()"
17420
+ (touchcancel)="cancelAttachmentLongPress()"
17421
+ >
17422
+ @for (fileAttachment of message.fileAttachments; track fileAttachment.id) {
17423
+ @if (fileAttachment.type === 'image') {
17424
+ <div class="message-image-attachment" (click)="handleImageClick(fileAttachment, message); $event.stopPropagation()">
17425
+ <img [src]="fileAttachment.src" [alt]="fileAttachment.name || 'Image'" class="inline-image" />
17426
+ </div>
17427
+ } @else {
17428
+ <ds-mobile-card-inline-file
17429
+ [fileName]="fileAttachment.name || 'Unknown file'"
17430
+ [fileSize]="fileAttachment.size || ''"
17431
+ [variant]="getFileVariant(fileAttachment.type)"
17432
+ [layout]="'compact'"
17433
+ (fileClick)="handleFileAttachmentClick(fileAttachment)"
17434
+ >
17435
+ </ds-mobile-card-inline-file>
17436
+ }
17436
17437
  }
17437
- }
17438
- </div>
17438
+ </div>
17439
+ }
17439
17440
  }
17440
17441
  }
17441
17442
  }
17442
- }
17443
+ </div>
17443
17444
  </div>
17444
- </div>
17445
- </ds-mobile-section>
17445
+ </ds-mobile-section>
17446
17446
  }
17447
17447
 
17448
17448
  <!-- Fixed message composer -->
@@ -33642,6 +33642,29 @@ class MobileInquiryDetailPageComponent {
33642
33642
  isOwnMessage: false,
33643
33643
  avatarInitials: messageThread.senderInitials,
33644
33644
  avatarType: 'initials',
33645
+ },
33646
+ {
33647
+ id: '11',
33648
+ content: 'Note til intern brug: Tjek også om ventilationen skal renses under besøget.',
33649
+ senderId: 'current-user',
33650
+ senderName: 'You',
33651
+ timestamp: new Date(Date.now() - 30000),
33652
+ isOwnMessage: true,
33653
+ isInternal: true,
33654
+ avatarInitials: this.userService.avatarInitials(),
33655
+ avatarType: 'initials',
33656
+ },
33657
+ {
33658
+ id: '12',
33659
+ content: 'Modtaget, jeg tager udstyr med til ventilationen også.',
33660
+ senderId: messageId,
33661
+ senderName: messageThread.senderName,
33662
+ senderRole: messageThread.role,
33663
+ timestamp: new Date(Date.now() - 10000),
33664
+ isOwnMessage: false,
33665
+ isInternal: true,
33666
+ avatarInitials: messageThread.senderInitials,
33667
+ avatarType: 'initials',
33645
33668
  }
33646
33669
  ],
33647
33670
  currentUserId: 'current-user',